Maak een “stoplicht” met Philips hue
Naar aanleiding van een post in het hue topic op Tweakers.net volgt hier een beschrijving hoe je een hue lamp automatisch van kleur kunt laten veranderen met alleen de hue bridge (dus geen app ofzo nodig).
Alle info hier is ook in de een of andere vorm beschikbaar op de Philips hue developer site (http://developers.meethue.com). Gratis registratie is vereist om de API documentatie in te zien.
Aangezien de vraagsteller zegt een “uber noob” te zijn is het uiteindelijk een behoorlijk uitgebreid verhaal geworden.
NOTE:
Deze beschrijving gebruikt de hue API. Dit is een methode die voor programmeurs bedoeld is om een App(licatie) tegenaan te schrijven, niet om met de hand te gebruiken. Daardoor komt het misschien wat onhandig over.
Als je Java of iOS apps wilt maken is waarschijnlijk handiger om de Philips hue SDKs te gebruiken en voor de vele andere talen zijn er bibliotheken beschikbaar om het een en ander te vereenvoudigen.
De vraagsteller wil het volgende:
In dit voorbeeld gebruik ik 20 seconden voor rood zodat er geen verwarring kan zijn tussen de timers voor oranje en rood. In alle voorbeelden stuur ik lamp 1 aan. Dit kan je natuurlijk vervangen door een het ID van een andere lamp
De aanpak die ik gekozen heb gebruikt 1 schedule om de lamp ‘s morgens aan te zetten en een ander schedule om de lamp ‘s avonds weer uit te zetten.
Het veranderen van de kleuren gebeurt met een combinatie van “schedules”, “sensors” en “rules” in de bridge.
Als je al weet hoe de hue API werkt en je commandos naar de bridge kunt sturen dan kan je meteen door naar Stap 1.
In dit document gebruik ik de “clip.html” pagina die beschikbaar is op elke Philips hue bridge. Hiermee kan je aanroepen richting de hue API doen. Het is niet meer dan een pagina die JSON berichten kan sturen. Er zijn andere applicaties en browser plugins die dit ook kunnen doen en extra functies bieden zoals de geschiedenis bijhouden, maar die laat ik buiten beschouwing.
Onderstaande stappen komen globaal uit de getting started op http://www.developers.meethue.com/documentation/getting-started
Om de pagina te openen moet je het IP adres van je bridge zien te achterhalen. Dit kan op een aantal manieren.
Nu je het IP adres hebt kan je de clip.html pagina openen op
http://<bridge ip address>/debug/clip.html
In mijn geval dus http://192.168.178.18/debug/clip.html
Je ziet nu een pagina zoals hier onder
Een korte uitleg:
URL:
Hier geeft je aan waar je een actie op wilt uitvoeren bijv: /lights om iets met lampen te doen.
Knoppen GET, PUT, POST en DELETE
Hiermee voer je een actie uit. Met GET haal je informatie op, met PUT verander je informatie, met POST creeer je dingen, met DELETE verwijder je dingen. De actie wordt Method genoemd
Message Body:
Hier geef je extra informatie op voor de actie die je uitvoert.
Command Response:
Hier komt het antwoord te staan wat de bridge terug stuurt
Om iets met de hue API te kunnen doen moet je een gebruiker aanmaken. Deze text is aangepast vanwege de aanpassing bij het aanmaken van een gebruiker in de 1.13 software van de bridge. Deze methode werkt op oude en nieuwe versies.
Om een gebruiker aan te maken gebruik je het POST commando op de URL “/api”. Het “devicetype” veld is verplicht. Normaal staat daar de naam van je applicatie en/of mobile device in, maar nu dus maar de naam van de webpagina.
URL: /api
METHOD: POST
BODY:
{
"devicetype": "CLIP API Debugger"
}
Als je dit intypt op de pagina en op de POST knop te drukt krijg je de volgende response:
[
{
"error": {
"type": 101,
"address": "",
"description": "link button not pressed"
}
}
]
In dit geval krijg je een error terug met een beschrijving. Alle errors zijn hier te vinden: http://www.developers.meethue.com/documentation/error-messages
Om een gebruiker aan te maken moet je de knop op je Bridge indrukken. Druk op de knop van je bridge en voer het commando nogmaals uit.
Je krijgt nu de volgende response:
[
{
"success": {
"username": "jifdi2093jfi3jiut9y8yh9nvcn92"
}
}
]
Vanaf nu kan je de username die je terug hebt gekregen gebruiken om commandos uit te voeren. In de voorbeelden gebruik ik <username> waar je de username moet gebruiken.
De username gebruik je in de URL als je commandos uitvoert.
Probeer het volgende commando om al je lampen aan te zetten:
URL: /api/<username>/groups/0/action
METHOD: PUT
BODY:
{
"on": true
}
En om alles uit te zetten:
URL: /api/<username>/groups/0/action
METHOD: PUT
BODY:
{
"on": false
}
Of om te knipperen:
URL: /api/<username>/groups/0/action
METHOD: PUT
BODY:
{
"alert": "select"
}
Aan/uit schakelen van de stoplicht lamp gaat met behulp van “schedules” je kan dit zien als een “alarm” van een wekker. Je stelt een tijd in en zegt wat er op dat tijdstip moet gebeuren.
Ik heb ervoor gekozen om alleen de “on” stand van de lamp te veranderen. De kleuren van de lamp worden compleet geregeld door de logica in Stap 2.
Je kunt een schedule aanmaken door een POST te doen op /schedules op de hue API.
Dit schedule zet op alle dagen van de week (aangegeven met W127 in het localtime veld) om 7:00 de lamp aan. Het aanzetten van de lamp zit in het “command” veld wat gewoon weer een hue API commando is. Het command wordt uitgevoerd op /lights/1/state. Het commando is {"on": true} wat dus betekent dat de lamp aan gaat. De "name" en "description" velden zijn optioneel, maar het is meestal wel handig om daar wat zinnigs in te zetten.
URL: /api/<username>/schedules
METHOD: POST
BODY:
{
"localtime": "W127/T07:00:00",
"name": "De lamp aan",
"description": "Zet de lamp aan om 7 uur",
"command": {
"address": "/api/<username>/lights/1/state",
"method": "PUT",
"body": {
"on": true
}
}
}
De bridge antwoord met het ID wat je nieuwe schedule heeft gekregen (ID is afhankelijk van het aantal schedules in je bridge). In mijn geval.
[{"success": {"id": "6"}}]
Je kunt het schedule bekijken door een GET te doen op /schedules/<ID>. Bij een GET is de body leeg. Dus in mijn geval:
URL: /api/<username>/schedules/6
METHOD: GET
BODY:
Response van de bridge:
{
"name": "De lamp aan",
"description": "Zet de lamp aan om 7 uur",
"command": {
"address": "/api/<username>/lights/1/state",
"body": {
"on": true
},
"method": "PUT"
},
"localtime": "W127/T07:00:00",
"time": "W127/T05:00:00",
"created": "2015-06-27T17:53:06",
"status": "enabled"
}
Je ziet dat in de response wat extra velden zitten zoals “time”, “created” en “status”. Sommige van deze velden worden door de bridge zelf bijgehouden en kunnen niet aangepast worden (zoals “created” wat aangeeft wanneer het schedule aangemaakt is). Andere krijgen een standaard waarde als je ze niet mee geeft zoals “status”. “status” geeft aan of een schedule actief is of niet, dit veld had je ook mee mogen geven bij het aanmaken. “time” is de UTC tijd van dit schedule, maar het is makkelijker om “localtime” te gebruiken.
Het schedule om de lamp uit te zetten is soortgelijk. Alleen de tijd en de body in het "command" veld is anders; namelijk {"on":false}
URL: /api/<username>/schedules
METHOD: POST
BODY:
{
"localtime": "W127/T22:00:00",
"name": "De lamp uit",
"description": "Zet de lamp uit om 22 uur",
"command": {
"address": "/api/<username>/lights/1/state",
"method": "PUT",
"body": {
"on": false
}
}
}
Response (ID is afhankelijk van het aantal schedules in je bridge):
[{"success": {"id": "7"}}]
Tadaa, de lamp gaat nu aan om 07:00 uur en uit om 22:00
Ik gebruik 1 sensor om de status van het stoplicht bij te houden (de kleur dus eigenlijk). Ik heb gekozen om een “CLIPGenericStatus” hiervoor te gebruiken. In het status veld van deze sensor kan je een nummer opslaan wat in dit geval de kleur van de lamp representeert.
1 = oranje
2 = rood
3 = groen
Daarnaast heb ik per kleur een “schedule” en per kleur een “rule”.
De schedules zijn in dit geval timers. Dat zijn schedules die nadat een bepaalde tijd verstreken is een commando uitvoeren. In dit geval worden de schedules ingesteld om na X seconden de sensor op een bepaalde status (=kleur) te zetten. Dus ik heb dadelijk de volgende schedules:
De rules worden gebruikt om de lamp op de goede kleur te zetten en het volgende schedule te starten. De condities op de rules worden zo ingesteld dat ze getriggered worden als de toestand van de sensor veranderd. Als dat gebeurt wordt de lamp op een kleur gezet en wordt een volgend schedule gestart. Ik krijg dus de volgende set van rules.
Dit zorgt voor de volgende acties.
Dit blijft voor eeuwig doorgaan. Omdat de rules de lamp alleen van kleur veranderen en de lamp niet aan of uit zet zorgen de eerder gemaakte schedules er nog steeds voor dat de lamp op de gewenste tijden aan en uit gaan.
De bridge kent verschillende typen sensoren. Sommige zijn echte sensoren, zoals bijvoorbeeld de hue Tap, andere kan je zelf aanmaken.
In dit geval maken we een CLIPGenericStatus sensor aan. De velden zijn allemaal verplicht en buiten het “type” maakt het niet echt uit wat je invult.
URL: /api/<username>/sensors
METHOD: POST
BODY:
{
"name": "Stoplicht",
"type": "CLIPGenericStatus",
"modelid": "SomeModelId",
"manufacturername": "Robsato",
"uniqueid": "Stoplicht1",
"swversion": "1"
}
De bridge geeft antwoord met het ID van de nieuwe sensor, schrijf dit nummer ergens op, we hebben het later nodig. In mijn geval kreeg ik de volgende response:
[{"success":{ "id":"12"}}]
Het ID van de sensor is dus 12.
Het aanmaken van de timer schedules gaat hetzelfde als de alarm schedules eerder. Er zijn alleen wat extra velden.
"autodelete" geeft aan dat de timer niet automatisch verwijderd moet worden als deze afgelopen is.
"status" geeft aan dat de timer standaard uit staat dus niet meteen af gaat lopen. Het starten en van de timer schedules wordt geregeld door de rules. Als een timer afloopt gaat status vanzelf naar “disabled”
"time" het time veld wordt hier gebruikt om de tijdsduur van de timer aan te geven. Aangezien het een tijdsduur is wordt localtime _niet_ gebruikt, maar dus gewoon time.
In dit schedule geven we een commando om de sensor status op 1 te zetten. In dit commando moet je het sensor nummer vervangen door het ID van dat je bij het aanmaken van de sensor terug hebt gekregen.
URL: /api/<username>/schedules
METHOD: POST
BODY:
{
"autodelete": false,
"time": "PT00:01:00",
"status": "disabled",
"name": "Schedule A",
"description": "Zet na 60 seconden sensor op 1",
"command": {
"address": "/api/<username>/sensors/12/state",
"method": "PUT",
"body": {
"status": 1
}
}
}
Na het aanmaken krijg je weer een ID terug. Schrijf dit op!!
In mijn geval was het ID 8
[{"success":{ "id":"8"}}]
De andere timers zijn ongeveer hetzelfde. Ze hebben andere namen en descriptions voor de duidelijkheid de tijdsduur verschilt en in de commandos is de status die gezet wordt anders.
Schedule B:
URL: /api/<username>/schedules
METHOD: POST
BODY:
{
"autodelete": false,
"time": "PT00:00:15",
"status": "disabled",
"name": "Schedule B",
"description": "Zet na 15 seconden sensor op 2",
"command": {
"address": "/api/<username>/sensors/12/state",
"method": "PUT",
"body": {
"status": 2
}
}
}
Response op mijn bridge:
[{"success":{ "id":"9"}}]
Schrijf het ID wat je terug krijgt op
Schedule C:
URL: /api/<username>/schedules
METHOD: POST
BODY:
{
"autodelete": false,
"time": "PT00:00:20",
"status": "disabled",
"name": "Schedule C",
"description": "Zet na 20 seconden sensor op 3",
"command": {
"address": "/api/<username>/sensors/12/state",
"method": "PUT",
"body": {
"status": 3
}
}
}
Response op mijn bridge:
[{"success":{ "id":"10"}}]
Schrijf het ID wat je terug krijgt op
Je hebt nu een lijst met schedules en IDs
Schedule A | 8 |
Schedule B | 9 |
Schedule C | 10 |
Bij het aanmaken van rules geef je een lijst van condities en een lijst van acties op. De condities bepalen wanneer er iets gebeurt. De lijst met acties die wordt uitgevoerd als alle condities waar zijn.
Voor de eerste rule gebruiken we één conditie. Deze conditie kijkt of de sensor met ID 12 de status 1 heeft. Je moet het sensor ID hier dus weer aanpassen aan het ID van de sensor die je eerder hebt aangemaakt.
"address" geeft aan waar de conditie vanaf hangt. In dit geval van het status veld van sensor 12. Condities kunnen alleen afhangen van velden in sensors.
"operator" geeft aan wanneer de conditie “geldig” wordt. Hier gebruiken we “eq” wat staat voor “equal”.
"value" geeft aan wat de waarde van het veld genoemd in “address” moet zijn om de conditie waar te laten zijn.
In de lijst van acties staan 2 acties.
De eerste actie is om het schedule te starten wat de lamp over een tijdje op de volgende kleur zet.
De tweede actie zet de lamp op de huidige kleur. Ofwel de kleur die bij de status van de sensor hoort. In deze rule is dat oranje. Ik heb ervoor gekozen om een transitietijd van 0 in te stellen waardoor de lamp meteen van kleur veranderd, dus zonder overgang, hierdoor valt het wat meer op.
URL: /api/<username>/rules
METHOD: POST
BODY:
{
"name": "Rule X",
"conditions": [
{
"address": "/sensors/12/state/status",
"operator": "eq",
"value": "1"
}
],
"actions": [
{
"address": "/schedules/9",
"method": "PUT",
"body": {"status": "enabled"}
},
{
"address": "/lights/1/state",
"method": "PUT",
"body": {"xy": [0.576,0.3917],"transitiontime": 0}
}
]
}
Response op mijn bridge:
[{"success":{ "id":"7"}}]
Verschillen met Rule X zijn:
URL: /api/<username>/rules
METHOD: POST
BODY:
{
"name": "Rule Y",
"conditions": [
{
"address": "/sensors/12/state/status",
"operator": "eq",
"value": "2"
}
],
"actions": [
{
"address": "/schedules/10",
"method": "PUT",
"body": {"status": "enabled"}
},
{
"address": "/lights/1/state",
"method": "PUT",
"body": {"xy": [0.6791,0.318],"transitiontime": 0}
}
]
}
Response op mijn bridge:
[{"success":{ "id":"8"}}]
Verschillen met Rule X zijn:
URL: /api/<username>/rules
METHOD: POST
BODY:
{
"name": "Rule Z",
"conditions": [
{
"address": "/sensors/12/state/status",
"operator": "eq",
"value": "3"
}
],
"actions": [
{
"address": "/schedules/8",
"method": "PUT",
"body": {"status": "enabled"}
},
{
"address": "/lights/1/state",
"method": "PUT",
"body": {"xy": [0.4082,0.5039],"transitiontime": 0}
}
]
}
Response op mijn bridge:
[{"success":{ "id":"9"}}]
Nu staat alles klaar. Het enige wat er nog moet gebeuren is het hele zaakje starten.
Dit doen we door één van de schedules aan te zetten. Ik kies hier voor Schedule B omdat het dan maar 15 seconden duurt voordat de lamp veranderd. Als het eerste schedule gestart is blijft alles lopen.
Het starten gaat door het status veld van een schedule op “enabled” te zetten.
Wederom het schedule ID vervangen door het ID wat je hebt gekregen voor schedule B.
URL: /api/<username>/schedules/9
METHOD: POST
BODY:
{
"status": "enabled"
}
Als na 15 seconden het schedule afloopt veranderd de lamp van kleur (wordt rood) en wordt het volgende schedule gestart
Wil je na het experimenteren alles opruimen, dan kan je de schedules, rules en sensor verwijderen. Dit gaat met de DELETE method een een lege body.
Dus om al mijn schedules, rules en sensor weg te gooien voer ik de volgende commandos uit met de method DELETE
URL: /api/<username>/schedules/6
URL: /api/<username>/schedules/7
URL: /api/<username>/schedules/8
URL: /api/<username>/schedules/9
URL: /api/<username>/schedules/10
URL: /api/<username>/rules/7
URL: /api/<username>/rules/8
URL: /api/<username>/rules/9
URL: /api/<username>/sensors/12
Hier volgen nog wat opties/ideen om bovenstaande te veranderen of uit te breiden.
In het algemeen als je vragen hebt over de hue API kan je op de hue developer forums terecht http://www.developers.meethue.com/forum
Nog wat dingen die me te binnen schoten tijden het schrijven, maar ik niet echt een plaats voor had.