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.

Philips Hue api v2
#1
Has anyone already made any code for the Philips Hue api V2?

Why the v2 api? because i want to trigger dynamic scenes and thats not possible in the v1 api.

Please correct my code is you see improvements.

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
--[[ https://developers.meethue.com/develop/hue-api-v2/api-reference/ https://developers.meethue.com/develop/hue-api-v2/getting-started/ --]] -- Load modules https = require('ssl.https') ltn12 = require('ltn12') json = require('json') local bridge = 'ip of the bridge' local usr = 'same user as api v1' -- bridge communication base function hueExec(iMethod, iCommand, iBody)   resp = {}   body = json.encode(iBody)   res, code, headers = https.request({     url = 'https://'..bridge..'/clip/v2/resource'..iCommand,     method = iMethod,     source = ltn12.source.string(body),     sink = ltn12.sink.table(resp),     headers = { ['hue-application-key'] = usr,                 ['Content-Type'] = 'application/json',                 ['Accept'] = 'application/json',                 ['Content-Length'] = #body                  }   })   -- handle feedback   if not res or code ~= 200 then     return   else     resp = table.concat(resp)     resp = json.pdecode(resp)     return resp   end end -- get all lights function getLights()     return hueExec('GET', '/light') end --log(getLights()) -- get light function getLight(iLight)     return hueExec('GET', '/light/'..iLight) end --log(getLight('e4a834c9-9ca3-4f2d-98be-669c55a90b5d')) -- activate scene (active or dynamic_palette) function runScene(iScene, iAction)   vAction = iAction or 'active'     hueExec('PUT', '/scene/'..iScene, {recall = {action = vAction}}) end --runScene('185d4226-213e-4f01-913b-91c22d85bfac') -- living soho scene --runScene('185d4226-213e-4f01-913b-91c22d85bfac', 'dynamic_palette') -- living soho dynamic
Reply
#2
Can anyone help me to setup an evenstream connection?

Migration Guide to the new Hue API - Philips Hue Developer Program (meethue.com)

The V2 API supports proactive notifications on changes through Server-Sent Events (SSE) under the /eventstream endpoint:

curl --insecure -N -H 'hue-application-key: <appkey>' -H 'Accept: text/event-stream' https://<ipaddress>/eventstream/clip/v2

Events have an id, timestamp, type (‘update’, ‘add’, ‘delete’, ‘error’), and data field which contains the changed properties of the resource in the same format as a GET response on the same resource type. The following is an example event stream that would result from turning a light on and off:

id: 1617322504:0
data: [{"creationtime":"2021-04-02T00:15:04Z","data":[{"id":"4413c8fd-6643-48b5-ad02-59453edf8a61","id_v1":"/lights/1","on":{"on":true},"type":"light"}],"id":"19845c30-2e4c-4205-a7b4-8bd496f3407d","type":"update"}]

id: 1617322505:0
data: [{"creationtime":"2021-04-02T00:15:05Z","data":[{"id":"4413c8fd-6643-48b5-ad02-59453edf8a61","id_v1":"/lights/1","on":{"on":false},"type":"light"}],"id":"bea68344-a36c-4bfd-a658-97830e4e2b1a","type":"update"}]

On HTTP1.1, you will need a separate connection for the SSE request and regular requests, but we recommend using HTTP2 to multiplex them over a single connection which is more resource efficient.

Currently there is a 1 second rate limit on the amount of event containers the Bridge will send. If the same property has changed twice within that timeframe, you only get the last state. If multiple resources have changed within that timeframe, you will get multiple events grouped in a single container.
Reply
#3
You can adapt this code for your use case: https://forum.logicmachine.net/showthrea...1#pid15941
Add headers to initial request lines and change APPKEY to the actual application key:
Code:
1234567
sock:send(   'GET ' .. path .. ' HTTP/1.1\r\n' ..   'Host: ' .. host .. '\r\n' ..   'Accept: text/event-stream\r\n' ..   'hue-application-key: APPKEY\r\n' ..   '\r\n' )
Reply
#4
(02.02.2022, 15:53)admin Wrote: You can adapt this code for your use case: https://forum.logicmachine.net/showthrea...1#pid15941
Add headers to initial request lines and change APPKEY to the actual application key:
Code:
1234567
sock:send(   'GET ' .. path .. ' HTTP/1.1\r\n' ..   'Host: ' .. host .. '\r\n' ..   'Accept: text/event-stream\r\n' ..   'hue-application-key: APPKEY\r\n' ..   '\r\n' )

i think i do something wrong because the output of the lines is the same as the bridge html source what i see in the browser

Code:
123456789101112131415161718192021222324252627282930313233
if not sock then   host = 'my bridge ip'   port = 80   path = '/eventstream/clip/v2'   appkey = 'mysecretappkey'   sock = require('socket').tcp()   sock:settimeout(10)   res, err = sock:connect(host, port)   if res then     sock:send(       'GET ' .. path .. ' HTTP/1.1\r\n' ..       'Host: ' .. host .. '\r\n' ..       'Accept: text/event-stream\r\n' ..       'hue-application-key: ' .. appkey .. '\r\n' ..       '\r\n'     )   else     log('connect failed: ' .. tostring(err))     sock:close()   end end line, err = sock:receive() if line then   log('line: ' .. line) else   log('receive failed: ' .. tostring(err))   sock:close()   sock = nil end
Reply
#5
Maybe some extra headers are needed. What do you get in the output?
Reply
#6
(03.02.2022, 07:21)admin Wrote: Maybe some extra headers are needed. What do you get in the output?

same url in the browser

Attached Files Thumbnail(s)
       
Reply
#7
It can return 404 if the appkey is incorrect.
Reply
#8
(03.02.2022, 09:22)admin Wrote: It can return 404 if the appkey is incorrect.

but its the same appkey as i use for the normal connection from the other example. And there it works.

with curl the code is:
curl --insecure -N -H 'hue-application-key: <appkey>' -H 'Accept: text/event-stream' https://<ipaddress>/eventstream/clip/v2

I see https.. Do the example also setup a https connection? and is this to port 80 or 443?
Reply
#9
Does it work for you with curl? HTTPS is 443 but some extra code is needed for the raw socket to use encryption: https://forum.logicmachine.net/showthrea...903#pid903
Reply
#10
(03.02.2022, 09:50)admin Wrote: Does it work for you with curl? HTTPS is 443 but some extra code is needed for the raw socket to use encryption: https://forum.logicmachine.net/showthrea...903#pid903

yep, curl for windows code works:
curl --insecure -N -H "hue-application-key: sameapiuserasbefore" -H "Accept: text/event-stream" https://myipaddress/eventstream/clip/v2

and thx, the raw socket example works also.

working code for evenstream

Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
if not sock then   host = 'fillyourip'   port = 443   proto = 'tlsv12'   path = '/eventstream/clip/v2'   appkey = 'fillyouruser'   require('ssl')   sock = require('socket').tcp()   sock:settimeout(10)   res, err = sock:connect(host, port)   if res then     sock = ssl.wrap(sock, proto)       res, err = sock:dohandshake()     if res then       sock:send(         'GET ' .. path .. ' HTTP/1.1\r\n' ..         'Host: ' .. host .. '\r\n' ..         'Accept: text/event-stream\r\n' ..         'hue-application-key: ' .. appkey .. '\r\n' ..         '\r\n'       )         else         log('handshake failed: ' .. tostring(err))       end   else     log('connect failed: ' .. tostring(err))     sock:close()   end end line, err = sock:receive() if line then   --log('line: ' .. line)   if line:find(': hi') then     log('connection ok: ', line)   elseif line:find('data:') then     --status = line:split(':')[2]     log('data', line)   end else   log('receive failed: ' .. tostring(err))   sock:close()   sock = nil end
Reply
#11
parsing the output is another thing:

line output: data: [{"creationtime":"2022-02-03T13:35:32Z","data":[{"id":"f2ef58b3-818e-45ea-a291-325e8eeb97bc","id_v1":"/lights/10","on":{"on":false},"owner":{"rid":"0120cec8-b58e-4206-a409-2bd99055af55","rtype":"device"},"type":"light"}],"id":"49142b93-3da7-49dc-9ad6-10809df8fe9d","type":"update"}]
Code:
12
line = string.sub(line,8,-2) -- remove "data: [" and the last ] character line = json.pdecode(line)
This works

But the second output combines more lines, how to decode this line?
line output: 
data: [{"creationtime":"2022-02-03T13:35:32Z","data":[{"id":"728be63c-dc61-42b1-9a84-54daeff76046","id_v1":"/groups/0","on":{"on":false},"type":"grouped_light"}],"id":"b201d09a-0ab2-4a60-b72f-3a099841ebbc","type":"update"},{"creationtime":"2022-02-03T13:35:32Z","data":[{"id":"33b4f136-c59e-4270-83af-814c4f5ba856","id_v1":"/groups/18","on":{"on":false},"type":"grouped_light"}],"id":"e2860e1b-ebd0-40b0-81ed-f1c0b27163a3","type":"update"},{"creationtime":"2022-02-03T13:35:32Z","data":[{"id":"7a8f900c-c312-403a-bf73-9d2fcb005489","id_v1":"/groups/19","on":{"on":false},"type":"grouped_light"}],"id":"1cc814e9-9210-4e75-92c0-29a543c32dcb","type":"update"}]
Reply
#12
I would like to contribute on this and started with the Hue discovey by changing the script i found from https://forum.logicmachine.net/showthrea...4#pid24214
Below the modified version that gives all the Hue Bridge information with most important the IP address.

Code:
123456789
hue = io.readproc('avahi-browse _hue._tcp') lines = hue:split('\n') for _, line in ipairs(lines) do   ip, port, name, descr = unpack(line:split('\t'))   if descr then     log(ip, port, name, descr)   end end
Reply
#13
Hi @gjniewenhuijse,

Have you been able to make any progress on using api V2? like you, I need to use dynamic scenes and motion sensors.

thanks you
Reply
#14
(04.11.2024, 14:17)Fcs Wrote: Hi @gjniewenhuijse,

Have you been able to make any progress on using api V2? like you, I need to use dynamic scenes and motion sensors.

thanks you

I made some code to use the api v2

Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
-- hue v2 api begin -------------------------------------------------------------------------------------------------- --[[ https://developers.meethue.com/develop/hue-api-v2/api-reference/ https://developers.meethue.com/develop/hue-api-v2/getting-started/ --]] -- bridge communication base function hueExec(iMethod, iCommand, iBody)     -- load modules   https = require('ssl.https')   ltn12 = require('ltn12')   json = require('json')   resp = {}   body = json.encode(iBody)   res, code, headers = https.request({     url = 'https://'..bridge..'/clip/v2/resource'..iCommand,     method = iMethod,     source = ltn12.source.string(body),     sink = ltn12.sink.table(resp),     headers = { ['hue-application-key'] = usr,                 ['Content-Type'] = 'application/json',                 ['Accept'] = 'application/json',                 ['Content-Length'] = #body                  }   })   -- handle feedback   if not res or code ~= 200 then     return res,code   else     return json.pdecode(table.concat(resp))   end end -- get all lights function getLights()     return hueExec('GET', '/light') end --log(getLights().data) -- get light function getLight(iLight)     return hueExec('GET', '/light/'..iLight) end --log(getLight('e4a916c9-9ca3-4f3d-98be-779c55a90b5d')) -- (api v2) activate scene (active or dynamic_palette) function runScene(iScene, iAction)   vAction = iAction or 'active'     hueExec('PUT', '/scene/'..iScene, {recall = {action = vAction}}) end --runScene('185d4336-273e-4f09-913c-91c76d85bfac') -- woonkamer soho --runScene('185d4336-273e-4f09-913c-91c76d85bfac', 'dynamic_palette') -- woonkamer soho dynamic -- hue v2 api end --------------------------------------------------------------------------------------------------

and tested with the event handler
Code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
--[[ https://developers.meethue.com/develop/hue-api-v2/migration-guide-to-the-new-hue-api/#Event%20Stream --]] -- load modules json = require('json') if not sock then   host = 'x.x.x.x'   port = 443   proto = 'tlsv12'   path = '/eventstream/clip/v2'   appkey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'   require('ssl')   sock = require('socket').tcp()   sock:settimeout(10)   res, err = sock:connect(host, port)   if res then     sock = ssl.wrap(sock, proto)       res, err = sock:dohandshake()     if res then       sock:send(         'GET ' .. path .. ' HTTP/1.1\r\n' ..         'Host: ' .. host .. '\r\n' ..         'Accept: text/event-stream\r\n' ..         'hue-application-key: ' .. appkey .. '\r\n' ..         '\r\n'       )         else         log('handshake failed: ' .. tostring(err))       end   else     log('connect failed: ' .. tostring(err))     sock:close()   end end line, err = sock:receive() if line then   log('line: ' .. line)   if line:find(': hi') then     log('connection ok: ', line)   elseif line:find('data:') then     line = '{"data": '..string.sub(line,7)..'}'         log('textline',line)     line = json.pdecode(line)     log(line.data)     for _l,l_items in pairs(line.data) do       log(l_items)       log(l_items.type, l_items.data[1].id_v1, l_items.data[1].on.on)     end   end else   log('receive failed: ' .. tostring(err))   sock:close()   sock = nil end
Reply


Forum Jump: