@homebridge-plugins/homebridge-ewelink 12.3.3
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 +1363 -0
- package/LICENSE +21 -0
- package/README.md +68 -0
- package/config.schema.json +1757 -0
- package/eslint.config.js +15 -0
- package/lib/connection/api.js +508 -0
- package/lib/connection/http.js +304 -0
- package/lib/connection/lan.js +318 -0
- package/lib/connection/ws.js +414 -0
- package/lib/device/curtain.js +324 -0
- package/lib/device/diffuser.js +473 -0
- package/lib/device/fan.js +349 -0
- package/lib/device/group.js +106 -0
- package/lib/device/humidifier.js +199 -0
- package/lib/device/index.js +61 -0
- package/lib/device/light-cct.js +333 -0
- package/lib/device/light-dimmer.js +257 -0
- package/lib/device/light-rgb-cct.js +809 -0
- package/lib/device/light-rgb.js +272 -0
- package/lib/device/motor.js +363 -0
- package/lib/device/outlet-multi.js +417 -0
- package/lib/device/outlet-single-inched.js +409 -0
- package/lib/device/outlet-single.js +384 -0
- package/lib/device/panel.js +382 -0
- package/lib/device/rf-bridge.js +321 -0
- package/lib/device/rf-button.js +125 -0
- package/lib/device/rf-sensor.js +173 -0
- package/lib/device/sensor-ambient.js +311 -0
- package/lib/device/sensor-contact.js +140 -0
- package/lib/device/sensor-temp-humi.js +182 -0
- package/lib/device/simulation/blind.js +253 -0
- package/lib/device/simulation/cooler.js +312 -0
- package/lib/device/simulation/door.js +253 -0
- package/lib/device/simulation/doorbell.js +190 -0
- package/lib/device/simulation/garage-eachen.js +235 -0
- package/lib/device/simulation/garage-four.js +176 -0
- package/lib/device/simulation/garage-od-switch.js +36 -0
- package/lib/device/simulation/garage-one.js +395 -0
- package/lib/device/simulation/garage-two.js +394 -0
- package/lib/device/simulation/gate-one.js +327 -0
- package/lib/device/simulation/heater.js +389 -0
- package/lib/device/simulation/index.js +75 -0
- package/lib/device/simulation/light-fan.js +258 -0
- package/lib/device/simulation/lock-eachen.js +163 -0
- package/lib/device/simulation/lock-one.js +366 -0
- package/lib/device/simulation/p-button.js +223 -0
- package/lib/device/simulation/purifier.js +289 -0
- package/lib/device/simulation/rf-blind.js +192 -0
- package/lib/device/simulation/rf-door.js +180 -0
- package/lib/device/simulation/rf-window.js +180 -0
- package/lib/device/simulation/sensor-hidden.js +105 -0
- package/lib/device/simulation/sensor-leak.js +123 -0
- package/lib/device/simulation/sensor-visible.js +231 -0
- package/lib/device/simulation/sensor.js +300 -0
- package/lib/device/simulation/switch-valve.js +351 -0
- package/lib/device/simulation/tap-one.js +283 -0
- package/lib/device/simulation/tap-two.js +266 -0
- package/lib/device/simulation/th-cooler.js +443 -0
- package/lib/device/simulation/th-dehumidifier.js +424 -0
- package/lib/device/simulation/th-heater.js +449 -0
- package/lib/device/simulation/th-humidifier.js +424 -0
- package/lib/device/simulation/th-thermostat.js +611 -0
- package/lib/device/simulation/tv.js +252 -0
- package/lib/device/simulation/valve-four.js +232 -0
- package/lib/device/simulation/valve-one.js +345 -0
- package/lib/device/simulation/valve-two.js +340 -0
- package/lib/device/simulation/window.js +253 -0
- package/lib/device/switch-man.js +106 -0
- package/lib/device/switch-mate.js +82 -0
- package/lib/device/switch-multi.js +411 -0
- package/lib/device/switch-single-inched.js +332 -0
- package/lib/device/switch-single.js +307 -0
- package/lib/device/template.js +43 -0
- package/lib/device/thermostat.js +286 -0
- package/lib/device/zigbee/index.js +27 -0
- package/lib/device/zigbee/light-cct.js +263 -0
- package/lib/device/zigbee/light-dimmer.js +148 -0
- package/lib/device/zigbee/light-rgb-cct.js +400 -0
- package/lib/device/zigbee/motor.js +301 -0
- package/lib/device/zigbee/sensor-ambient.js +177 -0
- package/lib/device/zigbee/sensor-contact.js +137 -0
- package/lib/device/zigbee/sensor-leak.js +119 -0
- package/lib/device/zigbee/sensor-motion.js +119 -0
- package/lib/device/zigbee/sensor-occupancy.js +119 -0
- package/lib/device/zigbee/sensor-smoke.js +96 -0
- package/lib/device/zigbee/switch-stateless.js +104 -0
- package/lib/device/zigbee/thermostat.js +323 -0
- package/lib/fakegato/LICENSE +21 -0
- package/lib/fakegato/fakegato-history.js +813 -0
- package/lib/fakegato/fakegato-storage.js +108 -0
- package/lib/fakegato/fakegato-timer.js +125 -0
- package/lib/fakegato/uuid.js +27 -0
- package/lib/homebridge-ui/public/index.html +365 -0
- package/lib/homebridge-ui/server.js +46 -0
- package/lib/index.js +7 -0
- package/lib/node-dns-sd/LICENSE +21 -0
- package/lib/node-dns-sd/README.md +613 -0
- package/lib/node-dns-sd/lib/dns-sd-classes.json +6 -0
- package/lib/node-dns-sd/lib/dns-sd-composer.js +83 -0
- package/lib/node-dns-sd/lib/dns-sd-parser.js +344 -0
- package/lib/node-dns-sd/lib/dns-sd-types.json +52 -0
- package/lib/node-dns-sd/lib/dns-sd.js +580 -0
- package/lib/platform.js +2156 -0
- package/lib/utils/colour.js +552 -0
- package/lib/utils/constants.js +589 -0
- package/lib/utils/custom-chars.js +33 -0
- package/lib/utils/eve-chars.js +130 -0
- package/lib/utils/functions.js +42 -0
- package/lib/utils/lang-en.js +160 -0
- package/lib/utils/lang-fr.js +163 -0
- package/lib/utils/lang-th.js +160 -0
- package/lib/utils/lang.js +5 -0
- package/package.json +75 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
export default class {
|
|
2
|
+
constructor(platform, accessory) {
|
|
3
|
+
// Set up variables from the platform
|
|
4
|
+
this.eveChar = platform.eveChar
|
|
5
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
6
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
7
|
+
this.hapServ = platform.api.hap.Service
|
|
8
|
+
this.lang = platform.lang
|
|
9
|
+
this.log = platform.log
|
|
10
|
+
this.platform = platform
|
|
11
|
+
|
|
12
|
+
// Set up variables from the accessory
|
|
13
|
+
this.name = accessory.displayName
|
|
14
|
+
this.accessory = accessory
|
|
15
|
+
|
|
16
|
+
// Initially set the online flag as true (to be then updated as false if necessary)
|
|
17
|
+
this.isOnline = true
|
|
18
|
+
|
|
19
|
+
// Set up custom variables for this device type
|
|
20
|
+
const deviceConf = platform.rfSubdevices[accessory.context.hbDeviceId] || {}
|
|
21
|
+
|
|
22
|
+
// Set the correct logging variables for this accessory
|
|
23
|
+
switch (deviceConf.overrideLogging) {
|
|
24
|
+
case 'standard':
|
|
25
|
+
this.enableLogging = true
|
|
26
|
+
this.enableDebugLogging = false
|
|
27
|
+
break
|
|
28
|
+
case 'debug':
|
|
29
|
+
this.enableLogging = true
|
|
30
|
+
this.enableDebugLogging = true
|
|
31
|
+
break
|
|
32
|
+
case 'disable':
|
|
33
|
+
this.enableLogging = false
|
|
34
|
+
this.enableDebugLogging = false
|
|
35
|
+
break
|
|
36
|
+
default:
|
|
37
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
38
|
+
this.enableDebugLogging = platform.config.debug
|
|
39
|
+
break
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If the accessory has a window covering service (from an old simulation) then remove it
|
|
43
|
+
if (this.accessory.getService(this.hapServ.WindowCovering)) {
|
|
44
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.WindowCovering))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// If the accessory has a door service (from an old simulation) then remove it
|
|
48
|
+
if (this.accessory.getService(this.hapServ.Door)) {
|
|
49
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Door))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// If the accessory has a window service (from an old simulation) then remove it
|
|
53
|
+
if (this.accessory.getService(this.hapServ.Window)) {
|
|
54
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Window))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// This instance is a remote control with buttons or curtain control
|
|
58
|
+
Object.entries(this.accessory.context.buttons).forEach(([chan, name]) => {
|
|
59
|
+
// For each curtain/button we create a separate switch service
|
|
60
|
+
|
|
61
|
+
// Add the switch service if it doesn't already exist
|
|
62
|
+
if (!this.accessory.getService(name)) {
|
|
63
|
+
this.accessory.addService(this.hapServ.Switch, name, `switch${chan}`)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Always start with the buttons off (useful when restarting Homebridge)
|
|
67
|
+
this.accessory.getService(name).updateCharacteristic(this.hapChar.On, false)
|
|
68
|
+
|
|
69
|
+
// Add the set handler to the switch on/off characteristic
|
|
70
|
+
this.accessory
|
|
71
|
+
.getService(name)
|
|
72
|
+
.getCharacteristic(this.hapChar.On)
|
|
73
|
+
.onSet(async value => this.internalPressUpdate(chan, name, value))
|
|
74
|
+
|
|
75
|
+
// Add the get handlers only if the user hasn't disabled the disableNoResponse setting
|
|
76
|
+
if (!platform.config.disableNoResponse) {
|
|
77
|
+
this.accessory
|
|
78
|
+
.getService(name)
|
|
79
|
+
.getCharacteristic(this.hapChar.On)
|
|
80
|
+
.onGet(() => {
|
|
81
|
+
if (!this.isOnline) {
|
|
82
|
+
throw new this.hapErr(-70402)
|
|
83
|
+
}
|
|
84
|
+
return this.accessory.getService(name).getCharacteristic(this.hapChar.On).value
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Output the customised options to the log
|
|
90
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
91
|
+
const opts = JSON.stringify({
|
|
92
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
93
|
+
})
|
|
94
|
+
this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async internalPressUpdate(rfChl, service, value) {
|
|
98
|
+
try {
|
|
99
|
+
if (!value) {
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
const params = {
|
|
103
|
+
cmd: 'transmit',
|
|
104
|
+
rfChl: Number.parseInt(rfChl, 10),
|
|
105
|
+
}
|
|
106
|
+
await this.platform.sendDeviceUpdate(this.accessory, params)
|
|
107
|
+
if (this.enableLogging) {
|
|
108
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.lang.buttonTrig)
|
|
109
|
+
}
|
|
110
|
+
setTimeout(() => {
|
|
111
|
+
this.accessory.getService(service).updateCharacteristic(this.hapChar.On, false)
|
|
112
|
+
}, 1000)
|
|
113
|
+
} catch (err) {
|
|
114
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
115
|
+
setTimeout(() => {
|
|
116
|
+
this.accessory.getService(service).updateCharacteristic(this.hapChar.On, false)
|
|
117
|
+
}, 2000)
|
|
118
|
+
throw new this.hapErr(-70402)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
markStatus(isOnline) {
|
|
123
|
+
this.isOnline = isOnline
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import platformConsts from '../utils/constants.js'
|
|
2
|
+
|
|
3
|
+
export default class {
|
|
4
|
+
constructor(platform, accessory) {
|
|
5
|
+
// Set up variables from the platform
|
|
6
|
+
this.eveChar = platform.eveChar
|
|
7
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
8
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
9
|
+
this.hapServ = platform.api.hap.Service
|
|
10
|
+
this.lang = platform.lang
|
|
11
|
+
this.log = platform.log
|
|
12
|
+
this.platform = platform
|
|
13
|
+
|
|
14
|
+
// Initially set the online flag as true (to be then updated as false if necessary)
|
|
15
|
+
this.isOnline = true
|
|
16
|
+
|
|
17
|
+
// Set up custom variables for this device type
|
|
18
|
+
const deviceConf = platform.rfSubdevices[accessory.context.hbDeviceId] || {}
|
|
19
|
+
this.sensorTimeLength = deviceConf.sensorTimeLength || platformConsts.defaultValues.sensorTimeLength
|
|
20
|
+
this.sensorTimeDifference = deviceConf.sensorTimeDifference || platformConsts.defaultValues.sensorTimeDifference
|
|
21
|
+
this.sensorType = deviceConf.type ? deviceConf.type : 'motion'
|
|
22
|
+
|
|
23
|
+
// Set the correct logging variables for this accessory
|
|
24
|
+
switch (deviceConf.overrideLogging) {
|
|
25
|
+
case 'standard':
|
|
26
|
+
this.enableLogging = true
|
|
27
|
+
this.enableDebugLogging = false
|
|
28
|
+
break
|
|
29
|
+
case 'debug':
|
|
30
|
+
this.enableLogging = true
|
|
31
|
+
this.enableDebugLogging = true
|
|
32
|
+
break
|
|
33
|
+
case 'disable':
|
|
34
|
+
this.enableLogging = false
|
|
35
|
+
this.enableDebugLogging = false
|
|
36
|
+
break
|
|
37
|
+
default:
|
|
38
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
39
|
+
this.enableDebugLogging = platform.config.debug
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// This instance is a sensor which the user can define as different types
|
|
44
|
+
let serv
|
|
45
|
+
let char
|
|
46
|
+
let eveType
|
|
47
|
+
let addLACharacteristic = false
|
|
48
|
+
|
|
49
|
+
// Create an array of hap sensor services to for later to check sensor type hasn't changed
|
|
50
|
+
let hapServList = [
|
|
51
|
+
this.hapServ.LeakSensor,
|
|
52
|
+
this.hapServ.SmokeSensor,
|
|
53
|
+
this.hapServ.CarbonMonoxideSensor,
|
|
54
|
+
this.hapServ.CarbonDioxideSensor,
|
|
55
|
+
this.hapServ.ContactSensor,
|
|
56
|
+
this.hapServ.OccupancySensor,
|
|
57
|
+
this.hapServ.MotionSensor,
|
|
58
|
+
this.hapServ.StatelessProgrammableSwitch,
|
|
59
|
+
this.hapServ.Doorbell,
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
// Check which type this sensor is and get the correct service/characteristic
|
|
63
|
+
switch (this.sensorType) {
|
|
64
|
+
case 'water':
|
|
65
|
+
serv = this.hapServ.LeakSensor
|
|
66
|
+
char = this.hapChar.LeakDetected
|
|
67
|
+
eveType = 'motion'
|
|
68
|
+
break
|
|
69
|
+
case 'fire':
|
|
70
|
+
case 'smoke':
|
|
71
|
+
serv = this.hapServ.SmokeSensor
|
|
72
|
+
char = this.hapChar.SmokeDetected
|
|
73
|
+
eveType = 'motion'
|
|
74
|
+
break
|
|
75
|
+
case 'co':
|
|
76
|
+
serv = this.hapServ.CarbonMonoxideSensor
|
|
77
|
+
char = this.hapChar.CarbonMonoxideDetected
|
|
78
|
+
eveType = 'motion'
|
|
79
|
+
break
|
|
80
|
+
case 'co2':
|
|
81
|
+
serv = this.hapServ.CarbonDioxideSensor
|
|
82
|
+
char = this.hapChar.CarbonDioxideDetected
|
|
83
|
+
eveType = 'motion'
|
|
84
|
+
break
|
|
85
|
+
case 'contact':
|
|
86
|
+
serv = this.hapServ.ContactSensor
|
|
87
|
+
char = this.hapChar.ContactSensorState
|
|
88
|
+
eveType = 'door'
|
|
89
|
+
addLACharacteristic = true
|
|
90
|
+
break
|
|
91
|
+
case 'occupancy':
|
|
92
|
+
serv = this.hapServ.OccupancySensor
|
|
93
|
+
char = this.hapChar.OccupancyDetected
|
|
94
|
+
eveType = 'motion'
|
|
95
|
+
break
|
|
96
|
+
case 'p_button':
|
|
97
|
+
serv = this.hapServ.StatelessProgrammableSwitch
|
|
98
|
+
char = this.hapChar.ProgrammableSwitchEvent
|
|
99
|
+
break
|
|
100
|
+
case 'doorbell':
|
|
101
|
+
serv = this.hapServ.Doorbell
|
|
102
|
+
char = this.hapChar.ProgrammableSwitchEvent
|
|
103
|
+
break
|
|
104
|
+
default:
|
|
105
|
+
serv = this.hapServ.MotionSensor
|
|
106
|
+
char = this.hapChar.MotionDetected
|
|
107
|
+
eveType = 'motion'
|
|
108
|
+
addLACharacteristic = true
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Remove wanted sensor from hap sensor type list
|
|
113
|
+
hapServList = hapServList.filter(el => el !== serv)
|
|
114
|
+
|
|
115
|
+
// Check and remove and redundant hap sensor types
|
|
116
|
+
hapServList.forEach((hapSensor) => {
|
|
117
|
+
if (accessory.getService(hapSensor)) {
|
|
118
|
+
accessory.removeService(accessory.getService(hapSensor))
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// Add the sensor if it doesn't already exist
|
|
123
|
+
const service = accessory.getService(serv) || accessory.addService(serv)
|
|
124
|
+
|
|
125
|
+
// Remove double and long press from Button and Doorbell service
|
|
126
|
+
if (char === this.hapChar.ProgrammableSwitchEvent) {
|
|
127
|
+
service.getCharacteristic(this.hapChar.ProgrammableSwitchEvent).setProps({
|
|
128
|
+
validValues: [0],
|
|
129
|
+
})
|
|
130
|
+
} else {
|
|
131
|
+
// Always start with the sensor off (useful when restarting Homebridge, except Doorbell)
|
|
132
|
+
service.updateCharacteristic(char, 0)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// See if we need to add or remove the Last Activation characteristic
|
|
136
|
+
if (addLACharacteristic) {
|
|
137
|
+
if (!service.testCharacteristic(this.eveChar.LastActivation)) {
|
|
138
|
+
service.addCharacteristic(this.eveChar.LastActivation)
|
|
139
|
+
}
|
|
140
|
+
} else if (service.testCharacteristic(this.eveChar.LastActivation)) {
|
|
141
|
+
service.removeCharacteristic(service.getCharacteristic(this.eveChar.LastActivation))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Add the get handlers only if the user hasn't disabled the disableNoResponse setting
|
|
145
|
+
if (!platform.config.disableNoResponse) {
|
|
146
|
+
service.getCharacteristic(char).onGet(() => {
|
|
147
|
+
if (!this.isOnline) {
|
|
148
|
+
throw new this.hapErr(-70402)
|
|
149
|
+
}
|
|
150
|
+
return service.getCharacteristic(char).value
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Pass the accessory to Fakegato to set up with Eve
|
|
155
|
+
accessory.eveService = new platform.eveService(eveType, accessory, {
|
|
156
|
+
log: () => {},
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
// Output the customised options to the log
|
|
160
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
161
|
+
const opts = JSON.stringify({
|
|
162
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
163
|
+
sensorTimeDifference: this.sensorTimeDifference,
|
|
164
|
+
sensorTimeLength: this.sensorTimeLength,
|
|
165
|
+
type: this.sensorType,
|
|
166
|
+
})
|
|
167
|
+
this.log('[%s] %s %s.', accessory.displayName, this.lang.devInitOpts, opts)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
markStatus(isOnline) {
|
|
171
|
+
this.isOnline = isOnline
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import platformConsts from '../utils/constants.js'
|
|
2
|
+
import { hasProperty, parseError } from '../utils/functions.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.hapServ = platform.api.hap.Service
|
|
9
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
10
|
+
this.lang = platform.lang
|
|
11
|
+
this.log = platform.log
|
|
12
|
+
this.platform = platform
|
|
13
|
+
|
|
14
|
+
// Set up variables from the accessory
|
|
15
|
+
this.name = accessory.displayName
|
|
16
|
+
this.accessory = accessory
|
|
17
|
+
|
|
18
|
+
// Initially set the online flag as true (to be then updated as false if necessary)
|
|
19
|
+
this.isOnline = true
|
|
20
|
+
|
|
21
|
+
// Set up custom variables for this device type
|
|
22
|
+
const deviceConf = platform.deviceConf[accessory.context.eweDeviceId] || {}
|
|
23
|
+
this.hideSwitch = deviceConf.hideSwitch
|
|
24
|
+
this.tempOffset = deviceConf.offset || platformConsts.defaultValues.offset
|
|
25
|
+
this.tempOffsetFactor = deviceConf.offsetFactor
|
|
26
|
+
this.humiOffset = deviceConf.humidityOffset
|
|
27
|
+
? Number.parseInt(deviceConf.humidityOffset, 10)
|
|
28
|
+
: platformConsts.defaultValues.humidityOffset
|
|
29
|
+
this.humiOffsetFactor = deviceConf.humidityOffsetFactor
|
|
30
|
+
|
|
31
|
+
// Set the correct logging variables for this accessory
|
|
32
|
+
switch (deviceConf.overrideLogging) {
|
|
33
|
+
case 'standard':
|
|
34
|
+
this.enableLogging = true
|
|
35
|
+
this.enableDebugLogging = false
|
|
36
|
+
break
|
|
37
|
+
case 'debug':
|
|
38
|
+
this.enableLogging = true
|
|
39
|
+
this.enableDebugLogging = true
|
|
40
|
+
break
|
|
41
|
+
case 'disable':
|
|
42
|
+
this.enableLogging = false
|
|
43
|
+
this.enableDebugLogging = false
|
|
44
|
+
break
|
|
45
|
+
default:
|
|
46
|
+
this.enableLogging = !platform.config.disableDeviceLogging
|
|
47
|
+
this.enableDebugLogging = platform.config.debug
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// If the accessory has a thermostat service then remove it
|
|
52
|
+
if (this.accessory.getService(this.hapServ.Thermostat)) {
|
|
53
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Thermostat))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If the accessory has a heater service then remove it
|
|
57
|
+
if (this.accessory.getService(this.hapServ.HeaterCooler)) {
|
|
58
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.HeaterCooler))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If the accessory has a humidifier service then remove it
|
|
62
|
+
if (this.accessory.getService(this.hapServ.HumidifierDehumidifier)) {
|
|
63
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.HumidifierDehumidifier))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The user can choose to hide the switch service if they desire
|
|
67
|
+
if (this.hideSwitch) {
|
|
68
|
+
// User has hidden the switch service so remove it if it exists
|
|
69
|
+
if (this.accessory.getService(this.hapServ.Switch)) {
|
|
70
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.Switch))
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
// User has not hidden the switch service so add it if it doesn't already exist
|
|
74
|
+
this.switchService = this.accessory.getService(this.hapServ.Switch)
|
|
75
|
+
|| this.accessory.addService(this.hapServ.Switch)
|
|
76
|
+
|
|
77
|
+
// Add the set handler to the switch on/off characteristic
|
|
78
|
+
this.switchService
|
|
79
|
+
.getCharacteristic(this.hapChar.On)
|
|
80
|
+
.onSet(async value => this.internalStateUpdate(value))
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Add the temperature sensor service if it doesn't already exist
|
|
84
|
+
this.tempService = this.accessory.getService(this.hapServ.TemperatureSensor)
|
|
85
|
+
|| this.accessory.addService(this.hapServ.TemperatureSensor)
|
|
86
|
+
|
|
87
|
+
// Set custom properties of the current temperature characteristic
|
|
88
|
+
this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).setProps({
|
|
89
|
+
minStep: 0.1,
|
|
90
|
+
})
|
|
91
|
+
this.cacheTemp = this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value
|
|
92
|
+
this.updateCache()
|
|
93
|
+
|
|
94
|
+
// The DS18B20 sensor does not provide humidity readings
|
|
95
|
+
if (this.accessory.context.sensorType === 'DS18B20') {
|
|
96
|
+
if (this.accessory.getService(this.hapServ.HumiditySensor)) {
|
|
97
|
+
this.accessory.removeService(this.accessory.getService(this.hapServ.HumiditySensor))
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// Add the humidity sensor service if it doesn't already exist
|
|
101
|
+
this.humiService = this.accessory.getService(this.hapServ.HumiditySensor)
|
|
102
|
+
|| this.accessory.addService(this.hapServ.HumiditySensor)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add the get handlers only if the user hasn't disabled the disableNoResponse setting
|
|
106
|
+
if (!platform.config.disableNoResponse) {
|
|
107
|
+
if (this.switchService) {
|
|
108
|
+
this.switchService.getCharacteristic(this.hapChar.On).onGet(() => {
|
|
109
|
+
if (!this.isOnline) {
|
|
110
|
+
throw new this.hapErr(-70402)
|
|
111
|
+
}
|
|
112
|
+
return this.switchService.getCharacteristic(this.hapChar.On).value
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).onGet(() => {
|
|
116
|
+
if (!this.isOnline) {
|
|
117
|
+
throw new this.hapErr(-70402)
|
|
118
|
+
}
|
|
119
|
+
return this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value
|
|
120
|
+
})
|
|
121
|
+
if (this.humiService) {
|
|
122
|
+
this.humiService.getCharacteristic(this.hapChar.CurrentRelativeHumidity).onGet(() => {
|
|
123
|
+
if (!this.isOnline) {
|
|
124
|
+
throw new this.hapErr(-70402)
|
|
125
|
+
}
|
|
126
|
+
return this.humiService.getCharacteristic(this.hapChar.CurrentRelativeHumidity).value
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// The switch as the primary service ensures the status is reflected in the Home icon
|
|
132
|
+
if (this.switchService) {
|
|
133
|
+
this.switchService.setPrimaryService()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Pass the accessory to Fakegato to set up with Eve
|
|
137
|
+
this.accessory.eveService = new platform.eveService('custom', this.accessory, {
|
|
138
|
+
log: () => {},
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// Set up an interval to get eWeLink to send regular temperature/humidity updates
|
|
142
|
+
if (platform.config.mode !== 'lan') {
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
this.internalUIUpdate()
|
|
145
|
+
this.intervalPoll = setInterval(() => this.internalUIUpdate(), 120000)
|
|
146
|
+
}, 5000)
|
|
147
|
+
|
|
148
|
+
// Stop the intervals on Homebridge shutdown
|
|
149
|
+
platform.api.on('shutdown', () => clearInterval(this.intervalPoll))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Output the customised options to the log
|
|
153
|
+
const normalLogging = this.enableLogging ? 'standard' : 'disable'
|
|
154
|
+
const opts = JSON.stringify({
|
|
155
|
+
hideSwitch: this.hideSwitch,
|
|
156
|
+
humidityOffset: this.humiOffset,
|
|
157
|
+
humidityOffsetFactor: this.humiOffsetFactor,
|
|
158
|
+
logging: this.enableDebugLogging ? 'debug' : normalLogging,
|
|
159
|
+
offset: this.tempOffset,
|
|
160
|
+
offsetFactor: this.tempOffsetFactor,
|
|
161
|
+
showAs: 'default',
|
|
162
|
+
})
|
|
163
|
+
this.log('[%s] %s %s.', this.name, this.lang.devInitOpts, opts)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async internalStateUpdate(value) {
|
|
167
|
+
try {
|
|
168
|
+
const newValue = value ? 'on' : 'off'
|
|
169
|
+
if (newValue === this.cacheState) {
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
const params = {
|
|
173
|
+
switch: newValue,
|
|
174
|
+
mainSwitch: newValue,
|
|
175
|
+
deviceType: 'normal',
|
|
176
|
+
}
|
|
177
|
+
await this.platform.sendDeviceUpdate(this.accessory, params)
|
|
178
|
+
this.cacheState = newValue
|
|
179
|
+
if (this.enableLogging) {
|
|
180
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
181
|
+
}
|
|
182
|
+
} catch (err) {
|
|
183
|
+
this.platform.deviceUpdateError(this.accessory, err, true)
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
this.switchService.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
186
|
+
}, 2000)
|
|
187
|
+
throw new this.hapErr(-70402)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async internalUIUpdate() {
|
|
192
|
+
try {
|
|
193
|
+
// Skip polling if device isn't online
|
|
194
|
+
if (!this.isOnline) {
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Send the params to request the updates
|
|
199
|
+
await this.platform.sendDeviceUpdate(this.accessory, { uiActive: 120 })
|
|
200
|
+
} catch (err) {
|
|
201
|
+
// Suppress errors here
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async externalUpdate(params) {
|
|
206
|
+
try {
|
|
207
|
+
if (!this.hideSwitch && params.switch) {
|
|
208
|
+
const newState = params.switch
|
|
209
|
+
if (this.cacheState !== newState) {
|
|
210
|
+
this.cacheState = newState
|
|
211
|
+
this.switchService.updateCharacteristic(this.hapChar.On, this.cacheState === 'on')
|
|
212
|
+
this.accessory.eveService.addEntry({
|
|
213
|
+
status: this.cacheState === 'on' ? 1 : 0,
|
|
214
|
+
})
|
|
215
|
+
if (params.updateSource && this.enableLogging) {
|
|
216
|
+
this.log('[%s] %s [%s].', this.name, this.lang.curState, this.cacheState)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (
|
|
221
|
+
hasProperty(params, 'currentTemperature')
|
|
222
|
+
&& params.currentTemperature !== 'unavailable'
|
|
223
|
+
) {
|
|
224
|
+
let newTemp = Number(params.currentTemperature)
|
|
225
|
+
if (this.tempOffsetFactor) {
|
|
226
|
+
newTemp *= this.tempOffset
|
|
227
|
+
} else {
|
|
228
|
+
newTemp += this.tempOffset
|
|
229
|
+
}
|
|
230
|
+
if (newTemp !== this.cacheTemp) {
|
|
231
|
+
this.cacheTemp = newTemp
|
|
232
|
+
this.tempService.updateCharacteristic(this.hapChar.CurrentTemperature, this.cacheTemp)
|
|
233
|
+
this.accessory.eveService.addEntry({ temp: this.cacheTemp })
|
|
234
|
+
if (params.updateSource && this.enableLogging) {
|
|
235
|
+
this.log('[%s] %s [%s°C].', this.name, this.lang.curTemp, this.cacheTemp)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Update the cache file with the new temperature
|
|
239
|
+
this.updateCache()
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (
|
|
243
|
+
hasProperty(params, 'currentHumidity')
|
|
244
|
+
&& params.currentHumidity !== 'unavailable'
|
|
245
|
+
&& this.humiService
|
|
246
|
+
) {
|
|
247
|
+
let newHumi = Number.parseInt(params.currentHumidity, 10)
|
|
248
|
+
if (this.humiOffsetFactor) {
|
|
249
|
+
newHumi *= this.humiOffset
|
|
250
|
+
} else {
|
|
251
|
+
newHumi += this.humiOffset
|
|
252
|
+
}
|
|
253
|
+
newHumi = Math.max(Math.min(Number.parseInt(newHumi, 10), 100), 0)
|
|
254
|
+
if (newHumi !== this.cacheHumi) {
|
|
255
|
+
this.cacheHumi = newHumi
|
|
256
|
+
this.humiService.updateCharacteristic(
|
|
257
|
+
this.hapChar.CurrentRelativeHumidity,
|
|
258
|
+
this.cacheHumi,
|
|
259
|
+
)
|
|
260
|
+
this.accessory.eveService.addEntry({ humidity: this.cacheHumi })
|
|
261
|
+
if (params.updateSource && this.enableLogging) {
|
|
262
|
+
this.log('[%s] %s [%s%].', this.name, this.lang.curHumi, this.cacheHumi)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
} catch (err) {
|
|
267
|
+
this.platform.deviceUpdateError(this.accessory, err, false)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async updateCache() {
|
|
272
|
+
// Don't continue if the storage client hasn't initialised properly
|
|
273
|
+
if (!this.platform.storageClientData) {
|
|
274
|
+
return
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Attempt to save the new temperature to the cache
|
|
278
|
+
try {
|
|
279
|
+
await this.platform.storageData.setItem(
|
|
280
|
+
`${this.accessory.context.eweDeviceId}_temp`,
|
|
281
|
+
this.cacheTemp,
|
|
282
|
+
)
|
|
283
|
+
} catch (err) {
|
|
284
|
+
if (this.enableLogging) {
|
|
285
|
+
this.log.warn('[%s] %s %s.', this.name, this.lang.storageWriteErr, parseError(err))
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
currentState() {
|
|
291
|
+
const toReturn = {}
|
|
292
|
+
toReturn.services = ['switch', 'temperature']
|
|
293
|
+
toReturn.switch = {
|
|
294
|
+
state: this.cacheState,
|
|
295
|
+
}
|
|
296
|
+
toReturn.temperature = {
|
|
297
|
+
current: this.tempService.getCharacteristic(this.hapChar.CurrentTemperature).value,
|
|
298
|
+
}
|
|
299
|
+
if (this.humiService) {
|
|
300
|
+
toReturn.services.push('humidity')
|
|
301
|
+
toReturn.humidity = {
|
|
302
|
+
current: this.humiService.getCharacteristic(this.hapChar.CurrentRelativeHumidity).value,
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return toReturn
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
markStatus(isOnline) {
|
|
309
|
+
this.isOnline = isOnline
|
|
310
|
+
}
|
|
311
|
+
}
|