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.
Files changed (99) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +153 -0
  4. package/index.d.ts +2344 -0
  5. package/index.js +131 -0
  6. package/lib/controller/device.js +1317 -0
  7. package/lib/controller/features/alarm-feature.js +89 -0
  8. package/lib/controller/features/child-lock-feature.js +61 -0
  9. package/lib/controller/features/config-feature.js +54 -0
  10. package/lib/controller/features/consumption-feature.js +210 -0
  11. package/lib/controller/features/control-feature.js +62 -0
  12. package/lib/controller/features/diffuser-feature.js +411 -0
  13. package/lib/controller/features/digest-timer-feature.js +22 -0
  14. package/lib/controller/features/digest-trigger-feature.js +22 -0
  15. package/lib/controller/features/dnd-feature.js +79 -0
  16. package/lib/controller/features/electricity-feature.js +144 -0
  17. package/lib/controller/features/encryption-feature.js +259 -0
  18. package/lib/controller/features/garage-feature.js +337 -0
  19. package/lib/controller/features/hub-feature.js +687 -0
  20. package/lib/controller/features/light-feature.js +408 -0
  21. package/lib/controller/features/presence-sensor-feature.js +297 -0
  22. package/lib/controller/features/roller-shutter-feature.js +456 -0
  23. package/lib/controller/features/runtime-feature.js +74 -0
  24. package/lib/controller/features/screen-feature.js +67 -0
  25. package/lib/controller/features/sensor-history-feature.js +47 -0
  26. package/lib/controller/features/smoke-config-feature.js +50 -0
  27. package/lib/controller/features/spray-feature.js +166 -0
  28. package/lib/controller/features/system-feature.js +269 -0
  29. package/lib/controller/features/temp-unit-feature.js +55 -0
  30. package/lib/controller/features/thermostat-feature.js +804 -0
  31. package/lib/controller/features/timer-feature.js +507 -0
  32. package/lib/controller/features/toggle-feature.js +223 -0
  33. package/lib/controller/features/trigger-feature.js +333 -0
  34. package/lib/controller/hub-device.js +185 -0
  35. package/lib/controller/subdevice.js +1537 -0
  36. package/lib/device-factory.js +463 -0
  37. package/lib/error-budget.js +138 -0
  38. package/lib/http-api.js +766 -0
  39. package/lib/manager.js +1609 -0
  40. package/lib/model/channel-info.js +79 -0
  41. package/lib/model/constants.js +119 -0
  42. package/lib/model/enums.js +819 -0
  43. package/lib/model/exception.js +363 -0
  44. package/lib/model/http/device.js +215 -0
  45. package/lib/model/http/error-codes.js +121 -0
  46. package/lib/model/http/exception.js +151 -0
  47. package/lib/model/http/subdevice.js +133 -0
  48. package/lib/model/push/alarm.js +112 -0
  49. package/lib/model/push/bind.js +97 -0
  50. package/lib/model/push/common.js +282 -0
  51. package/lib/model/push/diffuser-light.js +100 -0
  52. package/lib/model/push/diffuser-spray.js +83 -0
  53. package/lib/model/push/factory.js +229 -0
  54. package/lib/model/push/generic.js +115 -0
  55. package/lib/model/push/hub-battery.js +59 -0
  56. package/lib/model/push/hub-mts100-all.js +64 -0
  57. package/lib/model/push/hub-mts100-mode.js +59 -0
  58. package/lib/model/push/hub-mts100-temperature.js +62 -0
  59. package/lib/model/push/hub-online.js +59 -0
  60. package/lib/model/push/hub-sensor-alert.js +61 -0
  61. package/lib/model/push/hub-sensor-all.js +59 -0
  62. package/lib/model/push/hub-sensor-smoke.js +110 -0
  63. package/lib/model/push/hub-sensor-temphum.js +62 -0
  64. package/lib/model/push/hub-subdevicelist.js +50 -0
  65. package/lib/model/push/hub-togglex.js +60 -0
  66. package/lib/model/push/index.js +81 -0
  67. package/lib/model/push/online.js +53 -0
  68. package/lib/model/push/presence-study.js +61 -0
  69. package/lib/model/push/sensor-latestx.js +106 -0
  70. package/lib/model/push/timerx.js +63 -0
  71. package/lib/model/push/togglex.js +78 -0
  72. package/lib/model/push/triggerx.js +62 -0
  73. package/lib/model/push/unbind.js +34 -0
  74. package/lib/model/push/water-leak.js +107 -0
  75. package/lib/model/states/diffuser-light-state.js +119 -0
  76. package/lib/model/states/diffuser-spray-state.js +58 -0
  77. package/lib/model/states/garage-door-state.js +71 -0
  78. package/lib/model/states/index.js +38 -0
  79. package/lib/model/states/light-state.js +134 -0
  80. package/lib/model/states/presence-sensor-state.js +239 -0
  81. package/lib/model/states/roller-shutter-state.js +82 -0
  82. package/lib/model/states/spray-state.js +58 -0
  83. package/lib/model/states/thermostat-state.js +297 -0
  84. package/lib/model/states/timer-state.js +192 -0
  85. package/lib/model/states/toggle-state.js +105 -0
  86. package/lib/model/states/trigger-state.js +155 -0
  87. package/lib/subscription.js +587 -0
  88. package/lib/utilities/conversion.js +62 -0
  89. package/lib/utilities/debug.js +165 -0
  90. package/lib/utilities/mqtt.js +152 -0
  91. package/lib/utilities/network.js +53 -0
  92. package/lib/utilities/options.js +64 -0
  93. package/lib/utilities/request-queue.js +161 -0
  94. package/lib/utilities/ssid.js +37 -0
  95. package/lib/utilities/state-changes.js +66 -0
  96. package/lib/utilities/stats.js +687 -0
  97. package/lib/utilities/timer.js +310 -0
  98. package/lib/utilities/trigger.js +286 -0
  99. package/package.json +73 -0
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ const { normalizeChannel } = require('../../utilities/options');
4
+
5
+ const MAX_ALARM_EVENTS_MEMORY = 10;
6
+
7
+ /**
8
+ * Alarm feature module.
9
+ * Handles alarm status queries and maintains a buffer of recent alarm events.
10
+ */
11
+ module.exports = {
12
+ /**
13
+ * Initializes alarm events storage.
14
+ *
15
+ * Called lazily when the first alarm event is received to avoid unnecessary initialization.
16
+ *
17
+ * @private
18
+ */
19
+ _initializeAlarmEvents() {
20
+ if (!this._lastAlarmEvents) {
21
+ this._lastAlarmEvents = [];
22
+ }
23
+ },
24
+
25
+ /**
26
+ * Gets the current alarm status from the device.
27
+ *
28
+ * @param {Object} [options={}] - Get options
29
+ * @param {number} [options.channel=0] - Channel to get alarm status for (default: 0)
30
+ * @returns {Promise<Object>} Alarm status response with `alarm` array
31
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
32
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
33
+ */
34
+ async getAlarmStatus(options = {}) {
35
+ const channel = normalizeChannel(options);
36
+ const payload = { 'alarm': [{ channel }] };
37
+ return await this.publishMessage('GET', 'Appliance.Control.Alarm', payload);
38
+ },
39
+
40
+ /**
41
+ * Gets a copy of the most recent alarm events.
42
+ *
43
+ * Alarm events are automatically stored when push notifications are received.
44
+ * The library maintains up to MAX_ALARM_EVENTS_MEMORY most recent events.
45
+ *
46
+ * @returns {Array<Object>} Copy of the alarm events array (most recent first)
47
+ */
48
+ getLastAlarmEvents() {
49
+ this._initializeAlarmEvents();
50
+ return [...this._lastAlarmEvents];
51
+ },
52
+
53
+ /**
54
+ * Updates the alarm events buffer from push notification data.
55
+ *
56
+ * Called automatically when alarm push notifications are received. Maintains a rolling
57
+ * buffer of the most recent events, discarding older ones when the limit is exceeded.
58
+ *
59
+ * @param {Object|Array} alarmData - Alarm data (single object or array)
60
+ * @private
61
+ */
62
+ _updateAlarmEvents(alarmData, source = 'push') {
63
+ if (!alarmData) {return;}
64
+
65
+ this._initializeAlarmEvents();
66
+
67
+ const alarmArray = Array.isArray(alarmData) ? alarmData : [alarmData];
68
+
69
+ for (const alarmEvent of alarmArray) {
70
+ const oldEvents = [...this._lastAlarmEvents];
71
+ this._lastAlarmEvents.unshift(alarmEvent);
72
+
73
+ if (this._lastAlarmEvents.length > MAX_ALARM_EVENTS_MEMORY) {
74
+ this._lastAlarmEvents = this._lastAlarmEvents.slice(0, MAX_ALARM_EVENTS_MEMORY);
75
+ }
76
+
77
+ const channel = alarmEvent.channel !== undefined ? alarmEvent.channel : 0;
78
+ this.emit('stateChange', {
79
+ type: 'alarm',
80
+ channel,
81
+ value: alarmEvent,
82
+ oldValue: oldEvents.length > 0 ? oldEvents[0] : undefined,
83
+ source,
84
+ timestamp: Date.now()
85
+ });
86
+ }
87
+ }
88
+ };
89
+
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ const { normalizeChannel } = require('../../utilities/options');
4
+
5
+ /**
6
+ * Child lock feature module.
7
+ * Provides control over physical control lock functionality.
8
+ */
9
+ module.exports = {
10
+ /**
11
+ * Gets the child lock status from the device.
12
+ *
13
+ * @param {Object} [options={}] - Get options
14
+ * @param {number} [options.channel=0] - Channel to get lock status for (default: 0)
15
+ * @param {string} [options.subId=null] - Optional subdevice ID
16
+ * @returns {Promise<Object>} Response containing lock status with `lock` 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 getChildLock(options = {}) {
21
+ const channel = normalizeChannel(options);
22
+ const payload = {
23
+ lock: [{
24
+ channel
25
+ }]
26
+ };
27
+ if (options.subId) {
28
+ payload.lock[0].subId = options.subId;
29
+ }
30
+ return await this.publishMessage('GET', 'Appliance.Control.PhysicalLock', payload);
31
+ },
32
+
33
+ /**
34
+ * Controls the child lock status.
35
+ *
36
+ * @param {Object} options - Child lock options
37
+ * @param {Object|Array<Object>} [options.lockData] - Lock data object or array of lock items (if provided, used directly)
38
+ * @param {number} [options.channel] - Channel to control
39
+ * @param {string} [options.subId] - Optional subdevice ID
40
+ * @param {number} [options.onoff] - Lock on (1) or off (0)
41
+ * @returns {Promise<Object>} Response from the device
42
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
43
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
44
+ */
45
+ async setChildLock(options = {}) {
46
+ let lockData;
47
+ if (options.lockData) {
48
+ lockData = Array.isArray(options.lockData) ? options.lockData : [options.lockData];
49
+ } else {
50
+ const channel = normalizeChannel(options);
51
+ lockData = [{
52
+ channel,
53
+ subId: options.subId,
54
+ onoff: options.onoff
55
+ }];
56
+ }
57
+ const payload = { lock: lockData };
58
+ return await this.publishMessage('SET', 'Appliance.Control.PhysicalLock', payload);
59
+ }
60
+ };
61
+
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Configuration feature module.
5
+ * Provides access to device configuration settings such as over-temperature protection.
6
+ */
7
+ module.exports = {
8
+ /**
9
+ * Gets the over-temperature protection configuration from the device.
10
+ * @param {Object} [options={}] - Get options
11
+ * @returns {Promise<Object>} Response containing over-temperature protection config
12
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
13
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
14
+ */
15
+ async getConfigOverTemp(_options = {}) {
16
+ return await this.publishMessage('GET', 'Appliance.Config.OverTemp', {});
17
+ },
18
+
19
+ /**
20
+ * Controls the over-temperature protection configuration.
21
+ *
22
+ * @param {Object} options - Over-temperature config options
23
+ * @param {boolean} options.enable - Enable state (true = on, false = off)
24
+ * @param {number} [options.type] - Protection type (1 = early warning, 2 = early warning and shutdown). If not provided, preserves current type
25
+ * @returns {Promise<Object>} Response from the device
26
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
27
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
28
+ */
29
+ async setConfigOverTemp(options = {}) {
30
+ if (options.enable === undefined) {
31
+ const { CommandError } = require('../../model/exception');
32
+ throw new CommandError('enable is required', { options }, this.uuid);
33
+ }
34
+
35
+ const enableValue = options.enable ? 1 : 2;
36
+ let overTempData;
37
+
38
+ if (options.type !== undefined) {
39
+ overTempData = { enable: enableValue, type: options.type };
40
+ } else {
41
+ try {
42
+ const currentConfig = await this.getConfigOverTemp();
43
+ const currentType = currentConfig?.overTemp?.type;
44
+ overTempData = { enable: enableValue, type: currentType !== undefined ? currentType : 1 };
45
+ } catch (e) {
46
+ overTempData = { enable: enableValue, type: 1 };
47
+ }
48
+ }
49
+
50
+ const payload = { overTemp: overTempData };
51
+ return await this.publishMessage('SET', 'Appliance.Config.OverTemp', payload);
52
+ }
53
+ };
54
+
@@ -0,0 +1,210 @@
1
+ 'use strict';
2
+
3
+ const { normalizeChannel } = require('../../utilities/options');
4
+
5
+ /**
6
+ * Consumption feature module.
7
+ * Provides access to historical power consumption data and consumption configuration settings.
8
+ */
9
+ module.exports = {
10
+ /**
11
+ * Initializes consumption cache.
12
+ *
13
+ * Called lazily when consumption data is first accessed to avoid unnecessary initialization.
14
+ *
15
+ * @private
16
+ */
17
+ _initializeConsumptionCache() {
18
+ if (this._channelCachedConsumption === undefined) {
19
+ this._channelCachedConsumption = new Map();
20
+ }
21
+ },
22
+
23
+ /**
24
+ * Gets daily power consumption data from the device.
25
+ *
26
+ * Returns parsed consumption data with Date objects and converted units (kWh). Date strings
27
+ * are parsed from YYYY-MM-DD format or standard Date string format. Use {@link getRawPowerConsumption}
28
+ * to get the raw API response without parsing.
29
+ *
30
+ * @param {Object} [options={}] - Get options
31
+ * @param {number} [options.channel=0] - Channel to read data from (default: 0)
32
+ * @returns {Promise<Array<{date: Date, totalConsumptionKwh: number}>>} Historical consumption data with date and totalConsumptionKwh
33
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
34
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
35
+ */
36
+ async getPowerConsumption(options = {}) {
37
+ const channel = normalizeChannel(options);
38
+ this._initializeConsumptionCache();
39
+
40
+ const result = await this.publishMessage('GET', 'Appliance.Control.Consumption', { channel });
41
+ const data = result && result.consumption ? result.consumption : [];
42
+
43
+ this._updateConsumptionState({ channel, consumption: data }, 'response');
44
+
45
+ return this._channelCachedConsumption.get(channel) || null;
46
+ },
47
+
48
+ /**
49
+ * Gets daily power consumption data from the device (X version).
50
+ *
51
+ * Returns parsed consumption data with Date objects and converted units (kWh). This is an
52
+ * alternative consumption endpoint that may provide different data or formatting. Use
53
+ * {@link getRawPowerConsumptionX} to get the raw API response without parsing.
54
+ *
55
+ * @param {Object} [options={}] - Get options
56
+ * @param {number} [options.channel=0] - Channel to read data from (default: 0)
57
+ * @returns {Promise<Array<{date: Date, totalConsumptionKwh: number}>>} Historical consumption data with date and totalConsumptionKwh
58
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
59
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
60
+ */
61
+ async getPowerConsumptionX(options = {}) {
62
+ const channel = normalizeChannel(options);
63
+ const result = await this.publishMessage('GET', 'Appliance.Control.ConsumptionX', { channel });
64
+ const data = result && result.consumptionx ? result.consumptionx : [];
65
+
66
+ const DATE_FORMAT = /^(\d{4})-(\d{2})-(\d{2})$/;
67
+ return data.map(x => {
68
+ const dateStr = x.date;
69
+ let date;
70
+ if (DATE_FORMAT.test(dateStr)) {
71
+ const [, year, month, day] = dateStr.match(DATE_FORMAT);
72
+ date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
73
+ } else {
74
+ date = new Date(dateStr);
75
+ }
76
+
77
+ return {
78
+ date,
79
+ totalConsumptionKwh: parseFloat(x.value) / 1000
80
+ };
81
+ });
82
+ },
83
+
84
+ /**
85
+ * Gets cached consumption data
86
+ *
87
+ * Returns the most recently fetched consumption data without making a request.
88
+ * Use {@link getPowerConsumption} to fetch fresh data from the device.
89
+ *
90
+ * @param {number} [channel=0] - Channel to get data for (default: 0)
91
+ * @returns {Array<{date: Date, totalConsumptionKwh: number}>|null} Cached consumption data or null if not available
92
+ */
93
+ getCachedConsumption(channel = 0) {
94
+ this._initializeConsumptionCache();
95
+ return this._channelCachedConsumption.get(channel) || null;
96
+ },
97
+
98
+ /**
99
+ * Gets the raw power consumption response from the device without parsing or unit conversion.
100
+ *
101
+ * For parsed data with Date objects and converted units, use {@link getPowerConsumption} instead.
102
+ *
103
+ * @param {Object} [options={}] - Get options
104
+ * @param {number} [options.channel=0] - Channel to read data from (default: 0)
105
+ * @returns {Promise<Object>} Raw API response containing consumption data
106
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
107
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
108
+ */
109
+ async getRawPowerConsumption(options = {}) {
110
+ const channel = normalizeChannel(options);
111
+ return await this.publishMessage('GET', 'Appliance.Control.Consumption', { channel });
112
+ },
113
+
114
+ /**
115
+ * Gets the raw power consumption X response from the device without parsing or unit conversion.
116
+ *
117
+ * For parsed data with Date objects and converted units, use {@link getPowerConsumptionX} instead.
118
+ *
119
+ * @param {Object} [options={}] - Get options
120
+ * @param {number} [options.channel=0] - Channel to read data from (default: 0)
121
+ * @returns {Promise<Object>} Raw API response containing consumption X data
122
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
123
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
124
+ */
125
+ async getRawPowerConsumptionX(options = {}) {
126
+ const channel = normalizeChannel(options);
127
+ return await this.publishMessage('GET', 'Appliance.Control.ConsumptionX', { channel });
128
+ },
129
+
130
+ /**
131
+ * Gets the consumption configuration from the device.
132
+ *
133
+ * Returns voltage and current calibration coefficients used for power consumption calculations.
134
+ *
135
+ * @returns {Promise<Object>} Response containing consumption configuration
136
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
137
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
138
+ */
139
+ async getConsumptionConfig() {
140
+ return await this.publishMessage('GET', 'Appliance.Control.ConsumptionConfig', {});
141
+ },
142
+
143
+ /**
144
+ * Updates the cached consumption state from consumption data.
145
+ *
146
+ * Called automatically when consumption data is received. Parses raw device data,
147
+ * converts dates and units, and emits stateChange events when data changes.
148
+ *
149
+ * @param {Object} consumptionData - Raw consumption data from device
150
+ * @param {number} consumptionData.channel - Channel index
151
+ * @param {Array} consumptionData.consumption - Array of consumption entries with date and value
152
+ * @param {string} [source='response'] - Source of the update ('push' | 'poll' | 'response')
153
+ * @private
154
+ */
155
+ _updateConsumptionState(consumptionData, source = 'response') {
156
+ if (!consumptionData) {return;}
157
+
158
+ this._initializeConsumptionCache();
159
+
160
+ const channelIndex = consumptionData.channel;
161
+ if (channelIndex === undefined || channelIndex === null) {return;}
162
+
163
+ const data = consumptionData.consumption || [];
164
+
165
+ const DATE_FORMAT = /^(\d{4})-(\d{2})-(\d{2})$/;
166
+ const parsedData = data.map(x => {
167
+ const dateStr = x.date;
168
+ let date;
169
+ if (DATE_FORMAT.test(dateStr)) {
170
+ const [, year, month, day] = dateStr.match(DATE_FORMAT);
171
+ date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
172
+ } else {
173
+ date = new Date(dateStr);
174
+ }
175
+
176
+ return {
177
+ date,
178
+ totalConsumptionKwh: parseFloat(x.value) / 1000
179
+ };
180
+ });
181
+
182
+ const oldData = this._channelCachedConsumption.get(channelIndex);
183
+ this._channelCachedConsumption.set(channelIndex, parsedData);
184
+
185
+ let hasChanges = false;
186
+ if (!oldData || oldData.length !== parsedData.length) {
187
+ hasChanges = true;
188
+ } else {
189
+ for (let i = 0; i < parsedData.length; i++) {
190
+ if (!oldData[i] ||
191
+ oldData[i].totalConsumptionKwh !== parsedData[i].totalConsumptionKwh ||
192
+ oldData[i].date.getTime() !== parsedData[i].date.getTime()) {
193
+ hasChanges = true;
194
+ break;
195
+ }
196
+ }
197
+ }
198
+
199
+ if (hasChanges) {
200
+ this.emit('stateChange', {
201
+ type: 'consumption',
202
+ channel: channelIndex,
203
+ value: parsedData,
204
+ oldValue: oldData || undefined,
205
+ source,
206
+ timestamp: Date.now()
207
+ });
208
+ }
209
+ }
210
+ };
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Control feature module.
5
+ * Provides advanced control capabilities including batch commands, event acknowledgments, and firmware upgrades.
6
+ */
7
+ module.exports = {
8
+ /**
9
+ * Executes multiple commands simultaneously.
10
+ *
11
+ * Allows sending multiple commands in a single request to reduce network overhead and improve
12
+ * efficiency when controlling multiple aspects of a device at once.
13
+ *
14
+ * @param {Array<Object>} commands - Array of command objects
15
+ * @param {string} commands[].namespace - Namespace for the command (e.g., "Appliance.Control.ToggleX")
16
+ * @param {string} commands[].method - Method for the command (e.g., "SET", "GET")
17
+ * @param {Object} commands[].payload - Payload for the command
18
+ * @returns {Promise<Object>} Response containing results for each command
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 setMultiple(commands) {
23
+ const payload = {
24
+ multiple: commands.map(cmd => ({
25
+ header: {
26
+ namespace: cmd.namespace,
27
+ method: cmd.method
28
+ },
29
+ payload: cmd.payload
30
+ }))
31
+ };
32
+ return await this.publishMessage('SET', 'Appliance.Control.Multiple', payload);
33
+ },
34
+
35
+ /**
36
+ * Acknowledges an over-temperature event.
37
+ *
38
+ * Over-temperature events are typically initiated by the device via SET. This method sends
39
+ * a SETACK response to acknowledge receipt of the event.
40
+ *
41
+ * @returns {Promise<Object>} Response from the device
42
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
43
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
44
+ */
45
+ async acknowledgeControlOverTemp() {
46
+ return await this.publishMessage('SETACK', 'Appliance.Control.OverTemp', {});
47
+ },
48
+
49
+ /**
50
+ * Initiates a device firmware upgrade.
51
+ *
52
+ * @param {Object} upgradeData - Upgrade data object containing upgrade parameters
53
+ * @returns {Promise<Object>} Response from the device
54
+ * @throws {import('../lib/errors/errors').UnconnectedError} If device is not connected
55
+ * @throws {import('../lib/errors/errors').CommandTimeoutError} If command times out
56
+ */
57
+ async setUpgrade(upgradeData) {
58
+ const payload = { upgrade: upgradeData };
59
+ return await this.publishMessage('SET', 'Appliance.Control.Upgrade', payload);
60
+ }
61
+ };
62
+