homebridge-mq77-customizer 1.5.0

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 (103) hide show
  1. package/CHANGELOG.md +323 -0
  2. package/LICENSE +21 -0
  3. package/README.md +164 -0
  4. package/config.schema.json +258 -0
  5. package/dist/adapters/index.d.ts +4 -0
  6. package/dist/adapters/index.js +14 -0
  7. package/dist/adapters/index.js.map +1 -0
  8. package/dist/adapters/json-topic/adapter.d.ts +50 -0
  9. package/dist/adapters/json-topic/adapter.js +270 -0
  10. package/dist/adapters/json-topic/adapter.js.map +1 -0
  11. package/dist/adapters/json-topic/keys.d.ts +27 -0
  12. package/dist/adapters/json-topic/keys.js +41 -0
  13. package/dist/adapters/json-topic/keys.js.map +1 -0
  14. package/dist/adapters/types.d.ts +90 -0
  15. package/dist/adapters/types.js +2 -0
  16. package/dist/adapters/types.js.map +1 -0
  17. package/dist/adapters/zigbee2mqtt/adapter.d.ts +58 -0
  18. package/dist/adapters/zigbee2mqtt/adapter.js +416 -0
  19. package/dist/adapters/zigbee2mqtt/adapter.js.map +1 -0
  20. package/dist/adapters/zigbee2mqtt/exposes.d.ts +17 -0
  21. package/dist/adapters/zigbee2mqtt/exposes.js +110 -0
  22. package/dist/adapters/zigbee2mqtt/exposes.js.map +1 -0
  23. package/dist/adapters/zigbee2mqtt/protocol.d.ts +64 -0
  24. package/dist/adapters/zigbee2mqtt/protocol.js +9 -0
  25. package/dist/adapters/zigbee2mqtt/protocol.js.map +1 -0
  26. package/dist/build-info.json +5 -0
  27. package/dist/catalog.d.ts +69 -0
  28. package/dist/catalog.js +129 -0
  29. package/dist/catalog.js.map +1 -0
  30. package/dist/config.d.ts +34 -0
  31. package/dist/config.js +190 -0
  32. package/dist/config.js.map +1 -0
  33. package/dist/homekit/manager.d.ts +70 -0
  34. package/dist/homekit/manager.js +346 -0
  35. package/dist/homekit/manager.js.map +1 -0
  36. package/dist/homekit/mapping.d.ts +59 -0
  37. package/dist/homekit/mapping.js +367 -0
  38. package/dist/homekit/mapping.js.map +1 -0
  39. package/dist/homekit/names.d.ts +10 -0
  40. package/dist/homekit/names.js +65 -0
  41. package/dist/homekit/names.js.map +1 -0
  42. package/dist/homekit/roles.d.ts +44 -0
  43. package/dist/homekit/roles.js +140 -0
  44. package/dist/homekit/roles.js.map +1 -0
  45. package/dist/homekit/values.d.ts +33 -0
  46. package/dist/homekit/values.js +162 -0
  47. package/dist/homekit/values.js.map +1 -0
  48. package/dist/index.d.ts +3 -0
  49. package/dist/index.js +6 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/logger.d.ts +15 -0
  52. package/dist/logger.js +16 -0
  53. package/dist/logger.js.map +1 -0
  54. package/dist/model/payload.d.ts +15 -0
  55. package/dist/model/payload.js +55 -0
  56. package/dist/model/payload.js.map +1 -0
  57. package/dist/model/types.d.ts +114 -0
  58. package/dist/model/types.js +11 -0
  59. package/dist/model/types.js.map +1 -0
  60. package/dist/mqtt/client.d.ts +43 -0
  61. package/dist/mqtt/client.js +129 -0
  62. package/dist/mqtt/client.js.map +1 -0
  63. package/dist/mqtt/topics.d.ts +4 -0
  64. package/dist/mqtt/topics.js +34 -0
  65. package/dist/mqtt/topics.js.map +1 -0
  66. package/dist/platform.d.ts +23 -0
  67. package/dist/platform.js +125 -0
  68. package/dist/platform.js.map +1 -0
  69. package/dist/rules/conditions.d.ts +26 -0
  70. package/dist/rules/conditions.js +94 -0
  71. package/dist/rules/conditions.js.map +1 -0
  72. package/dist/rules/convert.d.ts +13 -0
  73. package/dist/rules/convert.js +34 -0
  74. package/dist/rules/convert.js.map +1 -0
  75. package/dist/rules/engine.d.ts +168 -0
  76. package/dist/rules/engine.js +882 -0
  77. package/dist/rules/engine.js.map +1 -0
  78. package/dist/rules/match.d.ts +22 -0
  79. package/dist/rules/match.js +112 -0
  80. package/dist/rules/match.js.map +1 -0
  81. package/dist/rules/types.d.ts +298 -0
  82. package/dist/rules/types.js +45 -0
  83. package/dist/rules/types.js.map +1 -0
  84. package/dist/rules/validate.d.ts +12 -0
  85. package/dist/rules/validate.js +369 -0
  86. package/dist/rules/validate.js.map +1 -0
  87. package/dist/settings.d.ts +13 -0
  88. package/dist/settings.js +14 -0
  89. package/dist/settings.js.map +1 -0
  90. package/dist/store.d.ts +119 -0
  91. package/dist/store.js +270 -0
  92. package/dist/store.js.map +1 -0
  93. package/dist/web/auth.d.ts +20 -0
  94. package/dist/web/auth.js +75 -0
  95. package/dist/web/auth.js.map +1 -0
  96. package/dist/web/public/app.css +1356 -0
  97. package/dist/web/public/app.js +4235 -0
  98. package/dist/web/public/favicon.svg +27 -0
  99. package/dist/web/public/index.html +193 -0
  100. package/dist/web/server.d.ts +61 -0
  101. package/dist/web/server.js +510 -0
  102. package/dist/web/server.js.map +1 -0
  103. package/package.json +58 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,323 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## Unreleased
8
+
9
+ ## [1.5.0] - 2026-08-27
10
+
11
+ The first public release, on npm.
12
+
13
+ ### Added
14
+
15
+ - The web interface says plainly that it belongs on your own network: anybody past its one password can switch every device it publishes
16
+
17
+ ### Changed
18
+
19
+ - Installed from npm, the way any Homebridge plugin is installed
20
+
21
+ ## [1.4.1] - 2026-08-27
22
+
23
+ ### Changed
24
+
25
+ - Installing the plugin no longer asks for `sudo`, which `hb-service add` does not need
26
+
27
+ ### Fixed
28
+
29
+ - The build's progress messages go to stderr rather than stdout, so anything reading `npm pack --json` gets JSON and nothing else
30
+
31
+ ## [1.4.0] - 2026-08-27
32
+
33
+ ### Added
34
+
35
+ - A device panel says under Diagnostics whether the broker keeps that device's messages, read from Zigbee2MQTT's own configuration, and the timestamp the device last reported for itself
36
+ - Test builds and releases are built on GitHub and published as an installable tarball, so a Raspberry Pi installs what GitHub compiled rather than compiling it itself
37
+
38
+ ### Changed
39
+
40
+ - When a device was last heard now comes from the device rather than from this plugin, which no longer keeps arrival times of its own. Zigbee2MQTT publishes it once `advanced.last_seen` is turned on; a device that publishes none shows none, since a retained message replayed on connect says nothing about when the device spoke
41
+ - What a device is and the topic it lives on move off the card header onto the first line of the open panel, so the header reads as the name, when it was last heard, and what it became in HomeKit
42
+ - A device's functions are listed by name within Functions, Settings and Diagnostics, and the tile picker is called what it chooses: the HomeKit tile
43
+ - The README says what the settings are for and leaves naming them to the settings form, which describes its own fields more clearly. Installation is the command any plugin is installed with
44
+
45
+ ## [1.3.0] - 2026-08-25
46
+
47
+ ### Added
48
+
49
+ - A Cycle button for sliders: one button for the whole range, stepping up to the top, back down to off, and up again. It starts upward whenever the level was last set by something else, and ignores a second press within a second, unlike the stepping buttons
50
+
51
+ ### Changed
52
+
53
+ - The tabs become a dropdown below 960px rather than below 640px, aligned left with the Zigbee2MQTT link still at the end of the line. The Map is in the dropdown now, since a window that narrow can still draw one
54
+ - The Controllers tab draws two tables side by side where there is room, marks where one physical button gives way to the next, and drops the `Button | Action` heading row, which said what the two columns say themselves. `controller-config.md` keeps its heading, since a markdown table cannot do without one
55
+
56
+ ### Fixed
57
+
58
+ - The Clear button is back on the Activity tab, at the end of the line above the log. It was removed altogether when it should only have stood down on a phone, which is what it does now
59
+
60
+ ## [1.2.0] - 2026-08-25
61
+
62
+ ### Added
63
+
64
+ - The Controllers tab says `In HomeKit` of a button whose press reaches HomeKit, in place of `none` where no rule answers it and underneath the rules where one does
65
+ - A HomeKit buttons tick in the header, beside Unused buttons, says whether those lines are wanted. With both down a button nothing answers is left out entirely, in the tables and in `controller-config.md` alike
66
+
67
+ ## [1.1.0] - 2026-08-25
68
+
69
+ ### Added
70
+
71
+ - A Controllers tab, listing every button of every remote and what it sets off. Buttons nothing answers read as `none` and can be hidden, and the whole overview downloads as `controller-config.md` to keep beside the remote
72
+
73
+ ### Changed
74
+
75
+ - A press and the rule it sets off read as one line in the activity log, `Woonkamer Remote 4 Single Long → Woonkamer: All Off - ran: 2 actions sent`. Presses that set nothing off keep a line of their own, and start hidden
76
+ - Actions read as buttons in the activity log too, `4 Single Long` rather than `4_single_long`
77
+ - A slider says what it did in the words somebody would use: `Brightness+ 1/6`, `Brightness- 0/6 (off)`, `On to Brightness 94`
78
+ - A mirror says which function it read and which it wrote: `Gang Voor State → Gang Achter State`
79
+ - A rule with more than one outcome says which one ran, in quotes
80
+ - Held back and nothing to do both read as `ignored`, and a timer called off says so without repeating why
81
+ - On a phone a log line stacks into what set it off, which rule, and what it did
82
+
83
+ ## [1.0.0] - 2026-08-24
84
+
85
+ ### Added
86
+
87
+ - Settings can be downloaded and uploaded from the footer, which is the only copy that survives losing the machine
88
+ - The last ten dated copies of the settings are kept in a `backups` folder, one at startup and at most one an hour after that, and one can be taken on the spot from the footer
89
+ - A device that carries the same function more than once, such as a three gang switch, can put every channel into a mirror instead of one of them
90
+
91
+ ### Changed
92
+
93
+ - A remote's actions read as buttons, `1 Single Long` rather than `1_single_long`, and are listed in the order somebody would read them out
94
+ - Picking what sets a rule off marks with a `*` any value already used by another automation, slider or timer, so two rules do not end up on one button press by accident
95
+ - A rule just added stays at the top of the list until it is saved, including when the list is grouped by room, and has no enabled switch until then
96
+ - The footer reads left to right: which build this is, what the settings are doing, and the way out. It says when the last copy was taken and stacks onto two lines on a phone
97
+ - Descriptions break after the arrow rather than in the middle of what follows it, in rule lines and in the activity log
98
+ - Rule lists redraw far quicker, most of all when grouped by room. A panel is built when it is opened rather than for every rule in the list, sort keys are worked out once rather than inside every comparison, and devices are looked up by name rather than by walking the list
99
+ - A settings file that cannot be used says so in a dialog rather than in the corner of the header
100
+
101
+ ### Fixed
102
+
103
+ - A run that starts with nothing refuses to write over a settings file that has something in it, and says so
104
+
105
+ ## [0.16.1] - 2026-08-24
106
+
107
+ ### Fixed
108
+
109
+ - Adding a device to a mirror did nothing. The function rows were redrawn with the new device in them, but the group behind them was only written back when something was clicked, so saving sent the members it had before
110
+ - Taking devices away until one was left kept a group of one, which mirrors nothing. The save was then refused for a reason nothing on the screen explained, since the row had already gone
111
+
112
+ ## [0.16.0] - 2026-08-24
113
+
114
+ ### Changed
115
+
116
+ - Signing out and the build label move to a footer at the foot of the page, and how the connection is doing becomes a word beside the title, green when live
117
+ - Switching a rule on or off is a tick box in its header, saved as it is clicked. It writes the stored rule with one thing changed, so turning something off does not push half written panel edits out with it
118
+ - The "In HomeKit only" and "Enabled only" filters are gone: a rule switched off is still a rule you are looking for
119
+ - The activity log reads as three columns with room to breathe, so every description starts in the same place, and can be emptied
120
+ - The add buttons read "+ automation", "+ outcome" and the like, and each tab's description says what it is for in one line
121
+ - Inputs and selects state their height, since the same padding on both left them a few pixels apart on one row
122
+
123
+ ## [0.15.0] - 2026-08-23
124
+
125
+ ### Added
126
+
127
+ - A Timers tab waits between one thing and another: a light coming on, thirty seconds, the light going out again. The clock starts again if the same thing happens again, and is called off the moment what started it stops being so, which an automation with a delayed action cannot do. A timer counting when Homebridge restarts is forgotten
128
+ - An automation or a timer can be run by hand from its panel, switched on or not, once it has been saved. The conditions still hold sway, and the button is absent while the panel and the stored rule disagree
129
+
130
+ ## [0.14.0] - 2026-08-23
131
+
132
+ ### Added
133
+
134
+ - Every device takes a name, a room and a kind of its own, set in its panel. They are for the interface: HomeKit keeps rooms in the Home app, where no accessory can set or read them. The name reaches HomeKit only where the source names nothing itself
135
+ - Eight kinds, each drawing an icon: Light, Sensor, Controller, Fan, TV, Audio device, Media device and Other
136
+ - The device list sorts into groups by room or by kind, and the rule lists by room, meaning the rooms a rule acts in. A rule reaching two rooms is listed under both
137
+ - Button presses from a device marked as a Controller appear in the Activity tab, with a filter of their own
138
+
139
+ ### Changed
140
+
141
+ - A rule is named by the rooms it acts in rather than the room it is set off from: "Study: Nightlight toggle". The rooms come off only under a heading that has said all of them
142
+ - The line under a rule's name names devices and counts the rest, rather than spelling out which function of each it writes
143
+ - Under a room heading a device from another room keeps its room in its name, since which one it is still matters
144
+ - The activity log reads as a sentence, with the outcome and then what happened, and names devices the way every other list does
145
+ - Automation triggers and slider buttons are no longer joined by "or"
146
+ - The pencil rename button is gone: the name is one of the three fields now, and offered on every device
147
+ - Mirror and slider lists sort by name or room only
148
+
149
+ ## [0.13.0] - 2026-08-23
150
+
151
+ ### Added
152
+
153
+ - A Sliders tab drives a dimmer or a fan from buttons. The level is cut into steps and a press moves it one step, which as automations would be four to six rules that only make sense together. Either button switches the device on when it is off: step up goes to the level the device itself keeps, step down to the bottom of the range. Step down from the first step switches it off rather than leaving a light at zero brightness and still on
154
+ - Each slider button takes several triggers, so one slider can be driven by more than one remote
155
+
156
+ ### Changed
157
+
158
+ - Delete on a rule sits at the far end of the footer, is red, and asks once before deleting anything that has been saved, going back to asking after two seconds. A rule only just added still goes on the first click
159
+
160
+ ### Fixed
161
+
162
+ - A rule just added disappeared when the list was filtered, or when "Enabled only" was ticked, since it is saved the moment it is added and so starts with a placeholder name and switched off
163
+
164
+ ## [0.12.0] - 2026-08-22
165
+
166
+ ### Added
167
+
168
+ - A Map tab draws the Zigbee network: the hub on the left and a column per hop out from it, so what reaches it directly and what goes through something else can be read down the page. Every link found is drawn, with the route each device uses picked out, and clicking a device says what it can hear and how well. A device the scan found but nothing connects to is drawn dashed rather than left out
169
+ - Automations sorted by trigger are listed under the device that sets them off, one line per trigger, so a remote with six buttons reads as six lines. A rule with several triggers appears under each of them
170
+
171
+ ### Changed
172
+
173
+ - An outcome is called what it was named in the activity log, falling back to its number
174
+ - A rule just added stays at the top of its list until it is saved, rather than sorting under a name nobody has chosen yet
175
+ - Sorting automations by target device is gone
176
+ - Mirror device selection runs down three columns instead of wrapping across the page
177
+ - Described devices sit behind a collapsed panel in the config form, with Rules only moved up under ID
178
+
179
+ ### Fixed
180
+
181
+ - A child lock ticked on a socket showed nothing in the Home app. HomeKit allows a physical lock on its air services only, so on anything but a fan the lock now gets a switch of its own
182
+ - Every healthy router was reported as having failed the network scan, since an empty list of unanswered requests reads as true
183
+ - A tick box in the mirror editor was stretched to the width of a value box
184
+
185
+ ## [0.11.0] - 2026-08-22
186
+
187
+ ### Added
188
+
189
+ - A flat JSON source can describe functions a device has but never reports, such as the speed and swing of a fan. What was described is logged at startup, and a described topic nothing reports on is named in a warning alongside the topics that did
190
+ - Outcomes can be named, beside a remove button that is now a plain cross
191
+
192
+ ### Changed
193
+
194
+ - The automation editor keeps "or", "and" and the buttons that add another on the row they belong to, instead of each on a line of its own
195
+ - Remove group sits at the top right of its box
196
+ - Outcomes are spaced apart and faintly shaded
197
+ - Rule rows have fixed widths, so the columns line up from one row to the next
198
+ - Number inputs are styled like every other input instead of unstyled, which is what made the delay box look out of place
199
+ - In the config form, described devices sit behind a collapsed panel and Rules only moved up under ID
200
+
201
+ ### Fixed
202
+
203
+ - Sorting and filtering on the Automation and Mirror tabs, which threw on any rule saved since outcomes arrived and emptied both tabs without saying why
204
+ - The device picker in a rule was styled as a device card, since it shared its class
205
+
206
+ ## [0.10.0] - 2026-08-21
207
+
208
+ ### Changed
209
+
210
+ - The broker is configured as one address, `localhost:1883`, instead of a separate host and port. The port may be left off. A host and port stored separately are still read, so an existing install keeps its broker
211
+ - Broker username and password only appear once "Requires authentication" is ticked, and are ignored when it is not
212
+
213
+ ## [0.9.1] - 2026-08-20
214
+
215
+ ### Fixed
216
+
217
+ - Accessories are no longer dropped and re-added on every start. The catalog is empty before the broker answers because nothing has arrived, not because there is nothing, and removing an accessory makes HomeKit forget which room it is in
218
+
219
+ ## [0.9.0] - 2026-08-20
220
+
221
+ ### Added
222
+
223
+ - A rule can have several outcomes, each a condition and its own actions. The first that holds runs and the rest are skipped, which is if, else if and else
224
+ - Any outcome may be left without a condition, meaning it always holds
225
+ - The activity list says which outcome ran, and what each wanted when none did
226
+
227
+ ## [0.8.0] - 2026-08-20
228
+
229
+ ### Added
230
+
231
+ - Conditions are an expression: groups joined by or, tests within a group joined by and, and any group can be negated
232
+ - A rule can have several triggers, any of which fires it
233
+ - The interface header shows the version on a released build, or the branch it was built from on any other
234
+
235
+ ### Changed
236
+
237
+ - Failing an or reports what every branch had against it, rather than only the first
238
+
239
+ ## [0.7.0] - 2026-08-20
240
+
241
+ ### Added
242
+
243
+ - Activity is its own tab, listing both kinds of rule with each entry saying which it came from
244
+ - Each tab offers the controls that suit it: In HomeKit only on Devices, Enabled only on the rule tabs, a checkbox per kind on Activity
245
+ - Rule lists can be ordered by name, or by the first device on either side, and filtered by the devices a rule touches as well as its name
246
+
247
+ ### Changed
248
+
249
+ - Automation and mirrored devices are separate tabs rather than one list behind a checkbox
250
+ - Filters and orderings are kept per tab
251
+
252
+ ## [0.6.1] - 2026-08-19
253
+
254
+ ### Added
255
+
256
+ - Optional link to the Zigbee2MQTT interface in the tab bar, set with `web.zigbee2mqttUrl`
257
+
258
+ ## [0.6.0] - 2026-08-19
259
+
260
+ ### Added
261
+
262
+ - Sort the device list by name, topic, device or when it was last heard from
263
+
264
+ ### Changed
265
+
266
+ - Device pickers in rules are always ordered by name, whatever the device list is sorted by
267
+
268
+ ## [0.5.0] - 2026-08-19
269
+
270
+ ### Added
271
+
272
+ - Rules engine: when something happens on one device, send something to another, across sources
273
+ - Triggers, optional conditions and one or more actions, with optional delays
274
+ - An action can send a fixed value or match whatever triggered the rule, translated into the target's terms
275
+ - Mirror rules: pick devices and the functions to keep in step, every member both trigger and target
276
+ - Rule editor and a run log in the web interface
277
+ - Devices whose source does not name them can be renamed, from a pencil in the card header
278
+ - Show when a device was last heard from, and the local time behind any timestamp value
279
+ - Filter devices by name, topic, model or manufacturer, and hide anything not in HomeKit
280
+ - Toggle offered as an action wherever a device understands one
281
+
282
+ ### Changed
283
+
284
+ - Rules never run on retained messages, so reconnecting cannot replay an old press
285
+ - Per rule rate limit, a settling window for mirrors, and a rule that runs away is turned off and logged
286
+ - Accessory names are corrected to what HomeKit accepts, rather than warned about on every start
287
+ - Values that have not moved are no longer sent to HomeKit
288
+ - State is copied at startup, and what was loaded is reported in the log
289
+
290
+ ### Fixed
291
+
292
+ - The interface is sent the words a device uses for on and off, instead of assuming ON and OFF
293
+ - Endpoints are named in rule dropdowns, so a device's channels can be told apart
294
+ - A characteristic with no value yet reports the last known one rather than failing the read
295
+
296
+ ## [0.4.1] - 2026-08-18
297
+
298
+ ### Changed
299
+
300
+ - Marked private, since the package is not published. `npm publish` now refuses rather than putting it on the registry by accident
301
+ - Installation documents the only route that works, installing from source, rather than leading with an npm package that does not exist
302
+
303
+ ## [0.4.0] - 2026-08-18
304
+
305
+ First release. Everything below arrived across v0.1.0 to v0.4.0, none of which was published separately.
306
+
307
+ ### Added
308
+
309
+ - Homebridge platform plugin connecting to one MQTT broker shared by every source
310
+ - Pluggable source adapters producing one normalised device model, so the HomeKit mapping never sees a source format
311
+ - Zigbee2MQTT source discovering devices and their functions from `bridge/devices`, updating live on joins, renames and removals
312
+ - `json-topic` source for publishers that put flat JSON on a topic per device, with properties inferred from the keys seen and unrecognised keys kept rather than dropped
313
+ - Sources can be marked rules only, for devices another plugin already publishes to HomeKit
314
+ - Password protected web interface listing every device and function, with live values over server sent events
315
+ - Tick a function to publish it to HomeKit, applied immediately with no Homebridge restart
316
+ - Tile type per endpoint, optional separate accessory per endpoint, and name overrides
317
+ - Rename devices whose source does not name them itself
318
+ - Filter devices by name, topic, model or manufacturer, and hide anything not in HomeKit
319
+ - HomeKit mapping for on/off, brightness, fan speed and swing, thermostat, temperature, humidity, battery and child lock
320
+ - Buttons inferred from the actions a device publishes, one service per physical button, with per gesture selection
321
+ - Property name to characteristic table, so a new kind of sensor needs no change to the mapper
322
+ - Functions with no HomeKit equivalent stay listed and marked, ready for the rules engine
323
+ - Persistent state under the Homebridge storage path, kept out of `config.json`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026, Luud Jacobs
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.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # MQ77 Customizer 1.5.0
2
+
3
+ **This Homebridge plugin has been 100% vibe coded using Claude Code.**
4
+
5
+ A Homebridge plugin that exposes MQTT devices to HomeKit and links them together, configured from a web interface instead of a config form. Devices and their functions are discovered from the broker, so nothing has to be typed out by hand.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js 20.19, 22.12 or 24 and up
10
+ - Homebridge 1.8 or up
11
+ - An MQTT broker, for example Mosquitto
12
+ - Zigbee2MQTT, for the Zigbee2MQTT source
13
+
14
+ ## Installation
15
+
16
+ Install it the way you install any Homebridge plugin, from the Plugins screen of the Homebridge UI or from the command line:
17
+
18
+ ```
19
+ hb-service add homebridge-mq77-customizer
20
+ ```
21
+
22
+ ## Settings
23
+
24
+ Everything is set in the plugin's settings form in the Homebridge UI, and each field says what it is for. There are three things to fill in:
25
+
26
+ - **MQTT Broker**, where your broker is and what it wants to be called
27
+ - **Sources**, one per publisher on that broker. A Zigbee2MQTT source needs its base topic, `zigbee2mqtt` unless you changed it. With no sources at all, that is what is assumed
28
+ - **Web Interface**, a port and a password. The interface can switch your devices, so it refuses to start without one
29
+
30
+ Everything else, which devices reach HomeKit and what they do between them, is set in the web interface itself.
31
+
32
+ ### Sources
33
+
34
+ Two kinds. **Zigbee2MQTT** needs nothing but its base topic: it describes its own devices, so they arrive complete. **Flat JSON topics** reads any publisher that puts flat JSON on a topic per device, working the functions out from the keys it sees. Those accumulate across messages, so a partial update carrying one key does not redefine the device.
35
+
36
+ Recognised keys are `state`, `level`, `speed`, `swing`, `temperature`, `humidity` and `co2_levels`. Anything else still becomes a function, typed from its value, and stays available to the rules engine.
37
+
38
+ **Rules only** keeps a source's devices out of HomeKit while leaving them usable as rule triggers and targets. Set it where another plugin already publishes those devices, so they can't appear twice.
39
+
40
+ **Topic filter** narrows what a flat JSON source listens to, as an MQTT filter, `+` standing for one level and `#` for the rest. Everything under the base topic by default.
41
+
42
+ **Command topic suffix** is what is added to a device's topic to write to it, usually `set`. Without one the source is read only.
43
+
44
+ ### Describing a device
45
+
46
+ A flat JSON topic carries no schema, so a function is only known once it has turned up in a payload. A fan that reports nothing but `state` until somebody changes its speed has no speed to tick. Name the missing functions under **Described devices** and they are there from the moment the device first reports.
47
+
48
+ A device is named by the part of its topic after the base topic: one publishing on `<base topic>/kitchen_fan` is written as `kitchen_fan`, though the whole topic is accepted too. Only the recognised keys above can be named, since a name on its own says nothing about the kind of value it carries. A function the device does report is left exactly as reported.
49
+
50
+ What was described is logged at startup, so a topic that matches no device is visible rather than silent.
51
+
52
+ ## Usage
53
+
54
+ Open `http://<your-homebridge-host>:8888`, or whichever port you set, and sign in with the password from the settings.
55
+
56
+ Keep it on your own network. Anybody who gets past that one password can switch every device the plugin publishes, so the port does not belong on the open internet or behind a port forward. Reach it from outside through a VPN, the way you would reach Homebridge itself.
57
+
58
+ Every device found on the broker is listed with all of its functions, grouped into functions, settings and diagnostics and listed by name within each. Tick a function to publish it to HomeKit. Changes take effect immediately, with no Homebridge restart.
59
+
60
+ Per device you can also:
61
+
62
+ - choose the HomeKit tile: Switch, Outlet, Lightbulb or Fan
63
+ - publish each endpoint as its own accessory, for multi channel switches
64
+ - give it a name, a room and a kind, which this interface uses to label and group it
65
+
66
+ Functions with no HomeKit equivalent are still listed and marked, and stay available to the rules engine rather than being hidden.
67
+
68
+ Accessory names are corrected to what HomeKit accepts, which must start and end with a letter or number. A name in brackets, `Hall light (front door)`, is published as `Hall light front door`. The name shown here is left as you wrote it.
69
+
70
+ ### What reaches HomeKit
71
+
72
+ | Function | Becomes |
73
+ | --- | --- |
74
+ | on/off | Switch, Outlet, Lightbulb or Fan, your choice |
75
+ | brightness | Brightness on a Lightbulb |
76
+ | temperature, humidity | their sensor services |
77
+ | battery | a battery reading on the accessory, with a low warning |
78
+ | child lock | the physical controls lock on the tile |
79
+ | climate | a Thermostat, using the temperature range the device declares |
80
+ | speed, swing | a Fan with rotation speed and swing |
81
+ | button actions | one button per physical button, mapped to single, double and long press |
82
+
83
+ Button names and gestures are worked out from the action names the device publishes, so a double rocker becomes three buttons without anything being typed out. Gestures HomeKit has no equivalent for, such as triple press, stay available to the rules engine.
84
+
85
+ ### Naming and grouping
86
+
87
+ Every device takes a name, a room and a kind, set in its panel. They are for this interface: HomeKit keeps rooms in the Home app, where no accessory can set or read them.
88
+
89
+ Marking a device as a Controller puts its button presses in the Activity tab, with their own filter. Only marked devices: every remote in the house reporting in would bury the rules.
90
+
91
+ The name reaches HomeKit only where the source names nothing itself, which is the flat JSON publishers. Zigbee2MQTT owns its own names, so one set here stays in this interface. Renaming never changes an accessory's identity, so nothing is lost in the Home app either way.
92
+
93
+ ### Last seen and retainment
94
+
95
+ A device card says when the device was last heard, and its panel says the timestamp behind that along with whether the broker keeps its messages.
96
+
97
+ Both come from the source rather than from this plugin. When a message reached the broker is not an answer to when a device spoke: a retained message is replayed the moment the plugin connects, which would have every retaining device looking as though it had just reported. Zigbee2MQTT publishes the real answer once `advanced.last_seen` is set to something other than `disable`, and a flat JSON publisher that puts a `last_seen` in its payload is taken at its word the same way. A device that publishes no such time shows none, and sorting by Last seen puts those last.
98
+
99
+ Whether messages are retained is read from Zigbee2MQTT's own configuration, where three things decide it: the device's own `retain`, the `device_options` defaults it otherwise inherits, and `mqtt.force_disable_retain`, which overrides both. A source that keeps no such configuration says nothing rather than guessing.
100
+
101
+ ### Controllers
102
+
103
+ The Controllers tab lists every device marked as a Controller, one table per remote, saying what each of its buttons sets off. A button no rule answers reads as `none`, or `In HomeKit` where the press reaches HomeKit as well, said under any rules it does answer. The Unused buttons and HomeKit buttons ticks in the header say which of those lines are wanted, and a button neither tick keeps is left out. Download writes the whole overview to `controller-config.md`, which follows the tick: hidden buttons are left out of the file too.
104
+
105
+ ### Map
106
+
107
+ The Map tab draws the Zigbee network: what reaches the hub directly and what reaches it through something else. Every link found is drawn, and the route each device uses back to the hub is picked out.
108
+
109
+ A scan questions every device in turn, so it takes minutes on a mesh of any size and only runs when asked for. Zigbee2MQTT only: a flat JSON source has no network to describe.
110
+
111
+ ### Activity
112
+
113
+ The Activity tab lists what the rules have been doing, newest first, including the ones that decided not to run and why. A press and the rule it set off read as one line, and each entry says which kind of rule it was. Presses that set nothing off have a filter of their own, off by default.
114
+
115
+ ## Rules
116
+
117
+ Rules live in four tabs: Automation, Mirror devices, Sliders and Timers. Automation is the general one: when something happens on one device, send something to another. All four work across sources, so a Zigbee button can drive an infrared blaster, and apply the moment they are saved.
118
+
119
+ Across all four:
120
+
121
+ - anything readable can set a rule off, including functions that never reach HomeKit, and anything writable can be acted on
122
+ - an action can copy whatever set the rule off, restated in the target's own terms, so a switch that says `ON` can drive one that expects `true` and a dimmer counting to 254 can drive one counting to 100
123
+ - a rule with several outcomes runs the first whose condition holds and skips the rest
124
+ - picking what sets a rule off marks any value another rule already uses with a `*`, since two rules on one button press is a mistake nobody sees until both of them run
125
+ - rules never run on retained messages, so reconnecting to the broker cannot replay yesterday's button press
126
+ - a rule will not run more often than its rate limit, one second by default, and one that runs more than twenty times in ten seconds is switched off and logged on the assumption it is setting itself off
127
+
128
+ An automation or a timer can be run by hand with the Trigger button beside Save, whether or not it is switched on. Only what has been saved can be run.
129
+
130
+ ### Mirror devices
131
+
132
+ Which devices, and which of their functions, should stay in step. Every member is both a trigger and a target. Functions are matched on meaning rather than on name, so a socket calling its on/off `state` mirrors a two channel switch calling the same thing `state_l1`.
133
+
134
+ After a write the group is left to settle, one and a half seconds by default and set per rule between 0.25 and 60 seconds. A device reporting its old state once more is indistinguishable from somebody flipping a switch, so without the pause a group that disagrees would send itself back and forth for ever. The cost is that flipping a mirrored device again inside the window is ignored.
135
+
136
+ ### Timers
137
+
138
+ A wait between one thing and another: a light coming on, thirty seconds, the light going out again.
139
+
140
+ The clock starts again if the same thing happens again. It is called off the moment what started it stops being true: told to run when a light came on, it stops caring once the light is off, however that happened. A timer counting when Homebridge restarts is forgotten.
141
+
142
+ An automation with a delayed action does the first half of this and cannot be called off, which is the difference between the two.
143
+
144
+ ### Sliders
145
+
146
+ A dimmer driven from buttons. One press moves one step. Down from the first step switches the device off rather than leaving a light at zero brightness and still on, and either stepping button switches it on when it is off.
147
+
148
+ Coming on from off lands where the device says it should, which Zigbee2MQTT keeps as `level_config.on_level`. "On at" sets it for a device that has no such setting, and without either it comes on at the first step.
149
+
150
+ Cycle is one button for the whole range: up to the top, back down to off, and up again from there. It starts upward whenever the level was last set by something other than the slider, and ignores a second press within a second, since it is a button to press rather than to hold.
151
+
152
+ Each button takes several triggers, so one slider can be driven by more than one remote. Stepping counts from what the slider last sent for a couple of seconds rather than from what the device last reported, so a held button that sends faster than the light can answer still climbs.
153
+
154
+ ## Backup settings
155
+
156
+ Everything set here lives in `state.json` under the Homebridge storage path, alongside a `backups` folder holding the last ten dated copies. One is taken when the plugin starts, before anything is touched, and at most once an hour after that.
157
+
158
+ The footer offers `back up: download / upload`, along with when the last copy was taken and a way to take one now. Download hands you the lot as a file, which is the only copy that survives losing the machine it runs on. Upload takes one back, after copying what it replaces. The session secret is left out of the download and kept on upload, so a settings file is safe to keep somewhere else and putting one back does not sign you out.
159
+
160
+ A run that starts with nothing will not write over a file that has something in it. Somebody deleting their last rule is entitled to an empty file, but a run that began empty and is about to stamp on one that is not has misread something, and the file is worth more than the write. It says so in the log and in the interface rather than carrying on.
161
+
162
+ ## Links
163
+
164
+ [License](https://github.com/LuudJacobs/homebridge-mq77-customizer/blob/main/LICENSE) • [Changelog](https://github.com/LuudJacobs/homebridge-mq77-customizer/blob/main/CHANGELOG.md)