Husqvarna Automower Script

Posted on
Tue Oct 09, 2018 10:49 am
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: Husqvarna Automower Script

Gusten wrote:
Hi, mine is working and i am on 7.2 Iam running my script as files if it makes any differents?


Skickat från min iPhone med Tapatalk

Thanks. Probably a cut and paste issue that I will have to explore.

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Oct 20, 2018 8:27 am
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: Husqvarna Automower Script

Good news! Husqvarna is releasing a public API in January.

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Mon May 27, 2019 3:37 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: Husqvarna Automower Script

Gusten wrote:
Hi, mine is working and i am on 7.2 Iam running my script as files if it makes any differents?

I finally had a chance to look at this -- it turns out I needed to ensure the variables at lines 189-190 were strings.

Code: Select all
         indigo.variable.updateValue(525681493, value=str(mowerStatus))#Change number to yours variable ID
         indigo.variable.updateValue(145221338, value=str(batteryPercent))#Change number to yours variable ID


Thanks for making the original script work!

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Mon Mar 30, 2020 10:40 am
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: Husqvarna Automower Script

FYI, Husqvarna has published their official Automower API at https://developer.1689.cloud

It's a reasonably simple API. You have to register as a developer and then generate an Authorization Token. I did that with an Action Group. I didn't bother parsing the JSON and just copied the token over.

Code: Select all
import requests

grant_type = 'password'
client_id = '<YourHusqvarnaDeveloperAppID>'
username = '<YourHusqvarnaAppUserName>'
password = '<YourHusqvarnaAppPassword>'

post_url = 'https://api.authentication.husqvarnagroup.dev/v1/oauth2/token'

payload = {
   'grant_type': grant_type,
   'client_id': client_id,
   'username': username,
   'password': password,
}

r = requests.post(post_url, data = payload)

indigo.server.log(str(r.text))


From there, it was straightforward to use GhostXML to pull the mower status. Only 10K calls a month are allowed, so don't poll more than once every five minutes. Here's the raw cURL needed. First is to get mower list (run once). Second to get Mower status.

Code: Select all
https://api.amc.husqvarna.dev/v1/mowers
-X GET \
-H "accept: application/vnd.api+json" \
-H "X-Api-Key: < YourHusqvarnaDeveloperAppID>" \
-H "Authorization: Bearer <YourHusqvarnaTokenFromStep1>" \
-H "Authorization-Provider: husqvarna"

NOTE: data_0_id yields the MowerID
Code: Select all
url: https://api.amc.husqvarna.dev/v1/mowers/<YourMowerFromMowerList>
-X GET \
-H "accept: application/vnd.api+json" \
-H "X-Api-Key: < YourHusqvarnaDeveloperAppID>" \
-H "Authorization: Bearer <YourHusqvarnaTokenFrom Step1>" \
-H "Authorization-Provider: husqvarna"


Finally, I created two action groups to allow me to park the mower and resume schedule. I created triggers to park the mower when the sprinklers are running and in case of rain.
Code: Select all
# Park Until Further Notice
import requests

mower = (indigo.variables['husqvarnaMower'].value)
authorization = (indigo.variables['husqvarnaAuthorization'].value)
apikey = (indigo.variables['husqvarnaAPIKey'].value)

post_url = 'https://api.amc.husqvarna.dev/v1/mowers/' + mower + '/actions'

head = {
   'accept': '*/*',
   'X-Api-Key': apikey,
   'Authorization': authorization,
   'Authorization-Provider': 'husqvarna',
   'Content-Type': 'application/vnd.api+json',
}

payload = '{"data":{"type":"ParkUntilFurtherNotice"}}'

r = requests.post(post_url, headers = head, data = payload)

if str(r.status_code) == '202':
   indigo.server.log('Husqvarna Parked Until Further Notice')
   indigo.variable.updateValue('husqvarnaParked', value=str('true'))

Code: Select all
# Resume Schedule
import requests

mower = (indigo.variables['husqvarnaMower'].value)
authorization = (indigo.variables['husqvarnaAuthorization'].value)
apikey = (indigo.variables['husqvarnaAPIKey'].value)

post_url = 'https://api.amc.husqvarna.dev/v1/mowers/' + mower + '/actions'

head = {
   'accept': '*/*',
   'X-Api-Key': apikey,
   'Authorization': authorization,
   'Authorization-Provider': 'husqvarna',
   'Content-Type': 'application/vnd.api+json',
}

payload = '{"data":{"type":"ResumeSchedule"}}'

r = requests.post(post_url, headers = head, data = payload)

if str(r.status_code) == '202':
   indigo.server.log('Husqvarna Resume Schedule')
   indigo.variable.updateValue('husqvarnaParked', value=str('false'))

I have triggers that run from the GhostXML device and update based on changes to certain variables, in particular data_attributes_mower_errorCode. Just to save you some time, this converts the numeric error codes into their text equivalent:
Code: Select all
husqvarnaError = str(indigo.variables[1384099050].value) # "husqvarnaErrorCode"

dict = {
'0': 'Unexpected error',
'1': 'Outside working area',
'2': 'No loop signal',
'3': 'Wrong loop signal',
'4': 'Loop sensor problem, front',
'5': 'Loop sensor problem, rear',
'6': 'Loop sensor problem, left',
'7': 'Loop sensor problem, right',
'8': 'Wrong PIN code',
'9': 'Trapped',
'10': 'Upside down',
'11': 'Low battery',
'12': 'Empty battery',
'13': 'No drive',
'14': 'Mower lifted',
'15': 'Lifted',
'16': 'Stuck in charging station',
'17': 'Charging station blocked',
'18': 'Collision sensor problem, rear',
'19': 'Collision sensor problem, front',
'20': 'Wheel motor blocked, right',
'21': 'Wheel motor blocked, left',
'22': 'Wheel drive problem, right',
'23': 'Wheel drive problem, left',
'24': 'Cutting system blocked',
'25': 'Cutting system blocked',
'26': 'Invalid sub-device combination',
'27': 'Settings restored',
'28': 'Memory circuit problem',
'29': 'Slope too steep',
'30': 'Charging system problem',
'31': 'STOP button problem',
'32': 'Tilt sensor problem',
'33': 'Mower tilted',
'34': 'Cutting stopped - slope too steep',
'35': 'Wheel motor overloaded, right',
'36': 'Wheel motor overloaded, left',
'37': 'Charging current too high',
'38': 'Electronic problem',
'39': 'Cutting motor problem',
'40': 'Limited cutting height range',
'41': 'Unexpected cutting height adj',
'42': 'Limited cutting height range',
'43': 'Cutting height problem, drive',
'44': 'Cutting height problem, curr',
'45': 'Cutting height problem, dir',
'46': 'Cutting height blocked',
'47': 'Cutting height problem',
'48': 'No response from charger',
'49': 'Ultrasonic problem',
'50': 'Guide 1 not found',
'51': 'Guide 2 not found',
'52': 'Guide 3 not found',
'53': 'GPS navigation problem',
'54': 'Weak GPS signal',
'55': 'Difficult finding home',
'56': 'Guide calibration accomplished',
'57': 'Guide calibration failed',
'58': 'Temporary battery problem',
'59': 'Temporary battery problem',
'60': 'Temporary battery problem',
'61': 'Temporary battery problem',
'62': 'Temporary battery problem',
'63': 'Temporary battery problem',
'64': 'Temporary battery problem',
'65': 'Temporary battery problem',
'66': 'Battery problem',
'67': 'Battery problem',
'68': 'Temporary battery problem',
'69': 'Alarm! Mower switched off',
'70': 'Alarm! Mower stopped',
'71': 'Alarm! Mower lifted',
'72': 'Alarm! Mower tilted',
'73': 'Alarm! Mower in motion',
'74': 'Alarm! Outside geofence',
'75': 'Connection changed',
'76': 'Connection NOT changed',
'77': 'Com board not available',
'78': 'Slipped - Mower has Slipped.Situation not solved with moving pattern',
'79': 'Invalid battery combination - Invalid combination of different battery types.',
'80': 'Cutting system imbalance    Warning',
'81': 'Safety function faulty',
'82': 'Wheel motor blocked, rear right',
'83': 'Wheel motor blocked, rear left',
'84': 'Wheel drive problem, rear right',
'85': 'Wheel drive problem, rear left',
'86': 'Wheel motor overloaded, rear right',
'87': 'Wheel motor overloaded, rear left',
'88': 'Angular sensor problem',
'89': 'Invalid system configuration',
'90': 'No power in charging station',
}

dict[husqvarnaError]

indigo.server.log(str(dict[husqvarnaError]))
indigo.variable.updateValue('husqvarnaErrorCodeText', value=str(dict[husqvarnaError]))


If I'm not the only person using one of these mowers, it seems easy enough to turn into a plugin.

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Tue Mar 31, 2020 1:11 pm
kidney offline
Posts: 237
Joined: Jul 15, 2007

Re: Husqvarna Automower Script

I'm using that mower, and would mind having a plugin for sure, but lack the skills to do so!

Who is online

Users browsing this forum: No registered users and 2 guests