HueDriver
Source:
HueDriver.h
HueDriver¶
src/light/drivers/HueDriver.h:36Inherits:
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 returnslink 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.

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)