homebridge-lanternic 0.1.3 → 0.2.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/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Homebridge LanternIC
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/homebridge-lanternic.svg)](https://www.npmjs.com/package/homebridge-lanternic)
4
- [![npm downloads](https://img.shields.io/npm/dm/homebridge-lanternic.svg)](https://www.npmjs.com/package/homebridge-lanternic)
5
4
  [![CI](https://github.com/Gibsonmb71/homebridge-lanternic/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Gibsonmb71/homebridge-lanternic/actions/workflows/ci.yml)
6
5
  [![Node.js](https://img.shields.io/node/v/homebridge-lanternic.svg)](https://www.npmjs.com/package/homebridge-lanternic)
7
6
  [![Homebridge](https://img.shields.io/badge/homebridge-1.8%20%7C%202.x-blue.svg)](https://homebridge.io/)
@@ -16,6 +15,7 @@ These unbranded Magic Lantern BLE strips ship with multiple firmware variants so
16
15
  - HomeKit Lightbulb service
17
16
  - On/off with RGB-black fallback plus optional native Magic Lantern power frames
18
17
  - Brightness via RGB scaling by default, with optional native Magic Lantern brightness frames
18
+ - Optional HomeKit switches for Magic Lantern effects
19
19
  - HomeKit on/off, brightness, and color control confirmed on a `MELK-OC21WCT31` strip
20
20
  - Homebridge UI config schema
21
21
  - BLE discovery with log snippets and optional auto-add
@@ -23,7 +23,7 @@ These unbranded Magic Lantern BLE strips ship with multiple firmware variants so
23
23
  - Command-builder tests for the known Magic Lantern frames
24
24
  - Package smoke tests against Homebridge 1 and 2 on Node.js 22 and 24 in CI
25
25
 
26
- Effects and segment control are not supported as there is no good way to expose them in Apple Home.
26
+ Segment-level IC control is not supported yet.
27
27
 
28
28
  ## Install
29
29
 
@@ -40,6 +40,14 @@ npm install
40
40
  npm run build
41
41
  sudo hb-service link
42
42
  ```
43
+ > [!CAUTION]
44
+ >
45
+ > Only the following platforms are supported:
46
+ >
47
+ > - **macOS**
48
+ > - If using macOS, you'll need to give Node.js permission to use Bluetooth in **System Settings → Privacy & Security → Bluetooth**.
49
+ > - **Linux**
50
+ > - 64-bit, not tested on 32-bit systems
43
51
 
44
52
  ## Homebridge UI Setup
45
53
 
@@ -48,9 +56,11 @@ LanternIC supports Homebridge UI through `config.schema.json`.
48
56
  1. Install the plugin.
49
57
  2. Open Homebridge UI.
50
58
  3. Go to Plugins, select LanternIC, then Settings.
51
- 4. Enable `Log Discovered Candidate Devices`.
52
- 5. Restart Homebridge and open the logs.
53
- 6. Copy the `LanternIC device config: {...}` line for your strip into the `Light Strips` list.
59
+ 4. Choose `Auto Mode` for first setup, or `Manual Mode` if you already know your strip's Bluetooth address.
60
+ 5. Save and restart Homebridge.
61
+ 6. In Auto Mode, LanternIC scans and auto-adds matching first-run candidates. In Manual Mode, paste the address into the `Light Strips` list.
62
+
63
+ After at least one light strip is configured, the setup mode picker is hidden and the advanced Discovery/Bluetooth settings become available.
54
64
 
55
65
  You can also use the local scanner:
56
66
 
@@ -68,7 +78,7 @@ LANTERNIC_SCAN_ALL=1 lanternic-scan
68
78
 
69
79
  When working from this repository instead of a global install, use `npm run scan` in place of `lanternic-scan`.
70
80
 
71
- `Auto-Add Discovered Devices` can create HomeKit accessories automatically for matching BLE candidates. Leave it off until the discovery filters only match your strips, because nearby BLE devices may advertise similar services.
81
+ First-run `Auto Mode` can create HomeKit accessories automatically for matching BLE candidates. After setup, use the advanced `Auto-Add Discovered Devices` setting only when your filters are tight, because nearby BLE devices may advertise similar services.
72
82
 
73
83
  ## CLI Tools
74
84
 
@@ -79,6 +89,7 @@ lanternic-scan
79
89
  lanternic-explore <address>
80
90
  lanternic-send <address> rgb ff0000
81
91
  lanternic-send <address> brightness 50
92
+ lanternic-send <address> effect 207 39
82
93
  lanternic-send-sequence <address> 7e070503ff000010ef 7e07050300ff0010ef
83
94
  lanternic-calibrate <address>
84
95
  ```
@@ -138,6 +149,7 @@ Start with discovery enabled and no devices:
138
149
  {
139
150
  "platform": "LanternIC",
140
151
  "name": "LanternIC",
152
+ "setupMode": "auto",
141
153
  "devices": [],
142
154
  "discovery": {
143
155
  "enabled": true,
@@ -195,6 +207,31 @@ Restart Homebridge and look for candidate device addresses in the logs. Then add
195
207
  6. If colors are swapped, change `colorOrder`.
196
208
  7. If Off leaves the strip visibly on, keep `powerMode` as `both` or try `rgbBlack`.
197
209
  8. If brightness does not change, keep `brightnessMode` as `rgb`; if it double-dims, try `native`.
210
+ 9. If effects are enabled, test one effect switch at a time. Turning an effect switch off should restore the saved HomeKit color.
211
+
212
+ ## HomeKit Effects
213
+
214
+ Magic Lantern animation effects are exposed as optional `Switch` services on the same HomeKit accessory as the light. Apple Home does not provide a native effect picker for a `Lightbulb`, and custom effect characteristics usually do not appear in the Home app.
215
+
216
+ Effects are disabled by default. Enable them per strip:
217
+
218
+ ```json
219
+ {
220
+ "effects": {
221
+ "enabled": true,
222
+ "defaultSpeed": 39,
223
+ "restoreColorOnDisable": true
224
+ }
225
+ }
226
+ ```
227
+
228
+ When `effects.enabled` is true and no custom `items` list is provided, LanternIC creates these starter switches:
229
+
230
+ - AutoPlay: effect code `0`
231
+ - Magic Back: effect code `1`
232
+ - Yellow Marquee: effect code `207` (`0xcf`)
233
+
234
+ Only one effect switch is kept active at a time. Turning on an effect sends the speed frame followed by the effect frame. Turning off the active effect restores the saved HomeKit color and brightness when `restoreColorOnDisable` is true.
198
235
 
199
236
  ## Protocol Notes
200
237
 
@@ -15,12 +15,38 @@
15
15
  "type": "string",
16
16
  "default": "LanternIC"
17
17
  },
18
+ "setupMode": {
19
+ "title": "Setup Mode",
20
+ "type": "string",
21
+ "default": "auto",
22
+ "description": "Choose Auto Mode for first setup unless you already know your strip's Bluetooth address.",
23
+ "oneOf": [
24
+ {
25
+ "title": "Auto Mode",
26
+ "enum": [
27
+ "auto"
28
+ ]
29
+ },
30
+ {
31
+ "title": "Manual Mode",
32
+ "enum": [
33
+ "manual"
34
+ ]
35
+ }
36
+ ],
37
+ "condition": {
38
+ "functionBody": "return !model.devices || model.devices.length === 0;"
39
+ }
40
+ },
18
41
  "devices": {
19
42
  "title": "Light Strips",
20
43
  "type": "array",
21
44
  "buttonText": "Add Light Strip",
22
45
  "default": [],
23
46
  "description": "Use discovery logs or lanternic-scan to find Magic Lantern BLE device ids. On Linux this is usually the MAC address; on macOS it may be a long CoreBluetooth id.",
47
+ "condition": {
48
+ "functionBody": "return (model.devices && model.devices.length > 0) || model.setupMode === 'manual';"
49
+ },
24
50
  "items": {
25
51
  "type": "object",
26
52
  "required": [
@@ -144,6 +170,89 @@
144
170
  ]
145
171
  }
146
172
  ]
173
+ },
174
+ "effects": {
175
+ "title": "Effects",
176
+ "type": "object",
177
+ "additionalProperties": false,
178
+ "description": "Optional HomeKit switch services for Magic Lantern animation effects.",
179
+ "properties": {
180
+ "enabled": {
181
+ "title": "Expose Effect Switches",
182
+ "type": "boolean",
183
+ "default": false,
184
+ "description": "Add HomeKit switches for Magic Lantern effects on this strip. Turning an effect switch off restores the normal light color by default."
185
+ },
186
+ "defaultSpeed": {
187
+ "title": "Default Effect Speed",
188
+ "type": "integer",
189
+ "default": 39,
190
+ "minimum": 0,
191
+ "maximum": 100,
192
+ "description": "Speed frame value sent before effect frames. 0 is slowest, 100 is fastest."
193
+ },
194
+ "restoreColorOnDisable": {
195
+ "title": "Restore Color When Effect Turns Off",
196
+ "type": "boolean",
197
+ "default": true,
198
+ "description": "When an active effect switch is turned off, send the saved HomeKit color and brightness back to the strip."
199
+ },
200
+ "items": {
201
+ "title": "Effect Switches",
202
+ "type": "array",
203
+ "buttonText": "Add Effect",
204
+ "default": [
205
+ {
206
+ "name": "AutoPlay",
207
+ "code": 0
208
+ },
209
+ {
210
+ "name": "Magic Back",
211
+ "code": 1
212
+ },
213
+ {
214
+ "name": "Yellow Marquee",
215
+ "code": 207
216
+ }
217
+ ],
218
+ "description": "Effect codes are the xx byte in 7e0503xx06ffff00ef. Codes may be decimal, so Yellow Marquee is 207 for hex CF.",
219
+ "items": {
220
+ "type": "object",
221
+ "required": [
222
+ "name",
223
+ "code"
224
+ ],
225
+ "additionalProperties": false,
226
+ "properties": {
227
+ "name": {
228
+ "title": "Name",
229
+ "type": "string",
230
+ "default": "Effect"
231
+ },
232
+ "code": {
233
+ "title": "Effect Code",
234
+ "type": "integer",
235
+ "default": 0,
236
+ "minimum": 0,
237
+ "maximum": 255,
238
+ "description": "Decimal value for the effect byte. For example hex CF is decimal 207."
239
+ },
240
+ "id": {
241
+ "title": "Stable Id",
242
+ "type": "string",
243
+ "description": "Optional stable HomeKit service id. Leave blank unless you are renaming or reordering effects and want to preserve existing HomeKit tiles."
244
+ },
245
+ "speed": {
246
+ "title": "Effect Speed Override",
247
+ "type": "integer",
248
+ "minimum": 0,
249
+ "maximum": 100,
250
+ "description": "Optional speed override for this effect. Leave blank to use Default Effect Speed."
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
147
256
  }
148
257
  }
149
258
  }
@@ -152,6 +261,9 @@
152
261
  "title": "Discovery",
153
262
  "type": "object",
154
263
  "additionalProperties": false,
264
+ "condition": {
265
+ "functionBody": "return model.devices && model.devices.length > 0;"
266
+ },
155
267
  "properties": {
156
268
  "enabled": {
157
269
  "title": "Log Discovered Candidate Devices",
@@ -211,6 +323,9 @@
211
323
  "title": "Bluetooth",
212
324
  "type": "object",
213
325
  "additionalProperties": false,
326
+ "condition": {
327
+ "functionBody": "return model.devices && model.devices.length > 0;"
328
+ },
214
329
  "properties": {
215
330
  "binding": {
216
331
  "title": "Noble Binding",
@@ -14,3 +14,4 @@ export declare const buildPowerOnPrefixCommands: (powerMode?: PowerMode, brightn
14
14
  export declare const buildPowerOffCommands: (powerMode?: PowerMode) => Buffer[];
15
15
  export declare const buildEffectSpeedCommand: (speed: number) => Buffer;
16
16
  export declare const buildBasicEffectCommand: (effectCode: number) => Buffer;
17
+ export declare const buildBasicEffectCommands: (effectCode: number, speed: number) => Buffer[];
@@ -46,4 +46,10 @@ export const buildEffectSpeedCommand = (speed) => {
46
46
  export const buildBasicEffectCommand = (effectCode) => {
47
47
  return frame(0x7e, 0x05, 0x03, effectCode, 0x06, 0xff, 0xff, 0x00, 0xef);
48
48
  };
49
+ export const buildBasicEffectCommands = (effectCode, speed) => {
50
+ return [
51
+ buildEffectSpeedCommand(speed),
52
+ buildBasicEffectCommand(effectCode),
53
+ ];
54
+ };
49
55
  //# sourceMappingURL=magicLanternCommands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"magicLanternCommands.js","sourceRoot":"","sources":["../../src/ble/magicLanternCommands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"magicLanternCommands.js","sourceRoot":"","sources":["../../src/ble/magicLanternCommands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { LanternIcEffectConfig, LanternIcEffectsConfig } from './types.js';
2
+ export declare const EFFECT_SERVICE_SUBTYPE_PREFIX = "lanternic-effect-";
3
+ export interface ResolvedLanternIcEffect {
4
+ name: string;
5
+ code: number;
6
+ speed: number;
7
+ subtype: string;
8
+ }
9
+ export interface ResolvedLanternIcEffectsConfig {
10
+ effects: ResolvedLanternIcEffect[];
11
+ restoreColorOnDisable: boolean;
12
+ }
13
+ export declare const DEFAULT_EFFECT_SPEED = 39;
14
+ export declare const DEFAULT_EFFECTS: LanternIcEffectConfig[];
15
+ export declare const resolveEffectsConfig: (config: LanternIcEffectsConfig | undefined) => ResolvedLanternIcEffectsConfig;
@@ -0,0 +1,50 @@
1
+ import { clampByte, clampPercent } from './color.js';
2
+ export const EFFECT_SERVICE_SUBTYPE_PREFIX = 'lanternic-effect-';
3
+ export const DEFAULT_EFFECT_SPEED = 39;
4
+ export const DEFAULT_EFFECTS = [
5
+ { name: 'AutoPlay', code: 0 },
6
+ { name: 'Magic Back', code: 1 },
7
+ { name: 'Yellow Marquee', code: 0xcf },
8
+ ];
9
+ const slugify = (value) => {
10
+ return value
11
+ .trim()
12
+ .toLowerCase()
13
+ .replace(/[^a-z0-9_-]+/g, '-')
14
+ .replace(/^-+|-+$/g, '')
15
+ .slice(0, 48);
16
+ };
17
+ export const resolveEffectsConfig = (config) => {
18
+ if (config?.enabled !== true) {
19
+ return {
20
+ effects: [],
21
+ restoreColorOnDisable: config?.restoreColorOnDisable ?? true,
22
+ };
23
+ }
24
+ const defaultSpeed = clampPercent(config.defaultSpeed ?? DEFAULT_EFFECT_SPEED);
25
+ const usedSubtypes = new Set();
26
+ const effects = (config.items?.length ? config.items : DEFAULT_EFFECTS)
27
+ .filter(effect => typeof effect.name === 'string' && effect.name.trim().length > 0)
28
+ .map((effect) => {
29
+ const code = clampByte(effect.code);
30
+ const baseId = slugify(effect.id ?? `${effect.name}-${code}`) || `effect-${code}`;
31
+ let subtype = `${EFFECT_SERVICE_SUBTYPE_PREFIX}${baseId}`;
32
+ let suffix = 2;
33
+ while (usedSubtypes.has(subtype)) {
34
+ subtype = `${EFFECT_SERVICE_SUBTYPE_PREFIX}${baseId}-${suffix}`;
35
+ suffix += 1;
36
+ }
37
+ usedSubtypes.add(subtype);
38
+ return {
39
+ name: effect.name,
40
+ code,
41
+ speed: clampPercent(effect.speed ?? defaultSpeed),
42
+ subtype,
43
+ };
44
+ });
45
+ return {
46
+ effects,
47
+ restoreColorOnDisable: config.restoreColorOnDisable ?? true,
48
+ };
49
+ };
50
+ //# sourceMappingURL=effects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects.js","sourceRoot":"","sources":["../src/effects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGrD,MAAM,CAAC,MAAM,6BAA6B,GAAG,mBAAmB,CAAC;AAcjE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,MAAM,eAAe,GAA4B;IACtD,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE;IAC7B,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE;IAC/B,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE;CACvC,CAAC;AAEF,MAAM,OAAO,GAAG,CAAC,KAAa,EAAU,EAAE;IACxC,OAAO,KAAK;SACT,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;SAC7B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAA0C,EACV,EAAE;IAClC,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QAC7B,OAAO;YACL,OAAO,EAAE,EAAE;YACX,qBAAqB,EAAE,MAAM,EAAE,qBAAqB,IAAI,IAAI;SAC7D,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,YAAY,IAAI,oBAAoB,CAAC,CAAC;IAC/E,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IAEvC,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC;SACpE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;SAClF,GAAG,CAAC,CAAC,MAAM,EAA2B,EAAE;QACvC,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,IAAI,UAAU,IAAI,EAAE,CAAC;QAClF,IAAI,OAAO,GAAG,GAAG,6BAA6B,GAAG,MAAM,EAAE,CAAC;QAC1D,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,OAAO,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACjC,OAAO,GAAG,GAAG,6BAA6B,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;YAChE,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;QAED,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE1B,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI;YACJ,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,KAAK,IAAI,YAAY,CAAC;YACjD,OAAO;SACR,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,OAAO;QACL,OAAO;QACP,qBAAqB,EAAE,MAAM,CAAC,qBAAqB,IAAI,IAAI;KAC5D,CAAC;AACJ,CAAC,CAAC"}
@@ -18,6 +18,7 @@ export declare class LanternIcPlatform implements DynamicPlatformPlugin {
18
18
  private deviceFromCandidate;
19
19
  private isConfigured;
20
20
  private discoveryAutoAdd;
21
+ private firstSetupAutoMode;
21
22
  private validDevices;
22
23
  private deviceUniqueId;
23
24
  }
package/dist/platform.js CHANGED
@@ -39,7 +39,7 @@ export class LanternIcPlatform {
39
39
  if (activeUuids.has(uuid)) {
40
40
  continue;
41
41
  }
42
- if (this.discoveryAutoAdd() && accessory.context.autoDiscovered) {
42
+ if (this.discoveryAutoAdd(devices) && accessory.context.autoDiscovered) {
43
43
  const reason = discoverySucceeded ? 'it was previously auto-discovered' : 'discovery scan failed';
44
44
  this.log.info(`Keeping cached auto-discovered accessory because ${reason}:`, accessory.displayName);
45
45
  continue;
@@ -97,7 +97,7 @@ export class LanternIcPlatform {
97
97
  }
98
98
  for (const candidate of candidates) {
99
99
  this.logCandidate(candidate);
100
- if (!this.discoveryAutoAdd() || this.isConfigured(candidate, configuredDevices)) {
100
+ if (!this.discoveryAutoAdd(configuredDevices) || this.isConfigured(candidate, configuredDevices)) {
101
101
  continue;
102
102
  }
103
103
  const device = this.deviceFromCandidate(candidate);
@@ -130,8 +130,12 @@ export class LanternIcPlatform {
130
130
  const candidateId = normalizeBluetoothId(candidate.address || candidate.id);
131
131
  return devices.some(device => normalizeBluetoothId(device.address) === candidateId);
132
132
  }
133
- discoveryAutoAdd() {
134
- return this.config.discovery?.autoAdd === true;
133
+ discoveryAutoAdd(configuredDevices) {
134
+ return this.config.discovery?.autoAdd === true
135
+ || (this.firstSetupAutoMode() && configuredDevices.length === 0);
136
+ }
137
+ firstSetupAutoMode() {
138
+ return this.config.setupMode !== 'manual';
135
139
  }
136
140
  validDevices() {
137
141
  const devices = this.config.devices ?? [];
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@ export declare class LanternIcPlatformAccessory {
7
7
  private readonly client;
8
8
  private readonly accessory;
9
9
  private readonly service;
10
+ private readonly effectSettings;
11
+ private readonly effectServices;
10
12
  private readonly state;
11
13
  private colorTimer?;
12
14
  private colorWriteWaiters;
@@ -19,8 +21,13 @@ export declare class LanternIcPlatformAccessory {
19
21
  private buildCurrentColorCommand;
20
22
  private buildPowerOnCommands;
21
23
  private buildBrightnessUpdateCommands;
24
+ private buildEffectCommands;
22
25
  private powerMode;
23
26
  private brightnessMode;
27
+ private configureEffectServices;
28
+ private setEffectSwitch;
29
+ private updateEffectSwitches;
30
+ private findEffect;
24
31
  private resyncAfterReconnect;
25
32
  private saveState;
26
33
  }
@@ -1,11 +1,14 @@
1
1
  import { applyColorOrder, clampPercent, hsbToRgb } from './color.js';
2
- import { buildColorCommand, buildNativeBrightnessCommands, buildPowerOffCommands, buildPowerOnPrefixCommands, shouldScaleRgbBrightness, } from './ble/magicLanternCommands.js';
2
+ import { buildBasicEffectCommands, buildColorCommand, buildNativeBrightnessCommands, buildPowerOffCommands, buildPowerOnPrefixCommands, shouldScaleRgbBrightness, } from './ble/magicLanternCommands.js';
3
+ import { EFFECT_SERVICE_SUBTYPE_PREFIX, resolveEffectsConfig, } from './effects.js';
3
4
  export class LanternIcPlatformAccessory {
4
5
  platform;
5
6
  device;
6
7
  client;
7
8
  accessory;
8
9
  service;
10
+ effectSettings;
11
+ effectServices = new Map();
9
12
  state;
10
13
  colorTimer;
11
14
  colorWriteWaiters = [];
@@ -22,7 +25,12 @@ export class LanternIcPlatformAccessory {
22
25
  brightness: accessory.context.state?.brightness ?? 100,
23
26
  hue: accessory.context.state?.hue ?? 0,
24
27
  saturation: accessory.context.state?.saturation ?? 0,
28
+ activeEffect: accessory.context.state?.activeEffect,
25
29
  };
30
+ this.effectSettings = resolveEffectsConfig(this.device.effects);
31
+ if (this.state.activeEffect && !this.findEffect(this.state.activeEffect)) {
32
+ this.state.activeEffect = undefined;
33
+ }
26
34
  const informationService = accessory.getService(this.platform.Service.AccessoryInformation)
27
35
  ?? accessory.addService(this.platform.Service.AccessoryInformation);
28
36
  informationService
@@ -44,12 +52,15 @@ export class LanternIcPlatformAccessory {
44
52
  this.service.getCharacteristic(this.platform.Characteristic.Saturation)
45
53
  .onGet(() => this.state.saturation)
46
54
  .onSet(value => this.setSaturation(Number(value)));
55
+ this.configureEffectServices();
47
56
  this.client.onReconnect(() => this.resyncAfterReconnect());
48
57
  this.client.start();
49
58
  }
50
59
  async setOn(onValue) {
51
60
  this.state.on = onValue;
61
+ this.state.activeEffect = undefined;
52
62
  this.saveState();
63
+ this.updateEffectSwitches();
53
64
  if (!onValue) {
54
65
  await this.client.writeCommands(buildPowerOffCommands(this.powerMode()));
55
66
  return;
@@ -58,7 +69,9 @@ export class LanternIcPlatformAccessory {
58
69
  }
59
70
  async setBrightness(value) {
60
71
  this.state.brightness = clampPercent(Number(value));
72
+ this.state.activeEffect = undefined;
61
73
  this.saveState();
74
+ this.updateEffectSwitches();
62
75
  if (!this.state.on) {
63
76
  return;
64
77
  }
@@ -66,12 +79,16 @@ export class LanternIcPlatformAccessory {
66
79
  }
67
80
  async setHue(value) {
68
81
  this.state.hue = Number(value);
82
+ this.state.activeEffect = undefined;
69
83
  this.saveState();
84
+ this.updateEffectSwitches();
70
85
  await this.scheduleColorWrite();
71
86
  }
72
87
  async setSaturation(value) {
73
88
  this.state.saturation = clampPercent(Number(value));
89
+ this.state.activeEffect = undefined;
74
90
  this.saveState();
91
+ this.updateEffectSwitches();
75
92
  await this.scheduleColorWrite();
76
93
  }
77
94
  async scheduleColorWrite() {
@@ -118,17 +135,77 @@ export class LanternIcPlatformAccessory {
118
135
  ...(shouldScaleRgbBrightness(this.brightnessMode()) ? [this.buildCurrentColorCommand()] : []),
119
136
  ];
120
137
  }
138
+ buildEffectCommands(effect) {
139
+ return [
140
+ ...buildPowerOnPrefixCommands(this.powerMode(), this.brightnessMode(), this.state.brightness),
141
+ ...buildBasicEffectCommands(effect.code, effect.speed),
142
+ ];
143
+ }
121
144
  powerMode() {
122
145
  return this.device.powerMode ?? 'both';
123
146
  }
124
147
  brightnessMode() {
125
148
  return this.device.brightnessMode ?? 'rgb';
126
149
  }
150
+ configureEffectServices() {
151
+ const wantedSubtypes = new Set(this.effectSettings.effects.map(effect => effect.subtype));
152
+ for (const existingService of [...this.accessory.services]) {
153
+ if (existingService.UUID === this.platform.Service.Switch.UUID
154
+ && existingService.subtype?.startsWith(EFFECT_SERVICE_SUBTYPE_PREFIX)
155
+ && !wantedSubtypes.has(existingService.subtype)) {
156
+ this.accessory.removeService(existingService);
157
+ }
158
+ }
159
+ for (const effect of this.effectSettings.effects) {
160
+ const service = this.accessory.getServiceById(this.platform.Service.Switch, effect.subtype)
161
+ ?? this.accessory.addService(this.platform.Service.Switch, effect.name, effect.subtype);
162
+ service.setCharacteristic(this.platform.Characteristic.Name, effect.name);
163
+ service.getCharacteristic(this.platform.Characteristic.On)
164
+ .onGet(() => this.state.activeEffect === effect.subtype)
165
+ .onSet(value => this.setEffectSwitch(effect, Boolean(value)));
166
+ this.effectServices.set(effect.subtype, service);
167
+ }
168
+ this.updateEffectSwitches();
169
+ }
170
+ async setEffectSwitch(effect, onValue) {
171
+ if (!onValue) {
172
+ if (this.state.activeEffect !== effect.subtype) {
173
+ this.updateEffectSwitches();
174
+ return;
175
+ }
176
+ this.state.activeEffect = undefined;
177
+ this.saveState();
178
+ this.updateEffectSwitches();
179
+ if (this.effectSettings.restoreColorOnDisable && this.state.on) {
180
+ await this.client.writeCommands(this.buildPowerOnCommands());
181
+ }
182
+ return;
183
+ }
184
+ this.state.on = true;
185
+ this.state.activeEffect = effect.subtype;
186
+ this.saveState();
187
+ this.service.updateCharacteristic(this.platform.Characteristic.On, true);
188
+ this.updateEffectSwitches();
189
+ await this.client.writeCommands(this.buildEffectCommands(effect));
190
+ }
191
+ updateEffectSwitches() {
192
+ for (const [subtype, service] of this.effectServices) {
193
+ service.updateCharacteristic(this.platform.Characteristic.On, this.state.activeEffect === subtype);
194
+ }
195
+ }
196
+ findEffect(subtype) {
197
+ return this.effectSettings.effects.find(effect => effect.subtype === subtype);
198
+ }
127
199
  async resyncAfterReconnect() {
128
200
  if (!this.state.on) {
129
201
  return;
130
202
  }
131
203
  this.platform.log.debug(`[${this.device.name}] Resyncing desired state after BLE reconnect`);
204
+ const activeEffect = this.findEffect(this.state.activeEffect);
205
+ if (activeEffect) {
206
+ await this.client.writeCommands(this.buildEffectCommands(activeEffect));
207
+ return;
208
+ }
132
209
  await this.client.writeCommands(this.buildPowerOnCommands());
133
210
  }
134
211
  saveState() {
@@ -1 +1 @@
1
- {"version":3,"file":"platformAccessory.js","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platformAccessory.js","sourceRoot":"","sources":["../src/platformAccessory.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -5,6 +5,19 @@ export type BrightnessMode = 'rgb' | 'native' | 'both';
5
5
  export type NobleBinding = 'default' | 'hci' | 'mac' | 'win';
6
6
  export type HciDriver = 'default' | 'native' | 'usb' | 'uart';
7
7
  export type WriteMode = 'auto' | 'withResponse' | 'withoutResponse';
8
+ export type SetupMode = 'auto' | 'manual';
9
+ export interface LanternIcEffectConfig {
10
+ name: string;
11
+ code: number;
12
+ id?: string;
13
+ speed?: number;
14
+ }
15
+ export interface LanternIcEffectsConfig {
16
+ enabled?: boolean;
17
+ defaultSpeed?: number;
18
+ restoreColorOnDisable?: boolean;
19
+ items?: LanternIcEffectConfig[];
20
+ }
8
21
  export interface LanternIcDeviceConfig {
9
22
  name: string;
10
23
  address: string;
@@ -13,6 +26,7 @@ export interface LanternIcDeviceConfig {
13
26
  colorOrder?: ColorOrder;
14
27
  powerMode?: PowerMode;
15
28
  brightnessMode?: BrightnessMode;
29
+ effects?: LanternIcEffectsConfig;
16
30
  }
17
31
  export interface LanternIcDiscoveryConfig {
18
32
  enabled?: boolean;
@@ -45,6 +59,7 @@ export interface LanternIcBleConfig {
45
59
  }
46
60
  export interface LanternIcPlatformConfig extends PlatformConfig {
47
61
  name?: string;
62
+ setupMode?: SetupMode;
48
63
  devices?: LanternIcDeviceConfig[];
49
64
  discovery?: LanternIcDiscoveryConfig;
50
65
  ble?: LanternIcBleConfig;
@@ -54,6 +69,7 @@ export interface LanternIcStoredState {
54
69
  brightness?: number;
55
70
  hue?: number;
56
71
  saturation?: number;
72
+ activeEffect?: string;
57
73
  }
58
74
  export interface LanternIcAccessoryContext {
59
75
  autoDiscovered?: boolean;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "homebridge-lanternic",
3
3
  "displayName": "LanternIC",
4
4
  "type": "module",
5
- "version": "0.1.3",
5
+ "version": "0.2.0",
6
6
  "description": "Homebridge plugin for BLE RGBIC/RGBWIC light strips controlled by the Magic Lantern app.",
7
7
  "author": "Gibson Bell",
8
8
  "license": "MIT",
package/tools/send.mjs CHANGED
@@ -4,16 +4,20 @@ import { withBindings } from '@stoprocent/noble';
4
4
  const binding = process.env.LANTERNIC_BINDING ?? 'default';
5
5
  const serviceUuid = (process.env.LANTERNIC_SERVICE_UUID ?? 'fff0').replace(/[^0-9a-f]/gi, '').toLowerCase();
6
6
  const characteristicUuid = (process.env.LANTERNIC_CHARACTERISTIC_UUID ?? 'fff3').replace(/[^0-9a-f]/gi, '').toLowerCase();
7
+ const delayMs = Number(process.env.LANTERNIC_WRITE_DELAY_MS ?? 120);
7
8
  const address = process.argv[2];
8
9
  const command = process.argv[3];
9
10
  const value = process.argv[4];
11
+ const extraValue = process.argv[5];
10
12
 
11
13
  if (!address || !command) {
12
- console.error('Usage: lanternic-send <address> <on|off|brightness|rgb|raw> [value]');
13
- console.error('Repo development: npm run send -- <address> <on|off|brightness|rgb|raw> [value]');
14
+ console.error('Usage: lanternic-send <address> <on|off|brightness|speed|effect|rgb|raw> [value] [speed]');
15
+ console.error('Repo development: npm run send -- <address> <on|off|brightness|speed|effect|rgb|raw> [value] [speed]');
14
16
  console.error('Examples:');
15
17
  console.error(' lanternic-send be:16:70:00:08:2a on');
16
18
  console.error(' lanternic-send be:16:70:00:08:2a brightness 50');
19
+ console.error(' lanternic-send be:16:70:00:08:2a speed 39');
20
+ console.error(' lanternic-send be:16:70:00:08:2a effect 207 39');
17
21
  console.error(' lanternic-send be:16:70:00:08:2a rgb ff0000');
18
22
  console.error(' lanternic-send be:16:70:00:08:2a raw 7e0404f00001ff00ef');
19
23
  process.exit(2);
@@ -27,18 +31,33 @@ const noble = withBindings(binding);
27
31
  const byte = number => Math.max(0, Math.min(255, Math.round(number)));
28
32
  const percent = number => Math.max(0, Math.min(100, Math.round(number)));
29
33
  const frame = (...bytes) => Buffer.from(bytes.map(byte));
34
+ const wait = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
30
35
 
31
- const buildPayload = () => {
36
+ const buildPayloads = () => {
32
37
  if (command === 'on') {
33
- return Buffer.from('7e0404f00001ff00ef', 'hex');
38
+ return [Buffer.from('7e0404f00001ff00ef', 'hex')];
34
39
  }
35
40
 
36
41
  if (command === 'off') {
37
- return Buffer.from('7e0404000000ff00ef', 'hex');
42
+ return [Buffer.from('7e0404000000ff00ef', 'hex')];
38
43
  }
39
44
 
40
45
  if (command === 'brightness') {
41
- return frame(0x7e, 0x04, 0x01, percent(Number(value)), 0x01, 0xff, 0xff, 0x00, 0xef);
46
+ return [frame(0x7e, 0x04, 0x01, percent(Number(value)), 0x01, 0xff, 0xff, 0x00, 0xef)];
47
+ }
48
+
49
+ if (command === 'speed') {
50
+ return [frame(0x7e, 0x04, 0x02, percent(Number(value)), 0xff, 0xff, 0xff, 0x00, 0xef)];
51
+ }
52
+
53
+ if (command === 'effect') {
54
+ const payloads = [];
55
+ if (extraValue !== undefined) {
56
+ payloads.push(frame(0x7e, 0x04, 0x02, percent(Number(extraValue)), 0xff, 0xff, 0xff, 0x00, 0xef));
57
+ }
58
+
59
+ payloads.push(frame(0x7e, 0x05, 0x03, byte(Number(value)), 0x06, 0xff, 0xff, 0x00, 0xef));
60
+ return payloads;
42
61
  }
43
62
 
44
63
  if (command === 'rgb') {
@@ -46,18 +65,18 @@ const buildPayload = () => {
46
65
  if (rgb.length !== 6) {
47
66
  throw new Error('rgb value must be RRGGBB hex, for example ff0000');
48
67
  }
49
- return Buffer.from(`7e070503${rgb}10ef`, 'hex');
68
+ return [Buffer.from(`7e070503${rgb}10ef`, 'hex')];
50
69
  }
51
70
 
52
71
  if (command === 'raw') {
53
- return Buffer.from(cleanId(value), 'hex');
72
+ return [Buffer.from(cleanId(value), 'hex')];
54
73
  }
55
74
 
56
75
  throw new Error(`Unknown command: ${command}`);
57
76
  };
58
77
 
59
- const payload = buildPayload();
60
- console.log(`Sending ${payload.toString('hex')} to ${address} with binding=${binding}`);
78
+ const payloads = buildPayloads();
79
+ console.log(`Sending ${payloads.map(payload => payload.toString('hex')).join(', ')} to ${address} with binding=${binding}`);
61
80
 
62
81
  await noble.waitForPoweredOnAsync(15_000);
63
82
  await noble.startScanningAsync([], true);
@@ -98,7 +117,10 @@ try {
98
117
 
99
118
  const withoutResponse = !characteristic.properties.includes('write')
100
119
  && characteristic.properties.includes('writeWithoutResponse');
101
- await characteristic.writeAsync(payload, withoutResponse);
120
+ for (const payload of payloads) {
121
+ await characteristic.writeAsync(payload, withoutResponse);
122
+ await wait(delayMs);
123
+ }
102
124
  console.log(`Write complete withoutResponse=${withoutResponse}`);
103
125
  } finally {
104
126
  await peripheral.disconnectAsync();