@homebridge-plugins/homebridge-govee 10.12.1

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 (78) hide show
  1. package/CHANGELOG.md +1937 -0
  2. package/LICENSE +21 -0
  3. package/README.md +72 -0
  4. package/config.schema.json +1727 -0
  5. package/eslint.config.js +49 -0
  6. package/lib/connection/aws.js +174 -0
  7. package/lib/connection/ble.js +208 -0
  8. package/lib/connection/cert/AmazonRootCA1.pem +20 -0
  9. package/lib/connection/http.js +240 -0
  10. package/lib/connection/lan.js +284 -0
  11. package/lib/device/cooler-single.js +300 -0
  12. package/lib/device/dehumidifier-H7150.js +182 -0
  13. package/lib/device/dehumidifier-H7151.js +157 -0
  14. package/lib/device/diffuser-H7161.js +117 -0
  15. package/lib/device/diffuser-H7162.js +117 -0
  16. package/lib/device/fan-H7100.js +274 -0
  17. package/lib/device/fan-H7101.js +330 -0
  18. package/lib/device/fan-H7102.js +274 -0
  19. package/lib/device/fan-H7105.js +503 -0
  20. package/lib/device/fan-H7106.js +274 -0
  21. package/lib/device/fan-H7111.js +335 -0
  22. package/lib/device/heater-single.js +300 -0
  23. package/lib/device/heater1a.js +353 -0
  24. package/lib/device/heater1b.js +616 -0
  25. package/lib/device/heater2.js +838 -0
  26. package/lib/device/humidifier-H7140.js +224 -0
  27. package/lib/device/humidifier-H7141.js +257 -0
  28. package/lib/device/humidifier-H7142.js +522 -0
  29. package/lib/device/humidifier-H7143.js +157 -0
  30. package/lib/device/humidifier-H7148.js +157 -0
  31. package/lib/device/humidifier-H7160.js +446 -0
  32. package/lib/device/ice-maker-H7162.js +46 -0
  33. package/lib/device/index.js +105 -0
  34. package/lib/device/kettle.js +269 -0
  35. package/lib/device/light-switch.js +86 -0
  36. package/lib/device/light.js +617 -0
  37. package/lib/device/outlet-double.js +121 -0
  38. package/lib/device/outlet-single.js +172 -0
  39. package/lib/device/outlet-triple.js +160 -0
  40. package/lib/device/purifier-H7120.js +336 -0
  41. package/lib/device/purifier-H7121.js +336 -0
  42. package/lib/device/purifier-H7122.js +449 -0
  43. package/lib/device/purifier-H7123.js +411 -0
  44. package/lib/device/purifier-H7124.js +411 -0
  45. package/lib/device/purifier-H7126.js +296 -0
  46. package/lib/device/purifier-H7127.js +296 -0
  47. package/lib/device/purifier-H712C.js +296 -0
  48. package/lib/device/purifier-single.js +119 -0
  49. package/lib/device/sensor-button.js +22 -0
  50. package/lib/device/sensor-contact.js +22 -0
  51. package/lib/device/sensor-leak.js +87 -0
  52. package/lib/device/sensor-monitor.js +190 -0
  53. package/lib/device/sensor-presence.js +53 -0
  54. package/lib/device/sensor-thermo.js +144 -0
  55. package/lib/device/sensor-thermo4.js +55 -0
  56. package/lib/device/switch-double.js +121 -0
  57. package/lib/device/switch-single.js +95 -0
  58. package/lib/device/switch-triple.js +160 -0
  59. package/lib/device/tap-single.js +108 -0
  60. package/lib/device/template.js +43 -0
  61. package/lib/device/tv-single.js +84 -0
  62. package/lib/device/valve-single.js +155 -0
  63. package/lib/fakegato/LICENSE +21 -0
  64. package/lib/fakegato/fakegato-history.js +814 -0
  65. package/lib/fakegato/fakegato-storage.js +108 -0
  66. package/lib/fakegato/fakegato-timer.js +125 -0
  67. package/lib/fakegato/uuid.js +27 -0
  68. package/lib/homebridge-ui/public/index.html +433 -0
  69. package/lib/homebridge-ui/server.js +10 -0
  70. package/lib/index.js +8 -0
  71. package/lib/platform.js +1967 -0
  72. package/lib/utils/colour.js +564 -0
  73. package/lib/utils/constants.js +579 -0
  74. package/lib/utils/custom-chars.js +225 -0
  75. package/lib/utils/eve-chars.js +68 -0
  76. package/lib/utils/functions.js +117 -0
  77. package/lib/utils/lang-en.js +131 -0
  78. package/package.json +75 -0
@@ -0,0 +1,121 @@
1
+ import { parseError } from '../utils/functions.js'
2
+ import platformLang from '../utils/lang-en.js'
3
+
4
+ export default class {
5
+ constructor(platform, accessory) {
6
+ // Set up variables from the platform
7
+ this.hapChar = platform.api.hap.Characteristic
8
+ this.hapErr = platform.api.hap.HapStatusError
9
+ this.hapServ = platform.api.hap.Service
10
+ this.platform = platform
11
+
12
+ // Set up variables from the accessory
13
+ this.accessory = accessory
14
+
15
+ // Remove switch services if they exist
16
+ if (this.accessory.getService('Switch 1')) {
17
+ this.accessory.removeService(this.accessory.getService('Switch 1'))
18
+ }
19
+ if (this.accessory.getService('Switch 2')) {
20
+ this.accessory.removeService(this.accessory.getService('Switch 2'))
21
+ }
22
+
23
+ // Add the outlet services if they don't already exist
24
+ this.service1 = this.accessory.getService('Outlet 1')
25
+ || this.accessory.addService(this.hapServ.Outlet, 'Outlet 1', 'outlet1')
26
+ this.service2 = this.accessory.getService('Outlet 2')
27
+ || this.accessory.addService(this.hapServ.Outlet, 'Outlet 2', 'outlet2')
28
+
29
+ if (!this.service1.testCharacteristic(this.hapChar.ConfiguredName)) {
30
+ this.service1.addCharacteristic(this.hapChar.ConfiguredName)
31
+ this.service1.updateCharacteristic(this.hapChar.ConfiguredName, 'Outlet 1')
32
+ }
33
+ if (!this.service1.testCharacteristic(this.hapChar.ServiceLabelIndex)) {
34
+ this.service1.addCharacteristic(this.hapChar.ServiceLabelIndex)
35
+ this.service1.updateCharacteristic(this.hapChar.ServiceLabelIndex, 1)
36
+ }
37
+ if (!this.service2.testCharacteristic(this.hapChar.ConfiguredName)) {
38
+ this.service2.addCharacteristic(this.hapChar.ConfiguredName)
39
+ this.service2.updateCharacteristic(this.hapChar.ConfiguredName, 'Outlet 2')
40
+ }
41
+ if (!this.service2.testCharacteristic(this.hapChar.ServiceLabelIndex)) {
42
+ this.service2.addCharacteristic(this.hapChar.ServiceLabelIndex)
43
+ this.service2.updateCharacteristic(this.hapChar.ServiceLabelIndex, 2)
44
+ }
45
+
46
+ // Add the set handler to the switch on/off characteristic
47
+ this.service1.getCharacteristic(this.hapChar.On).onSet(async (value) => {
48
+ await this.internalStateUpdate(this.service1, value ? 17 : 16)
49
+ })
50
+ this.service1.cacheState = this.service1.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
51
+ this.service2.getCharacteristic(this.hapChar.On).onSet(async (value) => {
52
+ await this.internalStateUpdate(this.service2, value ? 34 : 32)
53
+ })
54
+ this.service2.cacheState = this.service2.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
55
+
56
+ // Output the customised options to the log
57
+ const opts = JSON.stringify({
58
+ showAs: 'outlet',
59
+ })
60
+ platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
61
+
62
+ // 51 turns BOTH ON
63
+ // 48 turns BOTH OFF
64
+ // 34 turns outlet 1 ON
65
+ // 32 turns outlet 1 OFF
66
+ // 17 turns outlet 2 ON
67
+ // 16 turns outlet 2 OFF
68
+ }
69
+
70
+ async internalStateUpdate(service, value) {
71
+ try {
72
+ const newValue = value % 16 === 0 ? 'off' : 'on'
73
+
74
+ // Don't continue if the new value is the same as before
75
+ if (service.cacheState === newValue) {
76
+ return
77
+ }
78
+
79
+ // Send the request to the platform sender function
80
+ await this.platform.sendDeviceUpdate(this.accessory, {
81
+ cmd: 'stateDual',
82
+ value,
83
+ })
84
+
85
+ // Cache the new state and log if appropriate
86
+ if (service.cacheState !== newValue) {
87
+ service.cacheState = newValue
88
+ this.accessory.log(`[${service.getCharacteristic(this.hapChar.ConfiguredName).value}] ${platformLang.curState} [${newValue}]`)
89
+ }
90
+ } catch (err) {
91
+ // Catch any errors during the process
92
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
93
+
94
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
95
+ setTimeout(() => {
96
+ service.updateCharacteristic(this.hapChar.On, service.cacheState === 'on')
97
+ }, 2000)
98
+ throw new this.hapErr(-70402)
99
+ }
100
+ }
101
+
102
+ externalUpdate(params) {
103
+ if (!Array.isArray(params.state)) {
104
+ return
105
+ }
106
+
107
+ if (params.state[0] !== this.service1.cacheState) {
108
+ this.service1.cacheState = params.state[0]
109
+ this.service1.updateCharacteristic(this.hapChar.On, this.service1.cacheState === 'on')
110
+
111
+ this.accessory.log(`[${this.service1.getCharacteristic(this.hapChar.ConfiguredName).value}] ${platformLang.curState} [${this.service1.cacheState}]`)
112
+ }
113
+
114
+ if (params.state[1] !== this.service2.cacheState) {
115
+ this.service2.cacheState = params.state[1]
116
+ this.service2.updateCharacteristic(this.hapChar.On, this.service2.cacheState === 'on')
117
+
118
+ this.accessory.log(`[${this.service2.getCharacteristic(this.hapChar.ConfiguredName).value}] ${platformLang.curState} [${this.service2.cacheState}]`)
119
+ }
120
+ }
121
+ }
@@ -0,0 +1,172 @@
1
+ import { base64ToHex, generateRandomString, getTwoItemPosition, hexToTwoItems, parseError } from '../utils/functions.js'
2
+ import platformLang from '../utils/lang-en.js'
3
+
4
+ export default class {
5
+ constructor(platform, accessory) {
6
+ // Set up variables from the platform
7
+ this.eveChar = platform.eveChar
8
+ this.hapChar = platform.api.hap.Characteristic
9
+ this.hapErr = platform.api.hap.HapStatusError
10
+ this.hapServ = platform.api.hap.Service
11
+ this.platform = platform
12
+
13
+ // Set up variables from the accessory
14
+ this.accessory = accessory;
15
+
16
+ // Remove any old services from simulations
17
+ ['AirPurifier', 'HeaterCooler', 'Lightbulb', 'Switch', 'Valve'].forEach((service) => {
18
+ if (this.accessory.getService(this.hapServ[service])) {
19
+ this.accessory.removeService(this.accessory.getService(this.hapServ[service]))
20
+ }
21
+ })
22
+
23
+ // Add the outlet service if it doesn't already exist
24
+ this.service = this.accessory.getService(this.hapServ.Outlet)
25
+ || this.accessory.addService(this.hapServ.Outlet)
26
+
27
+ // Add the set handler to the switch on/off characteristic
28
+ this.service.getCharacteristic(this.hapChar.On).onSet(async (value) => {
29
+ await this.internalStateUpdate(value)
30
+ })
31
+ this.cacheState = this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
32
+
33
+ if (this.accessory.context.gvModel === 'H5086') {
34
+ // Power readings
35
+ if (!this.service.testCharacteristic(this.eveChar.CurrentConsumption)) {
36
+ this.service.addCharacteristic(this.eveChar.CurrentConsumption)
37
+ }
38
+ if (!this.service.testCharacteristic(this.eveChar.ElectricCurrent)) {
39
+ this.service.addCharacteristic(this.eveChar.ElectricCurrent)
40
+ }
41
+ if (!this.service.testCharacteristic(this.eveChar.Voltage)) {
42
+ this.service.addCharacteristic(this.eveChar.Voltage)
43
+ }
44
+
45
+ this.cacheWatt = this.service.getCharacteristic(this.eveChar.CurrentConsumption).value || 0
46
+ this.cacheAmp = this.service.getCharacteristic(this.eveChar.ElectricCurrent).value || 0
47
+ this.cacheVolt = this.service.getCharacteristic(this.eveChar.Voltage).value || 0
48
+
49
+ // Pass the accessory to Fakegato to set up with Eve
50
+ this.accessory.eveService = new platform.eveService('energy', this.accessory, {
51
+ log: () => {},
52
+ })
53
+ } else {
54
+ // Pass the accessory to Fakegato to set up with Eve
55
+ this.accessory.eveService = new platform.eveService('switch', this.accessory, {
56
+ log: () => {},
57
+ })
58
+ }
59
+
60
+ // Output the customised options to the log
61
+ const opts = JSON.stringify({
62
+ showAs: 'outlet',
63
+ })
64
+ platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
65
+ }
66
+
67
+ async internalStateUpdate(value) {
68
+ try {
69
+ const newValue = value ? 'on' : 'off'
70
+
71
+ // Don't continue if the new value is the same as before
72
+ if (newValue === this.cacheState) {
73
+ return
74
+ }
75
+
76
+ // Set up a one-minute timeout for the plugin to ignore incoming updates
77
+ const timerKey = generateRandomString(5)
78
+ this.updateTimeout = timerKey
79
+ setTimeout(() => {
80
+ if (this.updateTimeout === timerKey) {
81
+ this.updateTimeout = false
82
+ }
83
+ }, 60000)
84
+
85
+ // Send the request to the platform sender function
86
+ await this.platform.sendDeviceUpdate(this.accessory, {
87
+ cmd: 'stateOutlet',
88
+ value: newValue,
89
+ })
90
+
91
+ // Cache the new state and log if appropriate
92
+ if (this.cacheState !== newValue) {
93
+ this.cacheState = newValue
94
+ this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
95
+ }
96
+
97
+ // Add the entry to the Eve history service
98
+ this.accessory.eveService.addEntry({ status: value ? 1 : 0 })
99
+ } catch (err) {
100
+ // Catch any errors during the process
101
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
102
+
103
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
104
+ setTimeout(() => {
105
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
106
+ }, 2000)
107
+ throw new this.hapErr(-70402)
108
+ }
109
+ }
110
+
111
+ externalUpdate(params) {
112
+ // Check to see if the provided state is different from the cached state
113
+ if (params.state && params.state !== this.cacheState) {
114
+ // State is different so update Homebridge with new values
115
+ this.cacheState = params.state
116
+ this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
117
+
118
+ // Log the change
119
+ this.accessory.log(`${platformLang.curState} [${this.cacheState}]`)
120
+
121
+ // Add the entry to the Eve history service
122
+ this.accessory.eveService.addEntry({
123
+ status: this.cacheState === 'on' ? 1 : 0,
124
+ })
125
+ }
126
+
127
+ // Check for some other scene/mode change
128
+ (params.commands || []).forEach((command) => {
129
+ const hexString = base64ToHex(command)
130
+ const hexParts = hexToTwoItems(hexString)
131
+
132
+ // Return now if not a device query update code
133
+ if (getTwoItemPosition(hexParts, 1) !== 'aa') {
134
+ return
135
+ }
136
+
137
+ const deviceFunction = `${getTwoItemPosition(hexParts, 1)}${getTwoItemPosition(hexParts, 2)}`
138
+
139
+ switch (deviceFunction) {
140
+ case 'aa19': { // power readings
141
+ const hexWatt = `${getTwoItemPosition(hexParts, 13)}${getTwoItemPosition(hexParts, 14)}${getTwoItemPosition(hexParts, 15)}`
142
+ const hexAmp = `${getTwoItemPosition(hexParts, 11)}${getTwoItemPosition(hexParts, 12)}`
143
+ const hexVolt = `${getTwoItemPosition(hexParts, 9)}${getTwoItemPosition(hexParts, 10)}`
144
+ const newWatt = Number.parseInt(hexWatt, 16) / 100
145
+ const newAmp = Number.parseInt(hexAmp, 16) / 100
146
+ const newVolt = Number.parseInt(hexVolt, 16) / 100
147
+
148
+ if (this.cacheWatt !== newWatt) {
149
+ this.cacheWatt = newWatt
150
+ this.service.updateCharacteristic(this.eveChar.CurrentConsumption, this.cacheWatt)
151
+ this.accessory.eveService.addEntry({ power: newWatt })
152
+ this.accessory.log(`${platformLang.curWatt} [${this.cacheWatt}W]`)
153
+ }
154
+ if (this.cacheAmp !== newAmp) {
155
+ this.cacheAmp = newAmp
156
+ this.service.updateCharacteristic(this.eveChar.ElectricCurrent, this.cacheAmp)
157
+ this.accessory.log(`${platformLang.curAmp} [${this.cacheAmp}A]`)
158
+ }
159
+ if (this.cacheVolt !== newVolt) {
160
+ this.cacheVolt = newVolt
161
+ this.service.updateCharacteristic(this.eveChar.Voltage, this.cacheVolt)
162
+ this.accessory.log(`${platformLang.curVolt} [${this.cacheVolt}V]`)
163
+ }
164
+ break
165
+ }
166
+ default:
167
+ this.accessory.logDebugWarn(`${platformLang.newScene}: [${command}] [${hexString}]`)
168
+ break
169
+ }
170
+ })
171
+ }
172
+ }
@@ -0,0 +1,160 @@
1
+ import { parseError } from '../utils/functions.js'
2
+ import platformLang from '../utils/lang-en.js'
3
+
4
+ export default class {
5
+ constructor(platform, accessory) {
6
+ // Set up variables from the platform
7
+ this.hapChar = platform.api.hap.Characteristic
8
+ this.hapErr = platform.api.hap.HapStatusError
9
+ this.hapServ = platform.api.hap.Service
10
+ this.platform = platform
11
+
12
+ // Set up variables from the accessory
13
+ this.accessory = accessory
14
+
15
+ // Remove switch services if they exist
16
+ if (this.accessory.getService('Switch 1')) {
17
+ this.accessory.removeService(this.accessory.getService('Switch 1'))
18
+ }
19
+ if (this.accessory.getService('Switch 2')) {
20
+ this.accessory.removeService(this.accessory.getService('Switch 2'))
21
+ }
22
+ if (this.accessory.getService('Switch 3')) {
23
+ this.accessory.removeService(this.accessory.getService('Switch 3'))
24
+ }
25
+
26
+ // Add the outlet services if they don't already exist
27
+ this.service1 = this.accessory.getService('Outlet 1')
28
+ || this.accessory.addService(this.hapServ.Outlet, 'Outlet 1', 'outlet1')
29
+ this.service2 = this.accessory.getService('Outlet 2')
30
+ || this.accessory.addService(this.hapServ.Outlet, 'Outlet 2', 'outlet2')
31
+ this.service3 = this.accessory.getService('Outlet 3')
32
+ || this.accessory.addService(this.hapServ.Outlet, 'Outlet 3', 'outlet3')
33
+
34
+ // Add the set handler to the switch on/off characteristic
35
+ this.service1.getCharacteristic(this.hapChar.On).onSet(async (value) => {
36
+ await this.internalStateUpdate(this.service1, value ? 17 : 16)
37
+ })
38
+ this.service1.cacheState = this.service1.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
39
+ this.service2.getCharacteristic(this.hapChar.On).onSet(async (value) => {
40
+ await this.internalStateUpdate(this.service2, value ? 34 : 32)
41
+ })
42
+ this.service2.cacheState = this.service2.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
43
+ this.service3.getCharacteristic(this.hapChar.On).onSet(async (value) => {
44
+ await this.internalStateUpdate(this.service3, value ? 68 : 64)
45
+ })
46
+ this.service3.cacheState = this.service3.getCharacteristic(this.hapChar.On).value ? 'on' : 'off'
47
+
48
+ // Output the customised options to the log
49
+ const opts = JSON.stringify({
50
+ showAs: 'outlet',
51
+ })
52
+ platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts)
53
+
54
+ // 119 turns BOTH ON
55
+ // 112 turns BOTH OFF
56
+
57
+ // 68 turns outlet 3 ON
58
+ // 64 turns outlet 3 OFF
59
+
60
+ // 34 turns outlet 2 ON
61
+ // 32 turns outlet 2 OFF
62
+
63
+ // 17 turns outlet 1 ON
64
+ // 16 turns outlet 1 OFF
65
+ }
66
+
67
+ async internalStateUpdate(service, value) {
68
+ try {
69
+ const newValue = value % 16 === 0 ? 'off' : 'on'
70
+
71
+ // Don't continue if the new value is the same as before
72
+ if (service.cacheState === newValue) {
73
+ return
74
+ }
75
+
76
+ // Send the request to the platform sender function
77
+ await this.platform.sendDeviceUpdate(this.accessory, {
78
+ cmd: 'stateDual',
79
+ value,
80
+ })
81
+
82
+ // Cache the new state and log if appropriate
83
+ service.cacheState = newValue
84
+ this.accessory.log(`[${service.displayName}] ${platformLang.curState} [${newValue}]`)
85
+ } catch (err) {
86
+ // Catch any errors during the process
87
+ this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`)
88
+
89
+ // Throw a 'no response' error and set a timeout to revert this after 2 seconds
90
+ setTimeout(() => {
91
+ service.updateCharacteristic(this.hapChar.On, service.cacheState === 'on')
92
+ }, 2000)
93
+ throw new this.hapErr(-70402)
94
+ }
95
+ }
96
+
97
+ externalUpdate(params) {
98
+ // Check to see if the provided state is different from the cached state
99
+ if (!params.stateDual) {
100
+ return
101
+ }
102
+
103
+ if ([112, 119].includes(params.stateDual)) {
104
+ // 112 -> both off
105
+ // 119 -> both on
106
+ const newState = params.stateDual === 119 ? 'on' : 'off'
107
+ if (newState !== this.service1.cacheState) {
108
+ this.service1.cacheState = newState
109
+ this.service1.updateCharacteristic(this.hapChar.On, this.service1.cacheState === 'on')
110
+
111
+ // Log the change
112
+ this.accessory.log(`[${this.service1.displayName}] ${platformLang.curState} [${this.service1.cacheState}]`)
113
+ }
114
+ if (newState !== this.service2.cacheState) {
115
+ this.service2.cacheState = newState
116
+ this.service2.updateCharacteristic(this.hapChar.On, this.service2.cacheState === 'on')
117
+
118
+ // Log the change
119
+ this.accessory.log(`[${this.service2.displayName}] ${platformLang.curState} [${this.service2.cacheState}]`)
120
+ }
121
+ if (newState !== this.service3.cacheState) {
122
+ this.service3.cacheState = newState
123
+ this.service3.updateCharacteristic(this.hapChar.On, this.service3.cacheState === 'on')
124
+
125
+ // Log the change
126
+ this.accessory.log(`[${this.service3.displayName}] ${platformLang.curState} [${this.service3.cacheState}]`)
127
+ }
128
+ }
129
+ if ([16, 17].includes(params.stateDual)) {
130
+ const newState = params.stateDual === 17 ? 'on' : 'off'
131
+ if (newState !== this.service1.cacheState) {
132
+ this.service1.cacheState = newState
133
+ this.service1.updateCharacteristic(this.hapChar.On, this.service1.cacheState === 'on')
134
+
135
+ // Log the change
136
+ this.accessory.log(`[${this.service1.displayName}] ${platformLang.curState} [${this.service1.cacheState}]`)
137
+ }
138
+ }
139
+ if ([32, 34].includes(params.stateDual)) {
140
+ const newState = params.stateDual === 34 ? 'on' : 'off'
141
+ if (newState !== this.service2.cacheState) {
142
+ this.service2.cacheState = newState
143
+ this.service2.updateCharacteristic(this.hapChar.On, this.service2.cacheState === 'on')
144
+
145
+ // Log the change
146
+ this.accessory.log(`[${this.service2.displayName}] ${platformLang.curState} [${this.service2.cacheState}]`)
147
+ }
148
+ }
149
+ if ([64, 68].includes(params.stateDual)) {
150
+ const newState = params.stateDual === 68 ? 'on' : 'off'
151
+ if (newState !== this.service3.cacheState) {
152
+ this.service3.cacheState = newState
153
+ this.service3.updateCharacteristic(this.hapChar.On, this.service3.cacheState === 'on')
154
+
155
+ // Log the change
156
+ this.accessory.log(`[${this.service3.displayName}] ${platformLang.curState} [${this.service3.cacheState}]`)
157
+ }
158
+ }
159
+ }
160
+ }