Skip to content

HueDriver

Source: HueDriver.h

HueDriver

class HueDriver
src/light/drivers/HueDriver.h:36

Inherits: DriverBase

Output driver: sends the buffer to Philips Hue bulbs as pixels — a driver, not a listed device.

The bulbs are pixels of an effect: make a small grid (e.g. 4×1×1), run any effect, and this driver reads its window of the shared buffer and pushes each light's colour to the bridge. Same shape as NetworkSendDriver (read a window, send it out), but over the Hue v1 HTTP API not UDP.

It's HTTP, not a wire protocol (GET /api/<key>/lights, PUT .../lights/<id>/state), so the rate is bounded by connection churn — each PUT opens a fresh TCP connection (the bridge speaks Connection: close), and [tick()] does at most one PUT every kPutIntervalMs (see there) — giving smooth ambient colour, not real-time. The shared output Correction applies as on the LED/network drivers, so the brightness slider and colour-order preset reach the Hue lights too (brightness 0 → light off). Only colour-capable, reachable lights are driven (see parseLights); the room and light dropdowns aim the effect at a subset (see rebuildDriven).

Wire contract (Hue v1 API, plain HTTP, no TLS — bench-confirmed on a BSB002 bridge, API 1.77):

  • Pair — POST http://<bridgeIp>/api``{"devicetype":"projectMM#device"}; before the link button, the bridge returns link button not pressed; after, [{"success":{"username":"<key>"}}].

  • List lights — GET http://<bridgeIp>/api/<appKey>/lights{"1":{…},"2":{…}} (window index → light id).

  • List rooms — GET http://<bridgeIp>/api/<appKey>/groups{"1":{"name":…,"lights":["1","2"],"type":"Room"},…}.

  • Set a light — PUT http://<bridgeIp>/api/<appKey>/lights/<id>/state``{"on":true,"bri":0-254,"hue":0-65535,"sat":0-254,"transitiontime":N} (or {"on":false} for a black pixel).

Prior art: the Hue v1 CLIP API (public docs); the effect-as-output mapping is projectMM's own.

HueDriver card

Public Attributes

uint8_t bridgeIp = {} : The bridge's LAN IP, entered in the UI (4 octets).

char appKey = {} : The Hue username/app key — filled by the Pair button, then persisted.

Public Methods

inline HueDriver() : HueDriver reads apply()'s output back as R,G,B to convert to HSV for the bridge, so it references the "RGB" preset (a GRB reorder would corrupt the hue).

virtual inline bool hasCorrectionControls() const override : Register the controls: bridge IP, the persisted app key, the Pair link-button, the room + light filter dropdowns (both default to index 0 = "All", rebuilt in place from the parsed bridge data on every control change), the shared window, then refresh the status line.

virtual inline void defineDriverControls() override : A driver's own controls (its pins, protocol, IP, window, …), added AFTER the correction block.

virtual inline void setSourceBuffer(Buffer * buf) override : Take the shared source buffer this driver reads its window from.

virtual inline void onControlChanged(constchar * controlName) override : A control click.

virtual inline void tick() override : Runs every render tick, but does at most ONE bounded PUT and only when the rate-limit interval has elapsed (a millis() gate, NOT work-every-tick) — otherwise a synchronous HTTP round-trip would stall the single-thread render loop (the "never block the loop" rule, lessons.md).

virtual inline void tick1s() override : The 1 Hz tick handles the non-render-critical, slower bridge work: the pairing poll, the one-shot light + group fetch, and the periodic DevicesModule announce.

virtual inline void release() override : Stop any in-flight pairing and release the dropdown-name heap (a re-add re-fetches and re-allocs), then chain to DriverBase::release to clear status.

inline bool wouldPushForTest(uint8_t idx, uint8_t r, uint8_t g, uint8_t b, char * outBody, size_t cap)

inline void parseLightsForTest(constchar * json)

inline uint8_t lightCountForTest() const

inline uint16_t hueIdForTest(uint8_t i) const

inline int8_t colorCountForTest() const

inline void parseGroupsForTest(constchar * json)

inline uint8_t roomCountForTest() const

inline void setRoomForTest(uint8_t r)

inline void setLightForTest(uint8_t l)

inline void refreshStatusForTest()

inline uint8_t drivenCountForTest() const

inline uint16_t drivenIdForTest(uint8_t i) const

Public Static Methods

static inline void rgbToHsvForTest(uint8_t r, uint8_t g, uint8_t b, uint16_t & h, uint8_t & s, uint8_t & v)

static inline bool bodyLooksCompleteForTest(constchar * body)