@switchbot/homebridge-switchbot 5.2.0 → 5.2.1-beta.1
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/.github/copilot-instructions.md +72 -169
- package/.github/npm-version-script-esm.js +100 -0
- package/.github/workflows/ci.yml +4 -1
- package/CHANGELOG.md +9 -0
- package/CLAUDE.md +13 -0
- package/README.md +2 -0
- package/config.schema.json +30 -0
- package/dist/SwitchBotHAPPlatform.d.ts.map +1 -1
- package/dist/SwitchBotHAPPlatform.js +32 -17
- package/dist/SwitchBotHAPPlatform.js.map +1 -1
- package/dist/devices/genericDevice.d.ts +2 -0
- package/dist/devices/genericDevice.d.ts.map +1 -1
- package/dist/devices/genericDevice.js +75 -0
- package/dist/devices/genericDevice.js.map +1 -1
- package/docs/index.html +2 -0
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/SwitchBotHAPPlatform.ts +32 -16
- package/src/devices/genericDevice.ts +82 -1
- package/test/device/bot-hap.spec.ts +184 -0
- package/src/device-types.js.map +0 -1
- package/src/deviceCommandMapper.js +0 -319
- package/src/deviceCommandMapper.js.map +0 -1
- package/src/errors.js +0 -32
- package/src/errors.js.map +0 -1
- package/src/settings.js +0 -8
- package/src/settings.js.map +0 -1
- package/src/switchbotClient.js +0 -247
- package/src/switchbotClient.js.map +0 -1
|
@@ -287,9 +287,13 @@ export class SwitchBotHAPPlatform {
|
|
|
287
287
|
continue
|
|
288
288
|
}
|
|
289
289
|
const service = accessory.getService(Service) || accessory.addService(Service)
|
|
290
|
-
const
|
|
290
|
+
const characteristicUUIDs = new Set(
|
|
291
|
+
Object.keys(s.characteristics || {})
|
|
292
|
+
.map(name => hap.Characteristic[name]?.UUID)
|
|
293
|
+
.filter(Boolean),
|
|
294
|
+
)
|
|
291
295
|
for (const existingChar of service.characteristics.slice()) {
|
|
292
|
-
if (!
|
|
296
|
+
if (!characteristicUUIDs.has(existingChar.UUID)) {
|
|
293
297
|
service.removeCharacteristic(existingChar)
|
|
294
298
|
}
|
|
295
299
|
}
|
|
@@ -318,20 +322,30 @@ export class SwitchBotHAPPlatform {
|
|
|
318
322
|
await getterSetter.set(value)
|
|
319
323
|
|
|
320
324
|
const refreshAfterSet = Array.isArray(getterSetter.refreshAfterSet) ? getterSetter.refreshAfterSet : []
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
325
|
+
// HAP stores the requested value after onSet resolves. Refresh on the next tick
|
|
326
|
+
// so a momentary control can return to its resting value.
|
|
327
|
+
if (refreshAfterSet.length > 0 || typeof getterSetter.afterSet === 'function') {
|
|
328
|
+
setTimeout(async () => {
|
|
329
|
+
for (const refreshCharName of refreshAfterSet) {
|
|
330
|
+
const refreshGetterSetter: any = (s.characteristics || {})[refreshCharName]
|
|
331
|
+
const RefreshCharacteristic = (hap.Characteristic as any)[refreshCharName]
|
|
332
|
+
if (!RefreshCharacteristic || typeof refreshGetterSetter?.get !== 'function') {
|
|
333
|
+
continue
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
service.getCharacteristic(RefreshCharacteristic).updateValue(await refreshGetterSetter.get())
|
|
337
|
+
} catch (e) {
|
|
338
|
+
this.log.debug?.(`Failed to refresh ${refreshCharName} after setting ${charName}`, e)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (typeof getterSetter.afterSet === 'function') {
|
|
342
|
+
try {
|
|
343
|
+
await getterSetter.afterSet(value, service, hap)
|
|
344
|
+
} catch (e) {
|
|
345
|
+
this.log.debug?.(`Failed afterSet for ${charName}`, e)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}, 0)
|
|
335
349
|
}
|
|
336
350
|
})
|
|
337
351
|
}
|
|
@@ -387,6 +401,8 @@ export class SwitchBotHAPPlatform {
|
|
|
387
401
|
id: d.deviceId ?? d.id,
|
|
388
402
|
type: d.configDeviceType ?? d.type,
|
|
389
403
|
name: d.configDeviceName ?? d.name,
|
|
404
|
+
botDisplay: d.botDisplay ?? d.type,
|
|
405
|
+
mode: d.mode,
|
|
390
406
|
})))
|
|
391
407
|
}
|
|
392
408
|
|
|
@@ -529,7 +529,88 @@ export class GenericDevice extends DeviceBase {
|
|
|
529
529
|
}
|
|
530
530
|
|
|
531
531
|
// Specific device classes can extend GenericDevice for custom behavior.
|
|
532
|
-
export class BotDevice extends GenericDevice {
|
|
532
|
+
export class BotDevice extends GenericDevice {
|
|
533
|
+
private lastCommand?: { on: boolean, at: number }
|
|
534
|
+
|
|
535
|
+
createHAPAccessory(api: any): any {
|
|
536
|
+
const config = this.cfg.devices?.find((device: any) => (device.deviceId ?? device.id) === this.opts.id)
|
|
537
|
+
// Keep the old per-device type override for configurations made before v5.
|
|
538
|
+
const display = config?.botDisplay ?? config?.type ?? 'switch'
|
|
539
|
+
const pressMode = config?.mode === 'press' || config?.mode === 'multipress'
|
|
540
|
+
|| (display === 'door' && config?.mode !== 'switch')
|
|
541
|
+
|
|
542
|
+
const isOn = async () => {
|
|
543
|
+
if (pressMode) {
|
|
544
|
+
return false
|
|
545
|
+
}
|
|
546
|
+
if (this.lastCommand && Date.now() - this.lastCommand.at < 15_000) {
|
|
547
|
+
return this.lastCommand.on
|
|
548
|
+
}
|
|
549
|
+
const state = await this.getState()
|
|
550
|
+
return !!(state && (state.on === true || state.state === 'on' || state.power === 'on'))
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
const setOn = async (on: boolean) => {
|
|
554
|
+
if (pressMode && !on) {
|
|
555
|
+
return
|
|
556
|
+
}
|
|
557
|
+
const command = pressMode ? 'press' : on ? 'turnOn' : 'turnOff'
|
|
558
|
+
const result = await this.setState({ command, parameter: 'default', commandType: 'command' })
|
|
559
|
+
if (result !== true && result?.success !== true) {
|
|
560
|
+
throw new Error(`SwitchBot Bot ${command} failed: ${result?.reason ?? 'unknown error'}`)
|
|
561
|
+
}
|
|
562
|
+
if (!pressMode) {
|
|
563
|
+
this.lastCommand = { on, at: Date.now() }
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const control = (name: string, active: number | boolean, inactive: number | boolean, requestedOn: (value: any) => boolean) => ({
|
|
568
|
+
get: async () => (await isOn()) ? active : inactive,
|
|
569
|
+
set: async (value: any) => setOn(requestedOn(value)),
|
|
570
|
+
...(pressMode ? { refreshAfterSet: [name] } : {}),
|
|
571
|
+
})
|
|
572
|
+
const position = () => ({
|
|
573
|
+
CurrentPosition: { get: async () => (await isOn()) ? 100 : 0 },
|
|
574
|
+
PositionState: { get: async () => 2 },
|
|
575
|
+
TargetPosition: control('TargetPosition', 100, 0, value => Number(value) > 0),
|
|
576
|
+
})
|
|
577
|
+
const active = (value: any) => Number(value) === 1
|
|
578
|
+
const presentations: Record<string, { type: string, characteristics: Record<string, any> }> = {
|
|
579
|
+
switch: { type: 'Switch', characteristics: { On: control('On', true, false, value => value === true) } },
|
|
580
|
+
outlet: { type: 'Outlet', characteristics: { On: control('On', true, false, value => value === true) } },
|
|
581
|
+
door: { type: 'Door', characteristics: position() },
|
|
582
|
+
window: { type: 'Window', characteristics: position() },
|
|
583
|
+
windowcovering: { type: 'WindowCovering', characteristics: position() },
|
|
584
|
+
garagedoor: { type: 'GarageDoorOpener', characteristics: {
|
|
585
|
+
CurrentDoorState: { get: async () => (await isOn()) ? 0 : 1 },
|
|
586
|
+
TargetDoorState: control('TargetDoorState', 0, 1, value => Number(value) === 0),
|
|
587
|
+
ObstructionDetected: { get: async () => false },
|
|
588
|
+
} },
|
|
589
|
+
lock: { type: 'LockMechanism', characteristics: {
|
|
590
|
+
LockCurrentState: { get: async () => (await isOn()) ? 0 : 1 },
|
|
591
|
+
LockTargetState: control('LockTargetState', 0, 1, value => Number(value) === 0),
|
|
592
|
+
} },
|
|
593
|
+
faucet: { type: 'Faucet', characteristics: { Active: control('Active', 1, 0, active) } },
|
|
594
|
+
fan: { type: 'Fanv2', characteristics: { Active: control('Active', 1, 0, active) } },
|
|
595
|
+
stateful: { type: 'StatefulProgrammableSwitch', characteristics: {
|
|
596
|
+
ProgrammableSwitchEvent: {},
|
|
597
|
+
ProgrammableSwitchOutputState: {
|
|
598
|
+
...control('ProgrammableSwitchOutputState', 1, 0, active),
|
|
599
|
+
...(pressMode ? { refreshAfterSet: ['ProgrammableSwitchOutputState'] } : {}),
|
|
600
|
+
afterSet: (value: any, service: any, hap: any) => {
|
|
601
|
+
if (!pressMode || active(value)) {
|
|
602
|
+
service.getCharacteristic(hap.Characteristic.ProgrammableSwitchEvent).sendEventNotification(0)
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
} },
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return {
|
|
610
|
+
services: [presentations[display] ?? presentations.switch],
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
533
614
|
|
|
534
615
|
export class CurtainDevice extends GenericDevice {
|
|
535
616
|
private lastKnownPosition = 0
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Accessory, Characteristic, Service, uuid } from '@homebridge/hap-nodejs'
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { BotDevice } from '../../src/devices/genericDevice.js'
|
|
5
|
+
import { SwitchBotHAPPlatform } from '../../src/SwitchBotHAPPlatform.js'
|
|
6
|
+
|
|
7
|
+
const id = 'bot-door-test'
|
|
8
|
+
const log = { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }
|
|
9
|
+
|
|
10
|
+
function bot(config: Record<string, unknown>, result: unknown = { success: true }) {
|
|
11
|
+
const setDeviceState = vi.fn(async () => result)
|
|
12
|
+
const device = new BotDevice(
|
|
13
|
+
{ id, type: 'Bot', name: 'Entrance', log, blePollingEnabled: false },
|
|
14
|
+
{ log, devices: [{ deviceId: id, configDeviceType: 'Bot', ...config }], _client: { setDeviceState } } as any,
|
|
15
|
+
)
|
|
16
|
+
return { device, setDeviceState }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const displays = [
|
|
20
|
+
['switch', 'Switch', 'On', true, false],
|
|
21
|
+
['outlet', 'Outlet', 'On', true, false],
|
|
22
|
+
['door', 'Door', 'TargetPosition', 100, 0],
|
|
23
|
+
['window', 'Window', 'TargetPosition', 100, 0],
|
|
24
|
+
['windowcovering', 'WindowCovering', 'TargetPosition', 100, 0],
|
|
25
|
+
['garagedoor', 'GarageDoorOpener', 'TargetDoorState', 0, 1],
|
|
26
|
+
['lock', 'LockMechanism', 'LockTargetState', 0, 1],
|
|
27
|
+
['faucet', 'Faucet', 'Active', 1, 0],
|
|
28
|
+
['fan', 'Fanv2', 'Active', 1, 0],
|
|
29
|
+
['stateful', 'StatefulProgrammableSwitch', 'ProgrammableSwitchOutputState', 1, 0],
|
|
30
|
+
] as const
|
|
31
|
+
|
|
32
|
+
describe('bot HomeKit presentation', () => {
|
|
33
|
+
it('keeps the default Switch presentation', () => {
|
|
34
|
+
expect(bot({}).device.createHAPAccessory({}).services[0].type).toBe('Switch')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it.each(displays)('restores %s as a HAP %s with Press Mode', async (display, serviceType, controlName, active, inactive) => {
|
|
38
|
+
const { device, setDeviceState } = bot({ botDisplay: display, mode: 'press' })
|
|
39
|
+
const descriptor = device.createHAPAccessory({}).services[0]
|
|
40
|
+
expect(descriptor.type).toBe(serviceType)
|
|
41
|
+
const required = new (Service as any)[serviceType]().characteristics
|
|
42
|
+
const provided = new Set(Object.keys(descriptor.characteristics).map(name => (Characteristic as any)[name]?.UUID))
|
|
43
|
+
for (const characteristic of required) {
|
|
44
|
+
expect(provided.has(characteristic.UUID)).toBe(true)
|
|
45
|
+
}
|
|
46
|
+
const control = descriptor.characteristics[controlName]
|
|
47
|
+
await control.set(active)
|
|
48
|
+
await control.set(inactive)
|
|
49
|
+
expect(await control.get()).toBe(inactive)
|
|
50
|
+
expect(setDeviceState).toHaveBeenCalledExactlyOnceWith(id, {
|
|
51
|
+
command: 'press',
|
|
52
|
+
parameter: 'default',
|
|
53
|
+
commandType: 'command',
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it.each(displays)('registers %s and resets its HAP control after a press', async (display, serviceType, controlName, active, inactive) => {
|
|
58
|
+
const { device } = bot({ botDisplay: display, mode: 'press' })
|
|
59
|
+
const accessory = new Accessory('Entrance', uuid.generate(id))
|
|
60
|
+
accessory.addService(Service.Switch)
|
|
61
|
+
const api = { hap: { Service, Characteristic, uuid }, registerPlatformAccessories: vi.fn() }
|
|
62
|
+
const platform = Object.create(SwitchBotHAPPlatform.prototype) as any
|
|
63
|
+
platform.api = api
|
|
64
|
+
platform.log = log
|
|
65
|
+
platform.accessories = new Map([[uuid.generate(id), accessory]])
|
|
66
|
+
platform.hapPushTargets = new Map()
|
|
67
|
+
const created = { instance: device, createAccessory: () => device.createHAPAccessory(api) }
|
|
68
|
+
|
|
69
|
+
await platform.registerHAPAccessories([{ created, d: { id, name: 'Entrance' }, type: 'Bot' }])
|
|
70
|
+
|
|
71
|
+
const service = accessory.getService((Service as any)[serviceType])!
|
|
72
|
+
expect(service).toBeDefined()
|
|
73
|
+
if (serviceType !== 'Switch') {
|
|
74
|
+
expect(accessory.getService(Service.Switch)).toBeUndefined()
|
|
75
|
+
}
|
|
76
|
+
const characteristic = service.getCharacteristic((Characteristic as any)[controlName])
|
|
77
|
+
await characteristic.handleSetRequest(active)
|
|
78
|
+
await new Promise(resolve => setTimeout(resolve, 10))
|
|
79
|
+
expect(characteristic.value).toBe(inactive)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('uses turnOn and turnOff for physical Switch Mode', async () => {
|
|
83
|
+
const { device, setDeviceState } = bot({ botDisplay: 'door', mode: 'switch' })
|
|
84
|
+
const target = device.createHAPAccessory({}).services[0].characteristics.TargetPosition
|
|
85
|
+
await target.set(100)
|
|
86
|
+
expect(await target.get()).toBe(100)
|
|
87
|
+
await target.set(0)
|
|
88
|
+
expect(await target.get()).toBe(0)
|
|
89
|
+
expect(setDeviceState.mock.calls.map(([, body]) => body.command)).toEqual(['turnOn', 'turnOff'])
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('reloads a Bot when its physical mode changes', async () => {
|
|
93
|
+
const platform = Object.create(SwitchBotHAPPlatform.prototype) as any
|
|
94
|
+
platform.config = { devices: [{ deviceId: id, configDeviceType: 'Bot', mode: 'switch' }] }
|
|
95
|
+
platform.lastConfigHash = platform.getConfigHash()
|
|
96
|
+
platform.config.devices[0].mode = 'press'
|
|
97
|
+
platform.log = log
|
|
98
|
+
platform.accessories = new Map()
|
|
99
|
+
platform.devices = []
|
|
100
|
+
platform.loadDevices = vi.fn(async () => {})
|
|
101
|
+
|
|
102
|
+
await platform.checkAndReloadDevices()
|
|
103
|
+
|
|
104
|
+
expect(platform.loadDevices).toHaveBeenCalledOnce()
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('emits each Stateful Programmable Switch press as an event', async () => {
|
|
108
|
+
const { device, setDeviceState } = bot({ botDisplay: 'stateful', mode: 'press' })
|
|
109
|
+
const accessory = new Accessory('Entrance', uuid.generate(id))
|
|
110
|
+
const api = { hap: { Service, Characteristic, uuid }, registerPlatformAccessories: vi.fn() }
|
|
111
|
+
const platform = Object.create(SwitchBotHAPPlatform.prototype) as any
|
|
112
|
+
platform.api = api
|
|
113
|
+
platform.log = log
|
|
114
|
+
platform.accessories = new Map([[uuid.generate(id), accessory]])
|
|
115
|
+
platform.hapPushTargets = new Map()
|
|
116
|
+
const created = { instance: device, createAccessory: () => device.createHAPAccessory(api) }
|
|
117
|
+
await platform.registerHAPAccessories([{ created, d: { id, name: 'Entrance' }, type: 'Bot' }])
|
|
118
|
+
|
|
119
|
+
const service = accessory.getService(Service.StatefulProgrammableSwitch)!
|
|
120
|
+
const event = service.getCharacteristic(Characteristic.ProgrammableSwitchEvent)
|
|
121
|
+
const notify = vi.spyOn(event, 'sendEventNotification')
|
|
122
|
+
const output = service.getCharacteristic(Characteristic.ProgrammableSwitchOutputState)
|
|
123
|
+
await output.handleSetRequest(1)
|
|
124
|
+
await new Promise(resolve => setTimeout(resolve, 10))
|
|
125
|
+
await output.handleSetRequest(1)
|
|
126
|
+
await new Promise(resolve => setTimeout(resolve, 10))
|
|
127
|
+
await output.handleSetRequest(0)
|
|
128
|
+
await new Promise(resolve => setTimeout(resolve, 10))
|
|
129
|
+
|
|
130
|
+
expect(notify).toHaveBeenCalledTimes(2)
|
|
131
|
+
expect(notify).toHaveBeenCalledWith(0)
|
|
132
|
+
expect(setDeviceState).toHaveBeenCalledTimes(2)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('sends one press for Open and none for Close', async () => {
|
|
136
|
+
const { device, setDeviceState } = bot({ botDisplay: 'door' })
|
|
137
|
+
const chars = device.createHAPAccessory({}).services[0].characteristics
|
|
138
|
+
expect(await chars.TargetPosition.get()).toBe(0)
|
|
139
|
+
expect(await chars.CurrentPosition.get()).toBe(0)
|
|
140
|
+
expect(await chars.PositionState.get()).toBe(2)
|
|
141
|
+
await chars.TargetPosition.set(100)
|
|
142
|
+
await chars.TargetPosition.set(0)
|
|
143
|
+
expect(setDeviceState).toHaveBeenCalledExactlyOnceWith(id, {
|
|
144
|
+
command: 'press',
|
|
145
|
+
parameter: 'default',
|
|
146
|
+
commandType: 'command',
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('reports a failed press to HomeKit', async () => {
|
|
151
|
+
const { device } = bot({ type: 'door' }, { success: false, reason: 'offline' })
|
|
152
|
+
await expect(device.createHAPAccessory({}).services[0].characteristics.TargetPosition.set(100))
|
|
153
|
+
.rejects
|
|
154
|
+
.toThrow('offline')
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
it('replaces a cached Switch and resets TargetPosition after HAP commits the write', async () => {
|
|
158
|
+
const { device, setDeviceState } = bot({ botDisplay: 'door' })
|
|
159
|
+
const accessory = new Accessory('Entrance', uuid.generate(id))
|
|
160
|
+
accessory.addService(Service.Switch)
|
|
161
|
+
const api = {
|
|
162
|
+
hap: { Service, Characteristic, uuid },
|
|
163
|
+
registerPlatformAccessories: vi.fn(),
|
|
164
|
+
}
|
|
165
|
+
const platform = Object.create(SwitchBotHAPPlatform.prototype) as any
|
|
166
|
+
platform.api = api
|
|
167
|
+
platform.log = log
|
|
168
|
+
platform.accessories = new Map([[uuid.generate(id), accessory]])
|
|
169
|
+
platform.hapPushTargets = new Map()
|
|
170
|
+
const created = { instance: device, createAccessory: () => device.createHAPAccessory(api) }
|
|
171
|
+
|
|
172
|
+
await platform.registerHAPAccessories([{ created, d: { id, name: 'Entrance' }, type: 'Bot' }])
|
|
173
|
+
|
|
174
|
+
expect(accessory.getService(Service.Switch)).toBeUndefined()
|
|
175
|
+
const door = accessory.getService(Service.Door)!
|
|
176
|
+
expect(door.getCharacteristic(Characteristic.CurrentPosition)).toBeDefined()
|
|
177
|
+
expect(door.getCharacteristic(Characteristic.PositionState)).toBeDefined()
|
|
178
|
+
const target = door.getCharacteristic(Characteristic.TargetPosition)
|
|
179
|
+
await target.handleSetRequest(100)
|
|
180
|
+
await new Promise(resolve => setTimeout(resolve, 20))
|
|
181
|
+
expect(target.value).toBe(0)
|
|
182
|
+
expect(setDeviceState).toHaveBeenCalledTimes(1)
|
|
183
|
+
})
|
|
184
|
+
})
|
package/src/device-types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"device-types.js","sourceRoot":"","sources":["device-types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,kBAAkB,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC;IACzE,gBAAgB,EAAE;QAChB,QAAQ;QACR,cAAc;QACd,eAAe;QACf,mBAAmB;QACnB,iBAAiB;QACjB,WAAW;QACX,YAAY;QACZ,gBAAgB;QAChB,kBAAkB;QAClB,gBAAgB;KACjB;IACD,SAAS,EAAE,CAAC,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,CAAC;IACnF,UAAU,EAAE;QACV,oBAAoB;QACpB,eAAe;QACf,mBAAmB;QACnB,YAAY;QACZ,YAAY;QACZ,uBAAuB;QACvB,4BAA4B;QAC5B,oBAAoB;QACpB,qBAAqB;QACrB,aAAa;QACb,eAAe;KAChB;IACD,iBAAiB,EAAE;QACjB,oBAAoB;QACpB,0BAA0B;QAC1B,kBAAkB;QAClB,wBAAwB;QACxB,wBAAwB;QACxB,gBAAgB;QAChB,YAAY;QACZ,aAAa;QACb,OAAO;QACP,WAAW;QACX,YAAY;QACZ,UAAU;QACV,WAAW;QACX,eAAe;QACf,iBAAiB;QACjB,2BAA2B;QAC3B,yBAAyB;QACzB,YAAY;KACb;IACD,kBAAkB,EAAE;QAClB,oBAAoB;QACpB,MAAM;QACN,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,kBAAkB;QAClB,kBAAkB;KACnB;IACD,eAAe,EAAE;QACf,MAAM;QACN,UAAU;QACV,qCAAqC;QACrC,2BAA2B;QAC3B,mCAAmC;QACnC,yBAAyB;QACzB,8BAA8B;QAC9B,0BAA0B;QAC1B,0BAA0B;KAC3B;IACD,MAAM,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,CAAC;IACnE,SAAS,EAAE;QACT,YAAY;QACZ,cAAc;QACd,iBAAiB;QACjB,sBAAsB;QACtB,sBAAsB;KACvB;IACD,YAAY,EAAE;QACZ,iBAAiB;QACjB,cAAc;QACd,QAAQ;QACR,KAAK;QACL,KAAK;QACL,OAAO;QACP,QAAQ;QACR,WAAW;QACX,aAAa;QACb,SAAS;QACT,UAAU;QACV,IAAI;QACJ,gBAAgB;QAChB,cAAc;KACf;IACD,eAAe,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,oBAAoB,CAAC;CACtF,CAAA;AAEV,MAAM,CAAC,MAAM,6BAA6B,GAA2B;IACnE,oDAAoD;IACpD,UAAU,EAAE,UAAU;IACtB,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,QAAQ;IAClB,WAAW,EAAE,gBAAgB,EAAE,yCAAyC;IACxE,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,qBAAqB;IAChC,aAAa,EAAE,iBAAiB,EAAE,4BAA4B;IAC9D,UAAU,EAAE,gBAAgB;IAC5B,WAAW,EAAE,WAAW;IACxB,gBAAgB,EAAE,gBAAgB;IAClC,2BAA2B,EAAE,2BAA2B;IACxD,eAAe,EAAE,oBAAoB;IACrC,wBAAwB,EAAE,YAAY;IACtC,0CAA0C;IAC1C,mEAAmE;IACnE,oBAAoB,EAAE,oBAAoB;IAC1C,sBAAsB,EAAE,sBAAsB;IAC9C,oBAAoB,EAAE,oBAAoB;IAC1C,QAAQ,EAAE,QAAQ;IAClB,gBAAgB,EAAE,gBAAgB;IAClC,gBAAgB,EAAE,gBAAgB;IAClC,2BAA2B,EAAE,2BAA2B;IACxD,YAAY,EAAE,YAAY;IAC1B,oBAAoB,EAAE,oBAAoB;IAC1C,0BAA0B,EAAE,0BAA0B;IACtD,kBAAkB,EAAE,kBAAkB;IACtC,wBAAwB,EAAE,wBAAwB;IAClD,gBAAgB,EAAE,gBAAgB;IAClC,4EAA4E;IAE5E,8BAA8B;IAC9B,aAAa,EAAE,aAAa;IAC5B,wBAAwB,EAAE,wBAAwB;IAClD,yBAAyB,EAAE,yBAAyB;IAEpD,0BAA0B;IAC1B,YAAY,EAAE,YAAY;IAC1B,gBAAgB,EAAE,gBAAgB;IAClC,kBAAkB,EAAE,kBAAkB;IACtC,cAAc,EAAE,cAAc;IAC9B,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,mBAAmB;IAExC,oBAAoB;IACpB,YAAY,EAAE,YAAY;IAC1B,eAAe,EAAE,eAAe;IAChC,mBAAmB,EAAE,mBAAmB;IACxC,oBAAoB,EAAE,oBAAoB;IAC1C,YAAY,EAAE,YAAY;IAC1B,uBAAuB,EAAE,uBAAuB;IAChD,4BAA4B,EAAE,4BAA4B;IAC1D,oBAAoB,EAAE,oBAAoB;IAC1C,qBAAqB,EAAE,qBAAqB;IAC5C,aAAa,EAAE,aAAa;IAC5B,eAAe,EAAE,eAAe;IAEhC,qBAAqB;IACrB,yBAAyB,EAAE,yBAAyB;IACpD,8BAA8B,EAAE,8BAA8B;IAC9D,0BAA0B,EAAE,0BAA0B;IACtD,0BAA0B,EAAE,0BAA0B;IACtD,qCAAqC,EAAE,qCAAqC;IAC5E,2BAA2B,EAAE,2BAA2B;IACxD,mCAAmC,EAAE,mCAAmC;IAExE,6DAA6D;IAC7D,gBAAgB,EAAE,gBAAgB;IAClC,YAAY,EAAE,YAAY;IAC1B,cAAc,EAAE,cAAc;IAC9B,UAAU,EAAE,UAAU;IACtB,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,WAAW;IACxB,UAAU,EAAE,UAAU;IACtB,eAAe,EAAE,eAAe;IAChC,cAAc,EAAE,cAAc;IAC9B,MAAM,EAAE,MAAM;IACd,6BAA6B,EAAE,6BAA6B;IAE5D,8EAA8E;IAC9E,WAAW,EAAE,WAAW;IACxB,iBAAiB,EAAE,iBAAiB;IACpC,YAAY,EAAE,YAAY;IAC1B,mBAAmB,EAAE,kBAAkB;IACvC,mBAAmB,EAAE,kBAAkB;IACvC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAEhC,qDAAqD;IACrD,iBAAiB,EAAE,iBAAiB,EAAE,gCAAgC;IACtE,6EAA6E;IAC7E,YAAY,EAAE,cAAc,EAAE,eAAe;IAE7C,2DAA2D;IAC3D,UAAU,EAAE,gBAAgB;IAC5B,0DAA0D;IAC1D,0DAA0D;IAC1D,qDAAqD;IACrD,wCAAwC;IACxC,oEAAoE;IACpE,oFAAoF;IACpF,oEAAoE;IACpE,wEAAwE;IACxE,oEAAoE;IACpE,4CAA4C;IAC5C,uEAAuE;IACvE,iDAAiD;CAClD,CAAA;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAA;IACpC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QACnD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAqC;IACvE,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,CAAA;IACjC,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IAEvC,yBAAyB;IACzB,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IACxC,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,0BAA0B;IAC1B,MAAM,UAAU,GAAG,6BAA6B,CAAC,SAAS,CAAC,CAAA;IAC3D,IAAI,UAAU,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7C,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,yBAAyB;IACzB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAAqC;IACrE,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IACxC,OAAO,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAA;AAC1C,CAAC"}
|
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
// deviceCommandMapper.ts
|
|
2
|
-
// Maps HAP/Matter commands to node-switchbot device methods for all supported device types
|
|
3
|
-
export const deviceTypeCommandMap = {
|
|
4
|
-
// SwitchBot AI Hub (read-only/generic)
|
|
5
|
-
'ai hub': {},
|
|
6
|
-
// SwitchBot Cameras (read-only/generic)
|
|
7
|
-
'indoor cam': {},
|
|
8
|
-
'pan/tilt cam': {},
|
|
9
|
-
'pan/tilt cam 2k': {},
|
|
10
|
-
'pan/tilt cam plus 2k': {},
|
|
11
|
-
'pan/tilt cam plus 3k': {},
|
|
12
|
-
// SwitchBot Air Purifiers (read-only/generic)
|
|
13
|
-
'air purifier pm2.5': {},
|
|
14
|
-
'air purifier table pm2.5': {},
|
|
15
|
-
'air purifier voc': {},
|
|
16
|
-
'air purifier table voc': {},
|
|
17
|
-
// SwitchBot Home Climate Panel (read-only/generic)
|
|
18
|
-
'home climate panel': {},
|
|
19
|
-
// SwitchBot WoIOSensor (read-only/generic)
|
|
20
|
-
'woiosensor': {},
|
|
21
|
-
// SwitchBot Candle Warmer Lamp
|
|
22
|
-
'candle warmer lamp': {
|
|
23
|
-
turnOn: async (device) => device.turnOn(),
|
|
24
|
-
turnOff: async (device) => device.turnOff(),
|
|
25
|
-
},
|
|
26
|
-
// SwitchBot Hubs (read-only/generic)
|
|
27
|
-
'hub': {},
|
|
28
|
-
'hub 2': {},
|
|
29
|
-
'hub 3': {},
|
|
30
|
-
'hub mini': {},
|
|
31
|
-
'hub plus': {},
|
|
32
|
-
// SwitchBot Robot Vacuum Cleaner K20 Plus Pro
|
|
33
|
-
'robot vacuum cleaner k20 plus pro': {
|
|
34
|
-
start: async (device) => device.start(),
|
|
35
|
-
stop: async (device) => device.stop(),
|
|
36
|
-
pause: async (device) => device.pause(),
|
|
37
|
-
dock: async (device) => device.dock(),
|
|
38
|
-
resume: async (device) => device.resume(),
|
|
39
|
-
locate: async (device) => device.locate(),
|
|
40
|
-
},
|
|
41
|
-
// SwitchBot Robot Vacuum Cleaner S1
|
|
42
|
-
'robot vacuum cleaner s1': {
|
|
43
|
-
start: async (device) => device.start(),
|
|
44
|
-
stop: async (device) => device.stop(),
|
|
45
|
-
pause: async (device) => device.pause(),
|
|
46
|
-
dock: async (device) => device.dock(),
|
|
47
|
-
resume: async (device) => device.resume(),
|
|
48
|
-
locate: async (device) => device.locate(),
|
|
49
|
-
},
|
|
50
|
-
// SwitchBot Robot Vacuum Cleaner S1 Plus
|
|
51
|
-
'robot vacuum cleaner s1 plus': {
|
|
52
|
-
start: async (device) => device.start(),
|
|
53
|
-
stop: async (device) => device.stop(),
|
|
54
|
-
pause: async (device) => device.pause(),
|
|
55
|
-
dock: async (device) => device.dock(),
|
|
56
|
-
resume: async (device) => device.resume(),
|
|
57
|
-
locate: async (device) => device.locate(),
|
|
58
|
-
},
|
|
59
|
-
// SwitchBot Robot Vacuum Cleaner S10
|
|
60
|
-
'robot vacuum cleaner s10': {
|
|
61
|
-
start: async (device) => device.start(),
|
|
62
|
-
stop: async (device) => device.stop(),
|
|
63
|
-
pause: async (device) => device.pause(),
|
|
64
|
-
dock: async (device) => device.dock(),
|
|
65
|
-
resume: async (device) => device.resume(),
|
|
66
|
-
locate: async (device) => device.locate(),
|
|
67
|
-
},
|
|
68
|
-
// SwitchBot Robot Vacuum Cleaner S20
|
|
69
|
-
'robot vacuum cleaner s20': {
|
|
70
|
-
start: async (device) => device.start(),
|
|
71
|
-
stop: async (device) => device.stop(),
|
|
72
|
-
pause: async (device) => device.pause(),
|
|
73
|
-
dock: async (device) => device.dock(),
|
|
74
|
-
resume: async (device) => device.resume(),
|
|
75
|
-
locate: async (device) => device.locate(),
|
|
76
|
-
},
|
|
77
|
-
// SwitchBot Relay Switch 2PM
|
|
78
|
-
'relay switch 2pm': {
|
|
79
|
-
turnOn: async (device) => device.turnOn(),
|
|
80
|
-
turnOff: async (device) => device.turnOff(),
|
|
81
|
-
},
|
|
82
|
-
// SwitchBot K10+
|
|
83
|
-
'k10+': {
|
|
84
|
-
start: async (device) => device.start(),
|
|
85
|
-
stop: async (device) => device.stop(),
|
|
86
|
-
pause: async (device) => device.pause(),
|
|
87
|
-
dock: async (device) => device.dock(),
|
|
88
|
-
resume: async (device) => device.resume(),
|
|
89
|
-
locate: async (device) => device.locate(),
|
|
90
|
-
},
|
|
91
|
-
// SwitchBot K10+ Pro
|
|
92
|
-
'k10+ pro': {
|
|
93
|
-
start: async (device) => device.start(),
|
|
94
|
-
stop: async (device) => device.stop(),
|
|
95
|
-
pause: async (device) => device.pause(),
|
|
96
|
-
dock: async (device) => device.dock(),
|
|
97
|
-
resume: async (device) => device.resume(),
|
|
98
|
-
locate: async (device) => device.locate(),
|
|
99
|
-
},
|
|
100
|
-
// SwitchBot Robot Vacuum Cleaner K10+ Pro Combo
|
|
101
|
-
'robot vacuum cleaner k10+ pro combo': {
|
|
102
|
-
start: async (device) => device.start(),
|
|
103
|
-
stop: async (device) => device.stop(),
|
|
104
|
-
pause: async (device) => device.pause(),
|
|
105
|
-
dock: async (device) => device.dock(),
|
|
106
|
-
resume: async (device) => device.resume(),
|
|
107
|
-
locate: async (device) => device.locate(),
|
|
108
|
-
},
|
|
109
|
-
// SwitchBot Robot Vacuum Cleaner K11+
|
|
110
|
-
'robot vacuum cleaner k11+': {
|
|
111
|
-
start: async (device) => device.start(),
|
|
112
|
-
stop: async (device) => device.stop(),
|
|
113
|
-
pause: async (device) => device.pause(),
|
|
114
|
-
dock: async (device) => device.dock(),
|
|
115
|
-
resume: async (device) => device.resume(),
|
|
116
|
-
locate: async (device) => device.locate(),
|
|
117
|
-
},
|
|
118
|
-
// SwitchBot MeterPro(CO2) (read-only)
|
|
119
|
-
'meterpro(co2)': {},
|
|
120
|
-
// SwitchBot Water Detector (read-only)
|
|
121
|
-
'water detector': {},
|
|
122
|
-
// SwitchBot Garage Door Opener
|
|
123
|
-
'garage door opener': {
|
|
124
|
-
open: async (device) => device.open(),
|
|
125
|
-
close: async (device) => device.close(),
|
|
126
|
-
stop: async (device) => device.stop(),
|
|
127
|
-
},
|
|
128
|
-
// SwitchBot Relay Switch 1
|
|
129
|
-
'relay switch 1': {
|
|
130
|
-
turnOn: async (device) => device.turnOn(),
|
|
131
|
-
turnOff: async (device) => device.turnOff(),
|
|
132
|
-
},
|
|
133
|
-
// SwitchBot Relay Switch 1PM
|
|
134
|
-
'relay switch 1pm': {
|
|
135
|
-
turnOn: async (device) => device.turnOn(),
|
|
136
|
-
turnOff: async (device) => device.turnOff(),
|
|
137
|
-
},
|
|
138
|
-
// SwitchBot Smart Radiator Thermostat (read-only or not directly controllable)
|
|
139
|
-
'smart radiator thermostat': {},
|
|
140
|
-
// SwitchBot Humidifier2
|
|
141
|
-
'humidifier2': {
|
|
142
|
-
turnOn: async (device) => device.turnOn(),
|
|
143
|
-
turnOff: async (device) => device.turnOff(),
|
|
144
|
-
setMode: async (device, body) => device.setMode(body?.parameter),
|
|
145
|
-
setHumidity: async (device, body) => device.setHumidity(body?.parameter),
|
|
146
|
-
},
|
|
147
|
-
// SwitchBot MeterPlus (read-only)
|
|
148
|
-
'meterplus': {},
|
|
149
|
-
// SwitchBot Meter Pro (read-only)
|
|
150
|
-
'meter pro': {},
|
|
151
|
-
// SwitchBot MeterPro (read-only)
|
|
152
|
-
'meterpro': {},
|
|
153
|
-
// SwitchBot RGBICWW Floor Lamp
|
|
154
|
-
'rgbicww floor lamp': {
|
|
155
|
-
turnOn: async (device) => device.turnOn(),
|
|
156
|
-
turnOff: async (device) => device.turnOff(),
|
|
157
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
158
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
159
|
-
},
|
|
160
|
-
// SwitchBot RGBICWW Strip Light
|
|
161
|
-
'rgbicww strip light': {
|
|
162
|
-
turnOn: async (device) => device.turnOn(),
|
|
163
|
-
turnOff: async (device) => device.turnOff(),
|
|
164
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
165
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
166
|
-
},
|
|
167
|
-
// SwitchBot Circulator Fan
|
|
168
|
-
'circulator fan': {
|
|
169
|
-
turnOn: async (device) => device.turnOn(),
|
|
170
|
-
turnOff: async (device) => device.turnOff(),
|
|
171
|
-
setSpeed: async (device, body) => device.setSpeed(body?.parameter),
|
|
172
|
-
swing: async (device) => device.swing(),
|
|
173
|
-
},
|
|
174
|
-
// SwitchBot Battery Circulator Fan
|
|
175
|
-
'battery circulator fan': {
|
|
176
|
-
turnOn: async (device) => device.turnOn(),
|
|
177
|
-
turnOff: async (device) => device.turnOff(),
|
|
178
|
-
setSpeed: async (device, body) => device.setSpeed(body?.parameter),
|
|
179
|
-
swing: async (device) => device.swing(),
|
|
180
|
-
},
|
|
181
|
-
// SwitchBot Standing Circulator Fan
|
|
182
|
-
'standing circulator fan': {
|
|
183
|
-
turnOn: async (device) => device.turnOn(),
|
|
184
|
-
turnOff: async (device) => device.turnOff(),
|
|
185
|
-
setSpeed: async (device, body) => device.setSpeed(body?.parameter),
|
|
186
|
-
swing: async (device) => device.swing(),
|
|
187
|
-
},
|
|
188
|
-
// SwitchBot Bot
|
|
189
|
-
'bot': {
|
|
190
|
-
turnOn: async (device) => device.turnOn(),
|
|
191
|
-
turnOff: async (device) => device.turnOff(),
|
|
192
|
-
press: async (device) => device.press(),
|
|
193
|
-
},
|
|
194
|
-
// SwitchBot Curtain
|
|
195
|
-
'curtain': {
|
|
196
|
-
open: async (device) => device.open(),
|
|
197
|
-
close: async (device) => device.close(),
|
|
198
|
-
pause: async (device) => device.pause(),
|
|
199
|
-
setPosition: async (device, body) => device.setPosition(body?.parameter),
|
|
200
|
-
},
|
|
201
|
-
// SwitchBot Blind Tilt
|
|
202
|
-
'blind tilt': {
|
|
203
|
-
open: async (device) => device.open(),
|
|
204
|
-
close: async (device) => device.close(),
|
|
205
|
-
pause: async (device) => device.pause(),
|
|
206
|
-
setPosition: async (device, body) => device.setPosition(body?.parameter),
|
|
207
|
-
},
|
|
208
|
-
// SwitchBot Roller Shade
|
|
209
|
-
'roller shade': {
|
|
210
|
-
open: async (device) => device.open(),
|
|
211
|
-
close: async (device) => device.close(),
|
|
212
|
-
pause: async (device) => device.pause(),
|
|
213
|
-
setPosition: async (device, body) => device.setPosition(body?.parameter),
|
|
214
|
-
},
|
|
215
|
-
// SwitchBot Plug
|
|
216
|
-
'plug': {
|
|
217
|
-
turnOn: async (device) => device.turnOn(),
|
|
218
|
-
turnOff: async (device) => device.turnOff(),
|
|
219
|
-
},
|
|
220
|
-
// SwitchBot Strip Light 3
|
|
221
|
-
'strip light 3': {
|
|
222
|
-
turnOn: async (device) => device.turnOn(),
|
|
223
|
-
turnOff: async (device) => device.turnOff(),
|
|
224
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
225
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
226
|
-
},
|
|
227
|
-
// SwitchBot Floor Lamp
|
|
228
|
-
'floor lamp': {
|
|
229
|
-
turnOn: async (device) => device.turnOn(),
|
|
230
|
-
turnOff: async (device) => device.turnOff(),
|
|
231
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
232
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
233
|
-
},
|
|
234
|
-
// SwitchBot RGBIC Neon Rope Light
|
|
235
|
-
'rgbic neon rope light': {
|
|
236
|
-
turnOn: async (device) => device.turnOn(),
|
|
237
|
-
turnOff: async (device) => device.turnOff(),
|
|
238
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
239
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
240
|
-
},
|
|
241
|
-
// SwitchBot RGBIC Neon Wire Rope Light
|
|
242
|
-
'rgbic neon wire rope light': {
|
|
243
|
-
turnOn: async (device) => device.turnOn(),
|
|
244
|
-
turnOff: async (device) => device.turnOff(),
|
|
245
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
246
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
247
|
-
},
|
|
248
|
-
// SwitchBot Plug Mini
|
|
249
|
-
'plug mini': {
|
|
250
|
-
turnOn: async (device) => device.turnOn(),
|
|
251
|
-
turnOff: async (device) => device.turnOff(),
|
|
252
|
-
},
|
|
253
|
-
// SwitchBot Color Bulb
|
|
254
|
-
'color bulb': {
|
|
255
|
-
turnOn: async (device) => device.turnOn(),
|
|
256
|
-
turnOff: async (device) => device.turnOff(),
|
|
257
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
258
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
259
|
-
},
|
|
260
|
-
// SwitchBot Light Strip
|
|
261
|
-
'light strip': {
|
|
262
|
-
turnOn: async (device) => device.turnOn(),
|
|
263
|
-
turnOff: async (device) => device.turnOff(),
|
|
264
|
-
setBrightness: async (device, body) => device.setBrightness(body?.parameter),
|
|
265
|
-
setColor: async (device, body) => device.setColor(body?.parameter),
|
|
266
|
-
},
|
|
267
|
-
// SwitchBot Fan
|
|
268
|
-
'fan': {
|
|
269
|
-
turnOn: async (device) => device.turnOn(),
|
|
270
|
-
turnOff: async (device) => device.turnOff(),
|
|
271
|
-
setSpeed: async (device, body) => device.setSpeed(body?.parameter),
|
|
272
|
-
swing: async (device) => device.swing(),
|
|
273
|
-
},
|
|
274
|
-
// SwitchBot Lock
|
|
275
|
-
'lock': {
|
|
276
|
-
lock: async (device) => device.lock(),
|
|
277
|
-
unlock: async (device) => device.unlock(),
|
|
278
|
-
},
|
|
279
|
-
// SwitchBot Curtain 3
|
|
280
|
-
'curtain3': {
|
|
281
|
-
open: async (device) => device.open(),
|
|
282
|
-
close: async (device) => device.close(),
|
|
283
|
-
pause: async (device) => device.pause(),
|
|
284
|
-
setPosition: async (device, body) => device.setPosition(body?.parameter),
|
|
285
|
-
},
|
|
286
|
-
// SwitchBot Meter
|
|
287
|
-
'meter': {}, // Read-only
|
|
288
|
-
// SwitchBot Motion Sensor
|
|
289
|
-
'motion sensor': {}, // Read-only
|
|
290
|
-
// SwitchBot Contact Sensor
|
|
291
|
-
'contact sensor': {}, // Read-only
|
|
292
|
-
// SwitchBot Humidifier
|
|
293
|
-
'humidifier': {
|
|
294
|
-
turnOn: async (device) => device.turnOn(),
|
|
295
|
-
turnOff: async (device) => device.turnOff(),
|
|
296
|
-
setMode: async (device, body) => device.setMode(body?.parameter),
|
|
297
|
-
setHumidity: async (device, body) => device.setHumidity(body?.parameter),
|
|
298
|
-
},
|
|
299
|
-
// SwitchBot Vacuum
|
|
300
|
-
'vacuum': {
|
|
301
|
-
start: async (device) => device.start(),
|
|
302
|
-
stop: async (device) => device.stop(),
|
|
303
|
-
pause: async (device) => device.pause(),
|
|
304
|
-
dock: async (device) => device.dock(),
|
|
305
|
-
resume: async (device) => device.resume(),
|
|
306
|
-
locate: async (device) => device.locate(),
|
|
307
|
-
},
|
|
308
|
-
// Add more device types and commands as needed
|
|
309
|
-
};
|
|
310
|
-
// Helper to get the handler for a device type and command
|
|
311
|
-
export function getDeviceCommandHandler(deviceType, command) {
|
|
312
|
-
const typeKey = deviceType.toLowerCase();
|
|
313
|
-
const typeMap = deviceTypeCommandMap[typeKey];
|
|
314
|
-
if (!typeMap) {
|
|
315
|
-
return undefined;
|
|
316
|
-
}
|
|
317
|
-
return typeMap[command];
|
|
318
|
-
}
|
|
319
|
-
//# sourceMappingURL=deviceCommandMapper.js.map
|