Listen to the house: the refreshState event flow

Most interesting QAs react to other devices: the lamp watches the door sensor, the scene waits for the smoke detector. On the HC3 the mechanism is the refreshStates event feed; flua simulates it offline, so reactive logic is testable the same way timers are.

The high-level way is the RefreshStateSubscriber class — subscribe with a predicate and a callback, then run:

local subscriber = RefreshStateSubscriber()
subscriber:subscribe(
  function(event) return true end,          -- which events to react to
  function(event)
    print("Event:", json.encode(event))
  end)
subscriber:run()

function QuickApp:onInit()
  setTimeout(function()
    self:updateProperty("value", true)     -- the QA changes its own state
  end, 100)
end
Event: {"type": "DevicePropertyUpdatedEvent",
        "data": {"id": 5000, "property": "value", "oldValue": false, "newValue": true}, ...}

The event carries everything the HC3 delivers: the type, the device id, the changed property, and old/new values. Filter in the predicate — only door sensors, only breaches:

subscriber:subscribe(
  function(event)
    return event.type == "DevicePropertyUpdatedEvent"
      and event.data.property == "value"
  end,
  function(event) print("door changed to", event.data.newValue) end)

Because events flow through the same pump as timers, the whole chain is deterministic: open the door QA, the lamp QA reacts, the scene reacts to the lamp — in one log, tagged per QA, reproducible every run (flua door.lua lamp.lua — several QAs, one process, as in post 5). Debugging a reaction chain becomes reading a chat log instead of staring at a live controller.

The full event feed is also there at the API level — api.get("/refreshStates?last=0") returns the recorded events, and the HC3's polling contract holds — so QAs written against the raw feed port over unchanged.

Next post: the devices inside your QA — child devices.

Examples: flua --examples → refreshState.lua, trigger.lua · flua: https://github.com/jangabrielsson/flua