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,239 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { PresenceState } = require('../enums');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents the presence sensor state of a device channel.
|
|
7
|
+
*
|
|
8
|
+
* Encapsulates state information for presence sensor devices, including presence
|
|
9
|
+
* detection status, distance, and light/illuminance readings. State instances are
|
|
10
|
+
* managed by device controllers and updated automatically when device responses or
|
|
11
|
+
* push notifications are received.
|
|
12
|
+
*
|
|
13
|
+
* @class
|
|
14
|
+
* @example
|
|
15
|
+
* const presenceState = device.getCachedPresenceSensorState(0);
|
|
16
|
+
* if (presenceState) {
|
|
17
|
+
* console.log('Is present:', presenceState.isPresent);
|
|
18
|
+
* console.log('Distance:', presenceState.distanceMeters, 'm');
|
|
19
|
+
* console.log('Light:', presenceState.lightLux, 'lux');
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
class PresenceSensorState {
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new PresenceSensorState instance.
|
|
25
|
+
*
|
|
26
|
+
* @param {Object} [state=null] - Initial state object
|
|
27
|
+
* @param {Object} [state.presence] - Presence detection data
|
|
28
|
+
* @param {number} [state.presence.value] - Presence value (from PresenceState enum)
|
|
29
|
+
* @param {number} [state.presence.distance] - Distance in millimeters
|
|
30
|
+
* @param {number} [state.presence.timestamp] - Timestamp in seconds
|
|
31
|
+
* @param {number} [state.presence.times] - Times value
|
|
32
|
+
* @param {Object} [state.light] - Light/illuminance data
|
|
33
|
+
* @param {number} [state.light.value] - Light value in lux
|
|
34
|
+
* @param {number} [state.light.timestamp] - Timestamp in seconds
|
|
35
|
+
* @param {number} [state.channel] - Channel number
|
|
36
|
+
*/
|
|
37
|
+
constructor(state = null) {
|
|
38
|
+
this._state = state || {};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Updates the state with new data.
|
|
43
|
+
*
|
|
44
|
+
* Merges new state data into the existing state. Presence and light objects are
|
|
45
|
+
* deep-merged using spread operators to preserve existing nested properties that
|
|
46
|
+
* aren't included in the update. Called automatically by device controllers when
|
|
47
|
+
* state updates are received from device responses or push notifications.
|
|
48
|
+
*
|
|
49
|
+
* @param {Object} state - New state data to merge
|
|
50
|
+
*/
|
|
51
|
+
update(state) {
|
|
52
|
+
if (state) {
|
|
53
|
+
if (state.presence) {
|
|
54
|
+
this._state.presence = { ...(this._state.presence || {}), ...state.presence };
|
|
55
|
+
}
|
|
56
|
+
if (state.light) {
|
|
57
|
+
this._state.light = { ...(this._state.light || {}), ...state.light };
|
|
58
|
+
}
|
|
59
|
+
const { presence: _presence, light: _light, ...otherProps } = state;
|
|
60
|
+
Object.assign(this._state, otherProps);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets whether presence is currently detected.
|
|
66
|
+
*
|
|
67
|
+
* Converts the device's presence state enum value to a boolean for easier
|
|
68
|
+
* conditional logic in application code.
|
|
69
|
+
*
|
|
70
|
+
* @returns {boolean|undefined} True if presence detected, false if absence detected, undefined if no data
|
|
71
|
+
*/
|
|
72
|
+
get isPresent() {
|
|
73
|
+
const { presence } = this._state;
|
|
74
|
+
if (!presence || presence.value === undefined || presence.value === null) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
return presence.value === PresenceState.PRESENCE;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Gets the presence state value.
|
|
82
|
+
*
|
|
83
|
+
* Returns the raw presence state value from the PresenceState enum. Use this
|
|
84
|
+
* when you need the exact enum value rather than a boolean conversion.
|
|
85
|
+
*
|
|
86
|
+
* @returns {number|undefined} PresenceState.PRESENCE (2) or PresenceState.ABSENCE (1), undefined if no data
|
|
87
|
+
*/
|
|
88
|
+
get presenceValue() {
|
|
89
|
+
const { presence } = this._state;
|
|
90
|
+
if (!presence || presence.value === undefined || presence.value === null) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
return presence.value;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Gets the presence state as a string.
|
|
98
|
+
*
|
|
99
|
+
* Converts the boolean presence state to a human-readable string. Useful for
|
|
100
|
+
* logging and display purposes.
|
|
101
|
+
*
|
|
102
|
+
* @returns {string|undefined} 'presence' or 'absence', undefined if no data
|
|
103
|
+
*/
|
|
104
|
+
get presenceState() {
|
|
105
|
+
const { isPresent } = this;
|
|
106
|
+
if (isPresent === undefined) {return undefined;}
|
|
107
|
+
return isPresent ? 'presence' : 'absence';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Gets the detected distance in meters.
|
|
112
|
+
*
|
|
113
|
+
* The device reports distance in millimeters. This getter converts to meters
|
|
114
|
+
* for more convenient use in applications that work with metric units.
|
|
115
|
+
*
|
|
116
|
+
* @returns {number|undefined} Distance in meters, undefined if no data
|
|
117
|
+
*/
|
|
118
|
+
get distanceMeters() {
|
|
119
|
+
const { presence } = this._state;
|
|
120
|
+
if (!presence || presence.distance === undefined || presence.distance === null) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
return presence.distance / 1000;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gets the detected distance in millimeters.
|
|
128
|
+
*
|
|
129
|
+
* Returns the raw distance value as reported by the device. Use this when
|
|
130
|
+
* you need the exact format used in device communication protocols.
|
|
131
|
+
*
|
|
132
|
+
* @returns {number|undefined} Distance in millimeters, undefined if no data
|
|
133
|
+
*/
|
|
134
|
+
get distanceRaw() {
|
|
135
|
+
const { presence } = this._state;
|
|
136
|
+
if (!presence || presence.distance === undefined || presence.distance === null) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
return presence.distance;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Gets the timestamp when presence was detected.
|
|
144
|
+
*
|
|
145
|
+
* The device provides timestamps as Unix seconds. This getter converts to a
|
|
146
|
+
* JavaScript Date object for easier date manipulation and formatting.
|
|
147
|
+
*
|
|
148
|
+
* @returns {Date|undefined} Date object, undefined if no data
|
|
149
|
+
*/
|
|
150
|
+
get presenceTimestamp() {
|
|
151
|
+
const { presence } = this._state;
|
|
152
|
+
if (!presence || presence.timestamp === undefined || presence.timestamp === null) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
return new Date(presence.timestamp * 1000);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Gets the times value from presence data.
|
|
160
|
+
*
|
|
161
|
+
* @returns {number|undefined} Times value, undefined if no data
|
|
162
|
+
*/
|
|
163
|
+
get presenceTimes() {
|
|
164
|
+
const { presence } = this._state;
|
|
165
|
+
if (!presence || presence.times === undefined || presence.times === null) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
return presence.times;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Gets the light/illuminance value in lux.
|
|
173
|
+
*
|
|
174
|
+
* @returns {number|undefined} Light value in lux, undefined if no data
|
|
175
|
+
*/
|
|
176
|
+
get lightLux() {
|
|
177
|
+
const { light } = this._state;
|
|
178
|
+
if (!light || light.value === undefined || light.value === null) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
return light.value;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Gets the timestamp when light was measured.
|
|
186
|
+
*
|
|
187
|
+
* The device provides timestamps as Unix seconds. This getter converts to a
|
|
188
|
+
* JavaScript Date object for easier date manipulation and formatting.
|
|
189
|
+
*
|
|
190
|
+
* @returns {Date|undefined} Date object, undefined if no data
|
|
191
|
+
*/
|
|
192
|
+
get lightTimestamp() {
|
|
193
|
+
const { light } = this._state;
|
|
194
|
+
if (!light || light.timestamp === undefined || light.timestamp === null) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
return new Date(light.timestamp * 1000);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Gets the channel number.
|
|
202
|
+
*
|
|
203
|
+
* @returns {number|undefined} Channel number or undefined if not available
|
|
204
|
+
*/
|
|
205
|
+
get channel() {
|
|
206
|
+
const { channel } = this._state;
|
|
207
|
+
if (channel === undefined || channel === null) {return undefined;}
|
|
208
|
+
return channel;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Gets the raw presence data object.
|
|
213
|
+
*
|
|
214
|
+
* Returns the complete presence data object as received from the device. Use
|
|
215
|
+
* this when you need access to all presence properties, including those not
|
|
216
|
+
* exposed by individual getters.
|
|
217
|
+
*
|
|
218
|
+
* @returns {Object|undefined} Raw presence data object, undefined if no data
|
|
219
|
+
*/
|
|
220
|
+
get rawPresence() {
|
|
221
|
+
return this._state.presence;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Gets the raw light data object.
|
|
226
|
+
*
|
|
227
|
+
* Returns the complete light data object as received from the device. Use
|
|
228
|
+
* this when you need access to all light properties, including those not
|
|
229
|
+
* exposed by individual getters.
|
|
230
|
+
*
|
|
231
|
+
* @returns {Object|undefined} Raw light data object, undefined if no data
|
|
232
|
+
*/
|
|
233
|
+
get rawLight() {
|
|
234
|
+
return this._state.light;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = PresenceSensorState;
|
|
239
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents the state of a roller shutter device channel.
|
|
5
|
+
*
|
|
6
|
+
* Encapsulates state information for roller shutter devices, including position
|
|
7
|
+
* and movement status. State instances are managed by device controllers and
|
|
8
|
+
* updated automatically when device responses or push notifications are received.
|
|
9
|
+
*
|
|
10
|
+
* @class
|
|
11
|
+
* @example
|
|
12
|
+
* const rollerShutterState = device.getCachedRollerShutterState(0);
|
|
13
|
+
* if (rollerShutterState) {
|
|
14
|
+
* console.log('Position:', rollerShutterState.position);
|
|
15
|
+
* console.log('Status:', rollerShutterState.state);
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
class RollerShutterState {
|
|
19
|
+
/**
|
|
20
|
+
* Creates a new RollerShutterState instance.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} [state=null] - Initial state object
|
|
23
|
+
* @param {number} [state.state] - Movement status (from RollerShutterStatus enum: IDLE=0, OPENING=1, CLOSING=2, UNKNOWN=-1)
|
|
24
|
+
* @param {number} [state.position] - Position value (0-100, where 0=closed, 100=open)
|
|
25
|
+
* @param {number} [state.channel] - Channel number
|
|
26
|
+
*/
|
|
27
|
+
constructor(state = null) {
|
|
28
|
+
this._state = state || {};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Updates the state with new data.
|
|
33
|
+
*
|
|
34
|
+
* Merges new state data into the existing state using Object.assign to preserve
|
|
35
|
+
* properties not included in the update. Called automatically by device controllers
|
|
36
|
+
* when state updates are received from device responses or push notifications.
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} state - New state data to merge
|
|
39
|
+
*/
|
|
40
|
+
update(state) {
|
|
41
|
+
if (state) {
|
|
42
|
+
Object.assign(this._state, state);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Gets the movement status.
|
|
48
|
+
*
|
|
49
|
+
* @returns {number|undefined} Status value (0=idle, 1=opening, 2=closing, -1=unknown) or undefined if not available
|
|
50
|
+
* @see {@link module:lib/enums.RollerShutterStatus} for status constants
|
|
51
|
+
*/
|
|
52
|
+
get state() {
|
|
53
|
+
const { state } = this._state;
|
|
54
|
+
if (state === undefined || state === null) {return undefined;}
|
|
55
|
+
return state;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Gets the current position.
|
|
60
|
+
*
|
|
61
|
+
* @returns {number|undefined} Position value (0-100, where 0=fully closed, 100=fully open) or undefined if not available
|
|
62
|
+
*/
|
|
63
|
+
get position() {
|
|
64
|
+
const { position } = this._state;
|
|
65
|
+
if (position === undefined || position === null) {return undefined;}
|
|
66
|
+
return position;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the channel number.
|
|
71
|
+
*
|
|
72
|
+
* @returns {number|undefined} Channel number or undefined if not available
|
|
73
|
+
*/
|
|
74
|
+
get channel() {
|
|
75
|
+
const { channel } = this._state;
|
|
76
|
+
if (channel === undefined || channel === null) {return undefined;}
|
|
77
|
+
return channel;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = RollerShutterState;
|
|
82
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents the spray state of a spray/humidifier device channel.
|
|
5
|
+
*
|
|
6
|
+
* Encapsulates state information for spray/humidifier devices. State instances are
|
|
7
|
+
* managed by device controllers and updated automatically when device responses or
|
|
8
|
+
* push notifications are received.
|
|
9
|
+
*
|
|
10
|
+
* @class
|
|
11
|
+
* @example
|
|
12
|
+
* const sprayState = device.getCachedSprayState(0);
|
|
13
|
+
* if (sprayState) {
|
|
14
|
+
* console.log('Spray mode:', sprayState.mode);
|
|
15
|
+
* }
|
|
16
|
+
*/
|
|
17
|
+
class SprayState {
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new SprayState instance.
|
|
20
|
+
*
|
|
21
|
+
* @param {Object} [state=null] - Initial state object
|
|
22
|
+
* @param {number} [state.mode] - Spray mode (from SprayMode enum: OFF=0, CONTINUOUS=1, INTERMITTENT=2)
|
|
23
|
+
* @param {number} [state.channel] - Channel number
|
|
24
|
+
*/
|
|
25
|
+
constructor(state = null) {
|
|
26
|
+
this._state = state || {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Updates the state with new data.
|
|
31
|
+
*
|
|
32
|
+
* Merges new state data into the existing state using Object.assign to preserve
|
|
33
|
+
* properties not included in the update. Called automatically by device controllers
|
|
34
|
+
* when state updates are received from device responses or push notifications.
|
|
35
|
+
*
|
|
36
|
+
* @param {Object} state - New state data to merge
|
|
37
|
+
*/
|
|
38
|
+
update(state) {
|
|
39
|
+
if (state) {
|
|
40
|
+
Object.assign(this._state, state);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the spray mode.
|
|
46
|
+
*
|
|
47
|
+
* @returns {number|undefined} Spray mode value (0=off, 1=continuous, 2=intermittent) or undefined if not available
|
|
48
|
+
* @see {@link module:lib/enums.SprayMode} for mode constants
|
|
49
|
+
*/
|
|
50
|
+
get mode() {
|
|
51
|
+
const { mode } = this._state;
|
|
52
|
+
if (mode === undefined || mode === null) {return undefined;}
|
|
53
|
+
return mode;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = SprayState;
|
|
58
|
+
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { ThermostatMode, ThermostatWorkingMode, ThermostatModeBState } = require('../enums');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents the thermostat state of a device channel.
|
|
7
|
+
*
|
|
8
|
+
* Encapsulates state information for thermostat devices, including mode, target
|
|
9
|
+
* temperature, current temperature, and working mode. State instances are managed
|
|
10
|
+
* by device controllers and updated automatically when device responses or push
|
|
11
|
+
* notifications are received.
|
|
12
|
+
*
|
|
13
|
+
* @class
|
|
14
|
+
* @example
|
|
15
|
+
* const thermostatState = device.getCachedThermostatState(0);
|
|
16
|
+
* if (thermostatState) {
|
|
17
|
+
* console.log('Mode:', thermostatState.mode);
|
|
18
|
+
* console.log('Target temp:', thermostatState.targetTemp);
|
|
19
|
+
* console.log('Current temp:', thermostatState.currentTemp);
|
|
20
|
+
* }
|
|
21
|
+
*/
|
|
22
|
+
class ThermostatState {
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new ThermostatState instance.
|
|
25
|
+
*
|
|
26
|
+
* @param {Object} [state=null] - Initial state object
|
|
27
|
+
* @param {number} [state.onoff] - On/off state (0=off, 1=on)
|
|
28
|
+
* @param {number} [state.channel] - Channel number
|
|
29
|
+
* @param {number} [state.mode] - Thermostat mode (from ThermostatMode enum)
|
|
30
|
+
* @param {number} [state.targetTemp] - Target temperature
|
|
31
|
+
* @param {number} [state.currentTemp] - Current temperature
|
|
32
|
+
* @param {number} [state.working] - Working mode (from ThermostatWorkingMode enum)
|
|
33
|
+
* @param {number} [state.state] - Mode B state (from ThermostatModeBState enum)
|
|
34
|
+
*/
|
|
35
|
+
constructor(state = null) {
|
|
36
|
+
this._state = state || {};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Updates the state with new data.
|
|
41
|
+
*
|
|
42
|
+
* Merges new state data into the existing state using Object.assign to preserve
|
|
43
|
+
* properties not included in the update. Called automatically by device controllers
|
|
44
|
+
* when state updates are received from device responses or push notifications.
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} state - New state data to merge
|
|
47
|
+
*/
|
|
48
|
+
update(state) {
|
|
49
|
+
if (state) {
|
|
50
|
+
Object.assign(this._state, state);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Gets whether the thermostat is on.
|
|
56
|
+
*
|
|
57
|
+
* Converts the device's numeric on/off state (0 or 1) to a boolean for easier
|
|
58
|
+
* conditional logic in application code.
|
|
59
|
+
*
|
|
60
|
+
* @returns {boolean|undefined} True if on, false if off, undefined if state not available
|
|
61
|
+
*/
|
|
62
|
+
get isOn() {
|
|
63
|
+
const { onoff } = this._state;
|
|
64
|
+
if (onoff === undefined || onoff === null) {return undefined;}
|
|
65
|
+
return onoff === 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Gets the thermostat mode.
|
|
70
|
+
*
|
|
71
|
+
* Normalizes the mode value against the ThermostatMode enum. Returns the enum value
|
|
72
|
+
* if found, or the raw value if it's in the valid range (0-4) but not in the enum.
|
|
73
|
+
* This normalization allows handling of future enum values without breaking existing
|
|
74
|
+
* code while still providing enum constants when available.
|
|
75
|
+
*
|
|
76
|
+
* @returns {number|undefined} ThermostatMode enum value, raw value if valid but not in enum, or undefined if invalid
|
|
77
|
+
* @see {@link module:lib/enums.ThermostatMode} for mode constants
|
|
78
|
+
*/
|
|
79
|
+
get mode() {
|
|
80
|
+
const { mode } = this._state;
|
|
81
|
+
if (mode === undefined || mode === null) {return undefined;}
|
|
82
|
+
if (mode >= 0 && mode <= 4) {
|
|
83
|
+
const enumKey = Object.keys(ThermostatMode).find(key => ThermostatMode[key] === mode);
|
|
84
|
+
if (enumKey) {
|
|
85
|
+
return ThermostatMode[enumKey];
|
|
86
|
+
}
|
|
87
|
+
return mode;
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Gets the raw thermostat mode value.
|
|
94
|
+
*
|
|
95
|
+
* Returns the unvalidated mode value directly from state. Use this when you need
|
|
96
|
+
* the exact value without enum normalization, such as when debugging or working
|
|
97
|
+
* with device protocols directly.
|
|
98
|
+
*
|
|
99
|
+
* @returns {number|undefined} Raw mode value or undefined if not available
|
|
100
|
+
*/
|
|
101
|
+
get rawMode() {
|
|
102
|
+
return this._state.mode;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Gets the working mode.
|
|
107
|
+
*
|
|
108
|
+
* Normalizes the working mode value against the ThermostatWorkingMode enum.
|
|
109
|
+
* Returns undefined if the value doesn't match any enum constant.
|
|
110
|
+
*
|
|
111
|
+
* @returns {number|undefined} ThermostatWorkingMode enum value or undefined if not available
|
|
112
|
+
* @see {@link module:lib/enums.ThermostatWorkingMode} for mode constants
|
|
113
|
+
*/
|
|
114
|
+
get workingMode() {
|
|
115
|
+
const { working } = this._state;
|
|
116
|
+
if (working === undefined || working === null) {return undefined;}
|
|
117
|
+
const enumKey = Object.keys(ThermostatWorkingMode).find(key => ThermostatWorkingMode[key] === working);
|
|
118
|
+
return enumKey ? ThermostatWorkingMode[enumKey] : undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Gets the raw working mode value.
|
|
123
|
+
*
|
|
124
|
+
* Returns the unvalidated working mode value directly from state. Use this when
|
|
125
|
+
* you need the exact value without enum normalization.
|
|
126
|
+
*
|
|
127
|
+
* @returns {number|undefined} Raw working mode value or undefined if not available
|
|
128
|
+
*/
|
|
129
|
+
get rawWorkingMode() {
|
|
130
|
+
return this._state.working;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Gets the mode B state.
|
|
135
|
+
*
|
|
136
|
+
* Normalizes the mode B state value against the ThermostatModeBState enum.
|
|
137
|
+
* Returns undefined if the value doesn't match any enum constant.
|
|
138
|
+
*
|
|
139
|
+
* @returns {number|undefined} ThermostatModeBState enum value or undefined if not available
|
|
140
|
+
* @see {@link module:lib/enums.ThermostatModeBState} for state constants
|
|
141
|
+
*/
|
|
142
|
+
get state() {
|
|
143
|
+
const { state } = this._state;
|
|
144
|
+
if (state === undefined || state === null) {return undefined;}
|
|
145
|
+
const enumKey = Object.keys(ThermostatModeBState).find(key => ThermostatModeBState[key] === state);
|
|
146
|
+
return enumKey ? ThermostatModeBState[enumKey] : undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Gets the raw mode B state value.
|
|
151
|
+
*
|
|
152
|
+
* Returns the unvalidated mode B state value directly from state. Use this when
|
|
153
|
+
* you need the exact value without enum normalization.
|
|
154
|
+
*
|
|
155
|
+
* @returns {number|undefined} Raw mode B state value or undefined if not available
|
|
156
|
+
*/
|
|
157
|
+
get rawState() {
|
|
158
|
+
return this._state.state;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Gets whether a warning condition is active.
|
|
163
|
+
*
|
|
164
|
+
* Converts the device's numeric warning state (0 or 1) to a boolean for easier
|
|
165
|
+
* conditional logic in application code.
|
|
166
|
+
*
|
|
167
|
+
* @returns {boolean|undefined} True if warning is active, false otherwise, undefined if state not available
|
|
168
|
+
*/
|
|
169
|
+
get warning() {
|
|
170
|
+
const { warning } = this._state;
|
|
171
|
+
if (warning === undefined || warning === null) {return undefined;}
|
|
172
|
+
return warning === 1;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Gets the target temperature in Celsius.
|
|
177
|
+
*
|
|
178
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
179
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
180
|
+
* with standard temperature units.
|
|
181
|
+
*
|
|
182
|
+
* @returns {number|undefined} Target temperature in Celsius or undefined if not available
|
|
183
|
+
*/
|
|
184
|
+
get targetTemperatureCelsius() {
|
|
185
|
+
const temp = this._state.targetTemp;
|
|
186
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
187
|
+
return temp / 10.0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Gets the current temperature in Celsius.
|
|
192
|
+
*
|
|
193
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
194
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
195
|
+
* with standard temperature units.
|
|
196
|
+
*
|
|
197
|
+
* @returns {number|undefined} Current temperature in Celsius or undefined if not available
|
|
198
|
+
*/
|
|
199
|
+
get currentTemperatureCelsius() {
|
|
200
|
+
const temp = this._state.currentTemp;
|
|
201
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
202
|
+
return temp / 10.0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Gets the minimum temperature setting in Celsius.
|
|
207
|
+
*
|
|
208
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
209
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
210
|
+
* with standard temperature units.
|
|
211
|
+
*
|
|
212
|
+
* @returns {number|undefined} Minimum temperature in Celsius or undefined if not available
|
|
213
|
+
*/
|
|
214
|
+
get minTemperatureCelsius() {
|
|
215
|
+
const temp = this._state.min;
|
|
216
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
217
|
+
return temp / 10.0;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Gets the maximum temperature setting in Celsius.
|
|
222
|
+
*
|
|
223
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
224
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
225
|
+
* with standard temperature units.
|
|
226
|
+
*
|
|
227
|
+
* @returns {number|undefined} Maximum temperature in Celsius or undefined if not available
|
|
228
|
+
*/
|
|
229
|
+
get maxTemperatureCelsius() {
|
|
230
|
+
const temp = this._state.max;
|
|
231
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
232
|
+
return temp / 10.0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Gets the heat mode temperature setting in Celsius.
|
|
237
|
+
*
|
|
238
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
239
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
240
|
+
* with standard temperature units.
|
|
241
|
+
*
|
|
242
|
+
* @returns {number|undefined} Heat mode temperature in Celsius or undefined if not available
|
|
243
|
+
*/
|
|
244
|
+
get heatTemperatureCelsius() {
|
|
245
|
+
const temp = this._state.heatTemp;
|
|
246
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
247
|
+
return temp / 10.0;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Gets the cool mode temperature setting in Celsius.
|
|
252
|
+
*
|
|
253
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
254
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
255
|
+
* with standard temperature units.
|
|
256
|
+
*
|
|
257
|
+
* @returns {number|undefined} Cool mode temperature in Celsius or undefined if not available
|
|
258
|
+
*/
|
|
259
|
+
get coolTemperatureCelsius() {
|
|
260
|
+
const temp = this._state.coolTemp;
|
|
261
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
262
|
+
return temp / 10.0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Gets the eco mode temperature setting in Celsius.
|
|
267
|
+
*
|
|
268
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
269
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
270
|
+
* with standard temperature units.
|
|
271
|
+
*
|
|
272
|
+
* @returns {number|undefined} Eco mode temperature in Celsius or undefined if not available
|
|
273
|
+
*/
|
|
274
|
+
get ecoTemperatureCelsius() {
|
|
275
|
+
const temp = this._state.ecoTemp;
|
|
276
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
277
|
+
return temp / 10.0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Gets the manual mode temperature setting in Celsius.
|
|
282
|
+
*
|
|
283
|
+
* The device stores temperature values as integers in tenths of a degree (e.g., 250 = 25.0°C).
|
|
284
|
+
* This getter converts to decimal Celsius for easier use in applications that work
|
|
285
|
+
* with standard temperature units.
|
|
286
|
+
*
|
|
287
|
+
* @returns {number|undefined} Manual mode temperature in Celsius or undefined if not available
|
|
288
|
+
*/
|
|
289
|
+
get manualTemperatureCelsius() {
|
|
290
|
+
const temp = this._state.manualTemp;
|
|
291
|
+
if (temp === undefined || temp === null) {return undefined;}
|
|
292
|
+
return temp / 10.0;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
module.exports = ThermostatState;
|
|
297
|
+
|