@switchbot/homebridge-switchbot 5.0.0-beta.93 → 5.0.0-beta.95
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/dist/devices/genericDevice.d.ts +15 -0
- package/dist/devices/genericDevice.d.ts.map +1 -1
- package/dist/devices/genericDevice.js +31 -1
- package/dist/devices/genericDevice.js.map +1 -1
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +306 -38
- package/dist/platform.js.map +1 -1
- package/docs/variables/default.html +1 -1
- package/package.json +2 -2
- package/src/devices/genericDevice.ts +31 -1
- package/src/platform.ts +321 -38
|
@@ -764,14 +764,44 @@ export class HumidifierDevice extends GenericDevice {
|
|
|
764
764
|
return {
|
|
765
765
|
services: [
|
|
766
766
|
{
|
|
767
|
-
type: '
|
|
767
|
+
type: 'HumidifierDehumidifier',
|
|
768
768
|
characteristics: {
|
|
769
|
+
Active: {
|
|
770
|
+
get: async () => {
|
|
771
|
+
const s = await this.getState()
|
|
772
|
+
return s && s.on ? 1 : 0
|
|
773
|
+
},
|
|
774
|
+
set: async (v: any) => {
|
|
775
|
+
await this.setState({ on: v === 1 })
|
|
776
|
+
},
|
|
777
|
+
},
|
|
778
|
+
CurrentHumidifierDehumidifierState: {
|
|
779
|
+
get: async () => {
|
|
780
|
+
const s = await this.getState()
|
|
781
|
+
return s && s.on ? 2 : 0 // 0 = Inactive, 2 = Humidifying
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
TargetHumidifierDehumidifierState: {
|
|
785
|
+
get: async () => 1, // 1 = Humidifier
|
|
786
|
+
set: async (v: any) => {
|
|
787
|
+
// Support humidifier mode
|
|
788
|
+
},
|
|
789
|
+
},
|
|
769
790
|
CurrentRelativeHumidity: {
|
|
770
791
|
get: async () => {
|
|
771
792
|
const s = await this.getState()
|
|
772
793
|
return typeof s.humidity === 'number' ? s.humidity : 0
|
|
773
794
|
},
|
|
774
795
|
},
|
|
796
|
+
RelativeHumidityHumidifierThreshold: {
|
|
797
|
+
get: async () => {
|
|
798
|
+
const s = await this.getState()
|
|
799
|
+
return typeof s.targetHumidity === 'number' ? s.targetHumidity : 50
|
|
800
|
+
},
|
|
801
|
+
set: async (v: any) => {
|
|
802
|
+
await this.setState({ humidity: Number(v) })
|
|
803
|
+
},
|
|
804
|
+
},
|
|
775
805
|
},
|
|
776
806
|
},
|
|
777
807
|
],
|
package/src/platform.ts
CHANGED
|
@@ -6,37 +6,224 @@ import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
|
|
|
6
6
|
import { SwitchBotClient } from './switchbotClient.js'
|
|
7
7
|
|
|
8
8
|
// Which device types should prefer Matter if available
|
|
9
|
+
// Based on HAP service mappings: device implementations use specific HomeKit services
|
|
10
|
+
// that map to corresponding Matter clusters when Matter is enabled
|
|
9
11
|
const DEVICE_MATTER_SUPPORTED: Record<string, boolean> = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
// Core devices
|
|
13
|
+
'bot': true, // Switch → OnOff
|
|
14
|
+
'curtain': true, // WindowCovering → WindowCovering
|
|
15
|
+
'fan': true, // Fan → FanControl
|
|
16
|
+
'light': true, // Lightbulb → OnOff + LevelControl
|
|
17
|
+
'lightstrip': true, // Lightbulb (color) → OnOff + LevelControl + ColorControl
|
|
18
|
+
'motion': true, // MotionSensor → OccupancySensing
|
|
19
|
+
'contact': true, // ContactSensor → BooleanState
|
|
20
|
+
'vacuum': true, // Switch → RobotVacuumCleaner
|
|
21
|
+
'lock': true, // LockMechanism → DoorLock
|
|
22
|
+
'humidifier': true, // Fan + Humidity → OnOff + FanControl + RelativeHumidityMeasurement
|
|
23
|
+
'temperature': true, // TemperatureSensor → TemperatureMeasurement
|
|
24
|
+
|
|
25
|
+
// Switch devices
|
|
26
|
+
'relay': true, // Switch → OnOff
|
|
27
|
+
'relay switch 1': true, // Switch → OnOff
|
|
28
|
+
'relay switch 1pm': true, // Switch → OnOff
|
|
29
|
+
'plug': true, // Outlet → OnOff
|
|
30
|
+
'plug mini (jp)': true, // Outlet → OnOff
|
|
31
|
+
'plug mini (us)': true, // Outlet → OnOff
|
|
32
|
+
|
|
33
|
+
// Window covering variants
|
|
34
|
+
'blindtilt': true, // WindowCovering → WindowCovering
|
|
35
|
+
'blind tilt': true, // WindowCovering → WindowCovering
|
|
36
|
+
'curtain3': true, // WindowCovering → WindowCovering
|
|
37
|
+
'rollershade': true, // WindowCovering → WindowCovering
|
|
38
|
+
'roller shade': true, // WindowCovering → WindowCovering
|
|
39
|
+
'worollershade': true, // WindowCovering → WindowCovering
|
|
40
|
+
'wo rollershade': true, // WindowCovering → WindowCovering
|
|
41
|
+
|
|
42
|
+
// Vacuum variants (normalized to 'vacuum' before lookup)
|
|
43
|
+
'wosweeper': true, // VacuumDevice → RobotVacuumCleaner
|
|
44
|
+
'wosweepermini': true, // VacuumDevice → RobotVacuumCleaner
|
|
45
|
+
'wosweeperminipro': true, // VacuumDevice → RobotVacuumCleaner
|
|
46
|
+
'k10+': true, // VacuumDevice → RobotVacuumCleaner
|
|
47
|
+
'k10+ pro': true, // VacuumDevice → RobotVacuumCleaner
|
|
48
|
+
|
|
49
|
+
// Sensors
|
|
50
|
+
'meter': true, // TemperatureSensor + HumiditySensor → TemperatureMeasurement + RelativeHumidityMeasurement
|
|
51
|
+
'meterplus': true, // TemperatureSensor + HumiditySensor → TemperatureMeasurement + RelativeHumidityMeasurement
|
|
52
|
+
'meter plus (jp)': true, // TemperatureSensor + HumiditySensor → TemperatureMeasurement + RelativeHumidityMeasurement
|
|
53
|
+
'meterpro': true, // TemperatureSensor + HumiditySensor → TemperatureMeasurement + RelativeHumidityMeasurement
|
|
54
|
+
'meterpro(co2)': true, // TemperatureSensor + HumiditySensor → TemperatureMeasurement + RelativeHumidityMeasurement
|
|
55
|
+
'waterdetector': true, // LeakSensor → BooleanState
|
|
56
|
+
'water detector': true, // LeakSensor → BooleanState
|
|
57
|
+
|
|
58
|
+
// Other devices
|
|
59
|
+
'smart fan': true, // Fan → FanControl
|
|
60
|
+
'strip light': true, // Lightbulb (color) → OnOff + LevelControl + ColorControl
|
|
61
|
+
'hub 2': false, // Hub device - not exposed as accessory
|
|
62
|
+
'walletfinder': false, // Button device - Matter support TBD
|
|
24
63
|
}
|
|
25
64
|
|
|
26
65
|
// Default Matter cluster configurations by device type
|
|
27
|
-
//
|
|
66
|
+
// Maps device types to their Matter cluster states (used when device doesn't provide clusters)
|
|
67
|
+
// Note: wosweeper/curtain/plug variants are normalized before cluster lookup (see loadDevices)
|
|
28
68
|
const DEVICE_MATTER_CLUSTERS: Record<string, any> = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
69
|
+
// Core devices - aligned with HAP service implementations
|
|
70
|
+
bot: { onOff: { onOff: false } }, // Switch → OnOff
|
|
71
|
+
vacuum: {
|
|
72
|
+
robotVacuumCleaner: { operationalState: 0, runMode: 0 },
|
|
73
|
+
operationalState: { operationalState: 0 },
|
|
74
|
+
}, // Switch in HAP, RobotVacuumCleaner in Matter
|
|
75
|
+
curtain: {
|
|
76
|
+
windowCovering: {
|
|
77
|
+
currentPositionLiftPercent100ths: 0,
|
|
78
|
+
targetPositionLiftPercent100ths: 0,
|
|
79
|
+
operationalStatus: 0,
|
|
80
|
+
},
|
|
81
|
+
}, // WindowCovering → WindowCovering (includes curtain3, rollershade variants via normalization)
|
|
82
|
+
blindtilt: {
|
|
83
|
+
windowCovering: {
|
|
84
|
+
currentPositionLiftPercent100ths: 0,
|
|
85
|
+
targetPositionLiftPercent100ths: 0,
|
|
86
|
+
currentPositionTiltPercent100ths: 0,
|
|
87
|
+
targetPositionTiltPercent100ths: 0,
|
|
88
|
+
operationalStatus: 0,
|
|
89
|
+
},
|
|
90
|
+
}, // WindowCovering with tilt → WindowCovering
|
|
91
|
+
fan: {
|
|
92
|
+
onOff: { onOff: false },
|
|
93
|
+
fanControl: {
|
|
94
|
+
fanMode: 0,
|
|
95
|
+
percentCurrent: 0,
|
|
96
|
+
percentSetting: 0,
|
|
97
|
+
speedCurrent: 0,
|
|
98
|
+
speedMax: 100,
|
|
99
|
+
},
|
|
100
|
+
}, // Fan → OnOff + FanControl
|
|
101
|
+
light: {
|
|
102
|
+
onOff: { onOff: false },
|
|
103
|
+
levelControl: {
|
|
104
|
+
currentLevel: 0,
|
|
105
|
+
minLevel: 0,
|
|
106
|
+
maxLevel: 254,
|
|
107
|
+
},
|
|
108
|
+
}, // Lightbulb → OnOff + LevelControl
|
|
109
|
+
lightstrip: {
|
|
110
|
+
onOff: { onOff: false },
|
|
111
|
+
levelControl: {
|
|
112
|
+
currentLevel: 0,
|
|
113
|
+
minLevel: 0,
|
|
114
|
+
maxLevel: 254,
|
|
115
|
+
},
|
|
116
|
+
colorControl: {
|
|
117
|
+
currentHue: 0,
|
|
118
|
+
currentSaturation: 0,
|
|
119
|
+
colorTemperatureMireds: 400,
|
|
120
|
+
colorMode: 0,
|
|
121
|
+
},
|
|
122
|
+
}, // Lightbulb with color → OnOff + LevelControl + ColorControl
|
|
123
|
+
lock: {
|
|
124
|
+
doorLock: {
|
|
125
|
+
lockState: 0,
|
|
126
|
+
lockType: 0,
|
|
127
|
+
actuatorEnabled: true,
|
|
128
|
+
operatingMode: 0,
|
|
129
|
+
},
|
|
130
|
+
}, // LockMechanism → DoorLock
|
|
131
|
+
motion: {
|
|
132
|
+
occupancySensing: {
|
|
133
|
+
occupancy: 0,
|
|
134
|
+
occupancySensorType: 0,
|
|
135
|
+
},
|
|
136
|
+
}, // MotionSensor → OccupancySensing
|
|
137
|
+
contact: {
|
|
138
|
+
booleanState: {
|
|
139
|
+
stateValue: false,
|
|
140
|
+
},
|
|
141
|
+
}, // ContactSensor → BooleanState
|
|
142
|
+
humidifier: {
|
|
143
|
+
onOff: { onOff: false },
|
|
144
|
+
fanControl: {
|
|
145
|
+
fanMode: 0,
|
|
146
|
+
percentCurrent: 0,
|
|
147
|
+
},
|
|
148
|
+
relativeHumidityMeasurement: {
|
|
149
|
+
measuredValue: 0,
|
|
150
|
+
minMeasuredValue: 0,
|
|
151
|
+
maxMeasuredValue: 100,
|
|
152
|
+
},
|
|
153
|
+
}, // HumidifierDehumidifier → OnOff + FanControl + RelativeHumidityMeasurement
|
|
154
|
+
temperature: {
|
|
155
|
+
temperatureMeasurement: {
|
|
156
|
+
measuredValue: 0,
|
|
157
|
+
minMeasuredValue: -27315,
|
|
158
|
+
maxMeasuredValue: 32767,
|
|
159
|
+
},
|
|
160
|
+
}, // TemperatureSensor → TemperatureMeasurement
|
|
161
|
+
|
|
162
|
+
// Switch/Outlet devices
|
|
163
|
+
relay: { onOff: { onOff: false } }, // Switch → OnOff
|
|
164
|
+
plug: {
|
|
165
|
+
onOff: { onOff: false },
|
|
166
|
+
electricalMeasurement: {
|
|
167
|
+
activePower: 0,
|
|
168
|
+
rmsCurrent: 0,
|
|
169
|
+
rmsVoltage: 0,
|
|
170
|
+
},
|
|
171
|
+
}, // Outlet → OnOff + ElectricalMeasurement (for PM models)
|
|
172
|
+
|
|
173
|
+
// Sensors
|
|
174
|
+
meter: {
|
|
175
|
+
temperatureMeasurement: {
|
|
176
|
+
measuredValue: 0,
|
|
177
|
+
minMeasuredValue: -27315,
|
|
178
|
+
maxMeasuredValue: 32767,
|
|
179
|
+
},
|
|
180
|
+
relativeHumidityMeasurement: {
|
|
181
|
+
measuredValue: 0,
|
|
182
|
+
minMeasuredValue: 0,
|
|
183
|
+
maxMeasuredValue: 100,
|
|
184
|
+
},
|
|
185
|
+
}, // TemperatureSensor + HumiditySensor → TemperatureMeasurement + RelativeHumidityMeasurement
|
|
186
|
+
waterdetector: {
|
|
187
|
+
booleanState: {
|
|
188
|
+
stateValue: false,
|
|
189
|
+
},
|
|
190
|
+
}, // LeakSensor → BooleanState
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const DEVICE_MATTER_DEVICE_TYPE_KEYS: Record<string, string> = {
|
|
194
|
+
bot: 'OnOffSwitch',
|
|
195
|
+
vacuum: 'RoboticVacuumCleaner',
|
|
196
|
+
curtain: 'WindowCovering',
|
|
197
|
+
blindtilt: 'WindowCovering',
|
|
198
|
+
fan: 'Fan',
|
|
199
|
+
light: 'DimmableLight',
|
|
200
|
+
lightstrip: 'ExtendedColorLight',
|
|
201
|
+
lock: 'DoorLock',
|
|
202
|
+
motion: 'MotionSensor',
|
|
203
|
+
contact: 'ContactSensor',
|
|
204
|
+
humidifier: 'Fan',
|
|
205
|
+
temperature: 'TemperatureSensor',
|
|
206
|
+
relay: 'OnOffSwitch',
|
|
207
|
+
plug: 'OnOffOutlet',
|
|
208
|
+
meter: 'TemperatureSensor',
|
|
209
|
+
waterdetector: 'LeakSensor',
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function resolveMatterDeviceType(matterApi: any, type: string, createdDeviceType?: any, clusters?: any): any {
|
|
213
|
+
if (createdDeviceType && typeof createdDeviceType === 'object' && typeof createdDeviceType.with === 'function') {
|
|
214
|
+
return createdDeviceType
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const lowerType = (typeof createdDeviceType === 'string' && createdDeviceType) ? createdDeviceType.toLowerCase() : (type || '').toLowerCase()
|
|
218
|
+
|
|
219
|
+
// Cluster-based upgrade for color lights if descriptor omitted device type.
|
|
220
|
+
const hasColorControl = !!clusters?.colorControl
|
|
221
|
+
const inferredType = hasColorControl && lowerType === 'light'
|
|
222
|
+
? 'lightstrip'
|
|
223
|
+
: lowerType
|
|
224
|
+
|
|
225
|
+
const mappedKey = DEVICE_MATTER_DEVICE_TYPE_KEYS[inferredType] || 'OnOffSwitch'
|
|
226
|
+
return matterApi?.deviceTypes?.[mappedKey] || matterApi?.deviceTypes?.OnOffSwitch
|
|
40
227
|
}
|
|
41
228
|
|
|
42
229
|
export class SwitchBotHAPPlatform {
|
|
@@ -125,10 +312,40 @@ export class SwitchBotHAPPlatform {
|
|
|
125
312
|
}
|
|
126
313
|
|
|
127
314
|
let type: string = d.type
|
|
128
|
-
// Normalize
|
|
129
|
-
|
|
315
|
+
// Normalize device type variants for consistent Matter cluster lookup
|
|
316
|
+
// Vacuum variants
|
|
317
|
+
if (['wosweeper', 'wosweepermini', 'wosweeperminipro', 'k10+', 'k10+ pro'].includes((type || '').toLowerCase())) {
|
|
130
318
|
type = 'vacuum'
|
|
131
319
|
}
|
|
320
|
+
// Window covering variants
|
|
321
|
+
if (['blindtilt', 'blind tilt', 'curtain3', 'rollershade', 'roller shade', 'worollershade', 'wo rollershade'].includes((type || '').toLowerCase())) {
|
|
322
|
+
type = 'curtain'
|
|
323
|
+
}
|
|
324
|
+
// Plug variants
|
|
325
|
+
if (['plug mini (jp)', 'plug mini (us)'].includes((type || '').toLowerCase())) {
|
|
326
|
+
type = 'plug'
|
|
327
|
+
}
|
|
328
|
+
// Meter variants
|
|
329
|
+
if (['meterplus', 'meter plus (jp)', 'meterpro', 'meterpro(co2)'].includes((type || '').toLowerCase())) {
|
|
330
|
+
type = 'meter'
|
|
331
|
+
}
|
|
332
|
+
// Relay switch variants
|
|
333
|
+
if (['relay switch 1', 'relay switch 1pm'].includes((type || '').toLowerCase())) {
|
|
334
|
+
type = 'relay'
|
|
335
|
+
}
|
|
336
|
+
// Water detector variants
|
|
337
|
+
if (['water detector'].includes((type || '').toLowerCase())) {
|
|
338
|
+
type = 'waterdetector'
|
|
339
|
+
}
|
|
340
|
+
// Fan variants
|
|
341
|
+
if (['smart fan'].includes((type || '').toLowerCase())) {
|
|
342
|
+
type = 'fan'
|
|
343
|
+
}
|
|
344
|
+
// Light variants
|
|
345
|
+
if (['strip light'].includes((type || '').toLowerCase())) {
|
|
346
|
+
type = 'lightstrip'
|
|
347
|
+
}
|
|
348
|
+
|
|
132
349
|
const matterSupported = !!DEVICE_MATTER_SUPPORTED[(type || '').toLowerCase()]
|
|
133
350
|
// Auto-detect Matter from Homebridge API, allow manual override via config
|
|
134
351
|
const matterAvailable = !!(this.api?.isMatterAvailable?.() && this.api?.isMatterEnabled?.())
|
|
@@ -149,17 +366,19 @@ export class SwitchBotHAPPlatform {
|
|
|
149
366
|
const createdDesc = created.createAccessory?.(this.api) || { id: d.id, name: d.name || type }
|
|
150
367
|
const uuid = matterApi.uuid.generate(`${d.id}`)
|
|
151
368
|
const defaultClusters = DEVICE_MATTER_CLUSTERS[type.toLowerCase()] || { onOff: { onOff: false } }
|
|
369
|
+
const clusters = createdDesc.clusters || defaultClusters
|
|
370
|
+
const deviceType = resolveMatterDeviceType(matterApi, type, createdDesc.deviceType, clusters)
|
|
152
371
|
const accessory: any = {
|
|
153
372
|
UUID: uuid,
|
|
154
373
|
displayName: createdDesc.name || d.name || type,
|
|
155
|
-
deviceType
|
|
374
|
+
deviceType,
|
|
156
375
|
manufacturer: createdDesc.manufacturer || 'SwitchBot',
|
|
157
376
|
model: createdDesc.model || type,
|
|
158
377
|
serialNumber: createdDesc.serialNumber || d.id,
|
|
159
378
|
reachable: createdDesc.reachable !== false,
|
|
160
379
|
firmwareRevision: createdDesc.firmwareRevision || '1.0.0',
|
|
161
380
|
hardwareRevision: createdDesc.hardwareRevision || '',
|
|
162
|
-
clusters
|
|
381
|
+
clusters,
|
|
163
382
|
context: { deviceId: d.id, type, _created: true },
|
|
164
383
|
}
|
|
165
384
|
try {
|
|
@@ -369,10 +588,40 @@ export class SwitchBotMatterPlatform {
|
|
|
369
588
|
}
|
|
370
589
|
|
|
371
590
|
let type: string = d.type
|
|
372
|
-
// Normalize
|
|
373
|
-
|
|
591
|
+
// Normalize device type variants for consistent Matter cluster lookup
|
|
592
|
+
// Vacuum variants
|
|
593
|
+
if (['wosweeper', 'wosweepermini', 'wosweeperminipro', 'k10+', 'k10+ pro'].includes((type || '').toLowerCase())) {
|
|
374
594
|
type = 'vacuum'
|
|
375
595
|
}
|
|
596
|
+
// Window covering variants
|
|
597
|
+
if (['blindtilt', 'blind tilt', 'curtain3', 'rollershade', 'roller shade', 'worollershade', 'wo rollershade'].includes((type || '').toLowerCase())) {
|
|
598
|
+
type = 'curtain'
|
|
599
|
+
}
|
|
600
|
+
// Plug variants
|
|
601
|
+
if (['plug mini (jp)', 'plug mini (us)'].includes((type || '').toLowerCase())) {
|
|
602
|
+
type = 'plug'
|
|
603
|
+
}
|
|
604
|
+
// Meter variants
|
|
605
|
+
if (['meterplus', 'meter plus (jp)', 'meterpro', 'meterpro(co2)'].includes((type || '').toLowerCase())) {
|
|
606
|
+
type = 'meter'
|
|
607
|
+
}
|
|
608
|
+
// Relay switch variants
|
|
609
|
+
if (['relay switch 1', 'relay switch 1pm'].includes((type || '').toLowerCase())) {
|
|
610
|
+
type = 'relay'
|
|
611
|
+
}
|
|
612
|
+
// Water detector variants
|
|
613
|
+
if (['water detector'].includes((type || '').toLowerCase())) {
|
|
614
|
+
type = 'waterdetector'
|
|
615
|
+
}
|
|
616
|
+
// Fan variants
|
|
617
|
+
if (['smart fan'].includes((type || '').toLowerCase())) {
|
|
618
|
+
type = 'fan'
|
|
619
|
+
}
|
|
620
|
+
// Light variants
|
|
621
|
+
if (['strip light'].includes((type || '').toLowerCase())) {
|
|
622
|
+
type = 'lightstrip'
|
|
623
|
+
}
|
|
624
|
+
|
|
376
625
|
const matterSupported = !!DEVICE_MATTER_SUPPORTED[(type || '').toLowerCase()]
|
|
377
626
|
// Auto-detect Matter from Homebridge API, allow manual override via config
|
|
378
627
|
const matterAvailable = this.api?.isMatterAvailable?.() && this.api?.isMatterEnabled?.()
|
|
@@ -471,10 +720,40 @@ export class SwitchBotMatterPlatform {
|
|
|
471
720
|
}
|
|
472
721
|
|
|
473
722
|
let type: string = d.type
|
|
474
|
-
// Normalize
|
|
475
|
-
|
|
723
|
+
// Normalize device type variants for consistent Matter cluster lookup
|
|
724
|
+
// Vacuum variants
|
|
725
|
+
if (['wosweeper', 'wosweepermini', 'wosweeperminipro', 'k10+', 'k10+ pro'].includes((type || '').toLowerCase())) {
|
|
476
726
|
type = 'vacuum'
|
|
477
727
|
}
|
|
728
|
+
// Window covering variants
|
|
729
|
+
if (['blindtilt', 'blind tilt', 'curtain3', 'rollershade', 'roller shade', 'worollershade', 'wo rollershade'].includes((type || '').toLowerCase())) {
|
|
730
|
+
type = 'curtain'
|
|
731
|
+
}
|
|
732
|
+
// Plug variants
|
|
733
|
+
if (['plug mini (jp)', 'plug mini (us)'].includes((type || '').toLowerCase())) {
|
|
734
|
+
type = 'plug'
|
|
735
|
+
}
|
|
736
|
+
// Meter variants
|
|
737
|
+
if (['meterplus', 'meter plus (jp)', 'meterpro', 'meterpro(co2)'].includes((type || '').toLowerCase())) {
|
|
738
|
+
type = 'meter'
|
|
739
|
+
}
|
|
740
|
+
// Relay switch variants
|
|
741
|
+
if (['relay switch 1', 'relay switch 1pm'].includes((type || '').toLowerCase())) {
|
|
742
|
+
type = 'relay'
|
|
743
|
+
}
|
|
744
|
+
// Water detector variants
|
|
745
|
+
if (['water detector'].includes((type || '').toLowerCase())) {
|
|
746
|
+
type = 'waterdetector'
|
|
747
|
+
}
|
|
748
|
+
// Fan variants
|
|
749
|
+
if (['smart fan'].includes((type || '').toLowerCase())) {
|
|
750
|
+
type = 'fan'
|
|
751
|
+
}
|
|
752
|
+
// Light variants
|
|
753
|
+
if (['strip light'].includes((type || '').toLowerCase())) {
|
|
754
|
+
type = 'lightstrip'
|
|
755
|
+
}
|
|
756
|
+
|
|
478
757
|
const matterSupported = !!DEVICE_MATTER_SUPPORTED[(type || '').toLowerCase()]
|
|
479
758
|
const useMatter = matterEnabled && matterSupported
|
|
480
759
|
if (!useMatter) {
|
|
@@ -501,34 +780,38 @@ export class SwitchBotMatterPlatform {
|
|
|
501
780
|
if (existing) {
|
|
502
781
|
// Ensure context and displayName are up to date
|
|
503
782
|
const defaultClusters = DEVICE_MATTER_CLUSTERS[type.toLowerCase()] || { onOff: { onOff: false } }
|
|
783
|
+
const clusters = existing.clusters || createdDesc.clusters || defaultClusters
|
|
784
|
+
const deviceType = resolveMatterDeviceType(matterApi, type, existing.deviceType || createdDesc.deviceType, clusters)
|
|
504
785
|
existing.context = existing.context || {}
|
|
505
786
|
existing.context.deviceId = existing.context.deviceId || d.id
|
|
506
787
|
existing.context.type = existing.context.type || type
|
|
507
|
-
existing.deviceType =
|
|
788
|
+
existing.deviceType = deviceType
|
|
508
789
|
existing.manufacturer = existing.manufacturer || createdDesc.manufacturer || 'SwitchBot'
|
|
509
790
|
existing.model = existing.model || createdDesc.model || type
|
|
510
791
|
existing.serialNumber = existing.serialNumber || createdDesc.serialNumber || d.id
|
|
511
792
|
existing.reachable = existing.reachable !== false
|
|
512
793
|
existing.firmwareRevision = existing.firmwareRevision || createdDesc.firmwareRevision || '1.0.0'
|
|
513
794
|
existing.hardwareRevision = existing.hardwareRevision || createdDesc.hardwareRevision || ''
|
|
514
|
-
existing.clusters =
|
|
795
|
+
existing.clusters = clusters
|
|
515
796
|
existing.displayName = createdDesc.name || d.name || type
|
|
516
797
|
existing.UUID = existing.UUID || existing.uuid || uuid
|
|
517
798
|
accessoriesToRegister.push(existing)
|
|
518
799
|
this.accessories.set(existing.UUID || uuid, existing)
|
|
519
800
|
} else {
|
|
520
801
|
const defaultClusters = DEVICE_MATTER_CLUSTERS[type.toLowerCase()] || { onOff: { onOff: false } }
|
|
802
|
+
const clusters = createdDesc.clusters || defaultClusters
|
|
803
|
+
const deviceType = resolveMatterDeviceType(matterApi, type, createdDesc.deviceType, clusters)
|
|
521
804
|
const serialized: any = {
|
|
522
805
|
UUID: uuid,
|
|
523
806
|
displayName: createdDesc.name || d.name || type,
|
|
524
|
-
deviceType
|
|
807
|
+
deviceType,
|
|
525
808
|
manufacturer: createdDesc.manufacturer || 'SwitchBot',
|
|
526
809
|
model: createdDesc.model || type,
|
|
527
810
|
serialNumber: createdDesc.serialNumber || d.id,
|
|
528
811
|
reachable: createdDesc.reachable !== false,
|
|
529
812
|
firmwareRevision: createdDesc.firmwareRevision || '1.0.0',
|
|
530
813
|
hardwareRevision: createdDesc.hardwareRevision || '',
|
|
531
|
-
clusters
|
|
814
|
+
clusters,
|
|
532
815
|
context: { deviceId: d.id, type, created: true },
|
|
533
816
|
}
|
|
534
817
|
accessoriesToRegister.push(serialized)
|