homebridge-dyson-solarcycle-morph 0.4.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 CHANGED
@@ -5,6 +5,32 @@ 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
+
8
34
  ## [0.4.0] — 2026-09-18
9
35
 
10
36
  ### 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 provides for one:
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
- After setup nothing leaves your home. The lamp has no Wi-Fi at all: the plugin
27
- talks to it over Bluetooth, and the one cloud request — fetching the lamp's key —
28
- happens once, during pairing.
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.** The plugin talks to BlueZ over D-Bus, so macOS and Windows will
46
- not work. A Raspberry Pi running Homebridge is the usual home for it.
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
- ## Everyday use
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 ramps
94
- towards a value rather than jumping to it, and with auto brightness on it keeps
95
- trimming the level to suit the room. Asking for 100% and seeing 88% is the lamp
96
- working as designed. The Auto Brightness switch turns the trimming off.
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
- **Changes made at the lamp show up in the Home app**, usually at once and at
99
- worst within a minute.
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
- **When the lamp is out of reach**, the Home app shows it as *No Response* rather
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
- **Switching off is checked.** Control commands are unacknowledged, so one can be
106
- dropped in transit. Power is read back shortly after and resent if it did not
107
- take — a lamp still lit after being switched off is the one failure nobody can
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 the motion sensor** | Adds the lamp's motion detector as a HomeKit sensor |
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 reconnecting; if it does not recover, read on.
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.
128
175
 
129
- **The log repeats `le-connection-abort-by-local` and never connects.** The lamp's
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.
176
+ ## Under the hood
135
177
 
136
- **It connects, drops, reconnects, over and over.** Look at the signal line in the
137
- log:
178
+ Not needed to use the plugin, but useful when something looks odd.
179
+
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 — is the lamp too far away. Around −60 dBm
144
- is comfortable, −75 workable, −85 will not hold.
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,51 +199,44 @@ 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
- **`… is not paired yet`.** No key is stored for that serial. Open the plugin's
158
- settings and authorise your account. Check the serial matches the lamp exactly —
159
- it is what the key is filed under.
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.
160
204
 
161
- **`PayloadB failed HMAC verification`.** The stored key is wrong or corrupted.
162
- Pair the lamp again.
205
+ ### Why switching off is double-checked
163
206
 
164
- **404 when fetching the key.** The lamp is not registered to that Dyson account.
165
- See *Before you start*.
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.
166
211
 
167
- **`Not authorized` from D-Bus.** Only on distributions that restrict BlueZ
168
- access — Debian and Raspberry Pi OS already allow it. If yours does not, create
169
- `/etc/dbus-1/system.d/node-ble.conf` with a policy for the user Homebridge runs
170
- as, then restart `dbus`. There is an example in
171
- [the node-ble documentation](https://github.com/chrvadala/node-ble#provide-permissions).
212
+ Brightness and colour temperature are deliberately *not* checked, because the
213
+ lamp moves them itself and a correction would fight it.
172
214
 
173
- ## Good to know
215
+ ### What is stored, and where
174
216
 
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.
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.
177
220
 
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.
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.
182
224
 
183
- **The lamp's three modes appear as switches**, alongside the light itself:
225
+ ### Setting up without the Homebridge UI
184
226
 
185
- | switch | what it does | turn it off with |
186
- | --- | --- | --- |
187
- | Daylight | shifts colour temperature through the day | `daylightSwitch` |
188
- | Auto Brightness | trims the level to suit the room | `autoBrightnessSwitch` |
189
- | Movement | lights on movement, goes out once the room is still | `movementSwitch` |
227
+ `dyson-morph-pair` does the same pairing from a terminal. See
228
+ [CONTRIBUTING.md](CONTRIBUTING.md).
190
229
 
191
- All three show what the lamp is actually doing, and follow the buttons on its
192
- base and the MyDyson app as well as HomeKit. Daylight has one behaviour worth
193
- knowing: setting a colour temperature ends the tracking, so its switch turns
194
- itself off when you do. That is the lamp's own doing, not the plugin's.
230
+ ### Rarer errors
195
231
 
196
- The lamp also has a motion sensor, which is a different thing from the Movement
197
- switch: the sensor reports what the lamp sees, the switch decides whether the
198
- lamp acts on it. It is off by default — `motionSensor` adds it.
232
+ **`PayloadB failed HMAC verification`.** The stored key is wrong or corrupted.
233
+ Pair the lamp again.
199
234
 
200
- **Setup without the Homebridge UI.** `dyson-morph-pair` does the same pairing
201
- from a terminal. See [CONTRIBUTING.md](CONTRIBUTING.md).
235
+ **`Not authorized` from D-Bus.** Only on distributions that restrict BlueZ
236
+ access — Debian and Raspberry Pi OS already allow it. If yours does not, create
237
+ `/etc/dbus-1/system.d/node-ble.conf` with a policy for the user Homebridge runs
238
+ as, then restart `dbus`. There is an example in
239
+ [the node-ble documentation](https://github.com/chrvadala/node-ble#provide-permissions).
202
240
 
203
241
  ## For developers
204
242
 
@@ -45,12 +45,6 @@
45
45
  "required": true,
46
46
  "description": "Printed on the lamp base and shown in the MyDyson app."
47
47
  },
48
- "motionSensor": {
49
- "title": "Expose the motion sensor",
50
- "type": "boolean",
51
- "default": false,
52
- "description": "Adds the lamp's built-in motion detector as a HomeKit motion sensor."
53
- },
54
48
  "autoBrightnessSwitch": {
55
49
  "title": "Expose auto brightness",
56
50
  "type": "boolean",
@@ -61,7 +55,13 @@
61
55
  "title": "Expose movement mode",
62
56
  "type": "boolean",
63
57
  "default": true,
64
- "description": "Adds a switch for the lamp's movement mode, where it lights on movement and goes out once the room has been still. Not the same as the motion sensor above, which only reports what the lamp sees."
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."
65
65
  },
66
66
  "daylightSwitch": {
67
67
  "title": "Expose daylight tracking",
@@ -117,10 +117,10 @@
117
117
  "lights[].name",
118
118
  "lights[].mac",
119
119
  "lights[].serial",
120
- "lights[].motionSensor",
121
120
  "lights[].daylightSwitch",
122
121
  "lights[].autoBrightnessSwitch",
123
- "lights[].movementSwitch"
122
+ "lights[].movementSwitch",
123
+ "lights[].presetSwitches"
124
124
  ]
125
125
  }
126
126
  ]
@@ -14,10 +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?;
19
18
  private readonly autoBrightness?;
20
19
  private readonly movement?;
20
+ private readonly presets;
21
21
  private readonly lamp;
22
22
  constructor(platform: MorphPlatform, accessory: PlatformAccessory, config: ResolvedLightConfig);
23
23
  start(): Promise<void>;
@@ -30,6 +30,22 @@ export declare class MorphAccessory {
30
30
  * than saying nothing. Throwing a communication failure is how an accessory
31
31
  * reports itself as unavailable, and the Home app shows "No Response".
32
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;
33
49
  private live;
34
50
  /** Push "No Response" to every characteristic at once. */
35
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,10 +21,10 @@ export class MorphAccessory {
14
21
  accessory;
15
22
  config;
16
23
  lightbulb;
17
- motion;
18
24
  daylight;
19
25
  autoBrightness;
20
26
  movement;
27
+ presets = new Map();
21
28
  lamp;
22
29
  constructor(platform, accessory, config) {
23
30
  this.platform = platform;
@@ -73,7 +80,7 @@ export class MorphAccessory {
73
80
  this.daylight =
74
81
  this.accessory.getServiceById(Service.Switch, 'daylight') ??
75
82
  this.accessory.addService(Service.Switch, `${config.name} Daylight`, 'daylight');
76
- this.daylight.setCharacteristic(Characteristic.Name, `${config.name} Daylight`);
83
+ this.name(this.daylight, 'Daylight');
77
84
  this.daylight
78
85
  .getCharacteristic(Characteristic.On)
79
86
  .onGet(() => this.live(() => this.lamp.getState().daylight))
@@ -86,34 +93,47 @@ export class MorphAccessory {
86
93
  this.autoBrightness =
87
94
  this.accessory.getServiceById(Service.Switch, 'auto') ??
88
95
  this.accessory.addService(Service.Switch, `${config.name} Auto Brightness`, 'auto');
89
- this.autoBrightness.setCharacteristic(Characteristic.Name, `${config.name} Auto Brightness`);
96
+ this.name(this.autoBrightness, 'Auto Brightness');
90
97
  this.autoBrightness
91
98
  .getCharacteristic(Characteristic.On)
92
99
  .onGet(() => this.live(() => this.lamp.getState().autoBrightness))
93
100
  .onSet((value) => this.handleSet('auto brightness', () => this.lamp.setAutoBrightness(value)));
94
101
  }
95
102
  if (config.movementSwitch !== false) {
96
- // Not the motion sensor below: that reports what the lamp sees, this
97
- // decides whether the lamp acts on it.
103
+ // Whether the lamp acts on what its sensor sees. Reading the sensor
104
+ // itself is not possible; see docs/PROTOCOL.md.
98
105
  this.movement =
99
106
  this.accessory.getServiceById(Service.Switch, 'movement') ??
100
107
  this.accessory.addService(Service.Switch, `${config.name} Movement`, 'movement');
101
- this.movement.setCharacteristic(Characteristic.Name, `${config.name} Movement`);
108
+ this.name(this.movement, 'Movement');
102
109
  this.movement
103
110
  .getCharacteristic(Characteristic.On)
104
111
  .onGet(() => this.live(() => this.lamp.getState().movement))
105
112
  .onSet((value) => this.handleSet('movement mode', () => this.lamp.setMovement(value)));
106
113
  }
107
- if (config.motionSensor) {
108
- this.motion =
109
- this.accessory.getService(Service.MotionSensor) ??
110
- this.accessory.addService(Service.MotionSensor, `${config.name} Motion`);
111
- this.motion
112
- .getCharacteristic(Characteristic.MotionDetected)
113
- .onGet(() => this.live(() => this.motion?.getCharacteristic(Characteristic.MotionDetected).value ?? false));
114
- this.lamp.on('motion', (detected) => {
115
- this.motion?.updateCharacteristic(Characteristic.MotionDetected, detected);
116
- });
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
+ }
117
137
  }
118
138
  this.lamp.on('state', (state) => {
119
139
  this.lightbulb.updateCharacteristic(Characteristic.On, state.on);
@@ -145,6 +165,31 @@ export class MorphAccessory {
145
165
  * than saying nothing. Throwing a communication failure is how an accessory
146
166
  * reports itself as unavailable, and the Home app shows "No Response".
147
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
+ }
148
193
  live(read) {
149
194
  if (!this.lamp.isConnected()) {
150
195
  throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */);
@@ -158,7 +203,6 @@ export class MorphAccessory {
158
203
  for (const characteristic of [Characteristic.On, Characteristic.Brightness, Characteristic.ColorTemperature]) {
159
204
  this.lightbulb.updateCharacteristic(characteristic, error);
160
205
  }
161
- this.motion?.updateCharacteristic(Characteristic.MotionDetected, error);
162
206
  this.daylight?.updateCharacteristic(Characteristic.On, error);
163
207
  this.autoBrightness?.updateCharacteristic(Characteristic.On, error);
164
208
  this.movement?.updateCharacteristic(Characteristic.On, error);
@@ -1 +1 @@
1
- {"version":3,"file":"accessory.js","sourceRoot":"","sources":["../src/accessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accessory.js","sourceRoot":"","sources":["../src/accessory.ts"],"names":[],"mappings":"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"}
package/dist/config.d.ts CHANGED
@@ -15,8 +15,6 @@ 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
@@ -30,6 +28,10 @@ export interface LightConfig {
30
28
  autoBrightnessSwitch?: boolean;
31
29
  /** Expose movement-triggered lighting as a switch. On by default. */
32
30
  movementSwitch?: boolean;
31
+ /**
32
+ * Expose the lamp's preset modes as switches. On by default.
33
+ */
34
+ presetSwitches?: boolean;
33
35
  }
34
36
  /** A lamp whose credentials are known, from the config or the credential store. */
35
37
  export type ResolvedLightConfig = LightConfig & {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA4DA;;;;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"}
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"}
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from 'node:events';
2
+ import type { Preset } from './protocol.js';
2
3
  export interface LampState {
3
4
  on: boolean;
4
5
  /** HomeKit-style brightness, 0-100 %. */
@@ -22,6 +23,13 @@ export interface LampState {
22
23
  autoBrightness: boolean;
23
24
  /** Whether the lamp lights on movement and goes out when the room is still. */
24
25
  movement: boolean;
26
+ /**
27
+ * Which preset the lamp is in, or `none`.
28
+ *
29
+ * The lamp keeps these mutually exclusive itself and reports both sides of a
30
+ * change, so this follows rather than decides.
31
+ */
32
+ preset: Preset | 'none';
25
33
  }
26
34
  export interface LampOptions {
27
35
  /** BLE MAC, e.g. `AA:BB:CC:DD:EE:FF`. */
@@ -44,7 +52,6 @@ export declare interface DysonMorphLamp {
44
52
  on(event: 'connected', listener: () => void): this;
45
53
  on(event: 'disconnected', listener: () => void): this;
46
54
  on(event: 'state', listener: (state: LampState) => void): this;
47
- on(event: 'motion', listener: (detected: boolean) => void): this;
48
55
  }
49
56
  export declare class DysonMorphLamp extends EventEmitter {
50
57
  private readonly mac;
@@ -122,6 +129,13 @@ export declare class DysonMorphLamp extends EventEmitter {
122
129
  * within a moment if the write did not land.
123
130
  */
124
131
  private setFlag;
132
+ /**
133
+ * Put the lamp into a preset, or take it out of the one it is in.
134
+ *
135
+ * Only the chosen preset is written: the lamp turns the previous one off by
136
+ * itself and says so, and writing both would race that.
137
+ */
138
+ setPreset(preset: Preset | 'none'): Promise<void>;
125
139
  setDaylight(on: boolean): Promise<void>;
126
140
  setColorTemperature(kelvin: number): Promise<void>;
127
141
  private writeUint16;