Hue
HSYCO integrates Philips Hue lights, sensors, switches, rooms and Hue Secure devices through the bridge's local CLIP v2 API.
The driver talks to the bridge over HTTPS only, and receives state changes as push events rather than by polling, so lights and sensors report within about a second instead of at the polling interval.
Requirements
- A Hue Bridge Pro, or a square Hue bridge (v2 hardware) with software version 1948086000 or later. If a v2 bridge reports an older version, update it from the Hue app.
- The original round Hue bridge (v1 hardware) does not implement the CLIP v2 API, cannot be updated to a version that does, and is no longer supported. See Upgrading from HSYCO 4.1.
- The bridge must be reachable on the local network on TCP port 443.
HSYCO Configuration
Add a HUE I/O Server in the I/O Servers section of the Settings and set its parameters:
High Availability
- Shutdown when inactive: defaults to false.
Options
| ID | Default | Values | Description |
|---|---|---|---|
| ipaddress | <ip_address> | connect to the bridge at this fixed address, and never search for it. See Bridge discovery | |
| mac | <mac_address> | identify the bridge by its MAC address and locate it on the network. Recommended when the bridge address is assigned by DHCP | |
| startupevents | false | true | generate IO events also during the driver's start-up phase |
| false | start generating events only after HSYCO is aligned with the current status of the system | ||
| pollinterval | 300 | n > 0 | the interval, in seconds, of the full resynchronization with the bridge. This is a safety net only — normal operation is event-driven |
| resources | all | all | expose every supported resource family |
| <list> | a comma-separated subset of lights, sensors, switches, groups, scenes, secure | ||
| sensors | true | false | deprecated, kept for compatibility: equivalent to omitting sensors from resources |
| idmode | v1 | v1 | lights keep the numbers they had in the CLIP v1 API, so that projects migrated from HSYCO 4.1 keep working. See Identifiers |
| uuid | resources are addressed by their CLIP v2 UUID | ||
| powerup | powerfail | after a power loss every capable light returns to the state it had, and one that was off stays off. See Power-on behaviour | |
| last_on_state | the same, except that a light that was off comes back on in its last on state | ||
| safety | every capable light comes on at full brightness in warm white | ||
| (empty) | leave the power-on behaviour of the lights untouched | ||
| colorloopmode | effect | effect | the colorloop datapoint activates the closest effect the light supports |
| off | the colorloop datapoint is accepted but does nothing | ||
| discovery | local | local | find the bridge by mDNS only. The driver never connects outside the local network |
| cloud | also query Philips' cloud discovery service if mDNS finds nothing. Requires Internet access | ||
| off | no automatic discovery: use ipaddress, or the address remembered from the last successful start |
Setup
The first time HSYCO connects to the bridge, an authentication procedure is required. Configure the HUE I/O Server as described above and restart HSYCO. After a few seconds the datapoint authentication of the I/O Server is set to 1. At this point you have 60 seconds to press the button on the Hue bridge. From then on HSYCO stores the application key and the procedure is not needed again.
N.B. the application key is stored in bridge.ini, in the directory named after the ID assigned to the HUE I/O Server. Changing the ID requires performing the authentication procedure again.
An I/O Server upgraded from HSYCO 4.1 keeps the key it already had, and does not have to be paired again. See Upgrading from HSYCO 4.1.
Bridge discovery
The driver operates entirely on the local network by default. Nothing it does requires Internet access: the CLIP v2 API is served by the bridge itself, and the certificate authorities used to validate the bridge are embedded in the driver, so no certificate or revocation server is contacted either. The only exception is the optional cloud discovery service described below, which is not used unless it is explicitly enabled.
How the bridge is located depends on which of ipaddress and mac you set:
| Configuration | Behaviour |
|---|---|
| ipaddress | connect to that address, and only that address. The bridge is never searched for |
| mac | identify the bridge by its MAC and locate its current address. Follows the bridge when its address changes |
| both | connect to ipaddress, but refuse it if the unit answering there is not the one with that MAC |
| neither | use the address remembered from the last successful start, then search the network and take the bridge that no other I/O Server has paired with. See Adding a second bridge |
Which one to use
Set ipaddress when the bridge has a fixed address or a DHCP reservation. This is the most predictable configuration: if the bridge does not answer there, the driver reports the failure and keeps retrying that address. It will not look elsewhere and will not connect to a different bridge.
Set mac when the bridge address is assigned by DHCP and can change. The MAC address is printed on the underside of the bridge and never changes, so it identifies the unit for as long as you own it. The driver derives the bridge ID from it — the bridge ID is the MAC with fffe inserted in the middle, so 00:17:88:25:b8:f8 becomes 001788fffe25b8f8 — and matches that against the bridges answering on the network.
With mac set, a change of address is recovered from automatically, typically within about 15 seconds, without restarting HSYCO. The application key, the datapoint numbering and every project reference are preserved, because they belong to the bridge rather than to its address.
Whichever option is used, the bridge ID at every candidate address is verified before the driver connects. A different bridge answering at the expected address is detected and refused rather than adopted.
How the search works
When the address has to be found, the driver tries, in order:
- the address at which the bridge answered last time, remembered across restarts;
- mDNS on the local network;
- Philips' cloud discovery service — only if
discovery=cloudis set.
Philips deprecated UPnP/SSDP discovery and disabled it in 2022, so mDNS is the only local method still supported. It requires bridge firmware 1.23 or later, and the HSYCO server to be on the same subnet as the bridge — multicast traffic does not cross routers or, usually, VLANs. Setting discovery=off together with mac therefore defeats the purpose, and the driver logs a warning if you do.
A bridge that stays missing is searched for with a widening delay between attempts, up to five minutes, so that one left switched off does not cause continuous multicast traffic.
Keeping discovery local
The discovery option controls this:
| Value | Behaviour |
|---|---|
| local | (default) mDNS only. No connection is ever made outside the local network |
| cloud | mDNS first, then Philips' cloud service at https://discovery.meethue.com if mDNS found nothing |
| off | no automatic discovery at all: the bridge must be at ipaddress, or at the address remembered from last time |
discovery=cloud is opt-in because that service requires the HSYCO server to reach the Internet, only works if the bridge has itself contacted the Hue cloud recently, and is rate limited by Philips to one request every 15 minutes per public IP address. It is useful in one case only: a routed network where the bridge is reachable by unicast but multicast does not cross the segment boundary. Setting ipaddress solves that case too, without leaving the network.
With discovery=cloud, the service may refuse the request:
Initialization failed - the Hue discovery service is rate limited to one request every 15 minutes per network, and has refused this one (HTTP 429)
This happens when two or more HSYCO servers on the same network both query it: they share a public IP address, so Philips counts them as a single client and refuses the second request. It is only reached if mDNS already failed — check that the HSYCO server is on the same subnet as the bridge, or set ipaddress.
Adding a second bridge
More than one Hue bridge can be used from the same HSYCO server, with one HUE I/O Server for each.
When a newly configured I/O Server has neither ipaddress nor mac set, it searches the network and then picks the bridge that no other I/O Server is already paired with. So adding a second bridge normally needs no configuration at all: create the I/O Server, start it, and press the link button on the new bridge when the log asks for it. The log names the bridge it is asking about:
No application key stored for bridge 001788fffe25b8f8 at 192.168.1.42 - press the link button on that bridge within 60 seconds
If the choice is not obvious, the driver refuses rather than guessing, and says why:
- every bridge found is already in use — it lists them with the I/O Server that owns each one;
- more than one bridge is free — it lists those, and asks you to set ipaddress or mac to say which one this I/O Server should use.
Set up one new I/O Server and bridge at a time. A bridge is recorded as being in use only once its I/O Server has successfully paired with it, so two I/O Servers configured and started together, with two unpaired bridges available, can both choose the same one. Start the first, complete its pairing, and only then configure the second.
An I/O Server that already knows its bridge is unaffected by any of this: it goes straight to the address it used last time, and only searches the network if the bridge is not there.
Using one bridge with several HSYCO servers
A single Hue bridge can be used by more than one HSYCO server, and by the Hue app at the same time. Each HUE I/O Server obtains and stores its own application key, so the pairing procedure described in Setup has to be performed once per I/O Server — pressing the bridge button once does not authorize the others.
Security
The connection to the bridge is always HTTPS, with full certificate validation against the two Philips Hue root certificate authorities, and with the certificate's common name checked against the bridge ID. There is no option to disable validation and no fallback to plain HTTP.
If the driver reports a certificate error against a genuine Hue bridge, make sure automatic updates are enabled on the bridge, or update it manually by connecting to it with the Hue app: a small number of early bridges shipped with self-signed certificates and have since been updated.
Upgrading from HSYCO 4.1
In HSYCO 4.2 this driver was rewritten on the Hue CLIP v2 API. The datapoints and commands of the previous version are unchanged, and an existing installation is upgraded in place: no re-pairing and no renumbering.
The first time the new driver starts it takes over the state the previous one had left behind:
- the bridge username stored by the previous driver is adopted as the application key and written to bridge.ini. The two are the same value — what CLIP v1 called the username is what CLIP v2 calls the application key, and the bridge already holds it — so the button on the bridge does not have to be pressed again;
- light numbers are unchanged, because the numbering the previous driver used is the one the bridge still reports for each light, and the new driver reads it from there;
- the old persistent variable is left in place and ignored.
Nothing has to be done by hand, and this happens only when no HUE I/O Server has a bridge.ini yet.
What changed
- Rooms, zones, scenes, switches, dials and Hue Secure devices are now supported, as well as lights and motion sensors. See the datapoint sections below.
- State arrives as push events instead of polling, so changes are reported in about a second. The
pollintervaloption still exists but is now the interval of a background safety resynchronization, and its default has changed from 10 to 300 seconds. - The
masteroption is no longer available. Its purpose — restoring lights to their previous state after a power loss — is served better by the newpowerupoption, which is enforced by the lamp itself. See Power-on behaviour. - The
colorloopdatapoint still exists, but the effect behind it is different: Philips removed the color loop from the API. See Color loop. light.<n>.on = flipnow works. It was documented by the previous driver but had no effect.- The
rgbandxydatapoints are now comma separated rather than semicolon separated. See Color. - The
dimmerdatapoint reports 99% correctly. The previous driver reported it as 100%.
Bridge v1 is no longer supported
The original round Hue bridge does not implement the CLIP v2 API and cannot be updated to a firmware that does. An I/O Server pointing at one refuses to start and logs:
Initialization failed - bridge software version <n> does not support the CLIP v2 API, which requires 1948086000 or later. Update the bridge from the Hue app; the original round bridge cannot be updated to a supported version and is not usable with this driver
The bridge has to be replaced with a current one. Lights are moved across by resetting them and adding them to the new bridge, or with Touchlink.
The bridge.ini file
Everything the driver has to remember between restarts is kept in bridge.ini, in the state/drivers/hue/<io_server_id> directory, where <io_server_id> is the ID of the HUE I/O Server in lower case: the bridge application key and address, and the numbers used in datapoint names.
Each HUE I/O Server has its own file, so its entries don't carry the I/O Server ID:
# HSYCO Philips Hue API v2 driver
#
# The light, sensor, switch, group and scene numbers below are the ones
# used in datapoint names. They may be edited to renumber a resource;
# changes are applied the next time the I/O Server is restarted.
#
# The appkey entries are secrets: treat this file accordingly.
appkey = sFlEGnMAFXO6RtZV17aViNUB95G2uXWw64texDzD
address = 192.168.1.23
bridgeid = 001788fffe25b8f8
light.1 = c6b028c8-076e-4817-92b1-bcb0cbb78783
light.2 = 39a1b2c3-4d5e-6f70-8192-a3b4c5d6e7f8
sensor.5 = 73db1290-5b13-4494-ad58-a7fe5415039f
group.2 = 708d8a89-5d05-408f-b43c-830fbff8316e
The appkey entries give full control of the bridge and its lights. Philips documents the application key as a secret. The driver restricts the file to its owner when writing it; keep it out of backups and support bundles that are shared, and do not copy it between installations that should be independently authorized.
Renumbering a resource
The numbering is keyed by number, so the file reads as "light 3 is this bulb" and can be edited to make the numbering match a project. Change the number on the left of an entry, then restart the I/O Server.
Two resources cannot be given the same number: the file format does not allow a duplicate key, and the driver logs an error if it finds one.
Edits are noticed within a few seconds. A changed address or appkey is adopted immediately, without a restart.
A changed number cannot be applied to a running I/O Server, because the datapoint names come from it and renaming them underneath a project would leave every reference pointing at the wrong resource. The I/O Server therefore restarts itself, and comes back using the new numbering:
state/drivers/hue/<io_server_id>/bridge.ini: the resource numbering of this I/O Server was changed, restarting to apply it
Each I/O Server only checks its own file, so editing it restarts only the I/O Server it belongs to; the others keep running.
Losing the file
If bridge.ini is deleted, the driver has to pair with the bridge again — see Setup — and numbers every resource from scratch, which will not necessarily reproduce the previous numbering. Include it in your configuration backups.
Where the file comes from
A bridge is written into this file only once its I/O Server has actually paired with it, so a pairing that was never completed does not leave the bridge marked as in use. This is also what lets a new I/O Server tell which bridges on the network are still free — see Adding a second bridge.
If no HUE I/O Server has a bridge.ini yet when the driver starts, one is created: on an installation upgraded from HSYCO 4.1 it picks up the existing bridge credentials, as described in Upgrading from HSYCO 4.1, and otherwise it is filled in as the driver pairs with the bridge and discovers its resources. An installation that already has a bridge.ini is never overwritten.
Identifiers
The CLIP v2 API identifies every resource by a UUID, while HSYCO addresses resources by a short number. The driver assigns that number the first time it sees a resource and stores the mapping permanently in bridge.ini, so a number never changes once given.
Lights keep the number they had in the CLIP v1 API, which the bridge still reports for them. That is what allows a project written for HSYCO 4.1 to keep working: the previous version of this driver published lights and nothing else, so light.3 still refers to the same bulb. A light added since has no such number and is given the lowest free one, which the log records.
Everything else is numbered from 1 within its own kind. Switches, sensors, contacts, cameras, speakers, rooms, zones and scenes were not published by the previous version, so there is no earlier name to preserve — and inheriting the v1 numbers would import their oddities, since v1 counted switches and motion sensors in one series and rooms among all the groups.
Each kind of device is numbered independently, so the first speaker is speaker.1 whether or not there are motion sensors, and adding a device of one kind never shifts the numbers of another. In bridge.ini each kind has its own set of entries:
light.3 = …
sensor.1 = …
switch.1 = …
switch.2 = …
speaker.1 = …
The UUID of each resource is always published on the .uuid datapoint, so the mapping can be inspected at any time.
Datapoints — I/O Server
| ID | Value | R/W | Description |
|---|---|---|---|
| connection | online | R | connection established |
| offline | R | HSYCO can't connect to the bridge. Everything the bridge serves is unreachable while this lasts: see Reachability | |
| authentication | 1 | R | the Hue bridge is waiting for the authentication procedure to be performed |
| 0 | R | default value | |
| touchlink | 1 | W | start a Touchlink scan: claim the nearest light. See Touchlink |
| 1 | R | a Touchlink scan is running | |
| 0 | R | no scan is running |
Datapoints — lights
Each bulb is assigned an ID by the driver as described above. The driver generates several datapoints for each bulb, having the prefix light.<n>.
| ID | Value | R/W | Description |
|---|---|---|---|
| light.<n>.on | 1 | R/W | the light <n> is on / turn on light <n> |
| 0 | R/W | the light <n> is off / turn off light <n> | |
| flip | W | invert the state of light <n> | |
| light.<n>.reachable | 1 | R | the light <n> is connected to the bridge |
| 0 | R | the light <n> is out of reach, powered off, or still being added to the network | |
| light.<n>.brightness | 1 ... 254 | R/W | the brightness of light <n> |
| light.<n>.dimmer | off | R/W | the light <n> is off / turn off light <n> |
| 1% ... 100% | R/W | the light <n> is on at the reported brightness / turn on and set brightness | |
| on | W | turn on light <n> and set it to its last state before going off | |
| light.<n>.rgb(1) | <r>,<g>,<b> | R | the color of light <n>, whether it is on or off, e.g. "12,100,255" |
| W | set the color of light <n>. The light is not turned on. See Color | ||
| <r>,<g>,<b>,on | W | set the color and the state in one write, with on or off as the last field | |
| on | W | turn on light <n> | |
| off | W | turn off light <n> | |
| flip | W | invert the state of light <n> | |
| light.<n>.hue(1) | 0 ... 65535 | R/W | the color hue of light <n>. See Color |
| light.<n>.saturation(1) | 0 ... 254 | R/W | the color saturation of light <n>. See Color |
| light.<n>.xy(1) | <x>,<y> | R/W | the CIE color point of light <n>, e.g. "0.4575,0.4099". This is the API's native color format |
| light.<n>.temperature(2) | 153 ... 500 | R/W | the white color temperature of light <n>, in mirek (reciprocal megakelvin) |
| light.<n>.powerup(3) | powerfail | R/W | after a power loss light <n> returns to its previous state, staying off if it was off |
| last_on_state | R/W | the same, but it comes back on if it was off | |
| safety | R/W | it comes on at full brightness in warm white | |
| light.<n>.colorloop(1) | 1 | W | start a color changing effect on light <n>. See Color loop |
| 0 | W | stop the effect on light <n> | |
| light.<n>.blink | single | W | perform a single blink on light <n> |
| long | W | blink light <n> for about 15 seconds | |
| 0 | W | stop blinking light <n> | |
| light.<n>.name | <text> | R | the name of light <n> as configured in the Hue app |
| light.<n>.uuid | <uuid> | R | the CLIP v2 identifier of light <n> |
Note 1
Only available on lights with color capabilities. The driver detects this from the light itself, not from a model list.
Note 2
Only available on lights with tunable white capabilities. The supported range varies per model, and the bridge moves to the closest value it can produce.
Note 3
Only available on lights that support configurable power-on behaviour. See Power-on behaviour.
Datapoints — motion sensors
Each Hue motion sensor is a single device that provides motion detection, an ambient light level, a temperature reading and a battery level. All of them are published under a single sensor.<n> prefix.
| ID | Value | R/W | Description |
|---|---|---|---|
| sensor.<n>.motion | 1 | R | motion detected |
| 0 | R | no motion detected | |
| sensor.<n>.enabled | 1 | R/W | motion detection is enabled / enable it |
| 0 | R/W | motion detection is disabled / disable it | |
| sensor.<n>.illuminance | 0 ... n | R | ambient light level in lux |
| sensor.<n>.lightlevel | 0 ... n | R | ambient light level in the bridge's raw logarithmic scale, 10000*log10(lux)+1 |
| sensor.<n>.temperature | <n.n> | R | temperature in degrees Celsius, with one decimal |
| sensor.<n>.battery | 0 ... 100 | R | battery charge, in percent |
| sensor.<n>.batterystate | normal | R | battery level is sufficient |
| low | R | battery level low, replace the battery soon | |
| critical | R | battery level critical, the device can fail at any moment | |
| sensor.<n>.reachable | 1 / 0 | R | the sensor is connected to the bridge |
| sensor.<n>.update | <text> | R | firmware state. See Firmware updates |
| sensor.<n>.name, .uuid | <text> | R |
The motion datapoint is not published until the sensor has reported at least once, so a rule triggering on it will not fire on a stale value at start-up.
Datapoints — switches and dials
Hue Dimmer Switches, Tap Dials, Smart Buttons and Wall Switch Modules are published under switch.<n>, one prefix per physical device. Each control on the device has its own datapoint, numbered by the control identifier the device reports — for a Dimmer Switch that is the number printed next to each key. How a press is published is explained in How button events are published.
| ID | Value | R/W | Description |
|---|---|---|---|
| switch.<n>.button<c> | initial_press | R | key <c> was pressed |
| repeat | R | key <c> is being held | |
| short_release | R | key <c> was released after a short press | |
| long_release | R | key <c> was released after a long press | |
| double_short_release | R | key <c> was double-pressed | |
| long_press | R | key <c> has been held long enough to count as a long press | |
| switch.<n>.button<c>.cnt | 0 ... n | R | number of events received from key <c> since HSYCO started |
| switch.<n>.bell<c> | as above | R | same, for a doorbell button |
| switch.<n>.bell<c>.cnt | 0 ... n | R | |
| switch.<n>.dial | clock_wise | R | the dial was turned clockwise |
| counter_clock_wise | R | the dial was turned anticlockwise | |
| switch.<n>.dial.cnt | 0 ... n | R | number of rotation events received |
| switch.<n>.dial.steps | 0 ... 32767 | R | amount of rotation in the last event, 1000 steps per full turn |
| switch.<n>.dial.duration | 0 ... 65534 | R | duration of the last rotation, in milliseconds |
| switch.<n>.dial.action | start / repeat | R | whether the last event began a rotation or continued one |
| switch.<n>.battery | 0 ... 100 | R | battery charge, in percent |
| switch.<n>.batterystate | normal / low / critical | R | |
| switch.<n>.reachable | 1 / 0 | R | |
| switch.<n>.update | <text> | R | firmware state. See Firmware updates |
| switch.<n>.name, .uuid | <text> | R |
How button events are published
A key press is a moment, not a state, so each control publishes two datapoints.
The base datapoint holds the last event received, and is written on every event even when the value has not changed. So pressing the same key twice in a row reports short_release twice, and a rule watching for short_release fires both times. Between presses the datapoint keeps the last event, which makes it meaningful to read at any moment rather than resting empty.
The .cnt datapoint is a counter that increases by one on every event from that key. Use it when what matters is that something happened rather than which event it was, or to detect a burst of events without inspecting each one.
Counters start at zero when HSYCO starts and are not persisted.
Each control is numbered by the identifier the device itself reports — the number printed next to each key on a Dimmer Switch. A device with a single control, such as a Smart Button, publishes just that one, and its number is not necessarily zero.
The datapoints are written only when a key is actually pressed. The periodic resynchronization re-reads the state of everything, including the last press each key reported, but never republishes it: a press is reported once, when it happens.
Datapoints — rooms and zones
Rooms and zones are published under group.<n>. Controlling a group sends one command to the bridge instead of one per light, which is also the only way to dim a whole room without visible stagger.
| ID | Value | R/W | Description |
|---|---|---|---|
| group.<n>.on | 1 / 0 | R/W | any light in the group is on / turn the group on or off |
| flip | W | invert the state of the group | |
| group.<n>.dimmer | off, 1% ... 100% | R/W | average brightness of the lights that are on |
| on | W | turn the group on at its previous brightness | |
| group.<n>.brightness | 1 ... 254 | R/W | |
| group.<n>.motion | 1 / 0 | R | aggregated motion of the sensors in the group |
| group.<n>.lightlevel | 0 ... n | R | aggregated light level, raw scale |
| group.<n>.illuminance | 0 ... n | R | aggregated light level, in lux |
| group.<n>.type | room / zone | R | |
| group.<n>.name, .uuid | <text> | R |
Philips limits grouped commands to one per second, against ten per second for an individual light. The driver enforces this: rapid changes to a group are merged and sent at that rate. A slider bound to a group datapoint will therefore follow more coarsely than one bound to a single light.
Datapoints — scenes
| ID | Value | R/W | Description |
|---|---|---|---|
| scene.<n>.recall | 1 or active | W | activate the scene |
| dynamic_palette | W | activate the scene in dynamic mode, cycling through its colours | |
| static | W | activate the scene without any dynamic behaviour | |
| scene.<n>.name | <text> | R | |
| scene.<n>.group | <text> | R | the room or zone the scene belongs to |
| scene.<n>.uuid | <uuid> | R |
A bridge typically holds a large number of scenes. Use resources to leave them out if you do not need them.
Datapoints — Hue Secure
Contact sensors, cameras and sirens. Each device is published under the prefix matching what it is, and a device that combines functions — a camera with a built-in siren — publishes all of them under its own single prefix.
| ID | Value | R/W | Description |
|---|---|---|---|
| contact.<n>.contact | 1 | R | the contact is closed |
| 0 | R | the contact is open | |
| contact.<n>.tamper | 1 / 0 | R | the device reports tampering |
| contact.<n>.enabled | 1 / 0 | R/W | |
| camera.<n>.motion | 1 / 0 | R | motion detected by the camera |
| camera.<n>.enabled | 1 / 0 | R/W | |
| speaker.<n>.alarm | <sound> | R/W | sound the alarm. See Sounds |
| speaker.<n>.chime | <sound> | R/W | play a chime |
| speaker.<n>.alert | <sound> | W | play an alert |
| speaker.<n>.mute | 1 / 0 | R/W | mute the device. The siren is not affected by mute |
| speaker.<n>.alarm.sounds | <list> | R | the sounds this device accepts for alarm, comma separated |
| speaker.<n>.chime.sounds | <list> | R | the sounds it accepts for chime |
All Secure devices also publish .battery, .batterystate, .reachable, .update, .name and .uuid, and any of them that reports tampering publishes .tamper as shown above for contact sensors. Mains-powered and Wi-Fi devices report reachable from their Wi-Fi connection rather than from Zigbee.
Sounds
The sound datapoints take <sound>, <sound>;<volume> or, for alarm only, <sound>;<volume>;<seconds>. Volume is 0 to 100. Writing off, 0 or no_sound stops the sound.
IO hue.speaker.1.alarm = siren;100;30
IO hue.speaker.1.chime = ding_dong_classic;40
IO hue.speaker.1.alarm = off
Sounding a Hue Smart Chime is therefore:
IO hue.speaker.1.chime = ding_dong_classic
Devices differ in which sounds they have, and each feature has its own set — a chime sound is generally not available to the alarm, and the other way round. Rather than guessing, read the .sounds datapoints, which list exactly what the device in front of you accepts:
speaker.1.chime.sounds no_sound,ding_dong_classic,westminster_modern
speaker.1.alarm.sounds no_sound,siren,alert
Writing a sound the device does not have is refused before it reaches the bridge, and the message says what it does have:
Error executing command speaker.1.chime=siren - this device does not have the sound 'siren' for chime, it accepts: no_sound,ding_dong_classic,westminster_modern
Across the whole product range the sounds are alert, bleep, ding_dong_classic, ding_dong_modern, ding_dong_xylo, rise, siren, westminster_classic, westminster_modern, hue_default, sonar, swing, bright, bright_modern, glow, bounce, reveal, welcome, fairy, galaxy, echo and no_sound.
Firmware updates
Every device publishes an update datapoint reporting the state of its firmware: no_update, update_pending, ready_to_install or installing. Updates are managed by the bridge and the Hue app; HSYCO reports the state but does not trigger them.
Touchlink
Touchlink claims the nearest Zigbee light and adds it to this bridge, including a light that is currently joined to a different hub. It is the practical way to take over a light when the hub that currently owns it is unavailable, has been replaced, or is not a Hue bridge — no access to the old hub is needed, only physical proximity.
Write 1 to the touchlink datapoint to start a scan:
IO hue.touchlink = 1
The touchlink datapoint reads 1 while the scan is running and returns to 0 when it finishes. A light claimed by the scan appears as new light.<n> datapoints without a restart.
Preparation
The scan claims whichever light has the strongest signal, so it must be the one you intend:
- place the light within about a metre of the bridge, and closer to it than any other light,
- switch off, or move well away, every other light that could respond,
- make sure the light is powered on.
Claiming a light that belongs to a neighbouring installation is a real possibility if these precautions are ignored. For the same reason the driver only starts a scan on an explicit 1, refuses to run two scans at once, and never starts one by itself.
Lights only
Touchlink is part of the Zigbee Light Link profile, in which lights are the devices that can be claimed. It applies to bulbs, lightstrips and light-like devices such as Zigbee smart plugs, including third-party ones.
It does not work for motion sensors or switches. Those are battery-powered devices that do not listen for a Touchlink scan — a Hue Dimmer Switch is in fact a Touchlink initiator itself, which is what the "hold the dimmer next to the bulb" reset relies on. To move a sensor or a switch to this bridge, reset it with the setup button in its battery compartment and then add it from the Hue app.
Touchlink is only available through the CLIP v1 API, which this driver otherwise does not use.
There is no Touchlink in the Hue API v2, and Philips did not replace it: the word does not appear anywhere in the v2 documentation. Philips has stated that the v1 API will eventually be withdrawn, and when that happens on a given bridge firmware this command will stop working. It then reports:
Touchlink failed - the bridge no longer implements the CLIP v1 API (HTTP 404) - Touchlink is not available on the v2 API and cannot be used on this bridge
Every other feature of this driver uses the v2 API only and is unaffected.
The v2 alternative
If you do have access to the hub that currently owns the light, releasing it there is the supported route and does not depend on the v1 API. On a Hue bridge, deleting the device sends it a Zigbee leave command and it becomes available to be added elsewhere — but only if it is powered on and in range at that moment, otherwise the hub forgets it while the light stays bound and only a physical reset or Touchlink will recover it.
Power-on behaviour
A Hue light that loses power — a breaker, a wall switch, an unplugged lamp — comes back on at full brightness by default, and stays on. Modern lights can be told to do something else instead, and they remember it themselves: the setting lives in the lamp, so it is applied the moment power returns, with no involvement from the bridge or from HSYCO.
Set the powerup option to apply a behaviour to every capable light:
| Value | Hue app name | After power returns, the light… |
|---|---|---|
| powerfail | Power loss recovery | returns to the colour and brightness it had when power was lost, and if it was off it stays off |
| last_on_state | — | returns to the same settings, but if it was off it comes back on, in its last on state |
| safety | Default | comes on at full brightness in warm white (2700 K), whatever it was doing before |
powerfail is the one to use if the intent is that the lights stay as HSYCO left them: a light that HSYCO switched off stays off, and one that was on returns exactly as it was. The difference from last_on_state is only in that first case, and it is the difference between a room staying dark after a power cut and every lamp in it coming on.
A single light can also be set individually through its light.<n>.powerup datapoint, which reports the current setting and accepts a new one.
Which lights support it
The driver does not guess from model names. A light that supports the feature says so in its own description, and the datapoint is published only for those.
Because the setting is stored inside the lamp, the driver writes it only when it differs from what the lamp already has, and only once per light per run. It is a configuration value, not something to be enforced continuously — changing it later from the Hue app is respected, not overwritten.
At start-up, any light that cannot do this is named in the log:
These lights do not support the powerup feature and will not restore their state after a power loss: 4 (Garden spot), 7 (Old bedside lamp)
Those lights will still come on by themselves after a power loss. There is no way to change that from outside the lamp; the usual remedies are a firmware update from the Hue app, if one is available for that model, or replacing it.
This replaces the master option of the previous version of this driver, which polled the lights and pushed HSYCO's saved state back onto any that had changed. Letting the lamp hold the setting is both more reliable and less intrusive: it works even while HSYCO is stopped, it acts the instant power returns rather than at the next poll, and it never overrides a change made deliberately somewhere else.
Color
The rgb and xy datapoints hold their components separated by commas:
light.1.rgb 255,67,31
light.1.xy 0.6655,0.3173
Writing accepts a comma, a semicolon, an asterisk or spaces, so all of these set the same colour:
IO hue.light.1.rgb = 255,67,31
IO hue.light.1.rgb = 255;67;31
IO hue.light.1.rgb = 255*67*31
IO hue.light.1.rgb = 255 67 31
The HUE I/O Server of HSYCO 4.1 published these datapoints separated by semicolons. A project that reads light.<n>.rgb as text, rather than binding it to a colorpicker or another user interface object, has to be updated. User interface objects are not affected.
The CLIP v2 API represents color only as a CIE xy point plus a separate brightness, and has no hue or saturation values at all. The hue, saturation and rgb datapoints are computed by the driver, clamped to the color range the specific bulb can physically produce.
This has one consequence worth knowing. A color the bulb can produce reads back as it was written. A color outside its range, as fully saturated colors often are, is moved to the closest one the bulb can produce, and rgb reports that color, which is what the light is actually showing: 255,0,0 reads back as about 255,39,0 on a recent bulb, and as about 255,67,0 on an older one. The hue and saturation datapoints are the exception: when HSYCO sets a color, they read back exactly as written. When the color is changed from somewhere else — the Hue app, a wall dimmer, a scene — they are derived from the bulb's actual color point, and a fully saturated color that the bulb cannot reproduce reads back slightly less saturated than requested.
Use the xy datapoint when you need the exact value the bridge holds, with no conversion.
Reachability
light.<n>.reachable, and the same datapoint on sensors, switches and Secure devices, report whether the bridge can reach that device over Zigbee or Wi-Fi.
While the connection datapoint is offline the bridge itself cannot be reached, and nothing behind it can be either, so every device reports reachable as 0 and every user interface device carries the fault flag, whatever the bridge last said about them. What the bridge reported is not lost: when the connection comes back, each device returns to its own reachability immediately, without waiting for the next resynchronization.
Color and state
The rgb, hue, saturation and xy datapoints report the color of a light whether it is on or off. The bridge keeps the color of a light that is off, so this is the color it comes back to, and a colorpicker shows it instead of showing black.
Color and state are independent. Setting a color does not turn a light on, and the state moves only when it is written: with on, off or flip, on the on datapoint or on rgb itself, or by adding on or off as a last field to a color, which sets both in one write.
IO hue.light.1.rgb = 255,67,31 # set the color, on or off as it was
IO hue.light.1.rgb = 255,67,31,on # set the color and turn the light on
IO hue.light.1.on = 1 # turn it on, at the color it was given
A color of all zeros is not a color and is ignored: a light is turned off with off, 0, or its on datapoint. A status field is always the word on or off, never 1 or 0, so that it can never be read as one of the three components.
In the catalog, and therefore in the User Interface, a light is published as <r>*<g>*<b>*<on|off>, and an unreachable light carries fault as a further field, <r>*<g>*<b>*<on|off>*fault, so that the interface raises its fault flag while still showing the light as it is. This is the format the colorpicker object reads. The dimmer datapoint of a light or a group is published in the same way, as off or <n>%, with *fault appended.
Color loop
The color loop effect of the CLIP v1 API was removed by Philips and has no equivalent in the CLIP v2 API. With the default colorloopmode=effect, writing 1 to the colorloop datapoint starts the closest color changing effect the light supports, chosen from the effects the light itself advertises. Writing 0 stops it.
The effect is not identical to the old color loop, and lights that support no suitable effect log a message and ignore the command.
User Interface
To control a Hue light as a dimmer, i.e. to change its brightness without changing color, add a slider or a button object to your project page and set its address field to the corresponding dimmer datapoint. The same applies to a room or zone, using its group.<n>.dimmer datapoint.
To control a color light using its RGB channels use a colorpicker object and set its address to the corresponding rgb datapoint.
Release Notes
4.2.0
- the driver has been rewritten on the Philips Hue CLIP v2 API, replacing the discontinued Philips Java SDK. Existing installations are upgraded in place: the bridge does not have to be paired again, and lights keep their numbering — see Upgrading from HSYCO 4.1
- added support for the Hue Bridge Pro
- support for the first generation Hue bridge (v1, round) has been removed, as it does not implement the CLIP v2 API and cannot be updated to a firmware that does
- state is now received as push events over the bridge's event stream instead of being polled, so changes are reported in about a second instead of at the polling interval
- added support for rooms and zones, scenes, Hue Dimmer Switches, Tap Dials and Smart Buttons, and Hue Secure contact sensors, cameras and sirens
- added the
resourcesoption, to select which families of devices are exposed - added the
ipaddressoption and extended themacoption, which now also locates a bridge whose address is assigned by DHCP and follows it when the address changes - added the
discoveryoption: the driver operates entirely on the local network by default, and only queries the Philips cloud discovery service if explicitly configured to - added the
idmodeandcolorloopmodeoptions - the
pollintervaloption is now the interval of a background safety resynchronization, and its default has changed from 10 to 300 seconds - replaced the
masteroption with the newpowerupoption andlight.<n>.powerupdatapoint, which configure the lamp's own power-on behaviour so that a light restores its state after a power loss by itself, instead of being polled and corrected. Lights that do not support the feature are listed in the log at start-up — see Power-on behaviour - a newly configured I/O Server with no
ipaddressormacnow selects the bridge that no other I/O Server has paired with, instead of the first one to answer, so a second bridge can be added without configuring anything; when the choice is ambiguous the driver reports which bridges it found and which I/O Server owns each — see Adding a second bridge - persistent state, including the bridge application key and the resource numbering, is now kept in the bridge.ini file of each I/O Server instead of persistent variables — see The bridge.ini file
- the connection to the bridge is now HTTPS only, with full certificate validation against the Philips Hue root certificate authorities
- the
rgb,hue,saturationandxydatapoints now report the color of a light that is off, instead of reporting black, so the user interface can show the color the light will come back to. A light is published to the user interface as<r>*<g>*<b>*<on|off>, with*faultappended while it is unreachable — see Color and state - while the connection to the bridge is offline, every device now reports
reachableas0and carries the fault flag in the user interface, returning to its own state as soon as the bridge answers again — see Reachability - BREAKING CHANGE. Writing a color to the
rgbdatapoint no longer turns the light on, and writing0,0,0no longer turns it off: color and state are now independent, as they already are for thehue,saturationandxydatapoints. EVENTS and user code that relied on a color write to switch a light must add the state explicitly, asIO hue.light.1.rgb = 255,67,31,on, or write theondatapoint. Both forms of the write also accepton,offandflip
3.7.0
- added support for Hue White devices
3.6.0
- added support for Philips Hue bridge 2.0 (Java Hue SDK 1.8.1 API)
3.5.0
- initial release
Philips is a registered trademark of Koninklijke Philips N.V., used under licence. Hue and Philips Hue are trademarks of Signify Holding B.V.