homebridge-flume 0.3.1 → 0.7.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,6 +2,38 @@
2
2
 
3
3
  All notable changes to homebridge-flume will be documented in this file.
4
4
 
5
+ ## 0.7.0 (2021-11-24)
6
+
7
+ ### Added
8
+
9
+ - `StatusFault` and `StatusLowBattery` characteristics to the `LeakSensor` service
10
+
11
+ ## 0.6.0 (2021-11-24)
12
+
13
+ ### Added
14
+
15
+ - Leak sensor service
16
+
17
+ ### Changed
18
+
19
+ - Minimum refresh interval increased to two minutes
20
+
21
+ ## 0.5.0 (2021-11-23)
22
+
23
+ ### Added
24
+
25
+ - Make use of the debug logging option for HTTP responses
26
+
27
+ ### Changed
28
+
29
+ - `client_id` and `client_secret` config options changed to `clientId` and `clientSecret` for consistency
30
+
31
+ ## 0.4.0 (2021-11-23)
32
+
33
+ ### Added
34
+
35
+ - The plugin will remove 'stale' accessories that don't appear in the obtained device list
36
+
5
37
  ## 0.3.1 (2021-11-23)
6
38
 
7
39
  ### Fixed
@@ -18,4 +50,4 @@ Converted from accessory plugin to platform plugin
18
50
 
19
51
  ## 0.1.0 (2021-11-22)
20
52
 
21
- Initial release
53
+ Initial release
package/README.md CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  ### Credits
42
42
 
43
- - This is a forked rewrite of the [homebridge-flume-water-sensor](https://www.npmjs.com/package/homebridge-flume-water-sensor) plugin by @weallknowwhoisatfaulthere
43
+ - This is a forked rewrite of the [homebridge-flume-water-sensor](https://www.npmjs.com/package/homebridge-flume-water-sensor) plugin by @weallknowwhoisatfaulthere.
44
44
  - To the creators/contributors of [Homebridge](https://homebridge.io) who make this plugin possible.
45
45
 
46
46
  ### Disclaimer
@@ -17,75 +17,69 @@
17
17
  "title": "Username",
18
18
  "type": "string",
19
19
  "required": true,
20
- "description": "Your username for accessing the Flume site at https://portal.flumetech.com"
20
+ "description": "Your Flume username."
21
21
  },
22
22
  "password": {
23
23
  "title": "Password",
24
24
  "type": "string",
25
25
  "required": true,
26
- "description": "Your password for accessing the Flume site"
26
+ "description": "Your Flume password."
27
27
  },
28
- "client_id": {
28
+ "clientId": {
29
29
  "title": "Client ID",
30
30
  "type": "string",
31
- "placeholder": "12345678901234567890",
31
+ "placeholder": "1234567890ABCD",
32
32
  "required": true,
33
- "description": "Your Client ID for API access, found in Settings on the Flume site"
33
+ "description": "Your Flume Client ID, found at https://portal.flumetech.com."
34
34
  },
35
- "client_secret": {
35
+ "clientSecret": {
36
36
  "title": "Client Secret",
37
37
  "type": "string",
38
- "placeholder": "1234567890",
38
+ "placeholder": "1234567890ABCDEFGHIJ",
39
39
  "required": true,
40
- "description": "Your Client Secret for API access, found in Settings on the Flume site"
40
+ "description": "Your Flume Client Secret, found at https://portal.flumetech.com."
41
41
  },
42
42
  "refreshInterval": {
43
- "title": "Refresh interval",
43
+ "title": "Refresh Interval",
44
44
  "type": "integer",
45
- "placeholder": 1,
46
- "description": "Number of minutes between updates. API has a cap of 120 calls per hour."
45
+ "placeholder": 2,
46
+ "description": "Number of minutes between updates. Must be 2 or more."
47
47
  },
48
48
  "threshold": {
49
- "title": "Adjustment for False Positives",
49
+ "title": "Threshold",
50
50
  "type": "number",
51
51
  "placeholder": 0,
52
- "description": "Set to ignore a steady water draw below this value (gallons)."
52
+ "description": "Ignore a steady water draw below this value in gallons per refresh interval. Must be 0 or more."
53
53
  },
54
54
  "disableDeviceLogging": {
55
- "type": "boolean",
56
- "title": "Disable Device Logging",
57
- "description": "Global logging setting for accessory status changes. If true then accessory status changes will not be logged."
58
- },
59
- "debug": {
60
- "title": "Debug Logging",
61
- "type": "boolean",
62
- "description": "Global logging setting for the plugin. If true then debug information will be added to the log."
63
- },
64
- "disablePlugin": {
65
- "title": "Disable Plugin",
66
- "type": "boolean",
67
- "description": "If true, the plugin will remove all accessories and not load the plugin on restart."
68
- }
55
+ "type": "boolean",
56
+ "title": "Disable Device Logging",
57
+ "description": "Global logging setting for accessory status changes. If true then accessory status changes will not be logged."
58
+ },
59
+ "debug": {
60
+ "title": "Debug Logging",
61
+ "type": "boolean",
62
+ "description": "Global logging setting for the plugin. If true then debug information will be added to the log."
63
+ },
64
+ "disablePlugin": {
65
+ "title": "Disable Plugin",
66
+ "type": "boolean",
67
+ "description": "If true, the plugin will remove all accessories and not load the plugin on restart."
68
+ }
69
69
  }
70
70
  },
71
71
  "layout": [
72
72
  {
73
73
  "type": "fieldset",
74
74
  "title": "Required Settings",
75
- "items": ["username", "password", "client_id", "client_secret"]
75
+ "items": ["username", "password", "clientId", "clientSecret"]
76
76
  },
77
77
  {
78
78
  "type": "fieldset",
79
79
  "title": "Optional Settings",
80
80
  "description": "Optional settings for the plugin, including global logging settings.",
81
81
  "expandable": true,
82
- "items": [
83
- "refreshInterval",
84
- "threshold",
85
- "disableDeviceLogging",
86
- "debug",
87
- "disablePlugin"
88
- ]
82
+ "items": ["refreshInterval", "threshold", "disableDeviceLogging", "debug", "disablePlugin"]
89
83
  }
90
84
  ]
91
85
  }
@@ -15,8 +15,8 @@ module.exports = class connectionHTTP {
15
15
  this.log = platform.log
16
16
  this.username = platform.config.username
17
17
  this.password = platform.config.password
18
- this.client_id = platform.config.client_id
19
- this.client_secret = platform.config.client_secret
18
+ this.clientId = platform.config.clientId
19
+ this.clientSecret = platform.config.clientSecret
20
20
  }
21
21
 
22
22
  async obtainToken () {
@@ -24,8 +24,8 @@ module.exports = class connectionHTTP {
24
24
  // Generate the JSON data to send
25
25
  const body = {
26
26
  grant_type: 'password',
27
- client_id: this.client_id,
28
- client_secret: this.client_secret,
27
+ client_id: this.clientId,
28
+ client_secret: this.clientSecret,
29
29
  username: this.username,
30
30
  password: this.password
31
31
  }
@@ -38,7 +38,7 @@ module.exports = class connectionHTTP {
38
38
 
39
39
  // Check to see we got a response
40
40
  if (!res.data) {
41
- throw new Error(this.lang.noToken)
41
+ throw new Error(this.lang.noDataReceived)
42
42
  }
43
43
 
44
44
  /*
@@ -62,6 +62,11 @@ module.exports = class connectionHTTP {
62
62
  }
63
63
  */
64
64
 
65
+ // Log the response if in debug mode
66
+ if (this.debug) {
67
+ this.log('[HTTP obtainToken()] %s.', JSON.stringify(res.data))
68
+ }
69
+
65
70
  // Make the token available in other functions
66
71
  this.accessToken = res.data.data[0].access_token
67
72
  this.refreshToken = res.data.data[0].refresh_token
@@ -84,7 +89,7 @@ module.exports = class connectionHTTP {
84
89
  } catch (err) {
85
90
  if (err.code && this.consts.httpRetryCodes.includes(err.code)) {
86
91
  // Retry if another attempt could be successful
87
- this.log.warn('[HTTP login()] %s [%s].', this.lang.httpRetry, err.code)
92
+ this.log.warn('[HTTP obtainToken()] %s [%s].', this.lang.httpRetry, err.code)
88
93
  await this.funcs.sleep(30000)
89
94
  return await this.login()
90
95
  } else {
@@ -95,11 +100,16 @@ module.exports = class connectionHTTP {
95
100
 
96
101
  async renewToken () {
97
102
  try {
103
+ // Check we have a refresh token
104
+ if (!this.refreshToken) {
105
+ throw new Error(this.lang.noRefreshToken)
106
+ }
107
+
98
108
  // Generate the JSON data to send
99
109
  const body = {
100
110
  grant_type: 'refresh_token',
101
- client_id: this.client_id,
102
- client_secret: this.client_secret,
111
+ client_id: this.clientId,
112
+ client_secret: this.clientSecret,
103
113
  refresh_token: this.refreshToken
104
114
  }
105
115
  const now = Date.now()
@@ -111,7 +121,12 @@ module.exports = class connectionHTTP {
111
121
 
112
122
  // Check to see we got a response
113
123
  if (!res.data) {
114
- throw new Error(this.lang.noToken)
124
+ throw new Error(this.lang.noDataReceived)
125
+ }
126
+
127
+ // Log the response if in debug mode
128
+ if (this.debug) {
129
+ this.log('[HTTP renewToken()] %s.', JSON.stringify(res.data))
115
130
  }
116
131
 
117
132
  /*
@@ -142,11 +157,11 @@ module.exports = class connectionHTTP {
142
157
  } catch (err) {
143
158
  if (err.code && this.consts.httpRetryCodes.includes(err.code)) {
144
159
  // Retry if another attempt could be successful
145
- this.log.warn('[HTTP login()] %s [%s].', this.lang.httpRetry, err.code)
160
+ this.log.warn('[HTTP renewToken()] %s [%s].', this.lang.httpRetry, err.code)
146
161
  await this.funcs.sleep(30000)
147
162
  return await this.login()
148
163
  } else {
149
- throw new Error('[HTTP refreshToken()] ' + err.message)
164
+ throw new Error('[HTTP renewToken()] ' + err.message)
150
165
  }
151
166
  }
152
167
  }
@@ -154,8 +169,8 @@ module.exports = class connectionHTTP {
154
169
  async getDevices () {
155
170
  try {
156
171
  // Check we have a user id
157
- if (!this.userId) {
158
- throw new Error('No user id has been retrieved')
172
+ if (!this.userId || !this.accessToken) {
173
+ throw new Error(this.lang.noUserId)
159
174
  }
160
175
 
161
176
  // Perform the HTTP request
@@ -166,14 +181,19 @@ module.exports = class connectionHTTP {
166
181
 
167
182
  // Check to see we got a response
168
183
  if (!res.data) {
169
- throw new Error('No data received')
184
+ throw new Error(this.lang.noDataReceived)
185
+ }
186
+
187
+ // Log the response if in debug mode
188
+ if (this.debug) {
189
+ this.log('[HTTP getDevices()] %s.', JSON.stringify(res.data))
170
190
  }
171
191
 
172
192
  return res.data.data
173
193
  } catch (err) {
174
194
  if (err.code && this.consts.httpRetryCodes.includes(err.code)) {
175
195
  // Retry if another attempt could be successful
176
- this.log.warn('[HTTP login()] %s [%s].', this.lang.httpRetry, err.code)
196
+ this.log.warn('[HTTP getDevices()] %s [%s].', this.lang.httpRetry, err.code)
177
197
  await this.funcs.sleep(30000)
178
198
  return await this.login()
179
199
  } else {
@@ -182,7 +202,37 @@ module.exports = class connectionHTTP {
182
202
  }
183
203
  }
184
204
 
185
- async getDeviceInfo (deviceId, fromWhen) {
205
+ async getDeviceInfo (deviceId) {
206
+ // Refresh the access token if it has expired already
207
+ if (Date.now() > this.expiresIn) {
208
+ await this.renewToken()
209
+ }
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) {
186
236
  // Refresh the access token if it has expired already
187
237
  if (Date.now() > this.expiresIn) {
188
238
  await this.renewToken()
@@ -212,6 +262,46 @@ module.exports = class connectionHTTP {
212
262
  }
213
263
  )
214
264
 
265
+ // Check to see we got a response
266
+ if (!res.data) {
267
+ throw new Error(this.lang.noDataReceived)
268
+ }
269
+
270
+ // Log the response if in debug mode
271
+ if (this.debug) {
272
+ this.log('[HTTP getWaterInfo()] %s.', JSON.stringify(res.data))
273
+ }
274
+
275
+ // Parse the response
276
+ return res.data.data[0]
277
+ }
278
+
279
+ async getLeakInfo (deviceId) {
280
+ // Refresh the access token if it has expired already
281
+ if (Date.now() > this.expiresIn) {
282
+ await this.renewToken()
283
+ }
284
+
285
+ // Send the request
286
+ const res = await axios.get(
287
+ 'https://api.flumetech.com/users/' + this.userId + '/devices/' + deviceId + '/leaks/active',
288
+ {
289
+ headers: {
290
+ Authorization: 'Bearer ' + this.accessToken
291
+ }
292
+ }
293
+ )
294
+
295
+ // Check to see we got a response
296
+ if (!res.data) {
297
+ throw new Error(this.lang.noDataReceived)
298
+ }
299
+
300
+ // Log the response if in debug mode
301
+ if (this.debug) {
302
+ this.log('[HTTP getLeakInfo()] %s.', JSON.stringify(res.data))
303
+ }
304
+
215
305
  // Parse the response
216
306
  return res.data.data[0]
217
307
  }
@@ -6,30 +6,68 @@ module.exports = class deviceValve {
6
6
  constructor (platform, accessory) {
7
7
  // Set up variables from the platform
8
8
  this.accessory = accessory
9
- this.disableDeviceLogging = platform.config.disableDeviceLogging
10
9
  this.funcs = platform.funcs
11
10
  this.threshold = platform.config.threshold
12
11
  this.hapChar = platform.api.hap.Characteristic
13
12
  this.hapErr = platform.api.hap.HapStatusError
14
13
  this.hapServ = platform.api.hap.Service
15
14
  this.lang = platform.lang
16
- this.log = platform.log
15
+ this.log = platform.config.disableDeviceLogging ? () => {} : platform.log
17
16
  this.name = accessory.displayName
18
17
  this.platform = platform
19
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
20
28
  }
21
29
 
22
30
  externalUpdate (params) {
23
- // Here we deal with the incoming data
31
+ // Check the data for leak detection
32
+ if (
33
+ this.funcs.hasProperty(params.leakInfo, 'active') &&
34
+ params.leakInfo.active !== this.cacheLeak
35
+ ) {
36
+ this.cacheLeak = params.leakInfo.active
37
+ this.leakService.updateCharacteristic(this.hapChar.LeakDetected, this.cacheLeak ? 1 : 0)
38
+ this.log('[%s] current leak status [%sdetected].', this.name, this.cacheLeak ? '' : 'not ')
39
+ }
40
+
41
+ // Check the data for battery level, cacheBatt is true for OK and false for LOW
42
+ if (
43
+ this.funcs.hasProperty(params.devInfo, 'battery_level') &&
44
+ (params.devInfo.battery_level !== 'low') !== this.cacheBatt
45
+ ) {
46
+ this.cacheBatt = params.devInfo.battery_level !== 'low'
47
+ this.leakService.updateCharacteristic(this.hapChar.StatusLowBattery, this.cacheBatt ? 0 : 1)
48
+ this.log('[%s] current battery [%s].', this.name, this.cacheBatt ? 'ok' : 'low')
49
+ }
50
+
51
+ // Check the data for connectivity, cacheStatus is true for OK and false for NOT CONNECTED
52
+ if (
53
+ this.funcs.hasProperty(params.devInfo, 'connected') &&
54
+ params.devInfo.connected !== this.cacheStatus
55
+ ) {
56
+ this.cacheStatus = params.devInfo.connected
57
+ this.leakService.updateCharacteristic(this.hapChar.StatusFault, this.cacheStatus ? 0 : 1)
58
+ this.log('[%s] current status [%sconnected].', this.name, this.cacheStatus ? '' : 'not ')
59
+ }
60
+
24
61
  const usage =
25
- params.currentusage && params.currentusage[0] && params.currentusage[0].value
26
- ? params.currentusage[0].value
62
+ params.waterInfo.currentusage &&
63
+ params.waterInfo.currentusage[0] &&
64
+ params.waterInfo.currentusage[0].value
65
+ ? params.waterInfo.currentusage[0].value
27
66
  : 0
28
67
  if (usage > this.threshold) {
29
68
  this.log(
30
- '[%s] %s - [%s] gallons within the last [%s] minutes.',
69
+ '[%s] usage detected - [%s] gallons within the last [%s] minutes.',
31
70
  this.name,
32
- 'usage detected',
33
71
  usage,
34
72
  this.refreshInterval
35
73
  )
@@ -77,7 +77,11 @@
77
77
  <h4>Credits</h4>
78
78
  <ul>
79
79
  <li>
80
- This is a forked rewrite of the <a href="https://www.npmjs.com/package/homebridge-flume-water-sensor" target="_blank">homebridge-flume-water-sensor</a> plugin by @weallknowwhoisatfaulthere
80
+ This is a forked rewrite of the
81
+ <a href="https://www.npmjs.com/package/homebridge-flume-water-sensor" target="_blank"
82
+ >homebridge-flume-water-sensor</a
83
+ >
84
+ plugin by @weallknowwhoisatfaulthere
81
85
  </li>
82
86
  <li>
83
87
  To the creators/contributors of
package/lib/index.js CHANGED
@@ -88,8 +88,8 @@ class FlumePlatform {
88
88
  // Begin applying the user's config
89
89
  for (const [key, val] of Object.entries(config)) {
90
90
  switch (key) {
91
- case 'client_id':
92
- case 'client_secret':
91
+ case 'clientId':
92
+ case 'clientSecret':
93
93
  case 'password':
94
94
  case 'username':
95
95
  if (typeof val !== 'string' || val === '') {
@@ -161,8 +161,8 @@ class FlumePlatform {
161
161
  if (
162
162
  !this.config.username ||
163
163
  !this.config.password ||
164
- !this.config.client_id ||
165
- !this.config.client_secret
164
+ !this.config.clientId ||
165
+ !this.config.clientSecret
166
166
  ) {
167
167
  throw new Error(this.lang.noCreds)
168
168
  }
@@ -174,9 +174,11 @@ class FlumePlatform {
174
174
 
175
175
  // Check we have devices we can work with
176
176
  if (!Array.isArray(deviceList) || deviceList.length === 0) {
177
+ this.devicesInHB.forEach(accessory => this.removeAccessory(accessory))
177
178
  throw new Error(this.lang.noDevices)
178
179
  }
179
180
 
181
+ // Initialise each device into Homebridge
180
182
  deviceList.forEach(device => {
181
183
  if (!device.bridge_id) {
182
184
  return
@@ -184,6 +186,13 @@ class FlumePlatform {
184
186
  this.initialiseDevice(device)
185
187
  })
186
188
 
189
+ // Remove any stale accessories that don't appear in the device list
190
+ this.devicesInHB.forEach(accessory => {
191
+ if (!deviceList.find(el => accessory.context.deviceId === el.id)) {
192
+ this.removeAccessory(accessory)
193
+ }
194
+ })
195
+
187
196
  // Set up an initial last sync time
188
197
  this.lastSync = new Date(Date.now() - this.config.refreshInterval * 60000)
189
198
 
@@ -224,18 +233,23 @@ class FlumePlatform {
224
233
 
225
234
  async flumeSync () {
226
235
  try {
227
- const fromWhen = this.lastSync
236
+ const since = this.lastSync
228
237
  .toISOString()
229
238
  .substring(0, 19)
230
239
  .replace('T', ' ')
231
240
  this.devicesInHB.forEach(async accessory => {
232
241
  try {
233
- const res = await this.httpClient.getDeviceInfo(accessory.context.deviceId, fromWhen)
234
- res.fromWhen = fromWhen
235
- accessory.control.externalUpdate(res)
242
+ const toReturn = { since }
243
+ const devInfo = await this.httpClient.getDeviceInfo(accessory.context.deviceId)
244
+ toReturn.devInfo = devInfo
245
+ const waterInfo = await this.httpClient.getWaterInfo(accessory.context.deviceId, since)
246
+ toReturn.waterInfo = waterInfo
247
+ const leakInfo = await this.httpClient.getLeakInfo(accessory.context.deviceId)
248
+ toReturn.leakInfo = leakInfo
249
+ accessory.control.externalUpdate(toReturn)
236
250
  } catch (err) {
237
251
  const eText = this.funcs.parseError(err)
238
- this.log.warn(eText)
252
+ this.log.warn('[%s] %s %s.', accessory.displayName, this.lang.devNotRef, eText)
239
253
  }
240
254
  })
241
255
 
@@ -7,8 +7,8 @@ module.exports = {
7
7
  name: 'Flume',
8
8
  username: '',
9
9
  password: '',
10
- client_id: '',
11
- client_secret: '',
10
+ clientId: '',
11
+ clientSecret: '',
12
12
  refreshInterval: 1,
13
13
  threshold: 0,
14
14
  disableDeviceLogging: false,
@@ -18,12 +18,12 @@ module.exports = {
18
18
  },
19
19
 
20
20
  defaultValues: {
21
- refreshInterval: 1,
21
+ refreshInterval: 2,
22
22
  threshold: 0
23
23
  },
24
24
 
25
25
  minValues: {
26
- refreshInterval: 1,
26
+ refreshInterval: 2,
27
27
  threshold: 0
28
28
  },
29
29
 
@@ -4,7 +4,6 @@
4
4
 
5
5
  module.exports = {
6
6
  accNotFound: 'accessory not found',
7
- accNotReady: 'cannot currently be controlled, see plugin startup logs for any error',
8
7
  brand: 'Flume',
9
8
  cfgDef: 'is not a valid number so using default of',
10
9
  cfgDup: 'will be ignored since another entry with this ID already exists',
@@ -15,10 +14,6 @@ module.exports = {
15
14
  cfgRmv: 'is unused and can be removed',
16
15
  cfgQts: 'should not have quotes around its entry',
17
16
  complete: '✓ Setup complete',
18
- curHeat: 'current heating',
19
- curState: 'current state',
20
- curTarg: 'current target',
21
- curTemp: 'current temperature',
22
17
  devAdd: 'has been added to Homebridge',
23
18
  devInit: 'initialised with id',
24
19
  devNotAdd: 'could not be added to Homebridge as',
@@ -29,36 +24,28 @@ module.exports = {
29
24
  devNotUpdated: 'could not be updated as',
30
25
  devRemove: 'has been removed from Homebridge',
31
26
  disabled: 'To change this, set disablePlugin to false',
32
- disableHTTP: 'Disabling HTTP client as',
33
27
  disabling: 'Disabling plugin',
34
28
  hbVersionFail: 'Your version of Homebridge is too low - please update to v1.3',
35
29
  httpRetry: 'Unable to reach Flume, retrying in 30 seconds',
36
30
  initialised: 'Plugin initialised. Setting up accessories...',
37
31
  initialising: 'Initialising plugin',
38
- labelHeating: 'heating',
39
- labelIdle: 'idle',
40
- labelMan: 'manual',
41
- labelSch: 'schedule',
42
- noCreds: 'Flume username and/or password not configured',
43
- noDevices: 'no data received from Flume server whilst obtaining device list',
44
- noTokenExists: 'no Flume account token exists',
32
+ noCreds: 'Flume username and/or password and/or client id/secret not configured',
33
+ noDataReceived: 'No data received from request',
34
+ noRefreshToken: 'No refresh token has been retrieved',
35
+ noUserId: 'No user id has been retrieved',
45
36
  pluginNotConf: 'Plugin has not been configured',
46
- receivingUpdate: 'receiving update',
47
- scheduleFailed: 'Program schedule could not be updated as',
48
- scheduleInvalid: 'Not updating program schedule as configuration is invalid or incomplete',
49
- scheduleUpdated: 'Program schedule successfully updated',
50
37
  syncFailed: 'Sync process failed as',
51
38
  updateFail: 'could not be updated as',
52
39
  zWelcome: [
53
40
  "Don't forget to ☆ this plugin on GitHub if you're finding it useful!",
54
- // 'Have a feature request? Visit https://bit.ly/hb-thermobit-issues to ask!',
41
+ 'Have a feature request? Visit https://bit.ly/hb-flume-issues to ask!',
55
42
  'Interested in sponsoring this plugin? https://github.com/sponsors/bwp91',
56
43
  "Join the plugin's Discord community! https://discord.gg/cMGhNtZ3tW",
57
44
  'Thanks for using this plugin, I hope you find it helpful!',
58
45
  'This plugin has been made with ♥ by bwp91 from the UK!',
59
46
  'Check out my other Homebridge plugins! https://github.com/bwp91',
60
- // 'Have time to give this plugin a review? https://bit.ly/hb-thermobit-review',
61
- // "This plugin needs it's first ☆ rating on HOOBS! https://bit.ly/hb-thermobit-review",
47
+ 'Have time to give this plugin a review? https://bit.ly/hb-flume-review',
48
+ "This plugin needs it's first ☆ rating on HOOBS! https://bit.ly/hb-flume-review",
62
49
  'Want to see this plugin in your own language? Let me know!'
63
50
  ]
64
51
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-flume",
3
3
  "alias": "Flume",
4
- "version": "0.3.1",
4
+ "version": "0.7.0",
5
5
  "author": {
6
6
  "name": "Ben Potter",
7
7
  "email": "bwp91@icloud.com"
@@ -33,6 +33,24 @@
33
33
  "bugs": {
34
34
  "url": "https://github.com/bwp91/homebridge-flume/issues"
35
35
  },
36
+ "funding": [
37
+ {
38
+ "type": "github",
39
+ "url": "https://github.com/sponsors/bwp91"
40
+ },
41
+ {
42
+ "type": "kofi",
43
+ "url": "https://ko-fi.com/bwp91"
44
+ },
45
+ {
46
+ "type": "patreon",
47
+ "url": "https://www.patreon.com/bwp91"
48
+ },
49
+ {
50
+ "type": "paypal",
51
+ "url": "https://www.paypal.me/BenPotter"
52
+ }
53
+ ],
36
54
  "dependencies": {
37
55
  "@homebridge/plugin-ui-utils": "^0.0.19",
38
56
  "axios": "^0.24.0",