@switchbot/homebridge-switchbot 5.0.0-beta.1 → 5.0.0-beta.10
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-matter/ColorLightAccessory.d.ts +3 -1
- package/dist/devices-matter/ColorLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ColorLightAccessory.js +35 -36
- package/dist/devices-matter/ColorLightAccessory.js.map +1 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts +3 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.js +32 -37
- package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +1 -1
- package/dist/devices-matter/ContactSensorAccessory.d.ts +3 -1
- package/dist/devices-matter/ContactSensorAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ContactSensorAccessory.js +16 -13
- package/dist/devices-matter/ContactSensorAccessory.js.map +1 -1
- package/dist/devices-matter/DimmableLightAccessory.d.ts +3 -1
- package/dist/devices-matter/DimmableLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/DimmableLightAccessory.js +24 -27
- package/dist/devices-matter/DimmableLightAccessory.js.map +1 -1
- package/dist/devices-matter/DoorLockAccessory.d.ts +3 -1
- package/dist/devices-matter/DoorLockAccessory.d.ts.map +1 -1
- package/dist/devices-matter/DoorLockAccessory.js +25 -22
- package/dist/devices-matter/DoorLockAccessory.js.map +1 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.d.ts +3 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.js +40 -41
- package/dist/devices-matter/ExtendedColorLightAccessory.js.map +1 -1
- package/dist/devices-matter/FanAccessory.d.ts +3 -1
- package/dist/devices-matter/FanAccessory.d.ts.map +1 -1
- package/dist/devices-matter/FanAccessory.js +31 -23
- package/dist/devices-matter/FanAccessory.js.map +1 -1
- package/dist/devices-matter/HumiditySensorAccessory.d.ts +3 -1
- package/dist/devices-matter/HumiditySensorAccessory.d.ts.map +1 -1
- package/dist/devices-matter/HumiditySensorAccessory.js +16 -15
- package/dist/devices-matter/HumiditySensorAccessory.js.map +1 -1
- package/dist/devices-matter/LeakSensorAccessory.d.ts +3 -1
- package/dist/devices-matter/LeakSensorAccessory.d.ts.map +1 -1
- package/dist/devices-matter/LeakSensorAccessory.js +16 -13
- package/dist/devices-matter/LeakSensorAccessory.js.map +1 -1
- package/dist/devices-matter/LightSensorAccessory.d.ts +3 -1
- package/dist/devices-matter/LightSensorAccessory.d.ts.map +1 -1
- package/dist/devices-matter/LightSensorAccessory.js +16 -15
- package/dist/devices-matter/LightSensorAccessory.js.map +1 -1
- package/dist/devices-matter/OccupancySensorAccessory.d.ts +3 -1
- package/dist/devices-matter/OccupancySensorAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OccupancySensorAccessory.js +17 -21
- package/dist/devices-matter/OccupancySensorAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffLightAccessory.d.ts +3 -1
- package/dist/devices-matter/OnOffLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffLightAccessory.js +22 -21
- package/dist/devices-matter/OnOffLightAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffOutletAccessory.d.ts +3 -3
- package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffOutletAccessory.js +24 -27
- package/dist/devices-matter/OnOffOutletAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffSwitchAccessory.d.ts +3 -1
- package/dist/devices-matter/OnOffSwitchAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffSwitchAccessory.js +18 -19
- package/dist/devices-matter/OnOffSwitchAccessory.js.map +1 -1
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts +3 -1
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +1 -1
- package/dist/devices-matter/RoboticVacuumAccessory.js +77 -145
- package/dist/devices-matter/RoboticVacuumAccessory.js.map +1 -1
- package/dist/devices-matter/TemperatureSensorAccessory.d.ts +3 -1
- package/dist/devices-matter/TemperatureSensorAccessory.d.ts.map +1 -1
- package/dist/devices-matter/TemperatureSensorAccessory.js +18 -15
- package/dist/devices-matter/TemperatureSensorAccessory.js.map +1 -1
- package/dist/devices-matter/ThermostatAccessory.d.ts +3 -1
- package/dist/devices-matter/ThermostatAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ThermostatAccessory.js +37 -29
- package/dist/devices-matter/ThermostatAccessory.js.map +1 -1
- package/dist/devices-matter/VenetianBlindAccessory.d.ts +3 -1
- package/dist/devices-matter/VenetianBlindAccessory.d.ts.map +1 -1
- package/dist/devices-matter/VenetianBlindAccessory.js +39 -40
- package/dist/devices-matter/VenetianBlindAccessory.js.map +1 -1
- package/dist/devices-matter/WindowBlindAccessory.d.ts +3 -1
- package/dist/devices-matter/WindowBlindAccessory.d.ts.map +1 -1
- package/dist/devices-matter/WindowBlindAccessory.js +36 -37
- package/dist/devices-matter/WindowBlindAccessory.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/dist/platform-hap.d.ts.map +1 -1
- package/dist/platform-hap.js +13 -1
- package/dist/platform-hap.js.map +1 -1
- package/dist/platform-matter.d.ts +45 -0
- package/dist/platform-matter.d.ts.map +1 -1
- package/dist/platform-matter.js +607 -2
- package/dist/platform-matter.js.map +1 -1
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/devices-matter/ColorLightAccessory.ts +37 -40
- package/src/devices-matter/ColorTemperatureLightAccessory.ts +35 -41
- package/src/devices-matter/ContactSensorAccessory.ts +18 -14
- package/src/devices-matter/DimmableLightAccessory.ts +26 -30
- package/src/devices-matter/DoorLockAccessory.ts +28 -24
- package/src/devices-matter/ExtendedColorLightAccessory.ts +43 -47
- package/src/devices-matter/FanAccessory.ts +33 -25
- package/src/devices-matter/HumiditySensorAccessory.ts +18 -16
- package/src/devices-matter/LeakSensorAccessory.ts +18 -14
- package/src/devices-matter/LightSensorAccessory.ts +18 -16
- package/src/devices-matter/OccupancySensorAccessory.ts +18 -22
- package/src/devices-matter/OnOffLightAccessory.ts +23 -23
- package/src/devices-matter/OnOffOutletAccessory.ts +25 -31
- package/src/devices-matter/OnOffSwitchAccessory.ts +20 -21
- package/src/devices-matter/RoboticVacuumAccessory.ts +79 -156
- package/src/devices-matter/TemperatureSensorAccessory.ts +20 -16
- package/src/devices-matter/ThermostatAccessory.ts +39 -34
- package/src/devices-matter/VenetianBlindAccessory.ts +41 -44
- package/src/devices-matter/WindowBlindAccessory.ts +37 -39
- package/src/index.ts +27 -1
- package/src/platform-hap.ts +12 -1
- package/src/platform-matter.ts +647 -2
|
@@ -30,165 +30,88 @@ import { BaseMatterAccessory } from './BaseMatterAccessory.js'
|
|
|
30
30
|
export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
31
31
|
private activeTimers: NodeJS.Timeout[] = []
|
|
32
32
|
|
|
33
|
-
constructor(api: API, log: Logger) {
|
|
34
|
-
const serialNumber = 'VACUUM-001'
|
|
33
|
+
constructor(api: API, log: Logger, opts?: Partial<import('./BaseMatterAccessory').BaseMatterAccessoryConfig & { deviceId?: string }>) {
|
|
34
|
+
const serialNumber = opts?.serialNumber ?? 'VACUUM-001'
|
|
35
|
+
const clusters = opts?.clusters ?? {
|
|
36
|
+
powerSource: {
|
|
37
|
+
status: 0,
|
|
38
|
+
order: 0,
|
|
39
|
+
description: 'Battery',
|
|
40
|
+
batPercentRemaining: 100,
|
|
41
|
+
batChargeLevel: 2,
|
|
42
|
+
batReplaceability: 1,
|
|
43
|
+
},
|
|
44
|
+
rvcRunMode: {
|
|
45
|
+
supportedModes: [
|
|
46
|
+
{ label: 'Idle', mode: 0, modeTags: [{ value: 16384 }] },
|
|
47
|
+
{ label: 'Cleaning', mode: 1, modeTags: [{ value: 16385 }] },
|
|
48
|
+
{ label: 'Mapping', mode: 2, modeTags: [{ value: 16386 }] },
|
|
49
|
+
],
|
|
50
|
+
currentMode: 0,
|
|
51
|
+
},
|
|
52
|
+
rvcCleanMode: {
|
|
53
|
+
supportedModes: [
|
|
54
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
55
|
+
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
|
|
56
|
+
{ label: 'Vacuum & Mop', mode: 2, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
57
|
+
{ label: 'Deep Clean', mode: 3, modeTags: [{ value: 16384 }] },
|
|
58
|
+
{ label: 'Deep Vacuum', mode: 4, modeTags: [{ value: 16384 }, { value: 16385 }] },
|
|
59
|
+
{ label: 'Deep Mop', mode: 5, modeTags: [{ value: 16384 }, { value: 16386 }] },
|
|
60
|
+
{ label: 'Quick Clean', mode: 6, modeTags: [{ value: 1 }, { value: 16385 }] },
|
|
61
|
+
{ label: 'Max Clean', mode: 7, modeTags: [{ value: 7 }, { value: 16385 }] },
|
|
62
|
+
{ label: 'Min Clean', mode: 8, modeTags: [{ value: 6 }, { value: 16385 }] },
|
|
63
|
+
{ label: 'Quiet Vacuum', mode: 9, modeTags: [{ value: 2 }, { value: 16385 }] },
|
|
64
|
+
{ label: 'Quiet Mop', mode: 10, modeTags: [{ value: 2 }, { value: 16386 }] },
|
|
65
|
+
{ label: 'Night Mode', mode: 11, modeTags: [{ value: 8 }, { value: 16385 }] },
|
|
66
|
+
{ label: 'Eco Vacuum', mode: 12, modeTags: [{ value: 4 }, { value: 16385 }] },
|
|
67
|
+
{ label: 'Eco Mop', mode: 13, modeTags: [{ value: 4 }, { value: 16386 }] },
|
|
68
|
+
{ label: 'Auto', mode: 14, modeTags: [{ value: 0 }, { value: 16385 }] },
|
|
69
|
+
],
|
|
70
|
+
currentMode: 0,
|
|
71
|
+
},
|
|
72
|
+
rvcOperationalState: {
|
|
73
|
+
operationalStateList: [
|
|
74
|
+
{ operationalStateId: 0 },
|
|
75
|
+
{ operationalStateId: 1 },
|
|
76
|
+
{ operationalStateId: 2 },
|
|
77
|
+
{ operationalStateId: 3 },
|
|
78
|
+
{ operationalStateId: 64 },
|
|
79
|
+
{ operationalStateId: 65 },
|
|
80
|
+
{ operationalStateId: 66 },
|
|
81
|
+
],
|
|
82
|
+
operationalState: 66,
|
|
83
|
+
},
|
|
84
|
+
serviceArea: {
|
|
85
|
+
supportedMaps: [],
|
|
86
|
+
supportedAreas: [
|
|
87
|
+
{ areaId: 0, mapId: null, areaInfo: { locationInfo: { locationName: 'Living Room', floorNumber: 0, areaType: 7 }, landmarkInfo: null } },
|
|
88
|
+
{ areaId: 1, mapId: null, areaInfo: { locationInfo: { locationName: 'Kitchen', floorNumber: 0, areaType: 10 }, landmarkInfo: null } },
|
|
89
|
+
{ areaId: 2, mapId: null, areaInfo: { locationInfo: { locationName: 'Bedroom', floorNumber: 0, areaType: 2 }, landmarkInfo: null } },
|
|
90
|
+
{ areaId: 3, mapId: null, areaInfo: { locationInfo: { locationName: 'Bathroom', floorNumber: 0, areaType: 6 }, landmarkInfo: null } },
|
|
91
|
+
],
|
|
92
|
+
selectedAreas: [0, 1, 2, 3],
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const handlers = opts?.handlers ?? {
|
|
97
|
+
rvcRunMode: { changeToMode: async (request: MatterRequests.ChangeToMode) => this.handleChangeRunMode(request) },
|
|
98
|
+
rvcCleanMode: { changeToMode: async (request: MatterRequests.ChangeToMode) => this.handleChangeCleanMode(request) },
|
|
99
|
+
rvcOperationalState: { pause: async () => this.handlePause(), stop: async () => this.handleStop(), start: async () => this.handleStart(), resume: async () => this.handleResume(), goHome: async () => this.handleGoHome() },
|
|
100
|
+
serviceArea: { selectAreas: async (request: MatterRequests.SelectAreas) => this.handleSelectAreas(request), skipArea: async (request: MatterRequests.SkipArea) => this.handleSkipArea(request) },
|
|
101
|
+
}
|
|
102
|
+
|
|
35
103
|
super(api, log, {
|
|
36
|
-
uuid: api.matter.uuid.generate(serialNumber),
|
|
37
|
-
displayName: 'Robot Vacuum',
|
|
104
|
+
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
105
|
+
displayName: opts?.displayName ?? 'Robot Vacuum',
|
|
38
106
|
deviceType: api.matter.deviceTypes.RoboticVacuumCleaner,
|
|
39
107
|
serialNumber,
|
|
40
|
-
manufacturer: 'Homebridge Matter',
|
|
41
|
-
model: 'HB-MATTER-VACUUM-ROBOTIC',
|
|
42
|
-
firmwareRevision: '2.0.0',
|
|
43
|
-
hardwareRevision: '1.0.0',
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
powerSource: {
|
|
48
|
-
status: 0, // 0 = Active
|
|
49
|
-
order: 0, // Primary power source
|
|
50
|
-
description: 'Battery',
|
|
51
|
-
batPercentRemaining: 100, // 0-200, where 200 = 100% (0.5% increments)
|
|
52
|
-
batChargeLevel: 2, // 0 = Ok, 1 = Warning, 2 = Critical
|
|
53
|
-
batReplaceability: 1, // 0 = Unspecified, 1 = Not replaceable, 2 = User replaceable, 3 = Factory replaceable
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
// Run Mode: Controls what the vacuum is doing (Idle, Cleaning, Mapping)
|
|
57
|
-
rvcRunMode: {
|
|
58
|
-
supportedModes: [
|
|
59
|
-
{ label: 'Idle', mode: 0, modeTags: [{ value: 16384 }] }, // RvcRunMode.ModeTag.Idle
|
|
60
|
-
{ label: 'Cleaning', mode: 1, modeTags: [{ value: 16385 }] }, // RvcRunMode.ModeTag.Cleaning
|
|
61
|
-
{ label: 'Mapping', mode: 2, modeTags: [{ value: 16386 }] }, // RvcRunMode.ModeTag.Mapping
|
|
62
|
-
],
|
|
63
|
-
currentMode: 0,
|
|
64
|
-
},
|
|
65
|
-
|
|
66
|
-
// Clean Mode: Controls HOW the vacuum cleans
|
|
67
|
-
// You can combine semantic tags (0-9) with functional tags (16384-16386)
|
|
68
|
-
// Available semantic tags: Auto, Quick, Quiet, LowNoise, LowEnergy, Vacation, Min, Max, Night, Day
|
|
69
|
-
// Available functional tags: DeepClean, Vacuum, Mop
|
|
70
|
-
rvcCleanMode: {
|
|
71
|
-
supportedModes: [
|
|
72
|
-
// Basic functional modes
|
|
73
|
-
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] }, // Vacuum
|
|
74
|
-
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] }, // Mop
|
|
75
|
-
{ label: 'Vacuum & Mop', mode: 2, modeTags: [{ value: 16385 }, { value: 16386 }] }, // Both
|
|
76
|
-
|
|
77
|
-
// Deep clean modes
|
|
78
|
-
{ label: 'Deep Clean', mode: 3, modeTags: [{ value: 16384 }] }, // DeepClean
|
|
79
|
-
{ label: 'Deep Vacuum', mode: 4, modeTags: [{ value: 16384 }, { value: 16385 }] }, // DeepClean + Vacuum
|
|
80
|
-
{ label: 'Deep Mop', mode: 5, modeTags: [{ value: 16384 }, { value: 16386 }] }, // DeepClean + Mop
|
|
81
|
-
|
|
82
|
-
// Intensity modes
|
|
83
|
-
{ label: 'Quick Clean', mode: 6, modeTags: [{ value: 1 }, { value: 16385 }] }, // Quick + Vacuum
|
|
84
|
-
{ label: 'Max Clean', mode: 7, modeTags: [{ value: 7 }, { value: 16385 }] }, // Max + Vacuum
|
|
85
|
-
{ label: 'Min Clean', mode: 8, modeTags: [{ value: 6 }, { value: 16385 }] }, // Min + Vacuum
|
|
86
|
-
|
|
87
|
-
// Quiet modes
|
|
88
|
-
{ label: 'Quiet Vacuum', mode: 9, modeTags: [{ value: 2 }, { value: 16385 }] }, // Quiet + Vacuum
|
|
89
|
-
{ label: 'Quiet Mop', mode: 10, modeTags: [{ value: 2 }, { value: 16386 }] }, // Quiet + Mop
|
|
90
|
-
{ label: 'Night Mode', mode: 11, modeTags: [{ value: 8 }, { value: 16385 }] }, // Night + Vacuum
|
|
91
|
-
|
|
92
|
-
// Energy efficient
|
|
93
|
-
{ label: 'Eco Vacuum', mode: 12, modeTags: [{ value: 4 }, { value: 16385 }] }, // LowEnergy + Vacuum
|
|
94
|
-
{ label: 'Eco Mop', mode: 13, modeTags: [{ value: 4 }, { value: 16386 }] }, // LowEnergy + Mop
|
|
95
|
-
|
|
96
|
-
// Auto mode
|
|
97
|
-
{ label: 'Auto', mode: 14, modeTags: [{ value: 0 }, { value: 16385 }] }, // Auto + Vacuum
|
|
98
|
-
],
|
|
99
|
-
currentMode: 0, // start with basic Vacuum
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
// Operational State: Current state (Stopped, Running, Paused, Error, etc.)
|
|
103
|
-
rvcOperationalState: {
|
|
104
|
-
operationalStateList: [
|
|
105
|
-
{ operationalStateId: 0 }, // stopped (standard label from Matter spec)
|
|
106
|
-
{ operationalStateId: 1 }, // running
|
|
107
|
-
{ operationalStateId: 2 }, // paused
|
|
108
|
-
{ operationalStateId: 3 }, // error
|
|
109
|
-
{ operationalStateId: 64 }, // seeking charger
|
|
110
|
-
{ operationalStateId: 65 }, // charging
|
|
111
|
-
{ operationalStateId: 66 }, // docked
|
|
112
|
-
],
|
|
113
|
-
operationalState: 66, // start docked
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
// Service Area: Room/zone selection for targeted cleaning
|
|
117
|
-
serviceArea: {
|
|
118
|
-
supportedMaps: [], // empty array - we don't use map features
|
|
119
|
-
supportedAreas: [
|
|
120
|
-
{
|
|
121
|
-
areaId: 0,
|
|
122
|
-
mapId: null, // required: must be null when supportedMaps is empty
|
|
123
|
-
areaInfo: {
|
|
124
|
-
locationInfo: {
|
|
125
|
-
locationName: 'Living Room',
|
|
126
|
-
floorNumber: 0,
|
|
127
|
-
areaType: 7, // AreaNamespaceTag.LivingRoom
|
|
128
|
-
},
|
|
129
|
-
landmarkInfo: null,
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
areaId: 1,
|
|
134
|
-
mapId: null,
|
|
135
|
-
areaInfo: {
|
|
136
|
-
locationInfo: {
|
|
137
|
-
locationName: 'Kitchen',
|
|
138
|
-
floorNumber: 0,
|
|
139
|
-
areaType: 10, // AreaNamespaceTag.Kitchen
|
|
140
|
-
},
|
|
141
|
-
landmarkInfo: null,
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
areaId: 2,
|
|
146
|
-
mapId: null,
|
|
147
|
-
areaInfo: {
|
|
148
|
-
locationInfo: {
|
|
149
|
-
locationName: 'Bedroom',
|
|
150
|
-
floorNumber: 0,
|
|
151
|
-
areaType: 2, // AreaNamespaceTag.Bedroom
|
|
152
|
-
},
|
|
153
|
-
landmarkInfo: null,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
areaId: 3,
|
|
158
|
-
mapId: null,
|
|
159
|
-
areaInfo: {
|
|
160
|
-
locationInfo: {
|
|
161
|
-
locationName: 'Bathroom',
|
|
162
|
-
floorNumber: 0,
|
|
163
|
-
areaType: 6, // AreaNamespaceTag.Bathroom
|
|
164
|
-
},
|
|
165
|
-
landmarkInfo: null,
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
],
|
|
169
|
-
selectedAreas: [0, 1, 2, 3], // all areas selected by default
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
handlers: {
|
|
174
|
-
rvcRunMode: {
|
|
175
|
-
changeToMode: async (request: MatterRequests.ChangeToMode) => this.handleChangeRunMode(request),
|
|
176
|
-
},
|
|
177
|
-
rvcCleanMode: {
|
|
178
|
-
changeToMode: async (request: MatterRequests.ChangeToMode) => this.handleChangeCleanMode(request),
|
|
179
|
-
},
|
|
180
|
-
rvcOperationalState: {
|
|
181
|
-
pause: async () => this.handlePause(),
|
|
182
|
-
stop: async () => this.handleStop(),
|
|
183
|
-
start: async () => this.handleStart(),
|
|
184
|
-
resume: async () => this.handleResume(),
|
|
185
|
-
goHome: async () => this.handleGoHome(),
|
|
186
|
-
},
|
|
187
|
-
serviceArea: {
|
|
188
|
-
selectAreas: async (request: MatterRequests.SelectAreas) => this.handleSelectAreas(request),
|
|
189
|
-
skipArea: async (request: MatterRequests.SkipArea) => this.handleSkipArea(request),
|
|
190
|
-
},
|
|
191
|
-
},
|
|
108
|
+
manufacturer: opts?.manufacturer ?? 'Homebridge Matter',
|
|
109
|
+
model: opts?.model ?? 'HB-MATTER-VACUUM-ROBOTIC',
|
|
110
|
+
firmwareRevision: opts?.firmwareRevision ?? '2.0.0',
|
|
111
|
+
hardwareRevision: opts?.hardwareRevision ?? '1.0.0',
|
|
112
|
+
clusters,
|
|
113
|
+
handlers,
|
|
114
|
+
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}) },
|
|
192
115
|
})
|
|
193
116
|
|
|
194
117
|
this.logInfo('initialized and ready.')
|
|
@@ -7,25 +7,29 @@ import type { API, Logger } from 'homebridge'
|
|
|
7
7
|
import { BaseMatterAccessory } from './BaseMatterAccessory.js'
|
|
8
8
|
|
|
9
9
|
export class TemperatureSensorAccessory extends BaseMatterAccessory {
|
|
10
|
-
constructor(api: API, log: Logger) {
|
|
11
|
-
const serialNumber = 'SENSOR-004'
|
|
10
|
+
constructor(api: API, log: Logger, opts?: Partial<import('./BaseMatterAccessory').BaseMatterAccessoryConfig & { deviceId?: string }>) {
|
|
11
|
+
const serialNumber = opts?.serialNumber ?? 'SENSOR-004'
|
|
12
|
+
const displayName = opts?.displayName ?? 'Temperature Sensor'
|
|
13
|
+
const manufacturer = opts?.manufacturer ?? 'Homebridge Matter'
|
|
14
|
+
const model = opts?.model ?? 'HB-MATTER-SENSOR-TEMPERATURE'
|
|
15
|
+
const firmwareRevision = opts?.firmwareRevision ?? '2.0.0'
|
|
16
|
+
const hardwareRevision = opts?.hardwareRevision ?? '1.0.0'
|
|
17
|
+
|
|
18
|
+
const clusters = opts?.clusters ?? {
|
|
19
|
+
temperatureMeasurement: { measuredValue: 2100, minMeasuredValue: -5000, maxMeasuredValue: 10000 },
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
super(api, log, {
|
|
13
|
-
uuid: api.matter.uuid.generate(serialNumber),
|
|
14
|
-
displayName
|
|
23
|
+
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
24
|
+
displayName,
|
|
15
25
|
deviceType: api.matter.deviceTypes.TemperatureSensor,
|
|
16
26
|
serialNumber,
|
|
17
|
-
manufacturer
|
|
18
|
-
model
|
|
19
|
-
firmwareRevision
|
|
20
|
-
hardwareRevision
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
temperatureMeasurement: {
|
|
24
|
-
measuredValue: 2100, // 21.00°C (in hundredths)
|
|
25
|
-
minMeasuredValue: -5000,
|
|
26
|
-
maxMeasuredValue: 10000,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
27
|
+
manufacturer,
|
|
28
|
+
model,
|
|
29
|
+
firmwareRevision,
|
|
30
|
+
hardwareRevision,
|
|
31
|
+
clusters,
|
|
32
|
+
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}) },
|
|
29
33
|
})
|
|
30
34
|
|
|
31
35
|
this.logInfo('initialized.')
|
|
@@ -7,44 +7,49 @@ import type { API, Logger, MatterRequests } from 'homebridge'
|
|
|
7
7
|
import { BaseMatterAccessory } from './BaseMatterAccessory.js'
|
|
8
8
|
|
|
9
9
|
export class ThermostatAccessory extends BaseMatterAccessory {
|
|
10
|
-
constructor(api: API, log: Logger) {
|
|
11
|
-
const serialNumber = 'THERMOSTAT-001'
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
manufacturer: 'Homebridge Matter',
|
|
18
|
-
model: 'HB-MATTER-THERMOSTAT',
|
|
19
|
-
firmwareRevision: '2.0.0',
|
|
20
|
-
hardwareRevision: '1.0.0',
|
|
10
|
+
constructor(api: API, log: Logger, opts?: Partial<import('./BaseMatterAccessory').BaseMatterAccessoryConfig & { deviceId?: string }>) {
|
|
11
|
+
const serialNumber = opts?.serialNumber ?? 'THERMOSTAT-001'
|
|
12
|
+
const displayName = opts?.displayName ?? 'Thermostat'
|
|
13
|
+
const manufacturer = opts?.manufacturer ?? 'Homebridge Matter'
|
|
14
|
+
const model = opts?.model ?? 'HB-MATTER-THERMOSTAT'
|
|
15
|
+
const firmwareRevision = opts?.firmwareRevision ?? '2.0.0'
|
|
16
|
+
const hardwareRevision = opts?.hardwareRevision ?? '1.0.0'
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
18
|
+
const clusters = opts?.clusters ?? {
|
|
19
|
+
thermostat: {
|
|
20
|
+
localTemperature: 2100,
|
|
21
|
+
occupiedHeatingSetpoint: 2000,
|
|
22
|
+
occupiedCoolingSetpoint: 2400,
|
|
23
|
+
minHeatSetpointLimit: 700,
|
|
24
|
+
maxHeatSetpointLimit: 3000,
|
|
25
|
+
minCoolSetpointLimit: 1600,
|
|
26
|
+
maxCoolSetpointLimit: 3200,
|
|
27
|
+
controlSequenceOfOperation: 4,
|
|
28
|
+
systemMode: 0,
|
|
34
29
|
},
|
|
30
|
+
}
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
occupiedHeatingSetpointChange: async (request: { occupiedHeatingSetpoint: number, oldOccupiedHeatingSetpoint: number }) =>
|
|
43
|
-
this.handleOccupiedHeatingSetpointChange(request),
|
|
44
|
-
occupiedCoolingSetpointChange: async (request: { occupiedCoolingSetpoint: number, oldOccupiedCoolingSetpoint: number }) =>
|
|
45
|
-
this.handleOccupiedCoolingSetpointChange(request),
|
|
46
|
-
},
|
|
32
|
+
const handlers = opts?.handlers ?? {
|
|
33
|
+
thermostat: {
|
|
34
|
+
setpointRaiseLower: async (request: MatterRequests.SetpointRaiseLower) => this.handleSetpointRaiseLower(request),
|
|
35
|
+
systemModeChange: async (request: { systemMode: number, oldSystemMode: number }) => this.handleSystemModeChange(request),
|
|
36
|
+
occupiedHeatingSetpointChange: async (request: { occupiedHeatingSetpoint: number, oldOccupiedHeatingSetpoint: number }) => this.handleOccupiedHeatingSetpointChange(request),
|
|
37
|
+
occupiedCoolingSetpointChange: async (request: { occupiedCoolingSetpoint: number, oldOccupiedCoolingSetpoint: number }) => this.handleOccupiedCoolingSetpointChange(request),
|
|
47
38
|
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
super(api, log, {
|
|
42
|
+
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
43
|
+
displayName,
|
|
44
|
+
deviceType: api.matter.deviceTypes.Thermostat,
|
|
45
|
+
serialNumber,
|
|
46
|
+
manufacturer,
|
|
47
|
+
model,
|
|
48
|
+
firmwareRevision,
|
|
49
|
+
hardwareRevision,
|
|
50
|
+
clusters,
|
|
51
|
+
handlers,
|
|
52
|
+
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}) },
|
|
48
53
|
})
|
|
49
54
|
|
|
50
55
|
this.logInfo('initialized.')
|
|
@@ -8,54 +8,51 @@ import type { API, Logger, MatterRequests } from 'homebridge'
|
|
|
8
8
|
import { BaseMatterAccessory } from './BaseMatterAccessory.js'
|
|
9
9
|
|
|
10
10
|
export class VenetianBlindAccessory extends BaseMatterAccessory {
|
|
11
|
-
constructor(api: API, log: Logger) {
|
|
12
|
-
const serialNumber = 'BLIND-002'
|
|
11
|
+
constructor(api: API, log: Logger, opts?: Partial<import('./BaseMatterAccessory').BaseMatterAccessoryConfig & { deviceId?: string }>) {
|
|
12
|
+
const serialNumber = opts?.serialNumber ?? 'BLIND-002'
|
|
13
|
+
|
|
14
|
+
const clusters = opts?.clusters ?? {
|
|
15
|
+
windowCovering: {
|
|
16
|
+
targetPositionLiftPercent100ths: 5000,
|
|
17
|
+
currentPositionLiftPercent100ths: 5000,
|
|
18
|
+
targetPositionTiltPercent100ths: 5000,
|
|
19
|
+
currentPositionTiltPercent100ths: 5000,
|
|
20
|
+
operationalStatus: { global: 0, lift: 0, tilt: 0 },
|
|
21
|
+
endProductType: 8,
|
|
22
|
+
configStatus: {
|
|
23
|
+
operational: true,
|
|
24
|
+
onlineReserved: true,
|
|
25
|
+
liftMovementReversed: false,
|
|
26
|
+
liftPositionAware: true,
|
|
27
|
+
tiltPositionAware: true,
|
|
28
|
+
liftEncoderControlled: true,
|
|
29
|
+
tiltEncoderControlled: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const handlers = opts?.handlers ?? {
|
|
35
|
+
windowCovering: {
|
|
36
|
+
goToLiftPercentage: async (request: MatterRequests.GoToLiftPercentage) => this.handleGoToLift(request),
|
|
37
|
+
goToTiltPercentage: async (request: MatterRequests.GoToTiltPercentage) => this.handleGoToTilt(request),
|
|
38
|
+
upOrOpen: async () => this.handleUpOrOpen(),
|
|
39
|
+
downOrClose: async () => this.handleDownOrClose(),
|
|
40
|
+
stopMotion: async () => this.handleStop(),
|
|
41
|
+
},
|
|
42
|
+
}
|
|
13
43
|
|
|
14
44
|
super(api, log, {
|
|
15
|
-
uuid: api.matter.uuid.generate(serialNumber),
|
|
16
|
-
displayName: 'Venetian Blind (Tilt)',
|
|
45
|
+
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
46
|
+
displayName: opts?.displayName ?? 'Venetian Blind (Tilt)',
|
|
17
47
|
deviceType: api.matter.deviceTypes.WindowCovering,
|
|
18
48
|
serialNumber,
|
|
19
|
-
manufacturer: 'Homebridge Matter',
|
|
20
|
-
model: 'HB-MATTER-BLIND-VENETIAN',
|
|
21
|
-
firmwareRevision: '2.0.0',
|
|
22
|
-
hardwareRevision: '1.0.0',
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
targetPositionLiftPercent100ths: 5000,
|
|
27
|
-
currentPositionLiftPercent100ths: 5000,
|
|
28
|
-
targetPositionTiltPercent100ths: 5000,
|
|
29
|
-
currentPositionTiltPercent100ths: 5000,
|
|
30
|
-
operationalStatus: {
|
|
31
|
-
global: 0,
|
|
32
|
-
lift: 0,
|
|
33
|
-
tilt: 0,
|
|
34
|
-
},
|
|
35
|
-
endProductType: 8,
|
|
36
|
-
configStatus: {
|
|
37
|
-
operational: true,
|
|
38
|
-
onlineReserved: true,
|
|
39
|
-
liftMovementReversed: false,
|
|
40
|
-
liftPositionAware: true,
|
|
41
|
-
tiltPositionAware: true,
|
|
42
|
-
liftEncoderControlled: true,
|
|
43
|
-
tiltEncoderControlled: true,
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
handlers: {
|
|
49
|
-
windowCovering: {
|
|
50
|
-
goToLiftPercentage: async (request: MatterRequests.GoToLiftPercentage) =>
|
|
51
|
-
this.handleGoToLift(request),
|
|
52
|
-
goToTiltPercentage: async (request: MatterRequests.GoToTiltPercentage) =>
|
|
53
|
-
this.handleGoToTilt(request),
|
|
54
|
-
upOrOpen: async () => this.handleUpOrOpen(),
|
|
55
|
-
downOrClose: async () => this.handleDownOrClose(),
|
|
56
|
-
stopMotion: async () => this.handleStop(),
|
|
57
|
-
},
|
|
58
|
-
},
|
|
49
|
+
manufacturer: opts?.manufacturer ?? 'Homebridge Matter',
|
|
50
|
+
model: opts?.model ?? 'HB-MATTER-BLIND-VENETIAN',
|
|
51
|
+
firmwareRevision: opts?.firmwareRevision ?? '2.0.0',
|
|
52
|
+
hardwareRevision: opts?.hardwareRevision ?? '1.0.0',
|
|
53
|
+
clusters,
|
|
54
|
+
handlers,
|
|
55
|
+
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}) },
|
|
59
56
|
})
|
|
60
57
|
|
|
61
58
|
this.logInfo('initialized.')
|
|
@@ -8,50 +8,48 @@ import type { API, Logger, MatterRequests } from 'homebridge'
|
|
|
8
8
|
import { BaseMatterAccessory } from './BaseMatterAccessory.js'
|
|
9
9
|
|
|
10
10
|
export class WindowBlindAccessory extends BaseMatterAccessory {
|
|
11
|
-
constructor(api: API, log: Logger) {
|
|
12
|
-
const serialNumber = 'BLIND-001'
|
|
11
|
+
constructor(api: API, log: Logger, opts?: Partial<import('./BaseMatterAccessory').BaseMatterAccessoryConfig & { deviceId?: string }>) {
|
|
12
|
+
const serialNumber = opts?.serialNumber ?? 'BLIND-001'
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
operationalStatus: {
|
|
29
|
-
global: 0,
|
|
30
|
-
lift: 0,
|
|
31
|
-
tilt: 0,
|
|
32
|
-
},
|
|
33
|
-
endProductType: 0,
|
|
34
|
-
configStatus: {
|
|
35
|
-
operational: true,
|
|
36
|
-
onlineReserved: true,
|
|
37
|
-
liftMovementReversed: false,
|
|
38
|
-
liftPositionAware: true,
|
|
39
|
-
tiltPositionAware: false,
|
|
40
|
-
liftEncoderControlled: true,
|
|
41
|
-
tiltEncoderControlled: false,
|
|
42
|
-
},
|
|
14
|
+
const clusters = opts?.clusters ?? {
|
|
15
|
+
windowCovering: {
|
|
16
|
+
targetPositionLiftPercent100ths: 5000,
|
|
17
|
+
currentPositionLiftPercent100ths: 5000,
|
|
18
|
+
operationalStatus: { global: 0, lift: 0, tilt: 0 },
|
|
19
|
+
endProductType: 0,
|
|
20
|
+
configStatus: {
|
|
21
|
+
operational: true,
|
|
22
|
+
onlineReserved: true,
|
|
23
|
+
liftMovementReversed: false,
|
|
24
|
+
liftPositionAware: true,
|
|
25
|
+
tiltPositionAware: false,
|
|
26
|
+
liftEncoderControlled: true,
|
|
27
|
+
tiltEncoderControlled: false,
|
|
43
28
|
},
|
|
44
29
|
},
|
|
30
|
+
}
|
|
45
31
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
stopMotion: async () => this.handleStop(),
|
|
53
|
-
},
|
|
32
|
+
const handlers = opts?.handlers ?? {
|
|
33
|
+
windowCovering: {
|
|
34
|
+
goToLiftPercentage: async (request: MatterRequests.GoToLiftPercentage) => this.handleGoToLift(request),
|
|
35
|
+
upOrOpen: async () => this.handleUpOrOpen(),
|
|
36
|
+
downOrClose: async () => this.handleDownOrClose(),
|
|
37
|
+
stopMotion: async () => this.handleStop(),
|
|
54
38
|
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
super(api, log, {
|
|
42
|
+
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
43
|
+
displayName: opts?.displayName ?? 'Window Blind',
|
|
44
|
+
deviceType: api.matter.deviceTypes.WindowCovering,
|
|
45
|
+
serialNumber,
|
|
46
|
+
manufacturer: opts?.manufacturer ?? 'Homebridge Matter',
|
|
47
|
+
model: opts?.model ?? 'HB-MATTER-BLIND-WINDOW',
|
|
48
|
+
firmwareRevision: opts?.firmwareRevision ?? '2.0.0',
|
|
49
|
+
hardwareRevision: opts?.hardwareRevision ?? '1.0.0',
|
|
50
|
+
clusters,
|
|
51
|
+
handlers,
|
|
52
|
+
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}) },
|
|
55
53
|
})
|
|
56
54
|
|
|
57
55
|
this.logInfo('initialized.')
|
package/src/index.ts
CHANGED
|
@@ -12,7 +12,33 @@ import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
|
|
|
12
12
|
export default (api: API): void => {
|
|
13
13
|
// Call the instance method on the runtime `api` object (optional chaining in case
|
|
14
14
|
// older homebridge doesn't provide it). Treat undefined as false.
|
|
15
|
-
const isMatter =
|
|
15
|
+
const isMatter = (() => {
|
|
16
|
+
try {
|
|
17
|
+
const maybeFnOrProp = (api as any).isMatterEnabled
|
|
18
|
+
if (typeof maybeFnOrProp === 'function') {
|
|
19
|
+
return Boolean(maybeFnOrProp.call(api))
|
|
20
|
+
}
|
|
21
|
+
if (typeof maybeFnOrProp !== 'undefined') {
|
|
22
|
+
return Boolean(maybeFnOrProp)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Some Homebridge beta versions expose Matter info on an internal server object
|
|
26
|
+
const server = (api as any).server ?? (api as any).homebridgeServer ?? (api as any).homebridge_server
|
|
27
|
+
const serverFn = server?.isMatterEnabled
|
|
28
|
+
if (typeof serverFn === 'function') {
|
|
29
|
+
return Boolean(serverFn.call(server))
|
|
30
|
+
}
|
|
31
|
+
if (typeof server?.isMatterEnabled !== 'undefined') {
|
|
32
|
+
return Boolean(server.isMatterEnabled)
|
|
33
|
+
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
// ignore and fall through to false
|
|
36
|
+
}
|
|
37
|
+
return false
|
|
38
|
+
})()
|
|
39
|
+
|
|
40
|
+
const log = (api as any).logger ?? (api as any).log ?? console
|
|
41
|
+
log.info?.(`Homebridge SwitchBot Plugin initializing in ${isMatter ? 'Matter' : 'HAP'} mode.`)
|
|
16
42
|
// If Matter is enabled register the Matter platform, otherwise use HAP platform.
|
|
17
43
|
api.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, isMatter ? SwitchBotMatterPlatform : SwitchBotHAPPlatform)
|
|
18
44
|
}
|
package/src/platform-hap.ts
CHANGED
|
@@ -205,7 +205,18 @@ export class SwitchBotHAPPlatform implements DynamicPlatformPlugin {
|
|
|
205
205
|
this.debugLog('Executed didFinishLaunching callback')
|
|
206
206
|
// run the method to discover / register your devices as accessories
|
|
207
207
|
try {
|
|
208
|
-
|
|
208
|
+
// Does the user have a version of Homebridge that is compatible with matter?
|
|
209
|
+
if (!this.api.isMatterAvailable?.()) {
|
|
210
|
+
this.log.debug(`Matter is not available in this version of Homebridge. Please update Homebridge to use this plugin, ${this.api.isMatterAvailable?.() ? '' : ' (Matter is not available in this version of Homebridge)'}`)
|
|
211
|
+
}
|
|
212
|
+
if (!this.api.isMatterEnabled?.()) {
|
|
213
|
+
this.log.debug(`Matter is not enabled in Homebridge. Please enable Matter in the Homebridge settings to use this plugin, ${this.api.isMatterEnabled?.() ? '' : ' (Matter is not enabled in Homebridge)'}`)
|
|
214
|
+
}
|
|
215
|
+
if (!this.api.isMatterAvailable?.() && !this.api.isMatterEnabled?.()) {
|
|
216
|
+
await this.discoverDevices()
|
|
217
|
+
} else {
|
|
218
|
+
this.log.info('Matter is enabled in Homebridge. SwitchBot Matter devices will be handled by the Matter platform.')
|
|
219
|
+
}
|
|
209
220
|
} catch (e: any) {
|
|
210
221
|
this.errorLog(`Failed to Discover, Error Message: ${e.message ?? e}, Submit Bugs Here: ` + 'https://tinyurl.com/SwitchBotBug')
|
|
211
222
|
this.debugErrorLog(`Failed to Discover, Error: ${e.message ?? e}`)
|