meross-iot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/index.d.ts +2344 -0
- package/index.js +131 -0
- package/lib/controller/device.js +1317 -0
- package/lib/controller/features/alarm-feature.js +89 -0
- package/lib/controller/features/child-lock-feature.js +61 -0
- package/lib/controller/features/config-feature.js +54 -0
- package/lib/controller/features/consumption-feature.js +210 -0
- package/lib/controller/features/control-feature.js +62 -0
- package/lib/controller/features/diffuser-feature.js +411 -0
- package/lib/controller/features/digest-timer-feature.js +22 -0
- package/lib/controller/features/digest-trigger-feature.js +22 -0
- package/lib/controller/features/dnd-feature.js +79 -0
- package/lib/controller/features/electricity-feature.js +144 -0
- package/lib/controller/features/encryption-feature.js +259 -0
- package/lib/controller/features/garage-feature.js +337 -0
- package/lib/controller/features/hub-feature.js +687 -0
- package/lib/controller/features/light-feature.js +408 -0
- package/lib/controller/features/presence-sensor-feature.js +297 -0
- package/lib/controller/features/roller-shutter-feature.js +456 -0
- package/lib/controller/features/runtime-feature.js +74 -0
- package/lib/controller/features/screen-feature.js +67 -0
- package/lib/controller/features/sensor-history-feature.js +47 -0
- package/lib/controller/features/smoke-config-feature.js +50 -0
- package/lib/controller/features/spray-feature.js +166 -0
- package/lib/controller/features/system-feature.js +269 -0
- package/lib/controller/features/temp-unit-feature.js +55 -0
- package/lib/controller/features/thermostat-feature.js +804 -0
- package/lib/controller/features/timer-feature.js +507 -0
- package/lib/controller/features/toggle-feature.js +223 -0
- package/lib/controller/features/trigger-feature.js +333 -0
- package/lib/controller/hub-device.js +185 -0
- package/lib/controller/subdevice.js +1537 -0
- package/lib/device-factory.js +463 -0
- package/lib/error-budget.js +138 -0
- package/lib/http-api.js +766 -0
- package/lib/manager.js +1609 -0
- package/lib/model/channel-info.js +79 -0
- package/lib/model/constants.js +119 -0
- package/lib/model/enums.js +819 -0
- package/lib/model/exception.js +363 -0
- package/lib/model/http/device.js +215 -0
- package/lib/model/http/error-codes.js +121 -0
- package/lib/model/http/exception.js +151 -0
- package/lib/model/http/subdevice.js +133 -0
- package/lib/model/push/alarm.js +112 -0
- package/lib/model/push/bind.js +97 -0
- package/lib/model/push/common.js +282 -0
- package/lib/model/push/diffuser-light.js +100 -0
- package/lib/model/push/diffuser-spray.js +83 -0
- package/lib/model/push/factory.js +229 -0
- package/lib/model/push/generic.js +115 -0
- package/lib/model/push/hub-battery.js +59 -0
- package/lib/model/push/hub-mts100-all.js +64 -0
- package/lib/model/push/hub-mts100-mode.js +59 -0
- package/lib/model/push/hub-mts100-temperature.js +62 -0
- package/lib/model/push/hub-online.js +59 -0
- package/lib/model/push/hub-sensor-alert.js +61 -0
- package/lib/model/push/hub-sensor-all.js +59 -0
- package/lib/model/push/hub-sensor-smoke.js +110 -0
- package/lib/model/push/hub-sensor-temphum.js +62 -0
- package/lib/model/push/hub-subdevicelist.js +50 -0
- package/lib/model/push/hub-togglex.js +60 -0
- package/lib/model/push/index.js +81 -0
- package/lib/model/push/online.js +53 -0
- package/lib/model/push/presence-study.js +61 -0
- package/lib/model/push/sensor-latestx.js +106 -0
- package/lib/model/push/timerx.js +63 -0
- package/lib/model/push/togglex.js +78 -0
- package/lib/model/push/triggerx.js +62 -0
- package/lib/model/push/unbind.js +34 -0
- package/lib/model/push/water-leak.js +107 -0
- package/lib/model/states/diffuser-light-state.js +119 -0
- package/lib/model/states/diffuser-spray-state.js +58 -0
- package/lib/model/states/garage-door-state.js +71 -0
- package/lib/model/states/index.js +38 -0
- package/lib/model/states/light-state.js +134 -0
- package/lib/model/states/presence-sensor-state.js +239 -0
- package/lib/model/states/roller-shutter-state.js +82 -0
- package/lib/model/states/spray-state.js +58 -0
- package/lib/model/states/thermostat-state.js +297 -0
- package/lib/model/states/timer-state.js +192 -0
- package/lib/model/states/toggle-state.js +105 -0
- package/lib/model/states/trigger-state.js +155 -0
- package/lib/subscription.js +587 -0
- package/lib/utilities/conversion.js +62 -0
- package/lib/utilities/debug.js +165 -0
- package/lib/utilities/mqtt.js +152 -0
- package/lib/utilities/network.js +53 -0
- package/lib/utilities/options.js +64 -0
- package/lib/utilities/request-queue.js +161 -0
- package/lib/utilities/ssid.js +37 -0
- package/lib/utilities/state-changes.js +66 -0
- package/lib/utilities/stats.js +687 -0
- package/lib/utilities/timer.js +310 -0
- package/lib/utilities/trigger.js +286 -0
- package/package.json +73 -0
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RollerShutterState = require('../../model/states/roller-shutter-state');
|
|
4
|
+
const { RollerShutterStatus } = require('../../model/enums');
|
|
5
|
+
const { normalizeChannel } = require('../../utilities/options');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Roller shutter feature module.
|
|
9
|
+
* Provides control over roller shutter/blind position and movement state.
|
|
10
|
+
*/
|
|
11
|
+
module.exports = {
|
|
12
|
+
/**
|
|
13
|
+
* Sets the roller shutter position.
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} options - Roller shutter position options
|
|
16
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
17
|
+
* @param {number} options.position - Position value (0-100 for open/close, -1 for stop)
|
|
18
|
+
* @returns {Promise<Object>} Response from the device containing the updated position
|
|
19
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
20
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
21
|
+
*/
|
|
22
|
+
async setRollerShutterPosition(options = {}) {
|
|
23
|
+
if (options.position === undefined) {
|
|
24
|
+
throw new Error('position is required');
|
|
25
|
+
}
|
|
26
|
+
const channel = normalizeChannel(options);
|
|
27
|
+
const payload = { 'position': { position: options.position, channel } };
|
|
28
|
+
const response = await this.publishMessage('SET', 'Appliance.RollerShutter.Position', payload);
|
|
29
|
+
|
|
30
|
+
if (response && response.position) {
|
|
31
|
+
this._updateRollerShutterPosition(response.position, 'response');
|
|
32
|
+
this._lastFullUpdateTimestamp = Date.now();
|
|
33
|
+
} else {
|
|
34
|
+
this._updateRollerShutterPosition([{ channel, position: options.position }], 'response');
|
|
35
|
+
this._lastFullUpdateTimestamp = Date.now();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return response;
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Opens the roller shutter (moves to position 100).
|
|
43
|
+
*
|
|
44
|
+
* Convenience method that calls {@link setRollerShutterPosition} with position 100.
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} [options={}] - Open options
|
|
47
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
48
|
+
* @returns {Promise<Object>} Response from the device
|
|
49
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
50
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
51
|
+
* @see closeRollerShutter
|
|
52
|
+
* @see stopRollerShutter
|
|
53
|
+
*/
|
|
54
|
+
async setRollerShutterUp(options = {}) {
|
|
55
|
+
return await this.setRollerShutterPosition({ ...options, position: 100 });
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Closes the roller shutter (moves to position 0).
|
|
60
|
+
*
|
|
61
|
+
* Convenience method that calls {@link setRollerShutterPosition} with position 0.
|
|
62
|
+
*
|
|
63
|
+
* @param {Object} [options={}] - Close options
|
|
64
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
65
|
+
* @returns {Promise<Object>} Response from the device
|
|
66
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
67
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
68
|
+
* @see openRollerShutter
|
|
69
|
+
* @see stopRollerShutter
|
|
70
|
+
*/
|
|
71
|
+
async setRollerShutterDown(options = {}) {
|
|
72
|
+
return await this.setRollerShutterPosition({ ...options, position: 0 });
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Stops the roller shutter movement.
|
|
77
|
+
*
|
|
78
|
+
* Convenience method that calls {@link setRollerShutterPosition} with position -1.
|
|
79
|
+
*
|
|
80
|
+
* @param {Object} [options={}] - Stop options
|
|
81
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
82
|
+
* @returns {Promise<Object>} Response from the device
|
|
83
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
84
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
85
|
+
* @see openRollerShutter
|
|
86
|
+
* @see closeRollerShutter
|
|
87
|
+
*/
|
|
88
|
+
async setRollerShutterStop(options = {}) {
|
|
89
|
+
return await this.setRollerShutterPosition({ ...options, position: -1 });
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Opens the roller shutter (moves to position 100).
|
|
94
|
+
*
|
|
95
|
+
* Alias for {@link setRollerShutterUp}.
|
|
96
|
+
*
|
|
97
|
+
* @param {Object} [options={}] - Open options
|
|
98
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
99
|
+
* @returns {Promise<Object>} Response from the device
|
|
100
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
101
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
102
|
+
* @see closeRollerShutter
|
|
103
|
+
* @see stopRollerShutter
|
|
104
|
+
*/
|
|
105
|
+
async openRollerShutter(options = {}) {
|
|
106
|
+
return await this.setRollerShutterPosition({ ...options, position: 100 });
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Closes the roller shutter (moves to position 0).
|
|
111
|
+
*
|
|
112
|
+
* Alias for {@link setRollerShutterDown}.
|
|
113
|
+
*
|
|
114
|
+
* @param {Object} [options={}] - Close options
|
|
115
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
116
|
+
* @returns {Promise<Object>} Response from the device
|
|
117
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
118
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
119
|
+
* @see openRollerShutter
|
|
120
|
+
* @see stopRollerShutter
|
|
121
|
+
*/
|
|
122
|
+
async closeRollerShutter(options = {}) {
|
|
123
|
+
return await this.setRollerShutterPosition({ ...options, position: 0 });
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Stops the roller shutter movement.
|
|
128
|
+
*
|
|
129
|
+
* Alias for {@link setRollerShutterStop}.
|
|
130
|
+
*
|
|
131
|
+
* @param {Object} [options={}] - Stop options
|
|
132
|
+
* @param {number} [options.channel=0] - Channel to control (default: 0)
|
|
133
|
+
* @returns {Promise<Object>} Response from the device
|
|
134
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
135
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
136
|
+
* @see openRollerShutter
|
|
137
|
+
* @see closeRollerShutter
|
|
138
|
+
*/
|
|
139
|
+
async stopRollerShutter(options = {}) {
|
|
140
|
+
return await this.setRollerShutterPosition({ ...options, position: -1 });
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Gets the current roller shutter state from the device.
|
|
146
|
+
*
|
|
147
|
+
* Use {@link getCachedRollerShutterState} to get cached state without making a request.
|
|
148
|
+
* @param {Object} [options={}] - Get options
|
|
149
|
+
* @returns {Promise<Object>} Response containing roller shutter state with `state` array
|
|
150
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
151
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
152
|
+
*/
|
|
153
|
+
async getRollerShutterState(_options = {}) {
|
|
154
|
+
const response = await this.publishMessage('GET', 'Appliance.RollerShutter.State', {});
|
|
155
|
+
if (response && response.state) {
|
|
156
|
+
this._updateRollerShutterState(response.state, 'response');
|
|
157
|
+
this._lastFullUpdateTimestamp = Date.now();
|
|
158
|
+
}
|
|
159
|
+
return response;
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Gets the current roller shutter position from the device.
|
|
164
|
+
*
|
|
165
|
+
* Use {@link getRollerShutterPosition} (getter) to get cached position without making a request.
|
|
166
|
+
* @param {Object} [options={}] - Get options
|
|
167
|
+
* @returns {Promise<Object>} Response containing roller shutter position with `position` array
|
|
168
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
169
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
170
|
+
*/
|
|
171
|
+
async getRollerShutterPosition(_options = {}) {
|
|
172
|
+
const response = await this.publishMessage('GET', 'Appliance.RollerShutter.Position', {});
|
|
173
|
+
if (response && response.position) {
|
|
174
|
+
this._updateRollerShutterPosition(response.position, 'response');
|
|
175
|
+
}
|
|
176
|
+
return response;
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Gets the roller shutter configuration from the device.
|
|
181
|
+
*
|
|
182
|
+
* Use {@link getRollerShutterConfig} (getter) to get cached config without making a request.
|
|
183
|
+
* @param {Object} [options={}] - Get options
|
|
184
|
+
* @returns {Promise<Object>} Response containing roller shutter config with `config` array
|
|
185
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
186
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
187
|
+
*/
|
|
188
|
+
async getRollerShutterConfig(_options = {}) {
|
|
189
|
+
const response = await this.publishMessage('GET', 'Appliance.RollerShutter.Config', {});
|
|
190
|
+
if (response && response.config) {
|
|
191
|
+
this._updateRollerShutterConfig(response.config);
|
|
192
|
+
}
|
|
193
|
+
return response;
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Controls the roller shutter configuration.
|
|
198
|
+
*
|
|
199
|
+
* @param {Object} options - Roller shutter config options
|
|
200
|
+
* @param {Object|Array} options.config - Configuration object or array of configuration objects
|
|
201
|
+
* @returns {Promise<Object>} Response from the device
|
|
202
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
203
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
204
|
+
*/
|
|
205
|
+
async setRollerShutterConfig(options = {}) {
|
|
206
|
+
if (!options.config) {
|
|
207
|
+
throw new Error('config is required');
|
|
208
|
+
}
|
|
209
|
+
const payload = { config: options.config };
|
|
210
|
+
const response = await this.publishMessage('SET', 'Appliance.RollerShutter.Config', payload);
|
|
211
|
+
if (response && response.config) {
|
|
212
|
+
this._updateRollerShutterConfig(response.config);
|
|
213
|
+
} else if (options.config) {
|
|
214
|
+
const configArray = Array.isArray(options.config) ? options.config : [options.config];
|
|
215
|
+
this._updateRollerShutterConfig(configArray);
|
|
216
|
+
}
|
|
217
|
+
return response;
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Gets the roller shutter adjustment settings from the device.
|
|
222
|
+
* @param {Object} [options={}] - Get options
|
|
223
|
+
* @returns {Promise<Object>} Response containing roller shutter adjustment data
|
|
224
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
225
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
226
|
+
*/
|
|
227
|
+
async getRollerShutterAdjust(_options = {}) {
|
|
228
|
+
return await this.publishMessage('GET', 'Appliance.RollerShutter.Adjust', {});
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Gets the cached roller shutter state for the specified channel.
|
|
233
|
+
*
|
|
234
|
+
* Returns cached state without making a request. Use {@link getRollerShutterState} to fetch
|
|
235
|
+
* fresh state from the device. State is automatically updated when commands are sent or
|
|
236
|
+
* push notifications are received.
|
|
237
|
+
*
|
|
238
|
+
* @param {number} [channel=0] - Channel to get state for (default: 0)
|
|
239
|
+
* @returns {import('../lib/model/states/roller-shutter-state').RollerShutterState|undefined} Cached roller shutter state or undefined if not available
|
|
240
|
+
* @throws {Error} If state has not been initialized (call refreshState() first)
|
|
241
|
+
*/
|
|
242
|
+
getCachedRollerShutterState(channel = 0) {
|
|
243
|
+
this.validateState();
|
|
244
|
+
return this._rollerShutterStateByChannel.get(channel);
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Gets the roller shutter state value for the specified channel (cached).
|
|
249
|
+
*
|
|
250
|
+
* Returns the status enum (IDLE, OPENING, CLOSING) from cached state. Use {@link getRawRollerShutterState}
|
|
251
|
+
* to get the raw numeric value, or {@link getRollerShutterState} (async method) to fetch from device.
|
|
252
|
+
*
|
|
253
|
+
* @param {number} [channel=0] - Channel to get state for (default: 0)
|
|
254
|
+
* @returns {import('../lib/enums').RollerShutterStatus|undefined} RollerShutterStatus enum object (e.g., RollerShutterStatus.IDLE) or undefined if not available
|
|
255
|
+
* @throws {Error} If state has not been initialized (call refreshState() first)
|
|
256
|
+
* @see getRawRollerShutterState
|
|
257
|
+
*/
|
|
258
|
+
getRollerShutterState(channel = 0) {
|
|
259
|
+
this.validateState();
|
|
260
|
+
const state = this._rollerShutterStateByChannel.get(channel);
|
|
261
|
+
if (state && state.state !== undefined && state.state !== null) {
|
|
262
|
+
const enumKey = Object.keys(RollerShutterStatus).find(key => RollerShutterStatus[key] === state.state);
|
|
263
|
+
return enumKey ? RollerShutterStatus[enumKey] : undefined;
|
|
264
|
+
}
|
|
265
|
+
return undefined;
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Gets the raw numeric roller shutter state value for the specified channel (cached).
|
|
270
|
+
*
|
|
271
|
+
* Returns the raw numeric status value. For enum object, use {@link getRollerShutterState} instead.
|
|
272
|
+
*
|
|
273
|
+
* @param {number} [channel=0] - Channel to get state for (default: 0)
|
|
274
|
+
* @returns {number|undefined} Raw numeric state value or undefined if not available
|
|
275
|
+
* @throws {Error} If state has not been initialized (call refreshState() first)
|
|
276
|
+
* @see getRollerShutterState
|
|
277
|
+
*/
|
|
278
|
+
getRawRollerShutterState(channel = 0) {
|
|
279
|
+
this.validateState();
|
|
280
|
+
const state = this._rollerShutterStateByChannel.get(channel);
|
|
281
|
+
if (state) {
|
|
282
|
+
return state.state;
|
|
283
|
+
}
|
|
284
|
+
return undefined;
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Gets the roller shutter position for the specified channel (cached).
|
|
289
|
+
*
|
|
290
|
+
* Returns position (0-100) from cached state. Use {@link getRollerShutterPosition} (async method)
|
|
291
|
+
* to fetch fresh position from the device.
|
|
292
|
+
*
|
|
293
|
+
* @param {number} [channel=0] - Channel to get position for (default: 0)
|
|
294
|
+
* @returns {number|undefined} Position value (0-100, where 0 is closed and 100 is fully open) or undefined if not available
|
|
295
|
+
* @throws {Error} If state has not been initialized (call refreshState() first)
|
|
296
|
+
*/
|
|
297
|
+
getRollerShutterPosition(channel = 0) {
|
|
298
|
+
this.validateState();
|
|
299
|
+
const position = this._rollerShutterPositionByChannel.get(channel);
|
|
300
|
+
if (position !== undefined && position !== null) {
|
|
301
|
+
return position;
|
|
302
|
+
}
|
|
303
|
+
const state = this._rollerShutterStateByChannel.get(channel);
|
|
304
|
+
if (state) {
|
|
305
|
+
return state.position;
|
|
306
|
+
}
|
|
307
|
+
return undefined;
|
|
308
|
+
},
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Gets the roller shutter configuration for the specified channel (cached).
|
|
312
|
+
*
|
|
313
|
+
* Returns cached configuration without making a request. Use {@link getRollerShutterConfig} (async method)
|
|
314
|
+
* to fetch fresh configuration from the device.
|
|
315
|
+
*
|
|
316
|
+
* @param {number} [channel=0] - Channel to get config for (default: 0)
|
|
317
|
+
* @returns {Object|undefined} Roller shutter config or undefined if not available
|
|
318
|
+
* @throws {Error} If state has not been initialized (call refreshState() first)
|
|
319
|
+
*/
|
|
320
|
+
getRollerShutterConfig(channel = 0) {
|
|
321
|
+
this.validateState();
|
|
322
|
+
return this._rollerShutterConfigByChannel.get(channel);
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Updates the cached roller shutter state from state data.
|
|
327
|
+
*
|
|
328
|
+
* Called automatically when roller shutter push notifications are received or commands complete.
|
|
329
|
+
* Handles both single objects and arrays of state data.
|
|
330
|
+
*
|
|
331
|
+
* @param {Object|Array} stateData - State data (single object or array)
|
|
332
|
+
* @private
|
|
333
|
+
*/
|
|
334
|
+
_updateRollerShutterState(stateData, source = 'response') {
|
|
335
|
+
if (!stateData) {return;}
|
|
336
|
+
|
|
337
|
+
const stateArray = Array.isArray(stateData) ? stateData : [stateData];
|
|
338
|
+
|
|
339
|
+
for (const stateItem of stateArray) {
|
|
340
|
+
const channelIndex = stateItem.channel;
|
|
341
|
+
if (channelIndex === undefined || channelIndex === null) {continue;}
|
|
342
|
+
|
|
343
|
+
const oldState = this._rollerShutterStateByChannel.get(channelIndex);
|
|
344
|
+
const oldValue = oldState ? {
|
|
345
|
+
state: oldState.state,
|
|
346
|
+
position: oldState.position
|
|
347
|
+
} : undefined;
|
|
348
|
+
|
|
349
|
+
let state = this._rollerShutterStateByChannel.get(channelIndex);
|
|
350
|
+
if (!state) {
|
|
351
|
+
state = new RollerShutterState(stateItem);
|
|
352
|
+
this._rollerShutterStateByChannel.set(channelIndex, state);
|
|
353
|
+
} else {
|
|
354
|
+
state.update(stateItem);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const newValue = {};
|
|
358
|
+
if (oldValue === undefined || oldValue.state !== state.state) {
|
|
359
|
+
newValue.state = state.state;
|
|
360
|
+
}
|
|
361
|
+
if (oldValue === undefined || oldValue.position !== state.position) {
|
|
362
|
+
newValue.position = state.position;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (Object.keys(newValue).length > 0) {
|
|
366
|
+
this.emit('stateChange', {
|
|
367
|
+
type: 'rollerShutter',
|
|
368
|
+
channel: channelIndex,
|
|
369
|
+
value: newValue,
|
|
370
|
+
oldValue,
|
|
371
|
+
source,
|
|
372
|
+
timestamp: Date.now()
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Updates the cached roller shutter position from position data.
|
|
380
|
+
*
|
|
381
|
+
* Called automatically when roller shutter position responses are received. Updates both
|
|
382
|
+
* the position cache and the state cache.
|
|
383
|
+
*
|
|
384
|
+
* @param {Object|Array} positionData - Position data (single object or array)
|
|
385
|
+
* @private
|
|
386
|
+
*/
|
|
387
|
+
_updateRollerShutterPosition(positionData, source = 'response') {
|
|
388
|
+
if (!positionData) {return;}
|
|
389
|
+
|
|
390
|
+
const positionArray = Array.isArray(positionData) ? positionData : [positionData];
|
|
391
|
+
|
|
392
|
+
for (const positionItem of positionArray) {
|
|
393
|
+
const channelIndex = positionItem.channel;
|
|
394
|
+
if (channelIndex === undefined || channelIndex === null) {continue;}
|
|
395
|
+
|
|
396
|
+
const oldPosition = this._rollerShutterPositionByChannel.get(channelIndex);
|
|
397
|
+
const oldState = this._rollerShutterStateByChannel.get(channelIndex);
|
|
398
|
+
const oldValue = oldState ? {
|
|
399
|
+
state: oldState.state,
|
|
400
|
+
position: oldState.position
|
|
401
|
+
} : (oldPosition !== undefined ? { position: oldPosition } : undefined);
|
|
402
|
+
|
|
403
|
+
this._rollerShutterPositionByChannel.set(channelIndex, positionItem.position);
|
|
404
|
+
|
|
405
|
+
let state = this._rollerShutterStateByChannel.get(channelIndex);
|
|
406
|
+
if (!state) {
|
|
407
|
+
state = new RollerShutterState(positionItem);
|
|
408
|
+
this._rollerShutterStateByChannel.set(channelIndex, state);
|
|
409
|
+
} else {
|
|
410
|
+
state.update(positionItem);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const newValue = {};
|
|
414
|
+
if (oldValue === undefined || oldValue.state !== state.state) {
|
|
415
|
+
newValue.state = state.state;
|
|
416
|
+
}
|
|
417
|
+
if (oldValue === undefined || oldValue.position !== state.position) {
|
|
418
|
+
newValue.position = state.position;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (Object.keys(newValue).length > 0) {
|
|
422
|
+
this.emit('stateChange', {
|
|
423
|
+
type: 'rollerShutter',
|
|
424
|
+
channel: channelIndex,
|
|
425
|
+
value: newValue,
|
|
426
|
+
oldValue,
|
|
427
|
+
source,
|
|
428
|
+
timestamp: Date.now()
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Updates the cached roller shutter configuration from config data.
|
|
436
|
+
*
|
|
437
|
+
* Called automatically when roller shutter configuration responses are received.
|
|
438
|
+
* Handles both single objects and arrays of config data.
|
|
439
|
+
*
|
|
440
|
+
* @param {Object|Array} configData - Config data (single object or array)
|
|
441
|
+
* @private
|
|
442
|
+
*/
|
|
443
|
+
_updateRollerShutterConfig(configData) {
|
|
444
|
+
if (!configData) {return;}
|
|
445
|
+
|
|
446
|
+
const configArray = Array.isArray(configData) ? configData : [configData];
|
|
447
|
+
|
|
448
|
+
for (const configItem of configArray) {
|
|
449
|
+
const channelIndex = configItem.channel;
|
|
450
|
+
if (channelIndex === undefined || channelIndex === null) {continue;}
|
|
451
|
+
|
|
452
|
+
this._rollerShutterConfigByChannel.set(channelIndex, configItem);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Runtime feature module.
|
|
5
|
+
* Provides access to device runtime information such as uptime and system statistics.
|
|
6
|
+
*/
|
|
7
|
+
module.exports = {
|
|
8
|
+
/**
|
|
9
|
+
* Initializes runtime info storage.
|
|
10
|
+
*
|
|
11
|
+
* Called lazily to ensure the runtime info object exists before use.
|
|
12
|
+
*
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
_initializeRuntimeInfo() {
|
|
16
|
+
if (this._runtimeInfo === undefined) {
|
|
17
|
+
this._runtimeInfo = {};
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Gets the latest runtime information from the device.
|
|
23
|
+
*
|
|
24
|
+
* Runtime information may vary over time as Meross adds, removes, or changes runtime
|
|
25
|
+
* data fields in firmware updates. Use {@link cachedSystemRuntimeInfo} to access cached
|
|
26
|
+
* runtime info without making a request.
|
|
27
|
+
*
|
|
28
|
+
* @returns {Promise<Object>} Runtime information object
|
|
29
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
30
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
31
|
+
*/
|
|
32
|
+
async updateRuntimeInfo() {
|
|
33
|
+
this._initializeRuntimeInfo();
|
|
34
|
+
const result = await this.publishMessage('GET', 'Appliance.System.Runtime', {});
|
|
35
|
+
const data = result && result.runtime ? result.runtime : {};
|
|
36
|
+
this._runtimeInfo = data;
|
|
37
|
+
return data;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Gets the cached runtime information.
|
|
42
|
+
*
|
|
43
|
+
* Returns the most recently fetched runtime info without making a request. For fresh
|
|
44
|
+
* data, use {@link updateRuntimeInfo} instead.
|
|
45
|
+
*
|
|
46
|
+
* @returns {Object|null} Cached runtime info or null if not yet fetched
|
|
47
|
+
*/
|
|
48
|
+
get cachedSystemRuntimeInfo() {
|
|
49
|
+
this._initializeRuntimeInfo();
|
|
50
|
+
return this._runtimeInfo;
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Refreshes device state including runtime information.
|
|
55
|
+
*
|
|
56
|
+
* Calls the base refreshState implementation (getSystemAllData) and then updates
|
|
57
|
+
* runtime info to ensure all state is current.
|
|
58
|
+
*
|
|
59
|
+
* @returns {Promise<void>}
|
|
60
|
+
* @throws {import('../lib/errors/errors').UnknownDeviceTypeError} If device does not support refreshState
|
|
61
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
62
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
63
|
+
*/
|
|
64
|
+
async refreshState() {
|
|
65
|
+
if (typeof this.getSystemAllData === 'function') {
|
|
66
|
+
await this.getSystemAllData();
|
|
67
|
+
} else {
|
|
68
|
+
const { UnknownDeviceTypeError } = require('../../model/exception');
|
|
69
|
+
throw new UnknownDeviceTypeError('Device does not support refreshState()', this.deviceType);
|
|
70
|
+
}
|
|
71
|
+
await this.updateRuntimeInfo();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { normalizeChannel } = require('../../utilities/options');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Screen feature module.
|
|
7
|
+
* Provides control over device screen brightness settings for different operational states.
|
|
8
|
+
*/
|
|
9
|
+
module.exports = {
|
|
10
|
+
/**
|
|
11
|
+
* Gets the screen brightness configuration from the device.
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} [options={}] - Get options
|
|
14
|
+
* @param {number} [options.channel=0] - Channel to get brightness for (default: 0)
|
|
15
|
+
* @param {string} [options.subId=null] - Optional subdevice ID
|
|
16
|
+
* @returns {Promise<Object>} Response containing brightness configuration with `brightness` array
|
|
17
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
18
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
19
|
+
*/
|
|
20
|
+
async getScreenBrightness(options = {}) {
|
|
21
|
+
const channel = normalizeChannel(options);
|
|
22
|
+
const payload = {
|
|
23
|
+
brightness: [{
|
|
24
|
+
channel
|
|
25
|
+
}]
|
|
26
|
+
};
|
|
27
|
+
if (options.subId) {
|
|
28
|
+
payload.brightness[0].subId = options.subId;
|
|
29
|
+
}
|
|
30
|
+
return await this.publishMessage('GET', 'Appliance.Control.Screen.Brightness', payload);
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Controls the screen brightness configuration.
|
|
35
|
+
*
|
|
36
|
+
* Allows setting different brightness levels for standby, operation, and standby view modes.
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} options - Screen brightness options
|
|
39
|
+
* @param {Object|Array<Object>} [options.brightnessData] - Brightness data object or array of brightness items (if provided, used directly)
|
|
40
|
+
* @param {number} [options.channel] - Channel to configure
|
|
41
|
+
* @param {string} [options.subId] - Optional subdevice ID
|
|
42
|
+
* @param {number} [options.standby] - Standby brightness level
|
|
43
|
+
* @param {number} [options.operation] - Operation brightness level
|
|
44
|
+
* @param {number} [options.standbyView] - Standby view brightness level
|
|
45
|
+
* @returns {Promise<Object>} Response from the device
|
|
46
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
47
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
48
|
+
*/
|
|
49
|
+
async setScreenBrightness(options = {}) {
|
|
50
|
+
let brightnessData;
|
|
51
|
+
if (options.brightnessData) {
|
|
52
|
+
brightnessData = Array.isArray(options.brightnessData) ? options.brightnessData : [options.brightnessData];
|
|
53
|
+
} else {
|
|
54
|
+
const channel = normalizeChannel(options);
|
|
55
|
+
brightnessData = [{
|
|
56
|
+
channel,
|
|
57
|
+
subId: options.subId,
|
|
58
|
+
standby: options.standby,
|
|
59
|
+
operation: options.operation,
|
|
60
|
+
standbyView: options.standbyView
|
|
61
|
+
}];
|
|
62
|
+
}
|
|
63
|
+
const payload = { brightness: brightnessData };
|
|
64
|
+
return await this.publishMessage('SET', 'Appliance.Control.Screen.Brightness', payload);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { normalizeChannel, validateRequired } = require('../../utilities/options');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sensor history feature module.
|
|
7
|
+
* Provides access to historical sensor data and the ability to delete stored history.
|
|
8
|
+
*/
|
|
9
|
+
module.exports = {
|
|
10
|
+
/**
|
|
11
|
+
* Gets sensor history data from the device.
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} options - Get options
|
|
14
|
+
* @param {number} [options.channel=0] - Channel to get history for (default: 0)
|
|
15
|
+
* @param {number} options.capacity - Data collection type (see API docs for capacity values)
|
|
16
|
+
* @returns {Promise<Object>} Response containing sensor history data with `history` array
|
|
17
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
18
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
19
|
+
*/
|
|
20
|
+
async getSensorHistory(options = {}) {
|
|
21
|
+
const channel = normalizeChannel(options);
|
|
22
|
+
validateRequired(options, ['capacity']);
|
|
23
|
+
const payload = {
|
|
24
|
+
history: [{
|
|
25
|
+
channel,
|
|
26
|
+
capacity: options.capacity
|
|
27
|
+
}]
|
|
28
|
+
};
|
|
29
|
+
return await this.publishMessage('GET', 'Appliance.Control.Sensor.History', payload);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Deletes sensor history data from the device.
|
|
34
|
+
*
|
|
35
|
+
* @param {Object|Array<Object>} historyData - History data object or array of history items
|
|
36
|
+
* @param {number} [historyData.channel] - Channel to delete history for
|
|
37
|
+
* @param {number} [historyData.capacity] - Data collection type to delete
|
|
38
|
+
* @returns {Promise<Object>} Response from the device
|
|
39
|
+
* @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
|
|
40
|
+
* @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
|
|
41
|
+
*/
|
|
42
|
+
async deleteSensorHistory(historyData) {
|
|
43
|
+
const payload = { history: Array.isArray(historyData) ? historyData : [historyData] };
|
|
44
|
+
return await this.publishMessage('DELETE', 'Appliance.Control.Sensor.History', payload);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|