Created At

Oct 21, 2017

Last Update

Oct 24, 2017

Platforms

HC 2

Views

3074

Download

56

Function

This virtual device allows to see and control the status of a Husqvarna Automower equipped with the Husqvarna Automower Connect hardware (with a GPRS connection). It is based on the official Husqvarna Automower Connect APP. 

It also pushes errors generated by the Automower. 

 

Configuration

  • Create a new LUA scene with the code below. Note down the "Scene ID".
  • Create the Variables. 
  • Import the Virtual Device. Put the Scene ID in the TCP-port configuration of the virtual device. 

Variables

The following variables should be created as "Predefined variables". The values are not important. 

  • mower1Command
  • mower1Status
  • mower1Token

Scene

The scene below is required and contains the real logic behind the virtual device. Scene should be set on "Manual". 

--[[
%% properties
%% events
%% globals
--]]
local usr = "<INSERT YOUR HUSQVARNA ACCOUNT EMAIL>"
local pwd = "<INSERT YOUR HUSQVARNA ACCOUNT PASSWORD"
local mowerindex = 1 -- 1 = first robot in account
local token_url = "https://iam-api.dss.husqvarnagroup.net/api/v3"
local api_url = "https://amc-api.dss.husqvarnagroup.net/v1"


local MowerConnect = net.HTTPClient()
local aHeaders = {['Content-Type'] = 'application/json'}
local mower_id = ""

function Login()
  local req = '{"data": {"attributes": {"password": "'.. pwd .. '","username": "'.. usr .. '"},"type": "token"}}'
  local value, modificationTime = fibaro:getGlobal('mower1Token')
  local result = json.decode(value)
  
  if (result) then
    if (os.time() < (modificationTime + result.data.attributes.expires_in - (60*60))) then
      -- Token not expired, reuse
      aHeaders = {
          ['Content-Type'] = 'application/json',
          ['Authorization'] = 'Bearer ' .. result.data.id,
          ['Authorization-Provider'] = result.data.attributes.provider
        }
      GetRobot()
      req = nil
    else
      -- Token expired, refresh
      req = '{"data":{"type":"token","attributes":{"refresh_token":"'.. result.data.attributes.refresh_token ..'"}}}'
    end
  end

  if (req) then
    -- Request or refresh token
    MowerConnect:request(token_url .. "/token", {
      options = {
        headers = aHeaders,
        method = "POST",
        data = '{"data": {"attributes": {"password": "'.. pwd .. '","username": "'.. usr .. '"},"type": "token"}}'
      }, 
      success = function(status)
        local result = json.decode(status.data)
        fibaro:setGlobal("mower1Token", status.data)
        fibaro:debug(status.data)
        aHeaders = {
            ['Content-Type'] = 'application/json',
            ['Authorization'] = 'Bearer ' .. result.data.id,
            ['Authorization-Provider'] = result.data.attributes.provider
          }
        GetRobot()
      end, --success
      error = function(error)
        fibaro:setGlobal("mower1Token", '')
      end --error
    }) --request
  end --if
end
  
function GetRobot()
  MowerConnect:request(api_url .. "/mowers", {
    options = {
      headers = aHeaders,
      method = "GET"
    }, 
    success = function(status)
      local prevResult = json.decode(fibaro:getGlobalValue("mower1Status"))
      fibaro:setGlobal("mower1Status", status.data)
      local result = json.decode(status.data)

      if result then
          if result[mowerindex] then
            mower_id = result[mowerindex].id
              
            if result[mowerindex].status.mowerStatus == "ERROR" or result[mowerindex].status.mowerStatus == "ERROR_AT_POWER_UP" then
                if prevResult[mowerindex].status.lastErrorCode ~= result[mowerindex].status.lastErrorCode then
                	-- Push once; only if error changes
	                PushError(result[mowerindex].status.lastErrorCode)
                end
            end
              
            fibaro:debug(status.data)
            local cmd = fibaro:getGlobalValue("mower1Command")
            if cmd ~= "" then
                fibaro:debug(cmd)
                DoCommand(cmd)
            end
          end
      end --if result
    end, --success
    error = function(error)
      fibaro:debug(error)
      fibaro:setGlobal("mower1Token", '')
    end --error
  }) --request
end


-- not used
function GetStatus()
  MowerConnect:request(api_url .. "/mowers/" .. mower_id .. "/status" , {
    options = {
      headers = aHeaders,
      method = "GET"
    }, 
    success = function(status)
      fibaro:debug(status.data)
      result = json.decode(status.data)
    end
})
end

function DoCommand(cmd)
  MowerConnect:request(api_url .. "/mowers/" .. mower_id .. "/control", {
    options = {
      headers = aHeaders,
      method = "POST",
      data = '{"action": "' .. cmd ..'"}}'
    }, 
    success = function(status)
        fibaro:debug(status.data)
        fibaro:setGlobal("mower1Command", "")
      end
})
end

function PushError(err)
  -- err 19: bump probleem front
  -- err 18: bump probleem back
  -- err 15: lifted
  -- err 10: Upside down
  -- err 2: Empty battery
  -- err 1: outside mowing area
    HomeCenter.PopupService.publish({
        title = 'Fout met grasmaaier',
        subtitle = '',
        contentBody = 'Grasmaaier heeft fout gegenereerd: ' .. err,
        img = 'http://husqvarnacdn.azureedge.net//qs_mh=680&mw=680&ver=00000000T000000/_$$_/media/dam/husqvarna/garden%20lawnmowers%20and%20ride-on%20mowers/robotic%20lawnmowers/2014/12/08/20/34/h310-0866.ashx',
        type = 'Warning',
        buttons = {
            { caption = 'Ok', sceneId = 0 }
        }
    })  
end

Login()

Icons

 

See http://virtualstuff.org/fibaro/icons/ for original icons.

 

14 Comments,  Want to add comment please login
D51f15045800db206626b8f2447d4595

Is there anyone who can confirmed that this script and VD working with Husqvarna Automover 450X?

6d7fa30c9a0509bcd8e8646d04cabdc7

Also, to "restart" the virtual device, hit save again or simply reboot the HC2

6d7fa30c9a0509bcd8e8646d04cabdc7

I also got mine working by clearing the predefined variables. The problem in the predefined variables panel interface, as that it cannot handle the json-content, so the variables cannot be reliably edited that way. Viewing and saving of this variables does not work. The best way to resolve is to remove and recreate the variables.

0dc6dce5432b46456ffa607540ef80fd

@oskar & pieter: thank you both - i created each of the three predefined variable with a empty value box and i tested as you write below but the error messages: " [fatal] Unknown exception: /usr/share/lua/5.2/json/decode/util.lua:35: unexpected character @ character: 1 0:1 [W] line: ..... " are still the same as before. i don't know what i do wrong! i think the problem is the API?! or do has any other idea?

2a1a46d25d1ddf7bb3e9f48f60f550f7

Ronald, try to run the scene by itself couple of times and then check if it works. I'm pretty confident about this solution since it works on multiple Fibaro Home Centers for me. Make sure you did everything I said correctly. Good luck