@homebridge-plugins/homebridge-meross 10.13.1-beta.0 → 10.14.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 CHANGED
@@ -2,7 +2,18 @@
2
2
 
3
3
  All notable changes to `@homebridge-plugins/homebridge-meross` will be documented in this file.
4
4
 
5
- ## v10.13.1 (Pending Release)
5
+ ## v10.14.0 (2026-04-09)
6
+
7
+ ### Added
8
+
9
+ - feat: added new thermostat models
10
+
11
+ ### Changed
12
+
13
+ - chore: remove official node 20 support
14
+ - chore: dependency updates
15
+
16
+ ## v10.13.1 (2026-04-06)
6
17
 
7
18
  ### Fixed
8
19
 
package/README.md CHANGED
@@ -30,7 +30,7 @@ Homebridge plugin to integrate Meross devices into HomeKit
30
30
  ### Prerequisites
31
31
 
32
32
  - To use this plugin, you will need to already have:
33
- - [Node](https://nodejs.org): latest version of `v20`, `v22` or `v24` - any other major version is not supported.
33
+ - [Node](https://nodejs.org): latest version of `v22` or `v24` - any other major version is not supported.
34
34
  - [Homebridge](https://homebridge.io): `v1.6` - refer to link for more information and installation instructions.
35
35
 
36
36
  ### Setup
@@ -1344,6 +1344,22 @@
1344
1344
  "title": "MTS205",
1345
1345
  "enum": ["MTS205"]
1346
1346
  },
1347
+ {
1348
+ "title": "MTS205B",
1349
+ "enum": ["MTS205B"]
1350
+ },
1351
+ {
1352
+ "title": "MTS215",
1353
+ "enum": ["MTS215"]
1354
+ },
1355
+ {
1356
+ "title": "MTS215B",
1357
+ "enum": ["MTS215B"]
1358
+ },
1359
+ {
1360
+ "title": "MTS300",
1361
+ "enum": ["MTS300"]
1362
+ },
1347
1363
  {
1348
1364
  "title": "MTS960",
1349
1365
  "enum": ["MTS960"]
@@ -28,6 +28,7 @@ import deviceSensorPresence from './sensor-presence.js'
28
28
  import deviceSwitchMulti from './switch-multi.js'
29
29
  import deviceSwitchSingle from './switch-single.js'
30
30
  import deviceTemplate from './template.js'
31
+ import deviceThermostatMts300 from './thermostat-mts300.js'
31
32
  import deviceThermostat from './thermostat.js'
32
33
 
33
34
  export default {
@@ -62,4 +63,5 @@ export default {
62
63
  deviceSwitchSingle,
63
64
  deviceTemplate,
64
65
  deviceThermostat,
66
+ deviceThermostatMts300,
65
67
  }
@@ -0,0 +1,529 @@
1
+ import PQueue from 'p-queue'
2
+ import { TimeoutError } from 'p-timeout'
3
+
4
+ import mqttClient from '../connection/mqtt.js'
5
+ import platformConsts from '../utils/constants.js'
6
+ import { hasProperty, parseError } from '../utils/functions.js'
7
+ import platformLang from '../utils/lang-en.js'
8
+
9
+ export default class {
10
+ constructor(platform, accessory) {
11
+ // Set up variables from the platform
12
+ this.cusChar = platform.cusChar
13
+ this.hapChar = platform.api.hap.Characteristic
14
+ this.hapErr = platform.api.hap.HapStatusError
15
+ this.hapServ = platform.api.hap.Service
16
+ this.platform = platform
17
+
18
+ // Set up variables from the accessory
19
+ this.accessory = accessory
20
+ this.name = accessory.displayName
21
+ const cloudRefreshRate = hasProperty(platform.config, 'cloudRefreshRate')
22
+ ? platform.config.cloudRefreshRate
23
+ : platformConsts.defaultValues.cloudRefreshRate
24
+ const localRefreshRate = hasProperty(platform.config, 'refreshRate')
25
+ ? platform.config.refreshRate
26
+ : platformConsts.defaultValues.refreshRate
27
+ this.pollInterval = accessory.context.connection === 'local'
28
+ ? localRefreshRate
29
+ : cloudRefreshRate
30
+
31
+ // MTS300 temperature values are scaled by 100 (0.01°C resolution)
32
+ this.tempScale = 100
33
+
34
+ // MTS300 mode mapping: 0=off, 1=heat, 2=cool, 3=auto
35
+ this.mode2Label = {
36
+ 0: 'off',
37
+ 1: 'heat',
38
+ 2: 'cool',
39
+ 3: 'auto',
40
+ }
41
+
42
+ // Fan speed mapping: device 0-3 to HomeKit 0/33/66/100
43
+ this.mr2hk = (speed) => {
44
+ if (speed === 0) {
45
+ return 0
46
+ }
47
+ if (speed === 1) {
48
+ return 33
49
+ }
50
+ if (speed === 2) {
51
+ return 66
52
+ }
53
+ return 100
54
+ }
55
+ this.hk2mr = (speed) => {
56
+ if (speed <= 16) {
57
+ return 0
58
+ }
59
+ if (speed <= 49) {
60
+ return 1
61
+ }
62
+ if (speed <= 82) {
63
+ return 2
64
+ }
65
+ return 3
66
+ }
67
+
68
+ // Add the thermostat service if it doesn't already exist
69
+ this.service = this.accessory.getService(this.hapServ.Thermostat)
70
+ || this.accessory.addService(this.hapServ.Thermostat)
71
+
72
+ // MTS300 supports off/heat/cool/auto (0, 1, 2, 3)
73
+ this.service
74
+ .getCharacteristic(this.hapChar.TargetHeatingCoolingState)
75
+ .setProps({
76
+ minValue: 0,
77
+ maxValue: 3,
78
+ validValues: [0, 1, 2, 3],
79
+ })
80
+ .onSet(async value => this.internalStateUpdate(value))
81
+ this.cacheState = this.service.getCharacteristic(this.hapChar.TargetHeatingCoolingState).value
82
+
83
+ this.service
84
+ .getCharacteristic(this.hapChar.TargetTemperature)
85
+ .setProps({
86
+ minValue: 5,
87
+ maxValue: 35,
88
+ minStep: 0.5,
89
+ })
90
+ .onSet(async value => this.internalTargetUpdate(value))
91
+ this.cacheTarg = this.service.getCharacteristic(this.hapChar.TargetTemperature).value
92
+
93
+ this.cacheTemp = this.service.getCharacteristic(this.hapChar.CurrentTemperature).value
94
+ this.updateCache()
95
+
96
+ // Add the humidity sensor service if it doesn't already exist
97
+ this.humiService = this.accessory.getService(this.hapServ.HumiditySensor)
98
+ || this.accessory.addService(this.hapServ.HumiditySensor)
99
+ this.cacheHumi = this.humiService.getCharacteristic(this.hapChar.CurrentRelativeHumidity).value
100
+
101
+ // Add the fan service if it doesn't already exist
102
+ this.fanService = this.accessory.getService('Fan')
103
+ || this.accessory.addService(this.hapServ.Fan, 'Fan', 'fan')
104
+
105
+ this.fanService
106
+ .getCharacteristic(this.hapChar.On)
107
+ .onSet(async value => this.internalFanStateUpdate(value))
108
+ this.cacheFanState = this.fanService.getCharacteristic(this.hapChar.On).value
109
+
110
+ this.fanService
111
+ .getCharacteristic(this.hapChar.RotationSpeed)
112
+ .setProps({
113
+ minStep: 33,
114
+ validValues: [0, 33, 66, 100],
115
+ })
116
+ .onSet(async value => this.internalFanSpeedUpdate(value))
117
+ this.cacheFanSpeed = this.hk2mr(
118
+ this.fanService.getCharacteristic(this.hapChar.RotationSpeed).value,
119
+ )
120
+
121
+ // Pass the accessory to Fakegato to set up with Eve
122
+ this.accessory.eveService = new platform.eveService('custom', this.accessory, { log: () => {} })
123
+
124
+ // Create the queue used for sending device requests
125
+ this.updateInProgress = false
126
+ this.queue = new PQueue({
127
+ concurrency: 1,
128
+ interval: 250,
129
+ intervalCap: 1,
130
+ timeout: 10000,
131
+ throwOnTimeout: true,
132
+ })
133
+ this.queue.on('idle', () => {
134
+ this.updateInProgress = false
135
+ })
136
+
137
+ // Set up the mqtt client for cloud devices to send and receive device updates
138
+ if (accessory.context.connection !== 'local') {
139
+ this.accessory.mqtt = new mqttClient(platform, this.accessory)
140
+ this.accessory.mqtt.connect()
141
+ }
142
+
143
+ // Always request a device update on startup, then start the interval for polling
144
+ setTimeout(() => this.requestUpdate(true), 2000)
145
+ this.accessory.refreshInterval = setInterval(
146
+ () => this.requestUpdate(),
147
+ this.pollInterval * 1000,
148
+ )
149
+
150
+ // Output the customised options to the log
151
+ const opts = JSON.stringify({
152
+ connection: this.accessory.context.connection,
153
+ })
154
+ platform.log('[%s] %s %s.', this.name, platformLang.devInitOpts, opts)
155
+ }
156
+
157
+ async internalStateUpdate(value) {
158
+ try {
159
+ await this.queue.add(async () => {
160
+ if (value === this.cacheState) {
161
+ return
162
+ }
163
+
164
+ this.updateInProgress = true
165
+
166
+ const namespace = 'Appliance.Control.Thermostat.ModeC'
167
+ const payload = {
168
+ modeC: [
169
+ {
170
+ channel: 0,
171
+ onoff: value ? 1 : 0,
172
+ mode: value,
173
+ },
174
+ ],
175
+ }
176
+
177
+ await this.platform.sendUpdate(this.accessory, {
178
+ namespace,
179
+ payload,
180
+ })
181
+
182
+ this.cacheState = value
183
+ this.accessory.log(`${platformLang.curState} [${this.mode2Label[value] || 'unknown'}]`)
184
+ })
185
+ } catch (err) {
186
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
187
+ this.accessory.logWarn(`${platformLang.sendFailed} ${eText}`)
188
+ setTimeout(() => {
189
+ this.service.updateCharacteristic(this.hapChar.TargetHeatingCoolingState, this.cacheState)
190
+ }, 2000)
191
+ throw new this.hapErr(-70402)
192
+ }
193
+ }
194
+
195
+ async internalTargetUpdate(value) {
196
+ try {
197
+ await this.queue.add(async () => {
198
+ if (value === this.cacheTarg) {
199
+ return
200
+ }
201
+
202
+ this.updateInProgress = true
203
+
204
+ // Send the appropriate setpoint based on current mode
205
+ const scaledValue = value * this.tempScale
206
+ const payload = { modeC: [{ channel: 0 }] }
207
+ if (this.cacheState === 2) {
208
+ payload.modeC[0].coolSetpoint = scaledValue
209
+ } else {
210
+ payload.modeC[0].heatSetpoint = scaledValue
211
+ }
212
+
213
+ const namespace = 'Appliance.Control.Thermostat.ModeC'
214
+
215
+ await this.platform.sendUpdate(this.accessory, {
216
+ namespace,
217
+ payload,
218
+ })
219
+
220
+ this.cacheTarg = value
221
+ this.accessory.log(`${platformLang.curTarg} [${value}°C]`)
222
+
223
+ // Update the current heating/cooling state
224
+ this.updateCurrentState()
225
+ })
226
+ } catch (err) {
227
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
228
+ this.accessory.logWarn(`${platformLang.sendFailed} ${eText}`)
229
+ setTimeout(() => {
230
+ this.service.updateCharacteristic(this.hapChar.TargetTemperature, this.cacheTarg)
231
+ }, 2000)
232
+ throw new this.hapErr(-70402)
233
+ }
234
+ }
235
+
236
+ async internalFanStateUpdate(value) {
237
+ try {
238
+ await this.queue.add(async () => {
239
+ if (value === this.cacheFanState) {
240
+ return
241
+ }
242
+
243
+ this.updateInProgress = true
244
+
245
+ const namespace = 'Appliance.Control.Thermostat.ModeC'
246
+ const payload = {
247
+ modeC: [
248
+ {
249
+ channel: 0,
250
+ fMode: value ? 1 : 0,
251
+ },
252
+ ],
253
+ }
254
+
255
+ await this.platform.sendUpdate(this.accessory, {
256
+ namespace,
257
+ payload,
258
+ })
259
+
260
+ this.cacheFanState = value
261
+ this.accessory.log(`[fan] ${platformLang.curState} [${value ? 'on' : 'off'}]`)
262
+ })
263
+ } catch (err) {
264
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
265
+ this.accessory.logWarn(`${platformLang.sendFailed} ${eText}`)
266
+ setTimeout(() => {
267
+ this.fanService.updateCharacteristic(this.hapChar.On, this.cacheFanState)
268
+ }, 2000)
269
+ throw new this.hapErr(-70402)
270
+ }
271
+ }
272
+
273
+ async internalFanSpeedUpdate(value) {
274
+ try {
275
+ await this.queue.add(async () => {
276
+ const mrVal = this.hk2mr(value)
277
+ if (mrVal === this.cacheFanSpeed) {
278
+ return
279
+ }
280
+
281
+ this.updateInProgress = true
282
+
283
+ const namespace = 'Appliance.Control.Thermostat.ModeC'
284
+ const payload = {
285
+ modeC: [
286
+ {
287
+ channel: 0,
288
+ speed: mrVal,
289
+ },
290
+ ],
291
+ }
292
+
293
+ await this.platform.sendUpdate(this.accessory, {
294
+ namespace,
295
+ payload,
296
+ })
297
+
298
+ this.cacheFanSpeed = mrVal
299
+ this.accessory.log(`[fan] ${platformLang.curSpeed} [${mrVal}]`)
300
+ })
301
+ } catch (err) {
302
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
303
+ this.accessory.logWarn(`${platformLang.sendFailed} ${eText}`)
304
+ setTimeout(() => {
305
+ this.fanService.updateCharacteristic(
306
+ this.hapChar.RotationSpeed,
307
+ this.mr2hk(this.cacheFanSpeed),
308
+ )
309
+ }, 2000)
310
+ throw new this.hapErr(-70402)
311
+ }
312
+ }
313
+
314
+ updateCurrentState() {
315
+ let currentState = 0
316
+ if (this.cacheState === 1 && this.cacheTarg > this.cacheTemp) {
317
+ currentState = 1 // heating
318
+ } else if (this.cacheState === 2 && this.cacheTarg < this.cacheTemp) {
319
+ currentState = 2 // cooling
320
+ } else if (this.cacheState === 3) {
321
+ if (this.cacheTarg > this.cacheTemp) {
322
+ currentState = 1 // heating
323
+ } else if (this.cacheTarg < this.cacheTemp) {
324
+ currentState = 2 // cooling
325
+ }
326
+ }
327
+ this.service.updateCharacteristic(this.hapChar.CurrentHeatingCoolingState, currentState)
328
+ }
329
+
330
+ async updateCache() {
331
+ if (!this.platform.storageClientData) {
332
+ return
333
+ }
334
+
335
+ try {
336
+ await this.platform.storageData.setItem(
337
+ `${this.accessory.context.serialNumber}_temp`,
338
+ this.cacheTemp,
339
+ )
340
+ } catch (err) {
341
+ this.accessory.logWarn(`${platformLang.storageWriteErr} ${parseError(err)}`)
342
+ }
343
+ }
344
+
345
+ async requestUpdate(firstRun = false) {
346
+ try {
347
+ if (this.updateInProgress) {
348
+ return
349
+ }
350
+
351
+ await this.queue.add(async () => {
352
+ this.updateInProgress = true
353
+
354
+ const res = await this.platform.sendUpdate(this.accessory, {
355
+ namespace: 'Appliance.System.All',
356
+ payload: {},
357
+ })
358
+
359
+ this.accessory.logDebug(`${platformLang.incPoll}: ${JSON.stringify(res.data)}`)
360
+
361
+ const data = res.data.payload
362
+ if (data.all) {
363
+ if (data.all.digest?.thermostat) {
364
+ this.applyUpdate(data.all.digest.thermostat)
365
+ }
366
+
367
+ let needsUpdate = false
368
+
369
+ if (data.all.system) {
370
+ if (firstRun && data.all.system.hardware) {
371
+ this.accessory.context.macAddress = data.all.system.hardware.macAddress.toUpperCase()
372
+ this.accessory.context.hardware = data.all.system.hardware.version
373
+ }
374
+
375
+ if (data.all.system.firmware) {
376
+ if (this.accessory.context.ipAddress !== data.all.system.firmware.innerIp) {
377
+ this.accessory.context.ipAddress = data.all.system.firmware.innerIp
378
+ needsUpdate = true
379
+ }
380
+
381
+ if (firstRun) {
382
+ this.accessory.context.firmware = data.all.system.firmware.version
383
+ }
384
+ }
385
+ }
386
+
387
+ if (data.all.system.online) {
388
+ const isOnline = data.all.system.online.status === 1
389
+ if (this.accessory.context.isOnline !== isOnline) {
390
+ this.accessory.context.isOnline = isOnline
391
+ needsUpdate = true
392
+ }
393
+ }
394
+
395
+ if (needsUpdate || firstRun) {
396
+ this.platform.updateAccessory(this.accessory)
397
+ }
398
+ }
399
+ })
400
+ } catch (err) {
401
+ const eText = err instanceof TimeoutError ? platformLang.timeout : parseError(err)
402
+ this.accessory.logDebugWarn(`${platformLang.reqFailed}: ${eText}`)
403
+
404
+ if (
405
+ (this.accessory.context.isOnline || firstRun)
406
+ && ['EHOSTUNREACH', 'timed out'].some(el => eText.includes(el))
407
+ ) {
408
+ this.accessory.context.isOnline = false
409
+ this.platform.updateAccessory(this.accessory)
410
+ }
411
+ }
412
+ }
413
+
414
+ receiveUpdate(params) {
415
+ try {
416
+ this.accessory.logDebug(`${platformLang.incMQTT}: ${JSON.stringify(params)}`)
417
+ if (params.payload) {
418
+ this.applyUpdate(params.payload)
419
+ }
420
+ } catch (err) {
421
+ this.accessory.logWarn(`${platformLang.refFailed} ${parseError(err)}`)
422
+ }
423
+ }
424
+
425
+ applyUpdate(data) {
426
+ try {
427
+ // MTS300 uses modeC instead of mode
428
+ const modeData = data.modeC?.[0]
429
+ if (modeData) {
430
+ let needsUpdate = false
431
+
432
+ // Update on/off and mode state
433
+ if (hasProperty(modeData, 'onoff') || hasProperty(modeData, 'mode')) {
434
+ const newOnoff = hasProperty(modeData, 'onoff') ? modeData.onoff : undefined
435
+ const newMode = hasProperty(modeData, 'mode') ? modeData.mode : undefined
436
+
437
+ // Determine the target state: off if onoff=0, otherwise use mode
438
+ let newState
439
+ if (newOnoff === 0) {
440
+ newState = 0
441
+ } else if (newMode !== undefined) {
442
+ newState = newMode
443
+ }
444
+
445
+ if (newState !== undefined && this.cacheState !== newState) {
446
+ this.service.updateCharacteristic(this.hapChar.TargetHeatingCoolingState, newState)
447
+ this.cacheState = newState
448
+ this.accessory.log(`${platformLang.curState} [${this.mode2Label[newState] || 'unknown'}]`)
449
+ needsUpdate = true
450
+ }
451
+ }
452
+
453
+ // Update target temperature from heat or cool setpoint
454
+ if (hasProperty(modeData, 'heatSetpoint') || hasProperty(modeData, 'coolSetpoint')) {
455
+ let newTarg
456
+ if (this.cacheState === 2 && hasProperty(modeData, 'coolSetpoint')) {
457
+ newTarg = modeData.coolSetpoint / this.tempScale
458
+ } else if (hasProperty(modeData, 'heatSetpoint')) {
459
+ newTarg = modeData.heatSetpoint / this.tempScale
460
+ } else if (hasProperty(modeData, 'coolSetpoint')) {
461
+ newTarg = modeData.coolSetpoint / this.tempScale
462
+ }
463
+
464
+ if (newTarg !== undefined && this.cacheTarg !== newTarg) {
465
+ this.service.updateCharacteristic(this.hapChar.TargetTemperature, newTarg)
466
+ this.cacheTarg = newTarg
467
+ this.accessory.log(`${platformLang.curTarg} [${newTarg}°C]`)
468
+ needsUpdate = true
469
+ }
470
+ }
471
+
472
+ // Update current temperature
473
+ const tempField = hasProperty(modeData, 'currentTemp')
474
+ ? 'currentTemp'
475
+ : hasProperty(modeData, 'sensorTemp')
476
+ ? 'sensorTemp'
477
+ : null
478
+ if (tempField) {
479
+ const newTemp = modeData[tempField] / this.tempScale
480
+
481
+ if (this.cacheTemp !== newTemp) {
482
+ this.service.updateCharacteristic(this.hapChar.CurrentTemperature, newTemp)
483
+ this.cacheTemp = newTemp
484
+ this.accessory.eveService.addEntry({ temp: newTemp })
485
+ this.accessory.log(`${platformLang.curTemp} [${newTemp}°C]`)
486
+ needsUpdate = true
487
+ this.updateCache()
488
+ }
489
+ }
490
+
491
+ // Update fan state and speed
492
+ if (hasProperty(modeData, 'fMode')) {
493
+ const newFanState = modeData.fMode !== 0
494
+ if (this.cacheFanState !== newFanState) {
495
+ this.fanService.updateCharacteristic(this.hapChar.On, newFanState)
496
+ this.cacheFanState = newFanState
497
+ this.accessory.log(`[fan] ${platformLang.curState} [${newFanState ? 'on' : 'off'}]`)
498
+ }
499
+ }
500
+ if (hasProperty(modeData, 'speed')) {
501
+ const newSpeed = modeData.speed
502
+ if (this.cacheFanSpeed !== newSpeed) {
503
+ this.cacheFanSpeed = newSpeed
504
+ this.fanService.updateCharacteristic(this.hapChar.RotationSpeed, this.mr2hk(newSpeed))
505
+ this.accessory.log(`[fan] ${platformLang.curSpeed} [${newSpeed}]`)
506
+ }
507
+ }
508
+
509
+ if (needsUpdate) {
510
+ this.updateCurrentState()
511
+ }
512
+ }
513
+
514
+ // Humidity data may come in a "more" object or sensor data
515
+ const moreData = data.more || data.modeC?.[0]
516
+ if (moreData && hasProperty(moreData, 'humi')) {
517
+ const newHumi = moreData.humi / 10
518
+
519
+ if (this.cacheHumi !== newHumi) {
520
+ this.humiService.updateCharacteristic(this.hapChar.CurrentRelativeHumidity, newHumi)
521
+ this.cacheHumi = newHumi
522
+ this.accessory.log(`${platformLang.curHumi} [${newHumi}%]`)
523
+ }
524
+ }
525
+ } catch (err) {
526
+ this.accessory.logWarn(`${platformLang.refFailed} ${parseError(err)}`)
527
+ }
528
+ }
529
+ }
package/lib/platform.js CHANGED
@@ -835,6 +835,17 @@ export default class {
835
835
  // Set up the main accessory for the baby monitor
836
836
  accessory.control = new deviceTypes.deviceBaby(this, accessory, accessoryLight)
837
837
  /** */
838
+ } else if (platformConsts.models.thermostatMts300.includes(device.model)) {
839
+ /**
840
+ ********
841
+ THERMOSTATS (MTS300)
842
+ *********
843
+ */
844
+ accessory = this.devicesInHB.get(hbUUID) || this.addAccessory(device)
845
+ accessory.context = { ...accessory.context, ...context }
846
+ this.applyAccessoryLogging(accessory)
847
+ accessory.control = new deviceTypes.deviceThermostatMts300(this, accessory)
848
+ /** */
838
849
  } else if (platformConsts.models.thermostat.includes(device.model)) {
839
850
  /**
840
851
  ********
@@ -306,10 +306,11 @@ export default {
306
306
  garage: ['MSG100', 'MSG150', 'MSG200'],
307
307
  roller: ['MRS100', 'MRS105'],
308
308
  baby: ['HP110A', 'HP110AHK'],
309
- thermostat: ['MTS200', 'MTS200B', 'MTS205', 'MTS960'],
309
+ thermostat: ['MTS200', 'MTS200B', 'MTS205', 'MTS205B', 'MTS215', 'MTS215B', 'MTS960'],
310
+ thermostatMts300: ['MTS300'],
310
311
  sensorPresence: ['MS600'],
311
312
  hubMain: ['MSH300', 'MSH300HK', 'MSH400', 'MSH450'],
312
- hubSub: ['GS559A', 'MS100', 'MS100F', 'MS130', 'MS200', 'MS400', 'MST100', 'MTS100', 'MTS100V3', 'MTS150', 'MTS150P'],
313
+ hubSub: ['GS559A', 'MS100', 'MS100F', 'MS130', 'MS130H', 'MS200', 'MS400', 'MST100', 'MTS100', 'MTS100V3', 'MTS150', 'MTS150P'],
313
314
  template: [],
314
315
  },
315
316
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@homebridge-plugins/homebridge-meross",
3
3
  "alias": "Meross",
4
4
  "type": "module",
5
- "version": "10.13.1-beta.0",
5
+ "version": "10.14.0",
6
6
  "description": "Homebridge plugin to integrate Meross devices into HomeKit.",
7
7
  "author": {
8
8
  "name": "bwp91",
@@ -49,7 +49,7 @@
49
49
  "main": "lib/index.js",
50
50
  "engines": {
51
51
  "homebridge": "^1.6.0 || ^2.0.0-beta.0",
52
- "node": "^20 || ^22 || ^24"
52
+ "node": "^22 || ^24"
53
53
  },
54
54
  "scripts": {
55
55
  "lint": "eslint . --max-warnings=0",
@@ -57,13 +57,13 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "@homebridge/plugin-ui-utils": "^2.2.3",
60
- "axios": "^1.14.0",
60
+ "axios": "^1.15.0",
61
61
  "mqtt": "^5.15.1",
62
62
  "node-persist": "^4.0.4",
63
- "p-queue": "^9.1.1",
63
+ "p-queue": "^9.1.2",
64
64
  "p-timeout": "^7.0.1"
65
65
  },
66
66
  "devDependencies": {
67
- "@antfu/eslint-config": "^8.0.0"
67
+ "@antfu/eslint-config": "^8.1.1"
68
68
  }
69
69
  }