Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
https =
require (
'ssl.https' )
ltn12 =
require (
'ltn12' )
json =
require (
'json' )
local bridge =
'ip of the bridge'
local usr =
'same user as api v1'
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
}
})
if not res or code ~=
200 then
return
else
resp =
table.concat (
resp )
resp =
json.pdecode (
resp )
return resp
end
end
function getLights ()
return hueExec (
'GET' ,
'/light' )
end
function getLight (
iLight )
return hueExec (
'GET' ,
'/light/' ..
iLight )
end
function runScene (
iScene ,
iAction )
vAction =
iAction or 'active'
hueExec (
'PUT' ,
'/scene/' ..
iScene , {
recall = {
action =
vAction }})
end
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
02.02.2022, 14:53
(This post was last modified: 02.02.2022, 14:54 by gjniewenhuijse .)
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.
Posts: 8197
Threads: 43
Joined: Jun 2015
Reputation:
473
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:
1 2 3 4 5 6 7
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'
)
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
(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:
1 2 3 4 5 6 7
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
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
Posts: 8197
Threads: 43
Joined: Jun 2015
Reputation:
473
Maybe some extra headers are needed. What do you get in the output?
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
03.02.2022, 09:11
(This post was last modified: 03.02.2022, 09:14 by gjniewenhuijse .)
(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)
Posts: 8197
Threads: 43
Joined: Jun 2015
Reputation:
473
It can return 404 if the appkey is incorrect.
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
03.02.2022, 09:34
(This post was last modified: 03.02.2022, 09:45 by gjniewenhuijse .)
(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?
Posts: 8197
Threads: 43
Joined: Jun 2015
Reputation:
473
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
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
03.02.2022, 10:12
(This post was last modified: 03.02.2022, 10:44 by gjniewenhuijse .)
(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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
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
if line :
find (
': hi' )
then
log (
'connection ok: ' ,
line )
elseif line :
find (
'data:' )
then
log (
'data' ,
line )
end
else
log (
'receive failed: ' ..
tostring (
err ))
sock :
close ()
sock =
nil
end
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
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:
1 2
line =
string.sub (
line ,
8 ,-
2 )
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"}]
Posts: 119
Threads: 15
Joined: Nov 2019
Reputation:
6
10.01.2023, 09:16
(This post was last modified: 10.01.2023, 09:21 by Joep .)
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:
1 2 3 4 5 6 7 8 9
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
Posts: 20
Threads: 7
Joined: May 2023
Reputation:
0
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
Posts: 459
Threads: 97
Joined: Jun 2015
Reputation:
6
(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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
function hueExec (
iMethod ,
iCommand ,
iBody )
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
}
})
if not res or code ~=
200 then
return res ,
code
else
return json.pdecode (
table.concat (
resp ))
end
end
function getLights ()
return hueExec (
'GET' ,
'/light' )
end
function getLight (
iLight )
return hueExec (
'GET' ,
'/light/' ..
iLight )
end
function runScene (
iScene ,
iAction )
vAction =
iAction or 'active'
hueExec (
'PUT' ,
'/scene/' ..
iScene , {
recall = {
action =
vAction }})
end
and tested with the event handler
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
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