homebridge-dyson-solarcycle-morph 0.3.0 → 1.0.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.
- package/CHANGELOG.md +47 -0
- package/README.md +119 -70
- package/config.schema.json +20 -6
- package/dist/accessory.d.ts +19 -1
- package/dist/accessory.js +91 -15
- package/dist/accessory.js.map +1 -1
- package/dist/config.d.ts +11 -2
- package/dist/config.js.map +1 -1
- package/dist/dyson/lamp.d.ts +36 -1
- package/dist/dyson/lamp.js +88 -16
- package/dist/dyson/lamp.js.map +1 -1
- package/dist/dyson/protocol.d.ts +44 -5
- package/dist/dyson/protocol.js +56 -5
- package/dist/dyson/protocol.js.map +1 -1
- package/dist/dyson/reconcile.d.ts +4 -4
- package/dist/dyson/reconcile.js +4 -4
- package/dist/platform.js.map +1 -1
- package/docs/PROTOCOL.md +147 -50
- package/package.json +1 -1
- package/tools/daylight-test.js +116 -54
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,53 @@ All notable changes to this project are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.0] — 2026-09-18
|
|
9
|
+
|
|
10
|
+
Everything the lamp will tell us over Bluetooth is now in HomeKit, and the
|
|
11
|
+
protocol behind it is written down rather than inherited. Stable enough to call
|
|
12
|
+
it that.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **The lamp's preset modes, as switches.** Study, Relax and Precision apply a
|
|
17
|
+
set of values and spring back, the way a scene does. Turn them off per light
|
|
18
|
+
with `presetSwitches`.
|
|
19
|
+
|
|
20
|
+
### Removed
|
|
21
|
+
|
|
22
|
+
- **The motion sensor.** It reported motion permanently. The characteristic it
|
|
23
|
+
read holds a constant on this lamp — it never changed across the lamp being
|
|
24
|
+
on, off, and movement mode being switched either way — so there was nothing
|
|
25
|
+
behind it, and anything automated on it would have fired forever. The lamp's
|
|
26
|
+
movement mode, which is what most people want it for, is a switch and works.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Every switch showed in the Home app under the accessory's own name, so a lamp
|
|
31
|
+
with three of them had three controls all called the same thing. They now
|
|
32
|
+
carry their own names.
|
|
33
|
+
|
|
34
|
+
## [0.4.0] — 2026-09-18
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **The lamp's Auto and movement switches reach HomeKit.** Auto brightness, where
|
|
39
|
+
the lamp trims its own output to keep the room level, and movement mode, where
|
|
40
|
+
it lights on movement and goes out once the room is still, are both switches
|
|
41
|
+
now. They show the true state and follow the buttons on the lamp itself. Turn
|
|
42
|
+
either off per light with `autoBrightnessSwitch` and `movementSwitch`.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- The README lists the three mode switches in one place, with the settings that
|
|
47
|
+
turn each off and how the Movement switch differs from the motion sensor.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- The notes said the lamp trimmed brightness to track daylight from its location
|
|
52
|
+
and the time of day. Daylight mode moves colour temperature; what moves
|
|
53
|
+
brightness is auto brightness and the ramp towards a newly written value.
|
|
54
|
+
|
|
8
55
|
## [0.3.0] — 2026-09-18
|
|
9
56
|
|
|
10
57
|
### Added
|
package/README.md
CHANGED
|
@@ -15,17 +15,43 @@
|
|
|
15
15
|
|
|
16
16
|
## What you get
|
|
17
17
|
|
|
18
|
-
Your lamp appears in the Home app as a **light**, with the controls Apple
|
|
18
|
+
Your lamp appears in the Home app as a **light**, with the controls Apple
|
|
19
|
+
provides for one:
|
|
19
20
|
|
|
20
21
|
- **On and off**
|
|
21
22
|
- **Brightness**
|
|
22
23
|
- **Colour temperature**, across the lamp's full 2700–6500 K range
|
|
23
|
-
- **Motion**, from the lamp's own sensor, as a separate sensor you can automate on
|
|
24
24
|
- **Siri**: *"Hey Siri, turn on the desk light"*, *"Hey Siri, set the desk light to 50%"*
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Alongside it, the three modes that otherwise live only on the lamp's base or in
|
|
27
|
+
the MyDyson app — each a switch you can automate on, and each showing what the
|
|
28
|
+
lamp is really doing rather than what was last asked of it:
|
|
29
|
+
|
|
30
|
+
| switch | what it does |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| **Daylight** | shifts colour temperature through the day, warm in the evening and cool at midday |
|
|
33
|
+
| **Auto Brightness** | trims the level to suit the room as the light around it changes |
|
|
34
|
+
| **Movement** | lights when it sees movement, goes out once the room has been still |
|
|
35
|
+
|
|
36
|
+
Plus the lamp's three preset modes — **Study**, **Relax** and **Precision** — as
|
|
37
|
+
switches that apply a set of values and spring back, the way a scene does. They
|
|
38
|
+
are what the buttons in the MyDyson app do, and the lamp allows only one at a
|
|
39
|
+
time.
|
|
40
|
+
|
|
41
|
+
| preset | where it puts the lamp |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| Study | 4741 K, fairly bright |
|
|
44
|
+
| Relax | 2900 K, dim and warm |
|
|
45
|
+
| Precision | 4600 K, full output |
|
|
46
|
+
|
|
47
|
+
**It follows the lamp, not just the other way round.** Press a button on the
|
|
48
|
+
base, change something in the MyDyson app, or let the lamp end daylight tracking
|
|
49
|
+
by itself, and the Home app keeps up — usually within a second. A lamp that is
|
|
50
|
+
out of range says so, rather than showing you the last thing it knew.
|
|
51
|
+
|
|
52
|
+
**After setup nothing leaves your home.** The lamp has no Wi-Fi at all: the
|
|
53
|
+
plugin talks to it over Bluetooth, and the one cloud request — fetching the
|
|
54
|
+
lamp's key — happens once, during pairing.
|
|
29
55
|
|
|
30
56
|
## Before you start
|
|
31
57
|
|
|
@@ -34,7 +60,7 @@ happens once, during pairing.
|
|
|
34
60
|
| **Lamp** | Dyson Solarcycle Morph or Lightcycle Morph, added to your MyDyson account |
|
|
35
61
|
| **Homebridge** | 2.0.0 or newer, on Linux |
|
|
36
62
|
| **Node.js** | 22.18, 24 or 26 |
|
|
37
|
-
| **Range** | The Homebridge host must be within Bluetooth range of the lamp |
|
|
63
|
+
| **Range** | The Homebridge host must be within Bluetooth range of the lamp, and stay there — these lamps have no Wi-Fi, so there is no cloud fallback |
|
|
38
64
|
|
|
39
65
|
**The lamp must already be in the MyDyson app.** This is not a formality. The
|
|
40
66
|
lamp ignores every command until it is handed a key that only Dyson can issue,
|
|
@@ -42,8 +68,9 @@ against the account the lamp is registered to — there is no way to read it fro
|
|
|
42
68
|
the device. If the lamp is not on your account, pairing returns a 404 and there
|
|
43
69
|
is nothing the plugin can do about it.
|
|
44
70
|
|
|
45
|
-
**Linux only.**
|
|
46
|
-
not
|
|
71
|
+
**Linux only.** macOS and Windows will not work, for Bluetooth reasons that are
|
|
72
|
+
not worth going into here. A Raspberry Pi running Homebridge is the usual home
|
|
73
|
+
for it.
|
|
47
74
|
|
|
48
75
|
## Step 1 — Install the plugin
|
|
49
76
|
|
|
@@ -73,40 +100,37 @@ Open the plugin's **Settings**. The page walks through it:
|
|
|
73
100
|
|
|
74
101
|
Restart Homebridge when the page says so.
|
|
75
102
|
|
|
76
|
-
### What is stored, and where
|
|
77
|
-
|
|
78
|
-
The lamp's key and your account session go into the plugin's own storage
|
|
79
|
-
directory, not into `config.json`. The file you can open in the Homebridge UI —
|
|
80
|
-
and paste into a support thread — holds nothing sensitive.
|
|
81
|
-
|
|
82
|
-
Your password is only needed to exchange a code for a session. **Forget
|
|
83
|
-
password** removes it afterwards; the lamp keeps working, because its key does
|
|
84
|
-
not expire.
|
|
85
|
-
|
|
86
103
|
## Step 4 — Add the lamp to the Home app
|
|
87
104
|
|
|
88
105
|
The child bridge has its own QR code, under **Bridge Settings**. Scan it in the
|
|
89
106
|
Home app the same way you paired Homebridge itself.
|
|
90
107
|
|
|
91
|
-
##
|
|
108
|
+
## Using it
|
|
109
|
+
|
|
110
|
+
**Turning it on, dimming it, changing the colour** — all the usual Home app
|
|
111
|
+
controls, and Siri.
|
|
112
|
+
|
|
113
|
+
**The three switches can be automated like anything else.** A few that people
|
|
114
|
+
tend to want:
|
|
115
|
+
|
|
116
|
+
- Movement on when you leave for work, off when you get home
|
|
117
|
+
- Daylight on in the morning, so the lamp cools towards midday and warms again by evening on its own
|
|
118
|
+
- Auto Brightness off when you sit down to watch a film
|
|
92
119
|
|
|
93
|
-
**Brightness will not always land exactly where you put it.** The lamp
|
|
94
|
-
towards a
|
|
95
|
-
|
|
96
|
-
|
|
120
|
+
**Brightness will not always land exactly where you put it.** The lamp eases
|
|
121
|
+
towards a new level rather than jumping, and with Auto Brightness on it keeps
|
|
122
|
+
adjusting to suit the room. Asking for 100% and seeing 88% is the lamp doing its
|
|
123
|
+
job — turn Auto Brightness off if you would rather it stayed put.
|
|
97
124
|
|
|
98
|
-
**
|
|
99
|
-
|
|
125
|
+
**Setting a colour temperature ends daylight tracking**, and the Daylight switch
|
|
126
|
+
turns itself off when you do. That is the lamp's own behaviour, not something
|
|
127
|
+
the plugin decides. Flip the switch back on to resume.
|
|
100
128
|
|
|
101
|
-
**
|
|
102
|
-
than the last value it knew, and commands fail instead of being silently queued.
|
|
103
|
-
The plugin reconnects on its own and reads the lamp's real state when it does.
|
|
129
|
+
**Changes made at the lamp appear in the Home app**, usually straight away.
|
|
104
130
|
|
|
105
|
-
**
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
work around. Brightness and colour temperature are deliberately not checked,
|
|
109
|
-
because the lamp adjusts them itself and a correction would fight it.
|
|
131
|
+
**Out of range, the lamp shows as *No Response*** rather than the last thing it
|
|
132
|
+
knew, and commands fail rather than being quietly dropped. It comes back on its
|
|
133
|
+
own once the link does.
|
|
110
134
|
|
|
111
135
|
## Settings
|
|
112
136
|
|
|
@@ -118,30 +142,51 @@ Everything except the lights is optional.
|
|
|
118
142
|
| **Lights → Name** | What the lamp is called in the Home app |
|
|
119
143
|
| **Lights → BLE MAC address** | Filled in by the scan |
|
|
120
144
|
| **Lights → Serial number** | Filled in by the scan. Identifies the accessory, so changing it creates a new one |
|
|
121
|
-
| **Lights → Expose
|
|
145
|
+
| **Lights → Expose daylight tracking** | The Daylight switch. On by default |
|
|
146
|
+
| **Lights → Expose auto brightness** | The Auto Brightness switch. On by default |
|
|
147
|
+
| **Lights → Expose movement mode** | The Movement switch. On by default |
|
|
148
|
+
| **Lights → Expose the preset modes** | The Study, Relax and Precision switches. On by default |
|
|
122
149
|
| **Bluetooth adapter** | Only needed if the host has more than one, e.g. `hci1` |
|
|
123
150
|
|
|
124
151
|
## If something goes wrong
|
|
125
152
|
|
|
126
153
|
**The lamp shows as *No Response*.** There is no Bluetooth link at that moment.
|
|
127
|
-
The plugin keeps
|
|
154
|
+
The plugin keeps trying; it usually sorts itself out.
|
|
155
|
+
|
|
156
|
+
**It never connects at all, however long you leave it.** Unplug the lamp for ten
|
|
157
|
+
seconds. Its Bluetooth can get into a state where it looks perfectly healthy but
|
|
158
|
+
refuses every connection, and a power cycle is the only thing that clears it.
|
|
159
|
+
The plugin will pick the lamp up again by itself afterwards.
|
|
160
|
+
|
|
161
|
+
**It connects, drops, reconnects, over and over.** Usually either the lamp is too
|
|
162
|
+
far from the Homebridge host, or something nearby is using the same airwaves —
|
|
163
|
+
Wi-Fi especially. [Reading the signal](#reading-the-signal) below shows which.
|
|
164
|
+
|
|
165
|
+
**It says the lamp is not paired yet.** No key is stored for that serial. Open
|
|
166
|
+
the plugin's settings and authorise your account again, and check the serial
|
|
167
|
+
matches the lamp exactly — that is what the key is filed under.
|
|
168
|
+
|
|
169
|
+
**Pairing returns a 404.** The lamp is not on that Dyson account. It has to be
|
|
170
|
+
added in the MyDyson app first; there is no way round this.
|
|
171
|
+
|
|
172
|
+
**A few failed attempts at startup are normal.** Connecting to this lamp works
|
|
173
|
+
about two times in three whatever anyone does, so the plugin simply tries again.
|
|
174
|
+
Only a cycle that never succeeds is worth looking at.
|
|
175
|
+
|
|
176
|
+
## Under the hood
|
|
128
177
|
|
|
129
|
-
|
|
130
|
-
Bluetooth stack can reach a state where it advertises perfectly well — a scan
|
|
131
|
-
finds it, at a good signal strength — but refuses every connection.
|
|
132
|
-
**Disconnecting the lamp from power for ten seconds clears it**, reliably.
|
|
133
|
-
Nothing on the Homebridge side does. The plugin thins its attempts out to five
|
|
134
|
-
minutes apart, so it will pick the lamp up again by itself once you have.
|
|
178
|
+
Not needed to use the plugin, but useful when something looks odd.
|
|
135
179
|
|
|
136
|
-
|
|
137
|
-
|
|
180
|
+
### Reading the signal
|
|
181
|
+
|
|
182
|
+
Once a minute the log carries a line like:
|
|
138
183
|
|
|
139
184
|
```
|
|
140
185
|
Signal from F0:… : -73 dBm average, -80 to -67
|
|
141
186
|
```
|
|
142
187
|
|
|
143
|
-
The **average** answers one question
|
|
144
|
-
|
|
188
|
+
The **average** answers one question: is the lamp too far away. Around −60 dBm is
|
|
189
|
+
comfortable, −75 workable, −85 will not hold.
|
|
145
190
|
|
|
146
191
|
The **spread** answers a different one. A lamp that is not moving cannot swing by
|
|
147
192
|
20 dB on its own, so a wide spread means something else is using the band. So do
|
|
@@ -154,41 +199,45 @@ which sits directly on a Bluetooth advertising channel. If the host is on
|
|
|
154
199
|
Ethernet anyway, `sudo nmcli radio wifi off` settles it. Zigbee is worth checking
|
|
155
200
|
next: channels 15, 20 and 25 sit in the gaps between Wi-Fi 1, 6 and 11.
|
|
156
201
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
202
|
+
Moving the host closer is worth more than any of it. One measured move took a
|
|
203
|
+
link from −76 dBm with two drops an hour to −50 dBm with none.
|
|
204
|
+
|
|
205
|
+
### Why switching off is double-checked
|
|
206
|
+
|
|
207
|
+
Commands to this lamp are unacknowledged: the plugin sends one and the lamp says
|
|
208
|
+
nothing back, so a command can be lost with nothing to show for it. Power is
|
|
209
|
+
therefore read back shortly after and resent if it did not take — a lamp still
|
|
210
|
+
lit after being switched off is the one failure nobody can work around.
|
|
211
|
+
|
|
212
|
+
Brightness and colour temperature are deliberately *not* checked, because the
|
|
213
|
+
lamp moves them itself and a correction would fight it.
|
|
214
|
+
|
|
215
|
+
### What is stored, and where
|
|
216
|
+
|
|
217
|
+
The lamp's key and your account session go into the plugin's own storage
|
|
218
|
+
directory, not into `config.json`. The file you can open in the Homebridge UI —
|
|
219
|
+
and paste into a support thread — holds nothing sensitive.
|
|
220
|
+
|
|
221
|
+
Your password is only needed to exchange a code for a session. **Forget
|
|
222
|
+
password** removes it afterwards; the lamp keeps working, because its key does
|
|
223
|
+
not expire.
|
|
224
|
+
|
|
225
|
+
### Setting up without the Homebridge UI
|
|
226
|
+
|
|
227
|
+
`dyson-morph-pair` does the same pairing from a terminal. See
|
|
228
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
229
|
+
|
|
230
|
+
### Rarer errors
|
|
160
231
|
|
|
161
232
|
**`PayloadB failed HMAC verification`.** The stored key is wrong or corrupted.
|
|
162
233
|
Pair the lamp again.
|
|
163
234
|
|
|
164
|
-
**404 when fetching the key.** The lamp is not registered to that Dyson account.
|
|
165
|
-
See *Before you start*.
|
|
166
|
-
|
|
167
235
|
**`Not authorized` from D-Bus.** Only on distributions that restrict BlueZ
|
|
168
236
|
access — Debian and Raspberry Pi OS already allow it. If yours does not, create
|
|
169
237
|
`/etc/dbus-1/system.d/node-ble.conf` with a policy for the user Homebridge runs
|
|
170
238
|
as, then restart `dbus`. There is an example in
|
|
171
239
|
[the node-ble documentation](https://github.com/chrvadala/node-ble#provide-permissions).
|
|
172
240
|
|
|
173
|
-
## Good to know
|
|
174
|
-
|
|
175
|
-
**Bluetooth only.** These lamps have no Wi-Fi, so the Homebridge host has to be
|
|
176
|
-
within range. There is no cloud fallback when it is not.
|
|
177
|
-
|
|
178
|
-
**A few failed attempts at startup are normal.** Connecting to this lamp
|
|
179
|
-
succeeds roughly two times in three, whatever you do, so the plugin simply tries
|
|
180
|
-
several times in quick succession. Only a cycle that never succeeds is worth
|
|
181
|
-
looking at.
|
|
182
|
-
|
|
183
|
-
**Daylight tracking appears as its own switch.** It shows what the lamp is
|
|
184
|
-
actually doing, following the button on the lamp's base and the MyDyson app as
|
|
185
|
-
well as HomeKit. Setting a colour temperature ends the tracking — that is the
|
|
186
|
-
lamp's own behaviour, not the plugin's — so the switch turns itself off when you
|
|
187
|
-
do. Turn it off per light with `daylightSwitch` if you would rather not have it.
|
|
188
|
-
|
|
189
|
-
**Setup without the Homebridge UI.** `dyson-morph-pair` does the same pairing
|
|
190
|
-
from a terminal. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
191
|
-
|
|
192
241
|
## For developers
|
|
193
242
|
|
|
194
243
|
The protocol, including where a real lamp disagreed with the published notes, is
|
package/config.schema.json
CHANGED
|
@@ -45,11 +45,23 @@
|
|
|
45
45
|
"required": true,
|
|
46
46
|
"description": "Printed on the lamp base and shown in the MyDyson app."
|
|
47
47
|
},
|
|
48
|
-
"
|
|
49
|
-
"title": "Expose
|
|
48
|
+
"autoBrightnessSwitch": {
|
|
49
|
+
"title": "Expose auto brightness",
|
|
50
50
|
"type": "boolean",
|
|
51
|
-
"default":
|
|
52
|
-
"description": "Adds the lamp's
|
|
51
|
+
"default": true,
|
|
52
|
+
"description": "Adds a switch for the lamp's \"Auto\" setting, which trims brightness to keep the room at a steady level."
|
|
53
|
+
},
|
|
54
|
+
"movementSwitch": {
|
|
55
|
+
"title": "Expose movement mode",
|
|
56
|
+
"type": "boolean",
|
|
57
|
+
"default": true,
|
|
58
|
+
"description": "Adds a switch for the lamp's movement mode, where it lights on movement and goes out once the room has been still."
|
|
59
|
+
},
|
|
60
|
+
"presetSwitches": {
|
|
61
|
+
"title": "Expose the preset modes",
|
|
62
|
+
"type": "boolean",
|
|
63
|
+
"default": true,
|
|
64
|
+
"description": "Adds the lamp's Study, Relax and Precision modes as switches. Only one can be on at a time, which the lamp itself enforces."
|
|
53
65
|
},
|
|
54
66
|
"daylightSwitch": {
|
|
55
67
|
"title": "Expose daylight tracking",
|
|
@@ -105,8 +117,10 @@
|
|
|
105
117
|
"lights[].name",
|
|
106
118
|
"lights[].mac",
|
|
107
119
|
"lights[].serial",
|
|
108
|
-
"lights[].
|
|
109
|
-
"lights[].
|
|
120
|
+
"lights[].daylightSwitch",
|
|
121
|
+
"lights[].autoBrightnessSwitch",
|
|
122
|
+
"lights[].movementSwitch",
|
|
123
|
+
"lights[].presetSwitches"
|
|
110
124
|
]
|
|
111
125
|
}
|
|
112
126
|
]
|
package/dist/accessory.d.ts
CHANGED
|
@@ -14,8 +14,10 @@ export declare class MorphAccessory {
|
|
|
14
14
|
private readonly accessory;
|
|
15
15
|
private readonly config;
|
|
16
16
|
private readonly lightbulb;
|
|
17
|
-
private readonly motion?;
|
|
18
17
|
private readonly daylight?;
|
|
18
|
+
private readonly autoBrightness?;
|
|
19
|
+
private readonly movement?;
|
|
20
|
+
private readonly presets;
|
|
19
21
|
private readonly lamp;
|
|
20
22
|
constructor(platform: MorphPlatform, accessory: PlatformAccessory, config: ResolvedLightConfig);
|
|
21
23
|
start(): Promise<void>;
|
|
@@ -28,6 +30,22 @@ export declare class MorphAccessory {
|
|
|
28
30
|
* than saying nothing. Throwing a communication failure is how an accessory
|
|
29
31
|
* reports itself as unavailable, and the Home app shows "No Response".
|
|
30
32
|
*/
|
|
33
|
+
/**
|
|
34
|
+
* Let a momentary switch spring back.
|
|
35
|
+
*
|
|
36
|
+
* HomeKit has no stateless switch that appears as one, so this is the usual
|
|
37
|
+
* shape: report the press, then push the characteristic back to off shortly
|
|
38
|
+
* after so it does not sit there claiming to be a state.
|
|
39
|
+
*/
|
|
40
|
+
private release;
|
|
41
|
+
/**
|
|
42
|
+
* Name a service so the Home app shows it.
|
|
43
|
+
*
|
|
44
|
+
* `Name` alone is not enough: Home reads `ConfiguredName`, and without it
|
|
45
|
+
* every switch on an accessory shows under the accessory's own name — six
|
|
46
|
+
* controls all called "Desk Light".
|
|
47
|
+
*/
|
|
48
|
+
private name;
|
|
31
49
|
private live;
|
|
32
50
|
/** Push "No Response" to every characteristic at once. */
|
|
33
51
|
private markUnreachable;
|
package/dist/accessory.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { describeError } from './errors.js';
|
|
2
2
|
import { DysonMorphLamp } from './dyson/lamp.js';
|
|
3
|
-
import { kelvinToMired, miredToKelvin, MAX_KELVIN, MIN_KELVIN } from './dyson/protocol.js';
|
|
3
|
+
import { kelvinToMired, miredToKelvin, MAX_KELVIN, MIN_KELVIN, PRESETS } from './dyson/protocol.js';
|
|
4
|
+
/**
|
|
5
|
+
* How long a momentary switch stays on before springing back.
|
|
6
|
+
*
|
|
7
|
+
* Long enough that the Home app has drawn it as pressed, short enough that
|
|
8
|
+
* nobody reads it as a state the lamp is in.
|
|
9
|
+
*/
|
|
10
|
+
const RELEASE_MS = 1_000;
|
|
4
11
|
/**
|
|
5
12
|
* Bridges one lamp's BLE session to its HomeKit services.
|
|
6
13
|
*
|
|
@@ -14,8 +21,10 @@ export class MorphAccessory {
|
|
|
14
21
|
accessory;
|
|
15
22
|
config;
|
|
16
23
|
lightbulb;
|
|
17
|
-
motion;
|
|
18
24
|
daylight;
|
|
25
|
+
autoBrightness;
|
|
26
|
+
movement;
|
|
27
|
+
presets = new Map();
|
|
19
28
|
lamp;
|
|
20
29
|
constructor(platform, accessory, config) {
|
|
21
30
|
this.platform = platform;
|
|
@@ -59,15 +68,19 @@ export class MorphAccessory {
|
|
|
59
68
|
this.lightbulb.updateCharacteristic(Characteristic.Brightness, state.brightness);
|
|
60
69
|
this.lightbulb.updateCharacteristic(Characteristic.ColorTemperature, kelvinToMired(state.kelvin));
|
|
61
70
|
this.daylight?.updateCharacteristic(Characteristic.On, state.daylight);
|
|
71
|
+
this.autoBrightness?.updateCharacteristic(Characteristic.On, state.autoBrightness);
|
|
72
|
+
this.movement?.updateCharacteristic(Characteristic.On, state.movement);
|
|
62
73
|
});
|
|
63
74
|
if (config.daylightSwitch !== false) {
|
|
64
75
|
// A switch rather than a characteristic on the lightbulb: HomeKit renders
|
|
65
76
|
// only the characteristics it knows, so a custom one would be invisible in
|
|
66
77
|
// the Home app and reachable only from third-party clients.
|
|
78
|
+
// By subtype, not by type: this accessory carries more than one Switch,
|
|
79
|
+
// and a lookup by type alone would find whichever came first.
|
|
67
80
|
this.daylight =
|
|
68
|
-
this.accessory.
|
|
81
|
+
this.accessory.getServiceById(Service.Switch, 'daylight') ??
|
|
69
82
|
this.accessory.addService(Service.Switch, `${config.name} Daylight`, 'daylight');
|
|
70
|
-
this.
|
|
83
|
+
this.name(this.daylight, 'Daylight');
|
|
71
84
|
this.daylight
|
|
72
85
|
.getCharacteristic(Characteristic.On)
|
|
73
86
|
.onGet(() => this.live(() => this.lamp.getState().daylight))
|
|
@@ -76,16 +89,51 @@ export class MorphAccessory {
|
|
|
76
89
|
// than leave it showing a state the lamp is not in.
|
|
77
90
|
.onSet((value) => this.handleSet('daylight mode', () => this.lamp.setDaylight(value)));
|
|
78
91
|
}
|
|
79
|
-
if (config.
|
|
80
|
-
this.
|
|
81
|
-
this.accessory.
|
|
82
|
-
this.accessory.addService(Service.
|
|
83
|
-
this.
|
|
84
|
-
|
|
85
|
-
.
|
|
86
|
-
|
|
87
|
-
this.
|
|
88
|
-
|
|
92
|
+
if (config.autoBrightnessSwitch !== false) {
|
|
93
|
+
this.autoBrightness =
|
|
94
|
+
this.accessory.getServiceById(Service.Switch, 'auto') ??
|
|
95
|
+
this.accessory.addService(Service.Switch, `${config.name} Auto Brightness`, 'auto');
|
|
96
|
+
this.name(this.autoBrightness, 'Auto Brightness');
|
|
97
|
+
this.autoBrightness
|
|
98
|
+
.getCharacteristic(Characteristic.On)
|
|
99
|
+
.onGet(() => this.live(() => this.lamp.getState().autoBrightness))
|
|
100
|
+
.onSet((value) => this.handleSet('auto brightness', () => this.lamp.setAutoBrightness(value)));
|
|
101
|
+
}
|
|
102
|
+
if (config.movementSwitch !== false) {
|
|
103
|
+
// Whether the lamp acts on what its sensor sees. Reading the sensor
|
|
104
|
+
// itself is not possible; see docs/PROTOCOL.md.
|
|
105
|
+
this.movement =
|
|
106
|
+
this.accessory.getServiceById(Service.Switch, 'movement') ??
|
|
107
|
+
this.accessory.addService(Service.Switch, `${config.name} Movement`, 'movement');
|
|
108
|
+
this.name(this.movement, 'Movement');
|
|
109
|
+
this.movement
|
|
110
|
+
.getCharacteristic(Characteristic.On)
|
|
111
|
+
.onGet(() => this.live(() => this.lamp.getState().movement))
|
|
112
|
+
.onSet((value) => this.handleSet('movement mode', () => this.lamp.setMovement(value)));
|
|
113
|
+
}
|
|
114
|
+
if (config.presetSwitches !== false) {
|
|
115
|
+
// Momentary rather than stateful. The lamp does hold a preset and reports
|
|
116
|
+
// which, but what these are for is applying a set of values — so pressing
|
|
117
|
+
// one applies it and the switch springs back, the way a scene does.
|
|
118
|
+
for (const preset of Object.keys(PRESETS)) {
|
|
119
|
+
// "Preset" in the name, so a momentary one is not mistaken in a list
|
|
120
|
+
// for the mode switches above it, which do hold a state.
|
|
121
|
+
const label = `${preset[0].toUpperCase() + preset.slice(1)} Preset`;
|
|
122
|
+
const service = this.accessory.getServiceById(Service.Switch, preset) ??
|
|
123
|
+
this.accessory.addService(Service.Switch, `${config.name} ${label}`, preset);
|
|
124
|
+
this.name(service, label);
|
|
125
|
+
service
|
|
126
|
+
.getCharacteristic(Characteristic.On)
|
|
127
|
+
.onGet(() => false)
|
|
128
|
+
.onSet(async (value) => {
|
|
129
|
+
if (!value) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
await this.handleSet(`${label} preset`, () => this.lamp.setPreset(preset));
|
|
133
|
+
this.release(service);
|
|
134
|
+
});
|
|
135
|
+
this.presets.set(preset, service);
|
|
136
|
+
}
|
|
89
137
|
}
|
|
90
138
|
this.lamp.on('state', (state) => {
|
|
91
139
|
this.lightbulb.updateCharacteristic(Characteristic.On, state.on);
|
|
@@ -94,6 +142,8 @@ export class MorphAccessory {
|
|
|
94
142
|
// Follows the lamp leaving daylight mode on its own, which it does as soon
|
|
95
143
|
// as colour temperature is set by hand.
|
|
96
144
|
this.daylight?.updateCharacteristic(Characteristic.On, state.daylight);
|
|
145
|
+
this.autoBrightness?.updateCharacteristic(Characteristic.On, state.autoBrightness);
|
|
146
|
+
this.movement?.updateCharacteristic(Characteristic.On, state.movement);
|
|
97
147
|
});
|
|
98
148
|
}
|
|
99
149
|
async start() {
|
|
@@ -115,6 +165,31 @@ export class MorphAccessory {
|
|
|
115
165
|
* than saying nothing. Throwing a communication failure is how an accessory
|
|
116
166
|
* reports itself as unavailable, and the Home app shows "No Response".
|
|
117
167
|
*/
|
|
168
|
+
/**
|
|
169
|
+
* Let a momentary switch spring back.
|
|
170
|
+
*
|
|
171
|
+
* HomeKit has no stateless switch that appears as one, so this is the usual
|
|
172
|
+
* shape: report the press, then push the characteristic back to off shortly
|
|
173
|
+
* after so it does not sit there claiming to be a state.
|
|
174
|
+
*/
|
|
175
|
+
release(service) {
|
|
176
|
+
setTimeout(() => {
|
|
177
|
+
service.updateCharacteristic(this.platform.api.hap.Characteristic.On, false);
|
|
178
|
+
}, RELEASE_MS).unref();
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Name a service so the Home app shows it.
|
|
182
|
+
*
|
|
183
|
+
* `Name` alone is not enough: Home reads `ConfiguredName`, and without it
|
|
184
|
+
* every switch on an accessory shows under the accessory's own name — six
|
|
185
|
+
* controls all called "Desk Light".
|
|
186
|
+
*/
|
|
187
|
+
name(service, label) {
|
|
188
|
+
const { Characteristic } = this.platform.api.hap;
|
|
189
|
+
const full = `${this.config.name} ${label}`;
|
|
190
|
+
service.setCharacteristic(Characteristic.Name, full);
|
|
191
|
+
service.setCharacteristic(Characteristic.ConfiguredName, full);
|
|
192
|
+
}
|
|
118
193
|
live(read) {
|
|
119
194
|
if (!this.lamp.isConnected()) {
|
|
120
195
|
throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
|
|
@@ -128,8 +203,9 @@ export class MorphAccessory {
|
|
|
128
203
|
for (const characteristic of [Characteristic.On, Characteristic.Brightness, Characteristic.ColorTemperature]) {
|
|
129
204
|
this.lightbulb.updateCharacteristic(characteristic, error);
|
|
130
205
|
}
|
|
131
|
-
this.motion?.updateCharacteristic(Characteristic.MotionDetected, error);
|
|
132
206
|
this.daylight?.updateCharacteristic(Characteristic.On, error);
|
|
207
|
+
this.autoBrightness?.updateCharacteristic(Characteristic.On, error);
|
|
208
|
+
this.movement?.updateCharacteristic(Characteristic.On, error);
|
|
133
209
|
}
|
|
134
210
|
/**
|
|
135
211
|
* Apply a write, reporting failure to HomeKit rather than swallowing it.
|
package/dist/accessory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessory.js","sourceRoot":"","sources":["../src/accessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"accessory.js","sourceRoot":"","sources":["../src/accessory.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -15,14 +15,23 @@ export interface LightConfig {
|
|
|
15
15
|
ltk?: string;
|
|
16
16
|
/** Dyson account GUID the LTK was issued to. Stored alongside the key. */
|
|
17
17
|
accountId?: string;
|
|
18
|
-
/** Expose the built-in motion sensor as a separate HomeKit service. */
|
|
19
|
-
motionSensor?: boolean;
|
|
20
18
|
/**
|
|
21
19
|
* Expose daylight tracking as a switch. On by default: it is the lamp's
|
|
22
20
|
* defining feature and there is no other way to turn it back on from HomeKit
|
|
23
21
|
* once setting a colour temperature has ended it.
|
|
24
22
|
*/
|
|
25
23
|
daylightSwitch?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Expose the lamp's "Auto" brightness as a switch. On by default: it is a
|
|
26
|
+
* mode the lamp has and HomeKit would otherwise neither see nor reach.
|
|
27
|
+
*/
|
|
28
|
+
autoBrightnessSwitch?: boolean;
|
|
29
|
+
/** Expose movement-triggered lighting as a switch. On by default. */
|
|
30
|
+
movementSwitch?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Expose the lamp's preset modes as switches. On by default.
|
|
33
|
+
*/
|
|
34
|
+
presetSwitches?: boolean;
|
|
26
35
|
}
|
|
27
36
|
/** A lamp whose credentials are known, from the config or the credential store. */
|
|
28
37
|
export type ResolvedLightConfig = LightConfig & {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA8DA;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA2B,EAAE,KAAa;IAC5E,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,UAAU,KAAK,GAAG,CAAC;IAEjC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,mBAAmB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,sCAAsC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1E,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,8CAA8C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,qBAAqB,CAAC,CAAC;IAC/C,CAAC;IACD,yEAAyE;IACzE,8EAA8E;IAC9E,4CAA4C;IAC5C,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACjG,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,wCAAwC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QACjF,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,yCAAyC,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE,CAAC;QAClE,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,8FAA8F,CAAC,CAAC;IACxH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|