Not everything on the HC3 is reachable over the REST API. The
controller serves part of its surface only to local callers — QA
code running on the box. The most useful casualty: the single-key QA
variable endpoints. The list works fine, but
GET /plugins/<id>/variables/<key> and the variable
writes answer 500/501 to anything outside, which means no tool and no
other QA can read or change a QA's internalStorage from the
outside.
flua's fix: a small invisible helper QA deployed to the controller. It runs your call in the local context and reports back over a WebSocket to your laptop. Install it once:
flua --tool installHelper # FluaHelper already installed (v1.3.0) — HC3 device id 4378
Re-running it is safe and idempotent — it finds the helper by its
quickAppUuid (a renamed QA stays recognized), keeps the
newest copy, and removes any older ones. The helper never dials anywhere
on its own: it waits idle until flua needs it, then connects back on
demand. One helper serves many flua machines; every online-mode run gets
a free OS-assigned port, so parallel instances just work.
From a QA, calls route through the helper with the same
(data, status) contract as api.get:
--%%name:helper-demo
--%%mode:online
-- --------------- EOH ---------------
function QuickApp:onInit()
-- single-key variable read: the HC3 refuses this to external callers,
-- so it goes through the helper. Point 4366/x at one of your QAs.
local v, status = api.helper("GET", "/plugins/4366/variables/x", nil)
print("helper read:", v and v.value, status)
-- fibaro.* executed on the real controller
print("fibaro.getName:", api.helperFibaro("getName", {1}))
end
Run it online (credentials from the environment chain):
[helper-demo5000]: helper read: Hello world 200 [helper-demo5000]: fibaro.getName: zwave
The single-key read answers the variable's dto
({name, value, isHidden}) — read the
value field. api.helperFibaro(name, args) runs
fibaro.<name>(...) inside the helper and returns its
values — a window into the real controller's fibaro table from your
laptop. Keep the calls quick: a fibaro.sleep would block the
helper and drop the connection.
If the helper is missing or unreachable, the call answers
(nil, 0) and the run log says what to do — the QA never
crashes:
[helper-demo5000]: api.helper GET /plugins/4366/variables/x -> helper not connected (run flua --tool installHelper) [helper-demo5000]: helper read: nil 0
You rarely need api.helper explicitly for variables: in
online and proxy mode, api.* calls to variable endpoints on
an HC3-namespace id (below 5000 — the controller's own QAs) route through
the helper automatically, exactly like the other REST endpoints forward
to the HC3. Emulated ids (5000 and up) stay in the sim.
In proxy mode that becomes a persistence story: a proxy QA's variables — and its children's — live on the real controller. Reads answer from the HC3, writes land there first with the sim shadow mirroring after. Kill flua, start it again: the state is still there, no db needed. Libraries that keep their state in child variables (QwikChild and friends) just work across restarts.
Next time: the promised proxy-mode deep dive — flua mirrors a QA onto your real HC3, and the two stay in sync while you develop on the laptop.