homebridge-flume 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/config.schema.json +1 -7
- package/lib/connection/http.js +12 -3
- package/lib/device/{valve.js → leak-sensor.js} +32 -15
- package/lib/index.js +15 -25
- package/lib/utils/constants.js +2 -5
- package/lib/utils/custom-chars.js +38 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to homebridge-flume will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 1.1.0 (2021-11-30)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Daily and monthly usage custom characteristics (viewable in HomeKit apps like Eve)
|
|
10
|
+
|
|
11
|
+
### Removed
|
|
12
|
+
|
|
13
|
+
- `threshold` configuration option as unused
|
|
14
|
+
|
|
5
15
|
## 1.0.0 (2021-11-29)
|
|
6
16
|
|
|
7
17
|
### Added
|
package/config.schema.json
CHANGED
|
@@ -45,12 +45,6 @@
|
|
|
45
45
|
"placeholder": 2,
|
|
46
46
|
"description": "Number of minutes between updates. Must be 2 or more."
|
|
47
47
|
},
|
|
48
|
-
"threshold": {
|
|
49
|
-
"title": "Threshold",
|
|
50
|
-
"type": "number",
|
|
51
|
-
"placeholder": 0,
|
|
52
|
-
"description": "Ignore a steady water draw below this value in gallons per refresh interval. Must be 0 or more."
|
|
53
|
-
},
|
|
54
48
|
"disableDeviceLogging": {
|
|
55
49
|
"type": "boolean",
|
|
56
50
|
"title": "Disable Device Logging",
|
|
@@ -79,7 +73,7 @@
|
|
|
79
73
|
"title": "Optional Settings",
|
|
80
74
|
"description": "Optional settings for the plugin, including global logging settings.",
|
|
81
75
|
"expandable": true,
|
|
82
|
-
"items": ["refreshInterval", "
|
|
76
|
+
"items": ["refreshInterval", "disableDeviceLogging", "debug", "disablePlugin"]
|
|
83
77
|
}
|
|
84
78
|
]
|
|
85
79
|
}
|
package/lib/connection/http.js
CHANGED
|
@@ -237,14 +237,23 @@ module.exports = class connectionHTTP {
|
|
|
237
237
|
if (Date.now() > this.expiresIn) {
|
|
238
238
|
await this.renewToken()
|
|
239
239
|
}
|
|
240
|
+
const today = new Date().toISOString().substring(0, 10) + ' 00:00:00'
|
|
241
|
+
const month = today.substring(0, 8) + '01' + today.substring(10)
|
|
240
242
|
|
|
241
243
|
// Generate the JSON data to send
|
|
242
244
|
const body = {
|
|
243
245
|
queries: [
|
|
244
246
|
{
|
|
245
|
-
request_id: '
|
|
246
|
-
bucket: '
|
|
247
|
-
since_datetime:
|
|
247
|
+
request_id: 'today',
|
|
248
|
+
bucket: 'DAY',
|
|
249
|
+
since_datetime: today,
|
|
250
|
+
operation: 'SUM',
|
|
251
|
+
units: 'GALLONS'
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
request_id: 'month',
|
|
255
|
+
bucket: 'MON',
|
|
256
|
+
since_datetime: month,
|
|
248
257
|
operation: 'SUM',
|
|
249
258
|
units: 'GALLONS'
|
|
250
259
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
/* eslint-disable new-cap */
|
|
3
3
|
'use strict'
|
|
4
4
|
|
|
5
|
-
module.exports = class
|
|
5
|
+
module.exports = class deviceLeakSensor {
|
|
6
6
|
constructor (platform, accessory) {
|
|
7
7
|
// Set up variables from the platform
|
|
8
8
|
this.accessory = accessory
|
|
9
|
+
this.cusChar = platform.cusChar
|
|
9
10
|
this.funcs = platform.funcs
|
|
10
|
-
this.threshold = platform.config.threshold
|
|
11
11
|
this.hapChar = platform.api.hap.Characteristic
|
|
12
12
|
this.hapErr = platform.api.hap.HapStatusError
|
|
13
13
|
this.hapServ = platform.api.hap.Service
|
|
@@ -25,6 +25,14 @@ module.exports = class deviceValve {
|
|
|
25
25
|
this.cacheLeak = !!this.leakService.getCharacteristic(this.hapChar.LeakDetected).value
|
|
26
26
|
this.cacheBatt = !this.leakService.getCharacteristic(this.hapChar.StatusLowBattery).value
|
|
27
27
|
this.cacheStatus = !this.leakService.getCharacteristic(this.hapChar.StatusFault).value
|
|
28
|
+
|
|
29
|
+
// Add the custom characteristics if they haven't been already
|
|
30
|
+
if (!this.leakService.testCharacteristic(this.cusChar.TodayUsage)) {
|
|
31
|
+
this.leakService.addCharacteristic(this.cusChar.TodayUsage)
|
|
32
|
+
}
|
|
33
|
+
if (!this.leakService.testCharacteristic(this.cusChar.MonthUsage)) {
|
|
34
|
+
this.leakService.addCharacteristic(this.cusChar.MonthUsage)
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
externalUpdate (params) {
|
|
@@ -58,19 +66,28 @@ module.exports = class deviceValve {
|
|
|
58
66
|
this.log('[%s] current status [%sconnected].', this.name, this.cacheStatus ? '' : 'not ')
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
// Water info
|
|
70
|
+
if (params.waterInfo) {
|
|
71
|
+
if (
|
|
72
|
+
params.waterInfo.today &&
|
|
73
|
+
params.waterInfo.today[0] &&
|
|
74
|
+
this.funcs.hasProperty(params.waterInfo.today[0], 'value')
|
|
75
|
+
) {
|
|
76
|
+
this.leakService.updateCharacteristic(
|
|
77
|
+
this.cusChar.TodayUsage,
|
|
78
|
+
params.waterInfo.today[0].value
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
if (
|
|
82
|
+
params.waterInfo.month &&
|
|
83
|
+
params.waterInfo.month[0] &&
|
|
84
|
+
this.funcs.hasProperty(params.waterInfo.month[0], 'value')
|
|
85
|
+
) {
|
|
86
|
+
this.leakService.updateCharacteristic(
|
|
87
|
+
this.cusChar.MonthUsage,
|
|
88
|
+
params.waterInfo.month[0].value
|
|
89
|
+
)
|
|
90
|
+
}
|
|
74
91
|
}
|
|
75
92
|
}
|
|
76
93
|
}
|
package/lib/index.js
CHANGED
|
@@ -106,18 +106,6 @@ class FlumePlatform {
|
|
|
106
106
|
}
|
|
107
107
|
this.config[key] = val === 'false' ? false : !!val
|
|
108
108
|
break
|
|
109
|
-
case 'threshold': {
|
|
110
|
-
if (typeof v === 'string') {
|
|
111
|
-
logQuotes(key)
|
|
112
|
-
}
|
|
113
|
-
const numVal = Number(val)
|
|
114
|
-
if (isNaN(numVal)) {
|
|
115
|
-
logIgnore(key)
|
|
116
|
-
} else {
|
|
117
|
-
this.config[key] = numVal
|
|
118
|
-
}
|
|
119
|
-
break
|
|
120
|
-
}
|
|
121
109
|
case 'name':
|
|
122
110
|
case 'platform':
|
|
123
111
|
case 'plugin_map':
|
|
@@ -167,6 +155,9 @@ class FlumePlatform {
|
|
|
167
155
|
throw new Error(this.lang.noCreds)
|
|
168
156
|
}
|
|
169
157
|
|
|
158
|
+
// Require any libraries that the accessory instances use
|
|
159
|
+
this.cusChar = new (require('./utils/custom-chars'))(this.api)
|
|
160
|
+
|
|
170
161
|
// Setup the HTTP client if Thermobit username and password have been provided
|
|
171
162
|
this.httpClient = new (require('./connection/http'))(this)
|
|
172
163
|
await this.httpClient.obtainToken()
|
|
@@ -193,10 +184,8 @@ class FlumePlatform {
|
|
|
193
184
|
}
|
|
194
185
|
})
|
|
195
186
|
|
|
196
|
-
// Set up an initial last sync time
|
|
197
|
-
this.lastSync = new Date(Date.now() - this.config.refreshInterval * 60000)
|
|
198
|
-
|
|
199
187
|
// Perform a first sync and setup the refresh interval
|
|
188
|
+
this.counter = 0
|
|
200
189
|
this.flumeSync()
|
|
201
190
|
this.refreshInterval = setInterval(
|
|
202
191
|
() => this.flumeSync(),
|
|
@@ -233,17 +222,19 @@ class FlumePlatform {
|
|
|
233
222
|
|
|
234
223
|
async flumeSync () {
|
|
235
224
|
try {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
.
|
|
239
|
-
|
|
225
|
+
// Reset the counter for water info once we reach 10
|
|
226
|
+
if (this.counter === 10) {
|
|
227
|
+
this.counter = 0
|
|
228
|
+
}
|
|
240
229
|
this.devicesInHB.forEach(async accessory => {
|
|
241
230
|
try {
|
|
242
|
-
const toReturn = {
|
|
231
|
+
const toReturn = {}
|
|
243
232
|
const devInfo = await this.httpClient.getDeviceInfo(accessory.context.deviceId)
|
|
244
233
|
toReturn.devInfo = devInfo
|
|
245
|
-
|
|
246
|
-
|
|
234
|
+
if (this.counter === 0) {
|
|
235
|
+
const waterInfo = await this.httpClient.getWaterInfo(accessory.context.deviceId)
|
|
236
|
+
toReturn.waterInfo = waterInfo
|
|
237
|
+
}
|
|
247
238
|
const leakInfo = await this.httpClient.getLeakInfo(accessory.context.deviceId)
|
|
248
239
|
toReturn.leakInfo = leakInfo
|
|
249
240
|
accessory.control.externalUpdate(toReturn)
|
|
@@ -251,9 +242,8 @@ class FlumePlatform {
|
|
|
251
242
|
const eText = this.funcs.parseError(err)
|
|
252
243
|
this.log.warn('[%s] %s %s.', accessory.displayName, this.lang.devNotRef, eText)
|
|
253
244
|
}
|
|
245
|
+
this.counter++
|
|
254
246
|
})
|
|
255
|
-
|
|
256
|
-
this.lastSync = new Date()
|
|
257
247
|
} catch (err) {
|
|
258
248
|
// Catch any errors performing the sync
|
|
259
249
|
const eText = this.funcs.parseError(err, [])
|
|
@@ -289,7 +279,7 @@ class FlumePlatform {
|
|
|
289
279
|
}
|
|
290
280
|
|
|
291
281
|
// Create the instance for this device type
|
|
292
|
-
accessory.control = new (require('./device/
|
|
282
|
+
accessory.control = new (require('./device/leak-sensor'))(this, accessory)
|
|
293
283
|
|
|
294
284
|
// Log the device initialisation
|
|
295
285
|
this.log('[%s] %s [%s].', accessory.displayName, this.lang.devInit, device.id)
|
package/lib/utils/constants.js
CHANGED
|
@@ -10,7 +10,6 @@ module.exports = {
|
|
|
10
10
|
clientId: '',
|
|
11
11
|
clientSecret: '',
|
|
12
12
|
refreshInterval: 1,
|
|
13
|
-
threshold: 0,
|
|
14
13
|
disableDeviceLogging: false,
|
|
15
14
|
debug: false,
|
|
16
15
|
disablePlugin: false,
|
|
@@ -18,13 +17,11 @@ module.exports = {
|
|
|
18
17
|
},
|
|
19
18
|
|
|
20
19
|
defaultValues: {
|
|
21
|
-
refreshInterval: 2
|
|
22
|
-
threshold: 0
|
|
20
|
+
refreshInterval: 2
|
|
23
21
|
},
|
|
24
22
|
|
|
25
23
|
minValues: {
|
|
26
|
-
refreshInterval: 2
|
|
27
|
-
threshold: 0
|
|
24
|
+
refreshInterval: 2
|
|
28
25
|
},
|
|
29
26
|
|
|
30
27
|
httpRetryCodes: ['ENOTFOUND', 'ETIMEDOUT', 'EAI_AGAIN', 'ECONNABORTED']
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* jshint node: true, esversion: 10, -W014, -W033 */
|
|
2
|
+
/* eslint-disable new-cap */
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
module.exports = class customCharacteristics {
|
|
6
|
+
constructor (api) {
|
|
7
|
+
this.hapServ = api.hap.Service
|
|
8
|
+
this.hapChar = api.hap.Characteristic
|
|
9
|
+
this.uuids = {
|
|
10
|
+
todayUsage: 'E966F001-079E-48FF-8F27-9C2605A29F52',
|
|
11
|
+
monthUsage: 'E966F002-079E-48FF-8F27-9C2605A29F52'
|
|
12
|
+
}
|
|
13
|
+
const self = this
|
|
14
|
+
this.TodayUsage = function () {
|
|
15
|
+
self.hapChar.call(this, 'Today Usage', self.uuids.todayUsage)
|
|
16
|
+
this.setProps({
|
|
17
|
+
format: self.hapChar.Formats.UINT32,
|
|
18
|
+
perms: [self.hapChar.Perms.READ, self.hapChar.Perms.NOTIFY],
|
|
19
|
+
unit: 'Gallons'
|
|
20
|
+
})
|
|
21
|
+
this.value = this.getDefaultValue()
|
|
22
|
+
}
|
|
23
|
+
this.MonthUsage = function () {
|
|
24
|
+
self.hapChar.call(this, 'Month Usage', self.uuids.monthUsage)
|
|
25
|
+
this.setProps({
|
|
26
|
+
format: self.hapChar.Formats.UINT32,
|
|
27
|
+
perms: [self.hapChar.Perms.READ, self.hapChar.Perms.NOTIFY],
|
|
28
|
+
unit: 'Gallons'
|
|
29
|
+
})
|
|
30
|
+
this.value = this.getDefaultValue()
|
|
31
|
+
}
|
|
32
|
+
const inherits = require('util').inherits
|
|
33
|
+
inherits(this.TodayUsage, this.hapChar)
|
|
34
|
+
inherits(this.MonthUsage, this.hapChar)
|
|
35
|
+
this.TodayUsage.UUID = this.uuids.todayUsage
|
|
36
|
+
this.MonthUsage.UUID = this.uuids.monthUsage
|
|
37
|
+
}
|
|
38
|
+
}
|