fibaro-flua 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. fibaro_flua-0.1.1/LICENSE +21 -0
  2. fibaro_flua-0.1.1/PKG-INFO +306 -0
  3. fibaro_flua-0.1.1/README.md +444 -0
  4. fibaro_flua-0.1.1/USAGE.md +259 -0
  5. fibaro_flua-0.1.1/pyproject.toml +57 -0
  6. fibaro_flua-0.1.1/setup.cfg +4 -0
  7. fibaro_flua-0.1.1/src/fibaro_flua.egg-info/PKG-INFO +306 -0
  8. fibaro_flua-0.1.1/src/fibaro_flua.egg-info/SOURCES.txt +63 -0
  9. fibaro_flua-0.1.1/src/fibaro_flua.egg-info/dependency_links.txt +1 -0
  10. fibaro_flua-0.1.1/src/fibaro_flua.egg-info/entry_points.txt +2 -0
  11. fibaro_flua-0.1.1/src/fibaro_flua.egg-info/requires.txt +6 -0
  12. fibaro_flua-0.1.1/src/fibaro_flua.egg-info/top_level.txt +1 -0
  13. fibaro_flua-0.1.1/src/flua/__init__.py +3 -0
  14. fibaro_flua-0.1.1/src/flua/__main__.py +7 -0
  15. fibaro_flua-0.1.1/src/flua/api/__init__.py +211 -0
  16. fibaro_flua-0.1.1/src/flua/api/request.py +44 -0
  17. fibaro_flua-0.1.1/src/flua/api/routes/__init__.py +117 -0
  18. fibaro_flua-0.1.1/src/flua/api/routes/alarms.py +62 -0
  19. fibaro_flua-0.1.1/src/flua/api/routes/devices.py +104 -0
  20. fibaro_flua-0.1.1/src/flua/api/routes/plugins.py +174 -0
  21. fibaro_flua-0.1.1/src/flua/api/routes/scenes.py +49 -0
  22. fibaro_flua-0.1.1/src/flua/api/routes/system.py +75 -0
  23. fibaro_flua-0.1.1/src/flua/api/state.py +222 -0
  24. fibaro_flua-0.1.1/src/flua/bindings.py +208 -0
  25. fibaro_flua-0.1.1/src/flua/check.py +48 -0
  26. fibaro_flua-0.1.1/src/flua/cli.py +492 -0
  27. fibaro_flua-0.1.1/src/flua/clock.py +85 -0
  28. fibaro_flua-0.1.1/src/flua/config.py +156 -0
  29. fibaro_flua-0.1.1/src/flua/devices/__init__.py +83 -0
  30. fibaro_flua-0.1.1/src/flua/devices/devices.json +1 -0
  31. fibaro_flua-0.1.1/src/flua/engine.py +1064 -0
  32. fibaro_flua-0.1.1/src/flua/http.py +45 -0
  33. fibaro_flua-0.1.1/src/flua/lua/fibaro.lua +527 -0
  34. fibaro_flua-0.1.1/src/flua/lua/init.lua +675 -0
  35. fibaro_flua-0.1.1/src/flua/lua/json.lua +22 -0
  36. fibaro_flua-0.1.1/src/flua/lua/mobdebug.lua +2769 -0
  37. fibaro_flua-0.1.1/src/flua/lua/mqtt.lua +209 -0
  38. fibaro_flua-0.1.1/src/flua/lua/net.lua +300 -0
  39. fibaro_flua-0.1.1/src/flua/lua/quickapp.lua +483 -0
  40. fibaro_flua-0.1.1/src/flua/lua/socket.lua +113 -0
  41. fibaro_flua-0.1.1/src/flua/messages.py +196 -0
  42. fibaro_flua-0.1.1/src/flua/mqtt.py +500 -0
  43. fibaro_flua-0.1.1/src/flua/sync_socket.py +313 -0
  44. fibaro_flua-0.1.1/src/flua/timers.py +99 -0
  45. fibaro_flua-0.1.1/src/flua/websocket.py +357 -0
  46. fibaro_flua-0.1.1/tests/test_annotations.py +89 -0
  47. fibaro_flua-0.1.1/tests/test_api.py +463 -0
  48. fibaro_flua-0.1.1/tests/test_clock.py +97 -0
  49. fibaro_flua-0.1.1/tests/test_config.py +108 -0
  50. fibaro_flua-0.1.1/tests/test_devices.py +148 -0
  51. fibaro_flua-0.1.1/tests/test_dx.py +218 -0
  52. fibaro_flua-0.1.1/tests/test_engine.py +133 -0
  53. fibaro_flua-0.1.1/tests/test_http.py +168 -0
  54. fibaro_flua-0.1.1/tests/test_json.py +48 -0
  55. fibaro_flua-0.1.1/tests/test_lua.py +55 -0
  56. fibaro_flua-0.1.1/tests/test_mqtt.py +276 -0
  57. fibaro_flua-0.1.1/tests/test_qa.py +453 -0
  58. fibaro_flua-0.1.1/tests/test_quickapp.py +501 -0
  59. fibaro_flua-0.1.1/tests/test_socket.py +528 -0
  60. fibaro_flua-0.1.1/tests/test_sync_socket.py +112 -0
  61. fibaro_flua-0.1.1/tests/test_tcp.py +170 -0
  62. fibaro_flua-0.1.1/tests/test_timers.py +105 -0
  63. fibaro_flua-0.1.1/tests/test_udp.py +110 -0
  64. fibaro_flua-0.1.1/tests/test_virtual_time.py +85 -0
  65. fibaro_flua-0.1.1/tests/test_websocket.py +202 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jan Gabrielsson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,306 @@
1
+ Metadata-Version: 2.4
2
+ Name: fibaro-flua
3
+ Version: 0.1.1
4
+ Summary: Develop Fibaro Home Center 3 QuickApps offline: the HC3 Lua runtime (QuickApp, fibaro, api, net, mqtt) with a simulated HC3, virtual time, and a real debugger
5
+ Author-email: Jan Gabrielsson <jan@gabrielsson.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Jan Gabrielsson
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Keywords: fibaro,hc3,home center,quickapp,lua,smart home,automation
29
+ Classifier: Development Status :: 3 - Alpha
30
+ Classifier: License :: OSI Approved :: MIT License
31
+ Classifier: Operating System :: OS Independent
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: Programming Language :: Python :: 3.11
34
+ Classifier: Programming Language :: Python :: 3.12
35
+ Classifier: Programming Language :: Python :: 3.13
36
+ Classifier: Topic :: Home Automation
37
+ Classifier: Topic :: Software Development :: Interpreters
38
+ Requires-Python: >=3.11
39
+ Description-Content-Type: text/markdown
40
+ License-File: LICENSE
41
+ Requires-Dist: lupa>=2.4
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=8.0; extra == "dev"
44
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
45
+ Requires-Dist: ruff>=0.6.0; extra == "dev"
46
+ Dynamic: license-file
47
+
48
+ # flua — user guide for QA developers
49
+
50
+ flua runs Fibaro QuickApps **offline** on your Mac or PC. You write the same
51
+ Lua you'd write on the HC3 — `QuickApp`, `fibaro`, `api`, `net`, `mqtt` — and
52
+ flua provides the rest of the world: a simulated HC3, real network access, a
53
+ virtual clock, a proper debugger with breakpoints, and a one-command path back
54
+ to the HC3 as a `.fqa` file.
55
+
56
+ The HC3 editor is tiny and debugging there means `print()` statements. flua
57
+ exists so you can develop in your real editor, with real tooling, and upload
58
+ when it works.
59
+
60
+ - [Install](#install)
61
+ - [Your first QuickApp](#your-first-quickapp)
62
+ - [Running QAs](#running-qas)
63
+ - [VS Code setup](#vs-code-setup)
64
+ - [QA directives (`--%%`)](#qa-directives--)
65
+ - [Multi-file QAs](#multi-file-qas)
66
+ - [The offline HC3](#the-offline-hc3)
67
+ - [Loading QAs at runtime](#loading-qas-at-runtime)
68
+ - [Network clients](#network-clients)
69
+ - [Deploying to the HC3](#deploying-to-the-hc3)
70
+ - [Bringing an HC3 QA home](#bringing-an-hc3-qa-home)
71
+ - [Static checks](#static-checks)
72
+ - [flua extensions (`_FLUA`)](#flua-extensions-_flua)
73
+
74
+ ## Install
75
+
76
+ Python 3.11+. lupa (which bundles Lua) is the only runtime dependency.
77
+
78
+ ```bash
79
+ pip install fibaro-flua # from PyPI — installs the flua command
80
+ ```
81
+
82
+ From a checkout (development):
83
+
84
+ ```bash
85
+ cd flua
86
+ python3 -m venv .venv
87
+ .venv/bin/pip install -e ".[dev]"
88
+ flua --version
89
+ ```
90
+
91
+ ## Your first QuickApp
92
+
93
+ A QuickApp is an ordinary Lua file. `QuickApp:onInit` runs exactly like on
94
+ the HC3, and `self:debug` prints immediately (unlike the HC3, where you'd
95
+ only see it in the debug window):
96
+
97
+ ```lua
98
+ --%%name:hello
99
+ -- --------------- EOH ---------------
100
+ function QuickApp:onInit()
101
+ self:debug("I started")
102
+ setTimeout(function() self:debug("one second later") end, 1000)
103
+ end
104
+ ```
105
+
106
+ Save it as `hello.lua` and run it:
107
+
108
+ ```bash
109
+ .venv/bin/flua hello.lua
110
+ ```
111
+
112
+ Every `.lua` file you pass is a QuickApp — it gets `QuickApp`, `fibaro`,
113
+ `api`, `net`, `mqtt`, timers, and runs `onInit` exactly like on the HC3.
114
+ Anything that has nothing left to do (no timers, no network connections)
115
+ makes flua exit; QAs with timers or open connections keep running.
116
+
117
+ ## Running QAs
118
+
119
+ ```bash
120
+ .venv/bin/flua script.lua # one QA
121
+ .venv/bin/flua qa1.lua qa2.lua # several QAs, isolated, can talk to each other
122
+ .venv/bin/flua -e 'setTimeout(function() print("hi") end, 100)'
123
+ .venv/bin/flua --run-for 5 script.lua # at least 5 s, then exit when idle
124
+ .venv/bin/flua --run-for -3 script.lua # exactly 3 s
125
+ ```
126
+
127
+ Virtual time — great for testing long-running logic:
128
+
129
+ ```bash
130
+ .venv/bin/flua --speed 60 script.lua # 60x faster
131
+ .venv/bin/flua --instant script.lua # timers fire now, os.time() jumps ahead
132
+ ```
133
+
134
+ ## VS Code setup
135
+
136
+ The repo ships `.vscode/launch.json` with three configurations:
137
+
138
+ - **Flua: Run Current File** — runs the file in the panel.
139
+ - **Flua: Run Current File (Terminal)** — runs it in the integrated terminal
140
+ (pick this one for `self:debug` output you can scroll).
141
+ - **Flua: Debug Current File (mobdebug)** — real debugging: breakpoints,
142
+ stepping, variable inspection. Install the VS Code extension
143
+ **Lua MobDebug** (`alexeymelnichuk.lua-mobdebug`), open your QA, press F5
144
+ with the mobdebug configuration selected. flua waits for the debugger
145
+ before running your code.
146
+
147
+ While you step through code, `print`/`self:debug` output appears **immediately**
148
+ — logs never queue behind a paused program.
149
+
150
+ The fastest loop for tinkering:
151
+
152
+ ```bash
153
+ .venv/bin/flua --watch script.lua
154
+ ```
155
+
156
+ flua restarts the QA whenever you save the file (or any `--%%file` file).
157
+ Ctrl-C stops it. Works on top of the debugger too.
158
+
159
+ ## QA directives (`--%%`)
160
+
161
+ Directives are ordinary Lua comments at the top of the file. flua parses them
162
+ before running; the HC3 ignores them — the same file runs in both places.
163
+ Parsing stops at the end-of-header marker:
164
+
165
+ ```lua
166
+ --%%name:my-qa
167
+ -- --------------- EOH ---------------
168
+ -- nothing below this line is parsed as a directive
169
+ ```
170
+
171
+ | Directive | Meaning |
172
+ |---|---|
173
+ | `--%%name:x` | the device/QA name (`_FLUA.config.name`) |
174
+ | `--%%type:com.fibaro.binarySwitch` | device type (defaults to binarySwitch; unknown types are an error) |
175
+ | `--%%properties:value=false` | default device properties (plural form) |
176
+ | `--%%property:value=true` | raw property, scalar values; repeatable, merges |
177
+ | `--%%var:name=value` | initializes a **QuickApp variable** (string values; `self:getVariable(name)`) |
178
+ | `--%%uid:...` | sets `quickAppUuid` |
179
+ | `--%%description:...` | sets `userDescription` |
180
+ | `--%%model:...` | sets `model` |
181
+ | `--%%build:7` | sets `buildNumber` (a number) |
182
+ | `--%%manufacturer:...` | sets `manufacturer` |
183
+ | `--%%file:lib.lua,lib` | extra QA file, loads before main (see below) |
184
+ | `--%%speed:60` | virtual time speed (global) |
185
+ | `--%%instant:true` | instant mode (global) |
186
+ | `--%%maxhours:48` | stop after 48 virtual hours (global) |
187
+ | `--%%time:speed=2,instant=true,hours=48,start=2027/10/6 12:00:20` | combined runtime settings (global) |
188
+ | `--%%time:2027/10/6 12:00:20` | bare form: set the virtual start time |
189
+
190
+ Names follow plua: `--%%name:value` for scalars,
191
+ `--%%name:sub1=val1,sub2=val2` for subparameters. A typo'd directive is
192
+ silently ignored at runtime — run `flua --check` to catch those.
193
+
194
+ The virtual clock starts **now** unless you set a start time — handy for
195
+ testing dates: leap years, DST switches, New Year logic. Combine with
196
+ `--instant` to fast-forward through the interesting moments:
197
+
198
+ ```bash
199
+ .venv/bin/flua --start "2027/12/31 23:59:50" script.lua
200
+ # or in the file: --%%time:start=2027/12/31 23:59:50,instant=true
201
+ ```
202
+
203
+ ## Multi-file QAs
204
+
205
+ On the HC3 a QA is a set of named Lua files — one is `main`. flua keeps your
206
+ files on disk and declares the extras in the main file:
207
+
208
+ ```lua
209
+ --%%file:lib.lua,lib
210
+ --%%file:util.lua,util
211
+ -- --------------- EOH ---------------
212
+ print(helper())
213
+ ```
214
+
215
+ Files load in declaration order, **main loads last**. Paths resolve relative
216
+ to the main file's directory. See `examples/multifile.lua`. The HC3's file
217
+ API works offline too (`api.get('/quickApp/' .. _FLUA.qaId .. '/files')` etc.).
218
+
219
+ ## The offline HC3
220
+
221
+ `--seed` loads a simulated house (see `examples/house.json`):
222
+
223
+ ```bash
224
+ .venv/bin/flua --seed examples/house.json script.lua
225
+ ```
226
+
227
+ Your QAs become devices (ids from 5000) in the same simulated HC3, so
228
+ everything works between them:
229
+
230
+ - `api.get/post/put/delete` — the real HC3 REST surface (devices, plugins,
231
+ variables, globals, scenes, alarms, profiles, refreshStates, …)
232
+ - `fibaro.call(id, 'turnOn')` — calls another QA's QuickApp method
233
+ - `fibaro.emitCustomEvent(name)` → `QuickApp:onCustomEvent(name)` handlers
234
+ - `self:setVariable/getVariable` — persistent, survives restarts
235
+ - `GET /refreshStates?last=N` — the HC3's polling change feed
236
+
237
+ QAs find each other by name with `fibaro.getIds({type = "quickApp"})` — see
238
+ `examples/qa3.lua` and `examples/qa4.lua` calling each other.
239
+
240
+ ## Loading QAs at runtime
241
+
242
+ From VS Code you often run one QA — let it bring up the QAs it needs:
243
+
244
+ ```lua
245
+ local id = _FLUA.loadQAfromFile("examples/qa3.lua") -- annotations parsed
246
+ local id2 = _FLUA.loadQAfromString([[ ...inline QA... ]])
247
+ fibaro.call(id, "turnOn") -- immediately reachable
248
+ ```
249
+
250
+ Both return the new QA id (or `nil, error`). `examples/dynamic.lua` demos it.
251
+
252
+ ## Network clients
253
+
254
+ Real network, HC3-style APIs, all asynchronous through the pump (callbacks
255
+ run in your QA, timers keep running while requests are in flight):
256
+
257
+ - `net.HTTPClient()` → `request(url, {options, success, error})` — `examples/http.lua`
258
+ - `net.TCPSocket({timeout=ms})` → `connect/send/read/readUntil/close` — `examples/tcp.lua`
259
+ - `net.UDPSocket({broadcast, timeout})` → `sendTo/receive` — `examples/udp.lua`
260
+ - `net.WebSocketClient()/WebSocketClientTls()` → `addEventListener`, `connect`, `send` — `examples/websocket.lua`
261
+ - `mqtt.Client.connect(uri, options)` → `subscribe/publish/unsubscribe/disconnect`, `mqtt.QoS` — `examples/mqtt.lua`
262
+
263
+ ## Deploying to the HC3
264
+
265
+ ```bash
266
+ .venv/bin/flua export script.lua -o myqa.fqa
267
+ ```
268
+
269
+ Upload `myqa.fqa` through the HC3 web UI (Create QuickApp → import). The
270
+ package follows the HC3's schema — only the properties the HC3 accepts
271
+ travel; dynamic properties are left out.
272
+
273
+ ## Bringing an HC3 QA home
274
+
275
+ Export the QA from the HC3 UI (`.fqa`), then:
276
+
277
+ ```bash
278
+ .venv/bin/flua unpack myqa.fqa -d myqa-project/
279
+ ```
280
+
281
+ You get a runnable flua project: `main.lua` with generated `--%%` directives
282
+ and one file per QA file, ready for editing and debugging.
283
+
284
+ ## Static checks
285
+
286
+ ```bash
287
+ .venv/bin/flua --check script.lua
288
+ ```
289
+
290
+ Checks syntax, unknown `--%%` directives (typos), and deprecated API calls.
291
+ Warnings don't fail the run; syntax errors exit 1. Good in CI.
292
+
293
+ ## flua extensions (`_FLUA`)
294
+
295
+ Everything HC3-compatible is a plain global (`QuickApp`, `fibaro`, `api`,
296
+ `net`, `mqtt`, `json`, …). flua-specific helpers live on `_FLUA` so your code
297
+ stays portable:
298
+
299
+ - `_FLUA.qaId` — this QA's id; `_FLUA.config` — this QA's config table
300
+ - `_FLUA.arg` — the file path / `-e` marker
301
+ - `_FLUA.exit(code)` — stop the engine (vs `exit(code)` which stops only this QA)
302
+ - `_FLUA.qa(id)` — another QA's QuickApp instance (lupa proxy)
303
+ - `_FLUA.loadQAfromFile(path)` / `_FLUA.loadQAfromString(code)` — dynamic QA loading
304
+ - `_FLUA.async.run(fn)` / `_FLUA.async.await(worker)` / `_FLUA.async.wait(ms)` — coroutine awaits
305
+ - `_FLUA.setTimeout(fn, ms, qaId)` — timer with explicit QA attribution
306
+ - `if _FLUA then` — detect flua at runtime