This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Dyson Pure Hot+Cool
#28
Yes it works, i can switch the Dyson off, with the follow command (code is not perfect, but you can use it as start for yourself):

Code:
require('user.nit_dyson')   
runCommand(5,CMD_OFF)

My library
Code:
--[[
use getDevices('email@email.com','password') to get the encrypted password and fill it in dysons[] so you can use this offline.
--]]

-- product types
DYSON_PURE_COOL_LINK_TOUR = '475'
DYSON_PURE_COOL_LINK_DESK = '469'
DYSON_PURE_HOT_COOL_LINK_TOUR = '455'
DYSON_360_EYE = 'N223'
DYSON_PURE_HOT_COOL_2018 = '527' --HP04 Dyson Pure Hot+Cool 2018 (244289-01)

CMD_OFF = '{"fpwr":"OFF"}'

-- all dyson devices
dysons =     {} -- room(not used), ip, port(default 1883), type, username/serial, password
dysons[5] = {'Room', '192.168.x.xxx', 1883, DYSON_PURE_HOT_COOL_2018, 'A1B-EU-KNAXXXXX', 'verylongencryptedpasswordfromgetdevices'}


-- get devices from web portal
function getDevices(iPortalUser, iPortalPwd)
  https = require 'ssl.https'
  require('json')
  socket.http.TIMEOUT = 5

  local cUsername = iPortalUser
  local cPassword = iPortalPwd

  -- get session info
  local cBody1 = '{"Email":"' .. cUsername .. '","Password":"' .. cPassword ..'"}'
  local cReq1 = {}
  local cUrl1 = 'https://api.cp.dyson.com/v1/userregistration/authenticate?country=NL'
  result1 = https.request({
      url = cUrl1,
      method = 'POST',
      headers = {
        ['content-length'] = #cBody1,
        ['content-type'] = 'application/json'
      },
      source = ltn12.source.string(cBody1),
      sink = ltn12.sink.table(cReq1)
  })
  if result1 and cReq1 then
    cReq1 = table.concat(cReq1)
    cReq1 = json.pdecode(cReq1)
    cAccount = nil
    cPassword = nil
    if cReq1 then
      if cReq1.Account and cReq1.Password then
        cAccount = cReq1.Account
        cPassword = cReq1.Password
      end
    end
    --log(cAccount,cPassword)
  else
    log(result1)
  end

  mime = require("mime")
  local cAuth = "Basic " .. mime.b64(cAccount..":"..cPassword)
  local cReq2 = {}
  local cUrl2 = 'https://api.cp.dyson.com/v2/provisioningservice/manifest'   -- v2 for new devices
  result2, c, h = https.request({
    url = cUrl2,
    method = 'GET',
    headers = {
      ['authorization'] = cAuth
    },
    sink = ltn12.sink.table(cReq2)
  })
  --log(result2,c,h)
  log(cReq2)
end


-- decrypt password
function decryptPwd(iPwd)
  data = iPwd
  -- create key
  key = {}
  for i = 1, 32 do
    key[ #key + 1 ] = i
  end
  key = string.char(unpack(key))

  -- decrypt data
  data = require('encdec').base64dec(data)
  aes = require('user.aes')
  aes_256_cbc, err = aes:new(key, nil, aes.cipher(256, 'cbc'), { iv = string.rep('\0', 16) }, nil, 0)
  data = aes_256_cbc:decrypt(data)

  -- unpad data
  len = string.byte(data, #data) + 1
  data = data:sub(1, -len)

  -- decode json
  data, err = require('json').pdecode(data)

  if type(data) == 'table' then
    pass = data.apPasswordHash
  end
 
  --log(pass)
  return pass
end

-- run dyson command
function runCommand(IDevice, iCmd)
  broker = dysons[IDevice][2]
  port = dysons[IDevice][3]
  producttype = dysons[IDevice][4]
  username = dysons[IDevice][5]
  password = dysons[IDevice][6]
 
  -- after this initialization, you'll have to use the hashed password to connect to the fan. The hashed password is a base64 encoded of the sha512 of the password
  passwordDec = decryptPwd(password)

  topicCmd     = producttype .. '/' .. username .. '/command'

  mqtt = require('mosquitto')
  client = mqtt.new()

  client.ON_CONNECT = function(status, rc, err)
    if status then
      payload = '{"msg":"STATE-SET", "time":"'..os.date("%Y-%m-%dT%H:%M:%SZ")..'", "data":'..iCmd..'}'
      client:publish(topicCmd, payload)
    end
  end

  client.ON_PUBLISH = function()
    client:disconnect()
  end

  client:login_set(username, passwordDec)
  client:connect(broker, port)
  client:loop_forever() 
end

You can also make an event handler like:
Code:
require('user.nit_dyson')

broker = '192.168.x.xx'
port = 1883 -- default port is 1883
username = 'A1B-EU-KNAXXXXX' -- device serial
password = 'longpassword'
passwordDec = decryptPwd(password)
producttype = DYSON_PURE_HOT_COOL_2018

topic         = producttype .. '/' .. username .. '/status/current'
topicCmd     = producttype .. '/' .. username .. '/command'

mqtt = require('mosquitto')
client = mqtt.new()

client.ON_CONNECT = function(status, rc, err)
  if status then
    log('connect ok')
    client:subscribe(topic)
   
    --payload = '{"msg":"STATE-SET", "time":"'..os.date("%Y-%m-%dT%H:%M:%SZ")..'", "data":{"fpwr":"OFF"}}'
    --client:publish(topicCmd, payload)
   
  else
    log('connect error', rc, err)
  end
end

client.ON_MESSAGE = function(mid, topic, data)
  log('message', topic, data)
end

client.ON_PUBLISH = function()
  --log('publish')
    --client:disconnect()
end

client.ON_LOG = function()
  --log('log')
end

client.ON_DISCONNECT = function()
  --log('disconnect')
end

client:login_set(username, passwordDec)
client:connect(broker, port)
client:loop_forever()
Reply


Messages In This Thread
Dyson Pure Hot+Cool - by gjniewenhuijse - 13.02.2019, 16:04
RE: Dyson Pure Hot+Cool - by admin - 15.02.2019, 08:34
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 11.07.2019, 08:18
RE: Dyson Pure Hot+Cool - by admin - 11.07.2019, 08:41
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 12.07.2019, 09:41
RE: Dyson Pure Hot+Cool - by admin - 12.07.2019, 09:47
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 12.07.2019, 09:55
RE: Dyson Pure Hot+Cool - by admin - 12.07.2019, 10:00
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 30.01.2020, 12:16
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 15.07.2019, 11:25
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 15.07.2019, 12:48
RE: Dyson Pure Hot+Cool - by admin - 15.07.2019, 13:27
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 15.07.2019, 14:34
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 24.09.2019, 06:16
RE: Dyson Pure Hot+Cool - by admin - 16.07.2019, 07:59
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 16.07.2019, 08:32
RE: Dyson Pure Hot+Cool - by admin - 16.07.2019, 09:09
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 16.07.2019, 09:53
RE: Dyson Pure Hot+Cool - by admin - 16.07.2019, 10:49
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 16.07.2019, 13:44
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 17.07.2019, 14:39
RE: Dyson Pure Hot+Cool - by admin - 18.07.2019, 09:29
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 19.07.2019, 11:54
RE: Dyson Pure Hot+Cool - by admin - 19.07.2019, 12:28
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 20.08.2020, 08:33
RE: Dyson Pure Hot+Cool - by admin - 26.09.2019, 08:07
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 27.09.2019, 07:01
RE: Dyson Pure Hot+Cool - by admin - 01.10.2019, 06:46
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 01.10.2019, 08:00
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 04.10.2019, 08:49
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 09.10.2019, 12:16
RE: Dyson Pure Hot+Cool - by admin - 30.01.2020, 18:24
RE: Dyson Pure Hot+Cool - by admin - 20.08.2020, 08:34
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 20.08.2020, 08:41
RE: Dyson Pure Hot+Cool - by admin - 20.08.2020, 08:42
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 20.08.2020, 08:59
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 02.10.2021, 08:54
RE: Dyson Pure Hot+Cool - by admin - 04.10.2021, 06:41
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 04.10.2021, 12:58
RE: Dyson Pure Hot+Cool - by gjniewenhuijse - 12.10.2021, 11:32

Forum Jump: