homebridge-flume 0.5.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 +32 -0
- package/README.md +17 -13
- package/config.schema.json +4 -10
- package/lib/connection/http.js +74 -5
- package/lib/device/leak-sensor.js +93 -0
- package/lib/homebridge-ui/public/index.html +11 -0
- package/lib/index.js +20 -25
- package/lib/utils/constants.js +2 -5
- package/lib/utils/custom-chars.js +38 -0
- package/package.json +1 -1
- package/lib/device/valve.js +0 -36
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
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
|
+
|
|
15
|
+
## 1.0.0 (2021-11-29)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Plugin logo
|
|
20
|
+
|
|
21
|
+
## 0.7.0 (2021-11-24)
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `StatusFault` and `StatusLowBattery` characteristics to the `LeakSensor` service
|
|
26
|
+
|
|
27
|
+
## 0.6.0 (2021-11-24)
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Leak sensor service
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Minimum refresh interval increased to two minutes
|
|
36
|
+
|
|
5
37
|
## 0.5.0 (2021-11-23)
|
|
6
38
|
|
|
7
39
|
### Added
|
package/README.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/bwp91/homebridge-flume"><img src="https://user-images.githubusercontent.com/43026681/143831753-ed67cad2-909a-4337-9b18-dd8e65dfdf5e.png" width="600px"></a>
|
|
3
|
+
</p>
|
|
1
4
|
<span align="center">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
5
|
+
|
|
6
|
+
# homebridge-flume
|
|
7
|
+
|
|
8
|
+
Homebridge plugin to integrate Flume devices into HomeKit
|
|
9
|
+
|
|
10
|
+
[](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
|
|
11
|
+
[](https://www.npmjs.com/package/homebridge-flume)
|
|
12
|
+
[](https://github.com/bwp91/homebridge-flume/wiki/Beta-Version)
|
|
13
|
+
[](https://www.npmjs.com/package/homebridge-flume)
|
|
14
|
+
[](https://standardjs.com)
|
|
15
|
+
[](https://discord.com/channels/784827113378676736/784827113378676739)
|
|
16
|
+
[](https://discord.com/channels/432663330281226270/742733745743855627)
|
|
17
|
+
|
|
15
18
|
</span>
|
|
16
19
|
|
|
17
20
|
### Plugin Information
|
|
@@ -41,6 +44,7 @@
|
|
|
41
44
|
### Credits
|
|
42
45
|
|
|
43
46
|
- This is a forked rewrite of the [homebridge-flume-water-sensor](https://www.npmjs.com/package/homebridge-flume-water-sensor) plugin by @weallknowwhoisatfaulthere.
|
|
47
|
+
- To the creator of the awesome plugin header logo: [Keryan Belahcene](https://www.instagram.com/keryan.me).
|
|
44
48
|
- To the creators/contributors of [Homebridge](https://homebridge.io) who make this plugin possible.
|
|
45
49
|
|
|
46
50
|
### Disclaimer
|
package/config.schema.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"singular": true,
|
|
5
5
|
"customUi": true,
|
|
6
6
|
"customUiPath": "./lib/homebridge-ui",
|
|
7
|
-
"headerDisplay": "<p align=\"center\">For help and support please visit our <a href=\"https://github.com/bwp91/homebridge-
|
|
7
|
+
"headerDisplay": "<p align=\"center\"><img width=\"60%\" src=\"https://user-images.githubusercontent.com/43026681/143831753-ed67cad2-909a-4337-9b18-dd8e65dfdf5e.png\"></p><p align=\"center\">For help and support please visit our <a href=\"https://github.com/bwp91/homebridge-thermobit/wiki\">GitHub Wiki</a>. We hope you find this plugin useful!</p>",
|
|
8
8
|
"schema": {
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
@@ -42,14 +42,8 @@
|
|
|
42
42
|
"refreshInterval": {
|
|
43
43
|
"title": "Refresh Interval",
|
|
44
44
|
"type": "integer",
|
|
45
|
-
"placeholder":
|
|
46
|
-
"description": "Number of minutes between updates. Must be
|
|
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."
|
|
45
|
+
"placeholder": 2,
|
|
46
|
+
"description": "Number of minutes between updates. Must be 2 or more."
|
|
53
47
|
},
|
|
54
48
|
"disableDeviceLogging": {
|
|
55
49
|
"type": "boolean",
|
|
@@ -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
|
@@ -202,19 +202,58 @@ module.exports = class connectionHTTP {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
async getDeviceInfo (deviceId
|
|
205
|
+
async getDeviceInfo (deviceId) {
|
|
206
206
|
// Refresh the access token if it has expired already
|
|
207
207
|
if (Date.now() > this.expiresIn) {
|
|
208
208
|
await this.renewToken()
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
// Send the request
|
|
212
|
+
const res = await axios.get(
|
|
213
|
+
'https://api.flumetech.com/users/' + this.userId + '/devices/' + deviceId,
|
|
214
|
+
{
|
|
215
|
+
headers: {
|
|
216
|
+
Authorization: 'Bearer ' + this.accessToken
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
// Check to see we got a response
|
|
222
|
+
if (!res.data) {
|
|
223
|
+
throw new Error(this.lang.noDataReceived)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Log the response if in debug mode
|
|
227
|
+
if (this.debug) {
|
|
228
|
+
this.log('[HTTP getDeviceInfo()] %s.', JSON.stringify(res.data))
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Parse the response
|
|
232
|
+
return res.data.data[0]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async getWaterInfo (deviceId, fromWhen) {
|
|
236
|
+
// Refresh the access token if it has expired already
|
|
237
|
+
if (Date.now() > this.expiresIn) {
|
|
238
|
+
await this.renewToken()
|
|
239
|
+
}
|
|
240
|
+
const today = new Date().toISOString().substring(0, 10) + ' 00:00:00'
|
|
241
|
+
const month = today.substring(0, 8) + '01' + today.substring(10)
|
|
242
|
+
|
|
211
243
|
// Generate the JSON data to send
|
|
212
244
|
const body = {
|
|
213
245
|
queries: [
|
|
214
246
|
{
|
|
215
|
-
request_id: '
|
|
216
|
-
bucket: '
|
|
217
|
-
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,
|
|
218
257
|
operation: 'SUM',
|
|
219
258
|
units: 'GALLONS'
|
|
220
259
|
}
|
|
@@ -239,7 +278,37 @@ module.exports = class connectionHTTP {
|
|
|
239
278
|
|
|
240
279
|
// Log the response if in debug mode
|
|
241
280
|
if (this.debug) {
|
|
242
|
-
this.log('[HTTP
|
|
281
|
+
this.log('[HTTP getWaterInfo()] %s.', JSON.stringify(res.data))
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Parse the response
|
|
285
|
+
return res.data.data[0]
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async getLeakInfo (deviceId) {
|
|
289
|
+
// Refresh the access token if it has expired already
|
|
290
|
+
if (Date.now() > this.expiresIn) {
|
|
291
|
+
await this.renewToken()
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Send the request
|
|
295
|
+
const res = await axios.get(
|
|
296
|
+
'https://api.flumetech.com/users/' + this.userId + '/devices/' + deviceId + '/leaks/active',
|
|
297
|
+
{
|
|
298
|
+
headers: {
|
|
299
|
+
Authorization: 'Bearer ' + this.accessToken
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
// Check to see we got a response
|
|
305
|
+
if (!res.data) {
|
|
306
|
+
throw new Error(this.lang.noDataReceived)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Log the response if in debug mode
|
|
310
|
+
if (this.debug) {
|
|
311
|
+
this.log('[HTTP getLeakInfo()] %s.', JSON.stringify(res.data))
|
|
243
312
|
}
|
|
244
313
|
|
|
245
314
|
// Parse the response
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* jshint node: true, esversion: 10, -W014, -W033 */
|
|
2
|
+
/* eslint-disable new-cap */
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
module.exports = class deviceLeakSensor {
|
|
6
|
+
constructor (platform, accessory) {
|
|
7
|
+
// Set up variables from the platform
|
|
8
|
+
this.accessory = accessory
|
|
9
|
+
this.cusChar = platform.cusChar
|
|
10
|
+
this.funcs = platform.funcs
|
|
11
|
+
this.hapChar = platform.api.hap.Characteristic
|
|
12
|
+
this.hapErr = platform.api.hap.HapStatusError
|
|
13
|
+
this.hapServ = platform.api.hap.Service
|
|
14
|
+
this.lang = platform.lang
|
|
15
|
+
this.log = platform.config.disableDeviceLogging ? () => {} : platform.log
|
|
16
|
+
this.name = accessory.displayName
|
|
17
|
+
this.platform = platform
|
|
18
|
+
this.refreshInterval = platform.config.refreshInterval
|
|
19
|
+
|
|
20
|
+
// Add the leak sensor service if it doesn't exist already
|
|
21
|
+
this.leakService =
|
|
22
|
+
this.accessory.getService(this.hapServ.LeakSensor) ||
|
|
23
|
+
this.accessory.addService(this.hapServ.LeakSensor)
|
|
24
|
+
|
|
25
|
+
this.cacheLeak = !!this.leakService.getCharacteristic(this.hapChar.LeakDetected).value
|
|
26
|
+
this.cacheBatt = !this.leakService.getCharacteristic(this.hapChar.StatusLowBattery).value
|
|
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
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
externalUpdate (params) {
|
|
39
|
+
// Check the data for leak detection
|
|
40
|
+
if (
|
|
41
|
+
this.funcs.hasProperty(params.leakInfo, 'active') &&
|
|
42
|
+
params.leakInfo.active !== this.cacheLeak
|
|
43
|
+
) {
|
|
44
|
+
this.cacheLeak = params.leakInfo.active
|
|
45
|
+
this.leakService.updateCharacteristic(this.hapChar.LeakDetected, this.cacheLeak ? 1 : 0)
|
|
46
|
+
this.log('[%s] current leak status [%sdetected].', this.name, this.cacheLeak ? '' : 'not ')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check the data for battery level, cacheBatt is true for OK and false for LOW
|
|
50
|
+
if (
|
|
51
|
+
this.funcs.hasProperty(params.devInfo, 'battery_level') &&
|
|
52
|
+
(params.devInfo.battery_level !== 'low') !== this.cacheBatt
|
|
53
|
+
) {
|
|
54
|
+
this.cacheBatt = params.devInfo.battery_level !== 'low'
|
|
55
|
+
this.leakService.updateCharacteristic(this.hapChar.StatusLowBattery, this.cacheBatt ? 0 : 1)
|
|
56
|
+
this.log('[%s] current battery [%s].', this.name, this.cacheBatt ? 'ok' : 'low')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check the data for connectivity, cacheStatus is true for OK and false for NOT CONNECTED
|
|
60
|
+
if (
|
|
61
|
+
this.funcs.hasProperty(params.devInfo, 'connected') &&
|
|
62
|
+
params.devInfo.connected !== this.cacheStatus
|
|
63
|
+
) {
|
|
64
|
+
this.cacheStatus = params.devInfo.connected
|
|
65
|
+
this.leakService.updateCharacteristic(this.hapChar.StatusFault, this.cacheStatus ? 0 : 1)
|
|
66
|
+
this.log('[%s] current status [%sconnected].', this.name, this.cacheStatus ? '' : 'not ')
|
|
67
|
+
}
|
|
68
|
+
|
|
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
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
<p class="text-center">
|
|
2
|
+
<img
|
|
3
|
+
src="https://user-images.githubusercontent.com/43026681/143831753-ed67cad2-909a-4337-9b18-dd8e65dfdf5e.png"
|
|
4
|
+
alt="homebridge-flume logo"
|
|
5
|
+
style="width: 60%;"
|
|
6
|
+
/>
|
|
7
|
+
</p>
|
|
1
8
|
<div id="pageIntro" class="text-center" style="display: none;">
|
|
2
9
|
<p class="lead">Thank you for installing <strong>homebridge-flume</strong></p>
|
|
3
10
|
<p>
|
|
@@ -83,6 +90,10 @@
|
|
|
83
90
|
>
|
|
84
91
|
plugin by @weallknowwhoisatfaulthere
|
|
85
92
|
</li>
|
|
93
|
+
<li>
|
|
94
|
+
To the creator of the awesome plugin header logo:
|
|
95
|
+
<a href="https://www.instagram.com/keryan.me" target="_blank">Keryan Belahcene</a>.
|
|
96
|
+
</li>
|
|
86
97
|
<li>
|
|
87
98
|
To the creators/contributors of
|
|
88
99
|
<a href="https://homebridge.io" target="_blank">Homebridge</a> who make this plugin possible.
|
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,22 +222,28 @@ 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
|
|
243
|
-
|
|
244
|
-
|
|
231
|
+
const toReturn = {}
|
|
232
|
+
const devInfo = await this.httpClient.getDeviceInfo(accessory.context.deviceId)
|
|
233
|
+
toReturn.devInfo = devInfo
|
|
234
|
+
if (this.counter === 0) {
|
|
235
|
+
const waterInfo = await this.httpClient.getWaterInfo(accessory.context.deviceId)
|
|
236
|
+
toReturn.waterInfo = waterInfo
|
|
237
|
+
}
|
|
238
|
+
const leakInfo = await this.httpClient.getLeakInfo(accessory.context.deviceId)
|
|
239
|
+
toReturn.leakInfo = leakInfo
|
|
240
|
+
accessory.control.externalUpdate(toReturn)
|
|
245
241
|
} catch (err) {
|
|
246
242
|
const eText = this.funcs.parseError(err)
|
|
247
243
|
this.log.warn('[%s] %s %s.', accessory.displayName, this.lang.devNotRef, eText)
|
|
248
244
|
}
|
|
245
|
+
this.counter++
|
|
249
246
|
})
|
|
250
|
-
|
|
251
|
-
this.lastSync = new Date()
|
|
252
247
|
} catch (err) {
|
|
253
248
|
// Catch any errors performing the sync
|
|
254
249
|
const eText = this.funcs.parseError(err, [])
|
|
@@ -284,7 +279,7 @@ class FlumePlatform {
|
|
|
284
279
|
}
|
|
285
280
|
|
|
286
281
|
// Create the instance for this device type
|
|
287
|
-
accessory.control = new (require('./device/
|
|
282
|
+
accessory.control = new (require('./device/leak-sensor'))(this, accessory)
|
|
288
283
|
|
|
289
284
|
// Log the device initialisation
|
|
290
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:
|
|
22
|
-
threshold: 0
|
|
20
|
+
refreshInterval: 2
|
|
23
21
|
},
|
|
24
22
|
|
|
25
23
|
minValues: {
|
|
26
|
-
refreshInterval:
|
|
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
|
+
}
|
package/package.json
CHANGED
package/lib/device/valve.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/* jshint node: true, esversion: 10, -W014, -W033 */
|
|
2
|
-
/* eslint-disable new-cap */
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
|
-
module.exports = class deviceValve {
|
|
6
|
-
constructor (platform, accessory) {
|
|
7
|
-
// Set up variables from the platform
|
|
8
|
-
this.accessory = accessory
|
|
9
|
-
this.funcs = platform.funcs
|
|
10
|
-
this.threshold = platform.config.threshold
|
|
11
|
-
this.hapChar = platform.api.hap.Characteristic
|
|
12
|
-
this.hapErr = platform.api.hap.HapStatusError
|
|
13
|
-
this.hapServ = platform.api.hap.Service
|
|
14
|
-
this.lang = platform.lang
|
|
15
|
-
this.log = platform.config.disableDeviceLogging ? () => {} : platform.log
|
|
16
|
-
this.name = accessory.displayName
|
|
17
|
-
this.platform = platform
|
|
18
|
-
this.refreshInterval = platform.config.refreshInterval
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
externalUpdate (params) {
|
|
22
|
-
// Here we deal with the incoming data
|
|
23
|
-
const usage =
|
|
24
|
-
params.currentusage && params.currentusage[0] && params.currentusage[0].value
|
|
25
|
-
? params.currentusage[0].value
|
|
26
|
-
: 0
|
|
27
|
-
if (usage > this.threshold) {
|
|
28
|
-
this.log(
|
|
29
|
-
'[%s] usage detected - [%s] gallons within the last [%s] minutes.',
|
|
30
|
-
this.name,
|
|
31
|
-
usage,
|
|
32
|
-
this.refreshInterval
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|