bt-sensors-plugin-sk 1.2.0-beta.0.0.9 → 1.2.0-beta.0.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/BTSensor.js +14 -2
- package/README.md +10 -0
- package/classLoader.js +38 -0
- package/index.js +43 -95
- package/package.json +2 -1
- package/public/159.js +1 -2
- package/public/239.js +8 -0
- package/public/778.js +2 -0
- package/public/main.js +1 -1
- package/public/remoteEntry.js +1 -1
- package/sensor_classes/ATC.js +1 -0
- package/sensor_classes/Aranet/AranetSensor.js +1 -0
- package/sensor_classes/GobiusCTankMeter.js +362 -0
- package/sensor_classes/GoveeH50xx.js +1 -1
- package/sensor_classes/GoveeH510x.js +1 -1
- package/sensor_classes/IBeacon.js +9 -2
- package/sensor_classes/Inkbird.js +1 -1
- package/sensor_classes/JBDBMS.js +1 -0
- package/sensor_classes/KilovaultHLXPlus.js +2 -0
- package/sensor_classes/LancolVoltageMeter.js +1 -0
- package/sensor_classes/MopekaTankSensor.js +6 -2
- package/sensor_classes/Renogy/RenogySensor.js +1 -1
- package/sensor_classes/RuuviTag.js +1 -0
- package/sensor_classes/ShellySBHT003C.js +2 -5
- package/sensor_classes/SwitchBotMeterPlus.js +2 -1
- package/sensor_classes/SwitchBotTH.js +2 -0
- package/sensor_classes/UltrasonicWindMeter.js +2 -0
- package/sensor_classes/Victron/VictronSensor.js +1 -0
- package/sensor_classes/VictronInverterRS.js +2 -2
- package/sensor_classes/XiaomiMiBeacon.js +2 -1
- package/src/components/PluginConfigurationPanel.js +140 -81
- package/public/30.js +0 -8
- package/public/893.js +0 -1
- /package/public/{30.js.LICENSE.txt → 239.js.LICENSE.txt} +0 -0
- /package/public/{159.js.LICENSE.txt → 778.js.LICENSE.txt} +0 -0
package/BTSensor.js
CHANGED
|
@@ -102,7 +102,14 @@ function preparePath(obj, str) {
|
|
|
102
102
|
class BTSensor extends EventEmitter {
|
|
103
103
|
|
|
104
104
|
static DEFAULTS = require('./plugin_defaults.json');
|
|
105
|
-
|
|
105
|
+
|
|
106
|
+
static SensorDomains={
|
|
107
|
+
unknown: { name: "unknown", description: "Unknown sensor domain "},
|
|
108
|
+
environmental: { name: "environmental", description: "Sensors that measure environmental conditions - air temperature, humidity etc."},
|
|
109
|
+
electrical: { name: "electrical", description: "Electrical sensor - chargers, batteries, inverters etc."},
|
|
110
|
+
tanks: { name: "tanks", description: "Sensors that measure level in tanks (gas, propane, water etc.) "}
|
|
111
|
+
}
|
|
112
|
+
static Domain = this.SensorDomains.unknown
|
|
106
113
|
/**
|
|
107
114
|
*
|
|
108
115
|
* @param {module:node-ble/Device} device
|
|
@@ -404,7 +411,8 @@ class BTSensor extends EventEmitter {
|
|
|
404
411
|
path.type="string"
|
|
405
412
|
|
|
406
413
|
if (!path.pattern)
|
|
407
|
-
path.pattern
|
|
414
|
+
path.pattern=//"^(?:[^{}\\s]*\\{[a-zA-Z0-9]+\\}[^{}\\s]*|[^{}\\s]*)$"
|
|
415
|
+
"^((\\{[a-zA-Z0-9]+\\}|[a-zA-Z0-9]+))(\\.(\\{[a-zA-Z0-9]+\\}|[a-zA-Z0-9]+))*$"
|
|
408
416
|
this._schema.properties.paths.properties[tag]=path
|
|
409
417
|
return this._schema.properties.paths.properties[tag]
|
|
410
418
|
}
|
|
@@ -644,6 +652,10 @@ class BTSensor extends EventEmitter {
|
|
|
644
652
|
return this._state
|
|
645
653
|
}
|
|
646
654
|
|
|
655
|
+
getDomain(){
|
|
656
|
+
return this.constructor.Domain
|
|
657
|
+
}
|
|
658
|
+
|
|
647
659
|
isActive(){
|
|
648
660
|
return this._state=="ACTIVE"
|
|
649
661
|
}
|
package/README.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## What's New
|
|
4
4
|
|
|
5
|
+
## 1.2.0-beta-0.1.0
|
|
6
|
+
|
|
7
|
+
Sensors on config page appear under tabs indicating their domain (Environmental, Electrical etc.)
|
|
8
|
+
|
|
9
|
+
Gobius C tank meter support added.
|
|
10
|
+
|
|
11
|
+
## 1.2.0-beta-0.0.10
|
|
12
|
+
|
|
13
|
+
Better handling of plugin config screen when Disabled
|
|
14
|
+
|
|
5
15
|
## 1.2.0-beta-0.0.9
|
|
6
16
|
|
|
7
17
|
Fixes to config page RSSI update.
|
package/classLoader.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const semver = require('semver')
|
|
4
|
+
|
|
5
|
+
function loadClasses (dir, ext='.js')
|
|
6
|
+
{
|
|
7
|
+
const classMap = new Map()
|
|
8
|
+
const classFiles = fs.readdirSync(dir)
|
|
9
|
+
.filter(file => file.endsWith(ext));
|
|
10
|
+
|
|
11
|
+
classFiles.forEach(file => {
|
|
12
|
+
const filePath = path.join(dir, file);
|
|
13
|
+
const cls = require(filePath);
|
|
14
|
+
classMap.set(cls.name, cls);
|
|
15
|
+
})
|
|
16
|
+
return classMap
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadClassMap(app) {
|
|
20
|
+
const _classMap = loadClasses(path.join(__dirname, 'sensor_classes'))
|
|
21
|
+
const classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
|
|
22
|
+
const libPath = app.config.appPath +(
|
|
23
|
+
semver.gt(app.config.version,"2.13.5")?"dist":"lib"
|
|
24
|
+
)
|
|
25
|
+
import(libPath+"/modules.js").then( (modulesjs)=>{
|
|
26
|
+
const { default:defaultExport} = modulesjs
|
|
27
|
+
const modules = defaultExport.modulesWithKeyword(app.config, "signalk-bt-sensor-class")
|
|
28
|
+
modules.forEach((module)=>{
|
|
29
|
+
module.metadata.classFiles.forEach((classFile)=>{
|
|
30
|
+
const cls = require(module.location+module.module+"/"+classFile);
|
|
31
|
+
classMap.set(cls.name, cls);
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
classMap.get('UNKNOWN').classMap=new Map([...classMap].sort().filter(([k, v]) => !v.isSystem )) // share the classMap with Unknown for configuration purposes
|
|
35
|
+
})
|
|
36
|
+
return classMap
|
|
37
|
+
}
|
|
38
|
+
module.exports=loadClassMap
|
package/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const util = require('util')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const semver = require('semver')
|
|
5
1
|
const packageInfo = require("./package.json")
|
|
6
2
|
|
|
7
3
|
const {createBluetooth} = require('node-ble')
|
|
@@ -12,10 +8,10 @@ const BTSensor = require('./BTSensor.js')
|
|
|
12
8
|
const BLACKLISTED = require('./sensor_classes/BlackListedDevice.js')
|
|
13
9
|
const { createChannel, createSession } = require("better-sse");
|
|
14
10
|
const { clearTimeout } = require('timers')
|
|
11
|
+
const loadClassMap = require('./classLoader.js')
|
|
15
12
|
|
|
16
13
|
class MissingSensor {
|
|
17
14
|
|
|
18
|
-
|
|
19
15
|
constructor(config){
|
|
20
16
|
this.config=config
|
|
21
17
|
this.addPath=BTSensor.prototype.addPath.bind(this)
|
|
@@ -27,6 +23,7 @@ class MissingSensor {
|
|
|
27
23
|
this.getJSONSchema = BTSensor.prototype.getJSONSchema.bind(this)
|
|
28
24
|
this.initSchema = BTSensor.prototype.initSchema.bind(this)
|
|
29
25
|
|
|
26
|
+
|
|
30
27
|
this.initSchema()
|
|
31
28
|
var keys = Object.keys(config?.paths??{})
|
|
32
29
|
|
|
@@ -62,6 +59,9 @@ class MissingSensor {
|
|
|
62
59
|
getMacAddress(){
|
|
63
60
|
return this.mac_address
|
|
64
61
|
}
|
|
62
|
+
getDomain(){
|
|
63
|
+
return BTSensor.SensorDomains.unknown
|
|
64
|
+
}
|
|
65
65
|
getDescription(){
|
|
66
66
|
return ""
|
|
67
67
|
}
|
|
@@ -88,66 +88,14 @@ class MissingSensor {
|
|
|
88
88
|
|
|
89
89
|
}
|
|
90
90
|
module.exports = function (app) {
|
|
91
|
-
var adapterID = 'hci0'
|
|
92
|
-
|
|
93
|
-
|
|
94
91
|
var deviceConfigs
|
|
95
92
|
var starts=0
|
|
96
|
-
var classMap
|
|
97
|
-
|
|
98
|
-
var utilities_sk
|
|
99
93
|
|
|
100
94
|
var plugin = {};
|
|
101
95
|
plugin.id = 'bt-sensors-plugin-sk';
|
|
102
96
|
plugin.name = 'BT Sensors plugin';
|
|
103
97
|
plugin.description = 'Plugin to communicate with and update paths to BLE Sensors in Signalk';
|
|
104
98
|
|
|
105
|
-
//Try and load utilities-sk NOTE: should be installed from App Store--
|
|
106
|
-
//But there's a fail safe because I'm a reasonable man.
|
|
107
|
-
|
|
108
|
-
utilities_sk = {
|
|
109
|
-
loadClasses: function(dir, ext='.js')
|
|
110
|
-
{
|
|
111
|
-
const classMap = new Map()
|
|
112
|
-
const classFiles = fs.readdirSync(dir)
|
|
113
|
-
.filter(file => file.endsWith(ext));
|
|
114
|
-
|
|
115
|
-
classFiles.forEach(file => {
|
|
116
|
-
const filePath = path.join(dir, file);
|
|
117
|
-
const cls = require(filePath);
|
|
118
|
-
classMap.set(cls.name, cls);
|
|
119
|
-
})
|
|
120
|
-
return classMap
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function sleep(x) {
|
|
125
|
-
return new Promise((resolve) => {
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
resolve(x);
|
|
128
|
-
}, x);
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function loadClassMap() {
|
|
133
|
-
const _classMap = utilities_sk.loadClasses(path.join(__dirname, 'sensor_classes'))
|
|
134
|
-
classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
|
|
135
|
-
const libPath = app.config.appPath +(
|
|
136
|
-
semver.gt(app.config.version,"2.13.5")?"dist":"lib"
|
|
137
|
-
)
|
|
138
|
-
import(libPath+"/modules.js").then( (modulesjs)=>{
|
|
139
|
-
const { default:defaultExport} = modulesjs
|
|
140
|
-
const modules = defaultExport.modulesWithKeyword(app.config, "signalk-bt-sensor-class")
|
|
141
|
-
modules.forEach((module)=>{
|
|
142
|
-
module.metadata.classFiles.forEach((classFile)=>{
|
|
143
|
-
const cls = require(module.location+module.module+"/"+classFile);
|
|
144
|
-
classMap.set(cls.name, cls);
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
classMap.get('UNKNOWN').classMap=new Map([...classMap].sort().filter(([k, v]) => !v.isSystem )) // share the classMap with Unknown for configuration purposes
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
|
|
151
99
|
app.debug(`Loading plugin ${packageInfo.version}`)
|
|
152
100
|
|
|
153
101
|
plugin.schema = {
|
|
@@ -171,17 +119,17 @@ module.exports = function (app) {
|
|
|
171
119
|
}
|
|
172
120
|
}
|
|
173
121
|
|
|
174
|
-
const sensorMap=new Map()
|
|
175
122
|
|
|
176
123
|
plugin.started=false
|
|
177
|
-
|
|
178
|
-
loadClassMap()
|
|
124
|
+
|
|
179
125
|
var discoveryIntervalID, progressID, progressTimeoutID, deviceHealthID
|
|
180
126
|
var adapter
|
|
181
|
-
var adapterPower
|
|
182
127
|
const channel = createChannel()
|
|
128
|
+
const classMap = loadClassMap(app)
|
|
129
|
+
const sensorMap=new Map()
|
|
183
130
|
|
|
184
|
-
|
|
131
|
+
|
|
132
|
+
/* plugin.registerWithRouter = function(router) {
|
|
185
133
|
router.get('/sendPluginState', async (req, res) => {
|
|
186
134
|
|
|
187
135
|
res.status(200).json({
|
|
@@ -193,15 +141,16 @@ module.exports = function (app) {
|
|
|
193
141
|
channel.register(session)
|
|
194
142
|
});
|
|
195
143
|
|
|
196
|
-
}
|
|
144
|
+
}*/
|
|
197
145
|
|
|
198
146
|
plugin.start = async function (options, restartPlugin) {
|
|
199
147
|
plugin.started=true
|
|
200
148
|
var adapterID=options.adapter
|
|
201
149
|
var foundConfiguredDevices=0
|
|
150
|
+
|
|
202
151
|
plugin.registerWithRouter = function(router) {
|
|
203
152
|
|
|
204
|
-
router.post('/
|
|
153
|
+
router.post('/updateSensorData', async (req, res) => {
|
|
205
154
|
app.debug(req.body)
|
|
206
155
|
const i = deviceConfigs.findIndex((p)=>p.mac_address==req.body.mac_address)
|
|
207
156
|
if (i<0){
|
|
@@ -222,13 +171,9 @@ module.exports = function (app) {
|
|
|
222
171
|
const sensor = sensorMap.get(req.body.mac_address)
|
|
223
172
|
if (sensor) {
|
|
224
173
|
removeSensorFromList(sensor)
|
|
225
|
-
if (sensor.isActive())
|
|
226
|
-
sensor.stopListening()
|
|
227
|
-
|
|
228
|
-
)
|
|
229
|
-
} else {
|
|
230
|
-
initConfiguredDevice(req.body)
|
|
231
|
-
}
|
|
174
|
+
if (sensor.isActive())
|
|
175
|
+
await sensor.stopListening()
|
|
176
|
+
initConfiguredDevice(req.body)
|
|
232
177
|
}
|
|
233
178
|
|
|
234
179
|
}
|
|
@@ -244,7 +189,7 @@ module.exports = function (app) {
|
|
|
244
189
|
if (sensorMap.has(req.body.mac_address))
|
|
245
190
|
sensorMap.delete(req.body.mac_address)
|
|
246
191
|
app.savePluginOptions(
|
|
247
|
-
options,
|
|
192
|
+
options, () => {
|
|
248
193
|
app.debug('Plugin options saved')
|
|
249
194
|
res.status(200).json({message: "Sensor updated"})
|
|
250
195
|
channel.broadcast({},"resetSensors")
|
|
@@ -253,7 +198,7 @@ module.exports = function (app) {
|
|
|
253
198
|
|
|
254
199
|
});
|
|
255
200
|
|
|
256
|
-
router.post('/
|
|
201
|
+
router.post('/updateBaseData', async (req, res) => {
|
|
257
202
|
|
|
258
203
|
app.debug(req.body)
|
|
259
204
|
Object.assign(options,req.body)
|
|
@@ -266,9 +211,14 @@ module.exports = function (app) {
|
|
|
266
211
|
}
|
|
267
212
|
)
|
|
268
213
|
});
|
|
214
|
+
router.get('/getDomains', (req, res) => {
|
|
215
|
+
|
|
216
|
+
res.status(200).json(
|
|
217
|
+
BTSensor.SensorDomains
|
|
218
|
+
);
|
|
219
|
+
})
|
|
269
220
|
|
|
270
|
-
|
|
271
|
-
router.get('/base', (req, res) => {
|
|
221
|
+
router.get('/getBaseData', (req, res) => {
|
|
272
222
|
|
|
273
223
|
res.status(200).json(
|
|
274
224
|
{
|
|
@@ -282,13 +232,13 @@ module.exports = function (app) {
|
|
|
282
232
|
}
|
|
283
233
|
);
|
|
284
234
|
})
|
|
285
|
-
router.get('/
|
|
235
|
+
router.get('/getSensors', (req, res) => {
|
|
286
236
|
app.debug("Sending sensors")
|
|
287
237
|
const t = sensorsToJSON()
|
|
288
238
|
res.status(200).json(t)
|
|
289
239
|
});
|
|
290
240
|
|
|
291
|
-
router.get('/
|
|
241
|
+
router.get('/getProgress', (req, res) => {
|
|
292
242
|
app.debug("Sending progress")
|
|
293
243
|
const json = {"progress":foundConfiguredDevices/deviceConfigs.length, "maxTimeout": 1,
|
|
294
244
|
"deviceCount":foundConfiguredDevices,
|
|
@@ -297,7 +247,7 @@ module.exports = function (app) {
|
|
|
297
247
|
|
|
298
248
|
});
|
|
299
249
|
|
|
300
|
-
router.get('/
|
|
250
|
+
router.get('/getPluginState', async (req, res) => {
|
|
301
251
|
|
|
302
252
|
res.status(200).json({
|
|
303
253
|
"state":(plugin.started?"started":"stopped")
|
|
@@ -320,12 +270,12 @@ module.exports = function (app) {
|
|
|
320
270
|
|
|
321
271
|
function getSensorInfo(sensor){
|
|
322
272
|
|
|
323
|
-
const etslc = sensor.elapsedTimeSinceLastContact()
|
|
324
273
|
return { mac: sensor.getMacAddress(),
|
|
325
274
|
name: sensor.getName(),
|
|
275
|
+
domain: sensor.getDomain().name,
|
|
326
276
|
RSSI: sensor.getRSSI(),
|
|
327
277
|
signalStrength: sensor.getSignalStrength(),
|
|
328
|
-
lastContactDelta:
|
|
278
|
+
lastContactDelta: sensor.elapsedTimeSinceLastContact()
|
|
329
279
|
}
|
|
330
280
|
}
|
|
331
281
|
|
|
@@ -335,7 +285,6 @@ module.exports = function (app) {
|
|
|
335
285
|
info: getSensorInfo(sensor),
|
|
336
286
|
schema: sensor.getJSONSchema(),
|
|
337
287
|
config: config?config:{}
|
|
338
|
-
|
|
339
288
|
}
|
|
340
289
|
}
|
|
341
290
|
async function startScanner(transport) {
|
|
@@ -369,7 +318,7 @@ module.exports = function (app) {
|
|
|
369
318
|
channel.broadcast({mac:sensor.getMacAddress()},"removesensor")
|
|
370
319
|
}
|
|
371
320
|
|
|
372
|
-
|
|
321
|
+
function addSensorToList(sensor){
|
|
373
322
|
app.debug(`adding sensor to list ${sensor.getMacAddress()}`)
|
|
374
323
|
if (sensorMap.has(sensor.getMacAddress()) )
|
|
375
324
|
debugger
|
|
@@ -380,7 +329,7 @@ module.exports = function (app) {
|
|
|
380
329
|
return `${config?.name??""}${config.name?" at ":""}${config.mac_address}`
|
|
381
330
|
}
|
|
382
331
|
|
|
383
|
-
|
|
332
|
+
function createSensor(adapter, config) {
|
|
384
333
|
return new Promise( ( resolve, reject )=>{
|
|
385
334
|
var s
|
|
386
335
|
const startNumber=starts
|
|
@@ -531,14 +480,15 @@ module.exports = function (app) {
|
|
|
531
480
|
setInterval( findDevices, discoveryInterval*1000, discoveryTimeout)
|
|
532
481
|
}
|
|
533
482
|
|
|
534
|
-
|
|
483
|
+
channel.broadcast({state:"started"},"pluginstate")
|
|
484
|
+
|
|
485
|
+
|
|
535
486
|
if (!adapterID || adapterID=="")
|
|
536
487
|
adapterID = "hci0"
|
|
537
488
|
//Check if Adapter has changed since last start()
|
|
538
489
|
if (adapter) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
adapter.helper.removeAllListeners()
|
|
490
|
+
if (adapter.adapter!=adapterID) {
|
|
491
|
+
adapter.helper._propsProxy.removeAllListeners()
|
|
542
492
|
adapter=null
|
|
543
493
|
}
|
|
544
494
|
}
|
|
@@ -568,12 +518,10 @@ module.exports = function (app) {
|
|
|
568
518
|
if (!await adapter.isPowered()) {
|
|
569
519
|
app.debug(`Bluetooth Adapter ${adapterID} not powered on.`)
|
|
570
520
|
app.setPluginError(`Bluetooth Adapter ${adapterID} not powered on.`)
|
|
571
|
-
adapterPower=false
|
|
572
521
|
await plugin.stop()
|
|
573
522
|
return
|
|
574
523
|
}
|
|
575
524
|
}
|
|
576
|
-
adapterPower=true
|
|
577
525
|
|
|
578
526
|
sensorMap.clear()
|
|
579
527
|
if (channel)
|
|
@@ -581,9 +529,6 @@ module.exports = function (app) {
|
|
|
581
529
|
deviceConfigs=options?.peripherals??[]
|
|
582
530
|
|
|
583
531
|
if (plugin.stopped) {
|
|
584
|
-
//await sleep(5000) //Make sure plugin.stop() completes first
|
|
585
|
-
//plugin.start is called asynchronously for some reason
|
|
586
|
-
//and does not wait for plugin.stop to complete
|
|
587
532
|
plugin.stopped=false
|
|
588
533
|
}
|
|
589
534
|
|
|
@@ -689,17 +634,20 @@ module.exports = function (app) {
|
|
|
689
634
|
}
|
|
690
635
|
}
|
|
691
636
|
sensorMap.clear()
|
|
692
|
-
|
|
637
|
+
|
|
638
|
+
if (adapter) {
|
|
639
|
+
adapter.helper._propsProxy.removeAllListeners()
|
|
640
|
+
if( await adapter.isDiscovering())
|
|
693
641
|
try{
|
|
694
642
|
await adapter.stopDiscovery()
|
|
695
643
|
app.debug('Scan stopped')
|
|
696
644
|
} catch (e){
|
|
697
645
|
app.debug(`Error stopping scan: ${e.message}`)
|
|
698
646
|
}
|
|
699
|
-
|
|
647
|
+
}
|
|
700
648
|
app.debug('BT Sensors plugin stopped')
|
|
701
649
|
|
|
702
650
|
}
|
|
703
651
|
|
|
704
652
|
return plugin;
|
|
705
|
-
}
|
|
653
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bt-sensors-plugin-sk",
|
|
3
|
-
"version": "1.2.0-beta.0.0
|
|
3
|
+
"version": "1.2.0-beta.0.1.0",
|
|
4
4
|
"description": "Bluetooth Sensors for Signalk -- support for Victron devices, RuuviTag, Xiaomi, ATC and Inkbird, Ultrasonic wind meters, Mopeka tank readers, Renogy Battery and Solar Controllers, Aranet4 environment sensors, SwitchBot temp and humidity sensors, KilovaultHLXPlus smart batteries, and Govee GVH51xx temp sensors",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"int24": "^0.0.1",
|
|
13
13
|
"kaitai-struct": "^0.10.0",
|
|
14
14
|
"node-ble": "^1.13.0",
|
|
15
|
+
"rimraf": "^6.0.1",
|
|
15
16
|
"semver": "^7.7.1"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|
package/public/159.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
"use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[159,540],{5228:e=>{var r=Object.getOwnPropertySymbols,t=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var r={},t=0;t<10;t++)r["_"+String.fromCharCode(t)]=t;if("0123456789"!==Object.getOwnPropertyNames(r).map((function(e){return r[e]})).join(""))return!1;var n={};return"abcdefghijklmnopqrst".split("").forEach((function(e){n[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},n)).join("")}catch(e){return!1}}()?Object.assign:function(e,o){for(var u,c,f=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l<arguments.length;l++){for(var i in u=Object(arguments[l]))t.call(u,i)&&(f[i]=u[i]);if(r){c=r(u);for(var a=0;a<c.length;a++)n.call(u,c[a])&&(f[c[a]]=u[c[a]])}}return f}},5287:(e,r,t)=>{var n=t(5228),o="function"==typeof Symbol&&Symbol.for,u=o?Symbol.for("react.element"):60103,c=o?Symbol.for("react.portal"):60106,f=o?Symbol.for("react.fragment"):60107,l=o?Symbol.for("react.strict_mode"):60108,i=o?Symbol.for("react.profiler"):60114,a=o?Symbol.for("react.provider"):60109,s=o?Symbol.for("react.context"):60110,p=o?Symbol.for("react.forward_ref"):60112,y=o?Symbol.for("react.suspense"):60113,d=o?Symbol.for("react.memo"):60115,h=o?Symbol.for("react.lazy"):60116,b="function"==typeof Symbol&&Symbol.iterator;function v(e){for(var r="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t<arguments.length;t++)r+="&args[]="+encodeURIComponent(arguments[t]);return"Minified React error #"+e+"; visit "+r+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},_={};function g(e,r,t){this.props=e,this.context=r,this.refs=_,this.updater=t||m}function S(){}function k(e,r,t){this.props=e,this.context=r,this.refs=_,this.updater=t||m}g.prototype.isReactComponent={},g.prototype.setState=function(e,r){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(v(85));this.updater.enqueueSetState(this,e,r,"setState")},g.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},S.prototype=g.prototype;var w=k.prototype=new S;w.constructor=k,n(w,g.prototype),w.isPureReactComponent=!0;var j={current:null},O=Object.prototype.hasOwnProperty,C={key:!0,ref:!0,__self:!0,__source:!0};function $(e,r,t){var n,o={},c=null,f=null;if(null!=r)for(n in void 0!==r.ref&&(f=r.ref),void 0!==r.key&&(c=""+r.key),r)O.call(r,n)&&!C.hasOwnProperty(n)&&(o[n]=r[n]);var l=arguments.length-2;if(1===l)o.children=t;else if(1<l){for(var i=Array(l),a=0;a<l;a++)i[a]=arguments[a+2];o.children=i}if(e&&e.defaultProps)for(n in l=e.defaultProps)void 0===o[n]&&(o[n]=l[n]);return{$$typeof:u,type:e,key:c,ref:f,props:o,_owner:j.current}}function E(e){return"object"==typeof e&&null!==e&&e.$$typeof===u}var P=/\/+/g,x=[];function R(e,r,t,n){if(x.length){var o=x.pop();return o.result=e,o.keyPrefix=r,o.func=t,o.context=n,o.count=0,o}return{result:e,keyPrefix:r,func:t,context:n,count:0}}function A(e){e.result=null,e.keyPrefix=null,e.func=null,e.context=null,e.count=0,10>x.length&&x.push(e)}function I(e,r,t,n){var o=typeof e;"undefined"!==o&&"boolean"!==o||(e=null);var f=!1;if(null===e)f=!0;else switch(o){case"string":case"number":f=!0;break;case"object":switch(e.$$typeof){case u:case c:f=!0}}if(f)return t(n,e,""===r?"."+U(e,0):r),1;if(f=0,r=""===r?".":r+":",Array.isArray(e))for(var l=0;l<e.length;l++){var i=r+U(o=e[l],l);f+=I(o,i,t,n)}else if("function"==typeof(i=null===e||"object"!=typeof e?null:"function"==typeof(i=b&&e[b]||e["@@iterator"])?i:null))for(e=i.call(e),l=0;!(o=e.next()).done;)f+=I(o=o.value,i=r+U(o,l++),t,n);else if("object"===o)throw t=""+e,Error(v(31,"[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t,""));return f}function q(e,r,t){return null==e?0:I(e,"",r,t)}function U(e,r){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var r={"=":"=0",":":"=2"};return"$"+(""+e).replace(/[=:]/g,(function(e){return r[e]}))}(e.key):r.toString(36)}function F(e,r){e.func.call(e.context,r,e.count++)}function L(e,r,t){var n=e.result,o=e.keyPrefix;e=e.func.call(e.context,r,e.count++),Array.isArray(e)?M(e,n,t,(function(e){return e})):null!=e&&(E(e)&&(e=function(e,r){return{$$typeof:u,type:e.type,key:r,ref:e.ref,props:e.props,_owner:e._owner}}(e,o+(!e.key||r&&r.key===e.key?"":(""+e.key).replace(P,"$&/")+"/")+t)),n.push(e))}function M(e,r,t,n,o){var u="";null!=t&&(u=(""+t).replace(P,"$&/")+"/"),q(e,L,r=R(r,u,n,o)),A(r)}var N={current:null};function D(){var e=N.current;if(null===e)throw Error(v(321));return e}var T={ReactCurrentDispatcher:N,ReactCurrentBatchConfig:{suspense:null},ReactCurrentOwner:j,IsSomeRendererActing:{current:!1},assign:n};r.Children={map:function(e,r,t){if(null==e)return e;var n=[];return M(e,n,null,r,t),n},forEach:function(e,r,t){if(null==e)return e;q(e,F,r=R(null,null,r,t)),A(r)},count:function(e){return q(e,(function(){return null}),null)},toArray:function(e){var r=[];return M(e,r,null,(function(e){return e})),r},only:function(e){if(!E(e))throw Error(v(143));return e}},r.Component=g,r.Fragment=f,r.Profiler=i,r.PureComponent=k,r.StrictMode=l,r.Suspense=y,r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=T,r.cloneElement=function(e,r,t){if(null==e)throw Error(v(267,e));var o=n({},e.props),c=e.key,f=e.ref,l=e._owner;if(null!=r){if(void 0!==r.ref&&(f=r.ref,l=j.current),void 0!==r.key&&(c=""+r.key),e.type&&e.type.defaultProps)var i=e.type.defaultProps;for(a in r)O.call(r,a)&&!C.hasOwnProperty(a)&&(o[a]=void 0===r[a]&&void 0!==i?i[a]:r[a])}var a=arguments.length-2;if(1===a)o.children=t;else if(1<a){i=Array(a);for(var s=0;s<a;s++)i[s]=arguments[s+2];o.children=i}return{$$typeof:u,type:e.type,key:c,ref:f,props:o,_owner:l}},r.createContext=function(e,r){return void 0===r&&(r=null),(e={$$typeof:s,_calculateChangedBits:r,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:a,_context:e},e.Consumer=e},r.createElement=$,r.createFactory=function(e){var r=$.bind(null,e);return r.type=e,r},r.createRef=function(){return{current:null}},r.forwardRef=function(e){return{$$typeof:p,render:e}},r.isValidElement=E,r.lazy=function(e){return{$$typeof:h,_ctor:e,_status:-1,_result:null}},r.memo=function(e,r){return{$$typeof:d,type:e,compare:void 0===r?null:r}},r.useCallback=function(e,r){return D().useCallback(e,r)},r.useContext=function(e,r){return D().useContext(e,r)},r.useDebugValue=function(){},r.useEffect=function(e,r){return D().useEffect(e,r)},r.useImperativeHandle=function(e,r,t){return D().useImperativeHandle(e,r,t)},r.useLayoutEffect=function(e,r){return D().useLayoutEffect(e,r)},r.useMemo=function(e,r){return D().useMemo(e,r)},r.useReducer=function(e,r,t){return D().useReducer(e,r,t)},r.useRef=function(e){return D().useRef(e)},r.useState=function(e){return D().useState(e)},r.version="16.14.0"},6540:(e,r,t)=>{e.exports=t(5287)}}]);
|
|
1
|
+
"use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[159],{2995:(e,t,n)=>{n.r(t),n.d(t,{default:()=>A});var a=n(3490),s=n(4810),o=n(4147),r=n.n(o),l=n(7606),c=n(6452),i=n(3768),u=n(1431),g=n(9676),d=n(7041),m=n(3657),f=n(5027),p=n(3540),h=n(4712),E=n(5056),w=n(6890),S=n(3399);const v=e=>console.log.bind(console,e);var y,b={};const A=e=>{const[t,n]=(0,o.useState)({}),[A,D]=(0,o.useState)({}),[$,_]=(0,o.useState)({}),[k,x]=(0,o.useState)({"ui:submitButtonOptions":{props:{disabled:!1,className:"btn btn-info"},norender:!0,submitText:"Submit"}}),[C,T]=(0,o.useState)([]),[j,M]=(0,o.useState)(),[O,N]=(0,o.useState)(new Map),[B,U]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[J,L]=(0,o.useState)("unknown"),[P,K]=(0,o.useState)();function z(e,t){console.log(`sending ${e}`),console.log(t);const n=new Headers;return n.append("Content-Type","application/json"),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include",method:"POST",body:JSON.stringify(t),headers:n})}async function H(e){return console.log(`fetching ${e}`),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include"})}async function I(){console.log("getProgress");const e=await H("getProgress");if(200!=e.status)throw new Error(`Unable get progres: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}function R(){console.log("refreshing sensor map"),async function(){console.log("getSensors");const e=await H("getSensors");if(200!=e.status)throw new Error(`Unable get sensor data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{N(new Map(e.map((e=>[e.info.mac,e]))))})).catch((e=>{K(e)}))}function W(e){return Object.keys(e.config).length>0}function Y(e){const t=W(e);return r().createElement(w.A,{action:!0,onClick:()=>{e.config.mac_address=e.info.mac,_(e.schema),M(e.config)}},r().createElement("div",{class:"d-flex justify-content-between align-items-center",style:t?{fontWeight:"normal"}:{fontStyle:"italic"}},`${e._changesMade?"*":""}${e.info.name} MAC: ${e.info.mac} RSSI: ${n=e.info.RSSI,null==n?NaN:n}`,r().createElement("div",{class:"d-flex justify-content-between "},function(e){return null==e.info.lastContactDelta||e.info.lastContactDelta>e.config.discoveryTimeout?r().createElement(i.A,null):e.info.signalStrength>80?r().createElement(u.A,null):e.info.signalStrength>60?r().createElement(g.A,null):e.info.signalStrength>40?r().createElement(d.A,null):e.info.signalStrength>20?r().createElement(m.A,null):r().createElement(f.A,null)}(e))));var n}return(0,o.useEffect)((()=>{console.log("useEffect([])"),H("getPluginState").then((async e=>{if(404==e.status)throw L("unknown"),new Error("unable to get plugin state");const t=await e.json();L(t.state),await async function(){console.log("getDomains");const e=await H("getDomains");if(200!=e.status)throw new Error(`Unable get domain data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}(),console.log("Setting up eventsource");const n=new EventSource("/plugins/bt-sensors-plugin-sk/sse");return n.addEventListener("newsensor",(e=>{console.log("newsensor");let t=JSON.parse(e.data);y.has(t.info.mac)||(console.log(`New sensor: ${t.info.mac}`),N(new Map(y.set(t.info.mac,t))))})),n.addEventListener("sensorchanged",(e=>{let t=JSON.parse(e.data);if(console.log("sensorchanged"),console.log(t),y.has(t.mac)){let e=y.get(t.mac);Object.assign(e.info,t),N(new Map(y))}})),n.addEventListener("progress",(e=>{console.log("progress");const t=JSON.parse(e.data);U(t),console.log(t)})),n.addEventListener("pluginstate",(e=>{console.log("pluginstate");const t=JSON.parse(e.data);L(t.state)})),()=>n.close()})).catch((e=>{K(e)}))}),[]),(0,o.useEffect)((()=>{console.log("useEffect([pluginState])"),"started"==J?(R(),async function(){console.log("getBaseData");const e=await H("getBaseData");if(200!=e.status)throw new Error(`Unable get base data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{n(e.schema),D(e.data)})).catch((e=>{K(e)})),I().then((e=>{U(e)})).catch((e=>{K(e)}))):(N(new Map),n({}),D({}))}),[J]),(0,o.useEffect)((()=>{console.log("useEffect([sensorMap])"),y=O;const e=new Set(O.entries().map((e=>e[1].info.domain))),t={_configured:Array.from(O.entries()).filter((e=>W(e[1]))).map((e=>Y(O.get(e[0]))))};e.forEach((e=>{var n;t[e]=(n=e,Array.from(O.entries()).filter((e=>e[1].info.domain===n))).map((e=>Y(O.get(e[0]))))})),b=t}),[O]),"stopped"==J||"unknown"==J?r().createElement("h1",null,"Enable plugin to see configuration (if plugin is Enabled and you're seeing this message, restart SignalK)"):r().createElement("div",null,P?r().createElement("h2",{style:"color: red;"},P):"",r().createElement(a.Ay,{schema:t,validator:s.Ay,onChange:e=>D(e.formData),onSubmit:({formData:e},t)=>{var n;n=e,console.log("updateBaseData"),z("updateBaseData",n).then((e=>{200!=e.status?K(new Error(`Unable to update base data: ${e.statusText} (${e.status})`)):(I().then((e=>{U(e)})).catch((e=>{K(e)})),R())})),_({})},onError:v("errors"),formData:A}),r().createElement("p",null),r().createElement("p",null),B.deviceCount<B.totalDevices?r().createElement(S.A,{max:B.maxTimeout,now:B.progress}):"",r().createElement("h2",null,O.size>0?"Bluetooth Devices - Select to configure":""),r().createElement("h2",null,O.size>0?"(* = sensor has unsaved changes)":""),r().createElement("p",null),r().createElement(h.A,{defaultActiveKey:"_configured",id:"domain-tabs",className:"mb-3"},Object.keys(b).map((e=>{return n=(t=e).slice("_"===t.charAt(0)?1:0),r().createElement(E.A,{eventKey:t,title:n.charAt(0).toUpperCase()+n.slice(1)},r().createElement("div",{style:{paddingBottom:20},class:"d-flex flex-wrap justify-content-start align-items-start"},r().createElement(p.A,{style:{maxHeight:"300px",overflowY:"auto"}},function(e){return b[e]}(t)),r().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys($).length?"none":""}},r().createElement(a.Ay,{schema:$,validator:s.Ay,uiSchema:k,onChange:e=>{O.get(e.formData.mac_address)._changesMade=!0,M(e.formData)},onSubmit:({formData:e},t)=>{var n;console.log(e),n=e,console.log("updateSensorData"),z("updateSensorData",n).then((e=>{if(200!=e.status)throw new Error(e.statusText);O.get(n.mac_address)._changesMade=!1,O.get(n.mac_address).config=n})),_({}),alert("Changes saved")},onError:v("errors"),formData:j},r().createElement("div",null,r().createElement(l.A,{direction:"row",style:{spacing:5}},r().createElement(c.A,{type:"submit",color:"primary",variant:"contained"},"Save"),r().createElement(c.A,{variant:"contained",onClick:()=>{var e;e=j.mac_address,console.log("undoChanges"),O.get(e)._changesMade=!1,M(O.get(e).config)}},"Undo"),r().createElement(c.A,{variant:"contained",color:"secondary",onClick:e=>{return t=j.mac_address,void(window.confirm(`Delete configuration for ${t}?`)&&function(e){console.log("removeSensorData");try{z("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),y.delete(e),N(new Map(y)),_({})}catch{}}(t));var t}},"Delete")))))));var t,n}))))}}}]);
|