bt-sensors-plugin-sk 1.2.6-beta-4 → 1.2.6-beta-6
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 +120 -85
- package/README.md +9 -1
- package/index.js +43 -19
- package/package.json +2 -2
- package/public/847.js +1 -1
- package/sensor_classes/BankManager.js +23 -35
- package/sensor_classes/Beacon/Eddystone.js +1 -1
- package/sensor_classes/Beacon/iBeacon.js +1 -1
- package/sensor_classes/EcoWorthyBW02.js +13 -20
- package/sensor_classes/EctiveBMS.js +8 -11
- package/sensor_classes/GobiusCTankMeter.js +13 -26
- package/sensor_classes/JBDBMS.js +7 -10
- package/sensor_classes/JikongBMS.js +51 -32
- package/sensor_classes/Junctek.js +13 -24
- package/sensor_classes/KilovaultHLXPlus.js +16 -25
- package/sensor_classes/MercurySmartcraft.js +26 -36
- package/sensor_classes/MopekaTankSensor.js +1 -1
- package/sensor_classes/RemoranWave3.js +23 -31
- package/sensor_classes/Renogy/RenogySensor.js +6 -13
- package/sensor_classes/ShenzhenLiOnBMS.js +11 -23
- package/sensor_classes/UltrasonicWindMeter.js +26 -43
- package/sensor_classes/XiaomiMiBeacon.js +10 -27
- package/src/components/PluginConfigurationPanel.js +1 -2
package/BTSensor.js
CHANGED
|
@@ -102,7 +102,7 @@ class BTSensor extends EventEmitter {
|
|
|
102
102
|
Object.assign(this,config)
|
|
103
103
|
Object.assign(this,gattConfig)
|
|
104
104
|
|
|
105
|
-
this._state =
|
|
105
|
+
this._state = "UNKNOWN"
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* @function _test Test sensor parsing
|
|
@@ -257,6 +257,9 @@ class BTSensor extends EventEmitter {
|
|
|
257
257
|
|
|
258
258
|
_debugLog=[]
|
|
259
259
|
_errorLog=[]
|
|
260
|
+
_error = false
|
|
261
|
+
|
|
262
|
+
|
|
260
263
|
|
|
261
264
|
getErrorLog(){
|
|
262
265
|
return this._errorLog
|
|
@@ -267,22 +270,23 @@ class BTSensor extends EventEmitter {
|
|
|
267
270
|
|
|
268
271
|
debug(message){
|
|
269
272
|
if (this._app)
|
|
270
|
-
this._app.debug(message)
|
|
273
|
+
this._app.debug(`(${this.getName()} ${this.getMacAddress()}) ${message}`)
|
|
271
274
|
else
|
|
272
|
-
console.log(message)
|
|
275
|
+
console.log(`(${this.getName()} ${this.getMacAddress()})) ${message}`)
|
|
273
276
|
this._debugLog.push({timestamp:Date.now(), message:message})
|
|
274
277
|
}
|
|
275
278
|
|
|
276
279
|
setError(message){
|
|
277
280
|
if (this._app){
|
|
278
|
-
this._app.debug(message)
|
|
279
|
-
this._app.setPluginError(message)
|
|
281
|
+
this._app.debug(`(${this.getName()} ${this.getMacAddress()}) ${message}`)
|
|
282
|
+
this._app.setPluginError(`(${this.getName()} ${this.getMacAddress()}) ${message}`)
|
|
280
283
|
}
|
|
281
284
|
else
|
|
282
|
-
console.log(message)
|
|
285
|
+
console.log(`(${this.getName()} ${this.getMacAddress()}) ${message}`)
|
|
283
286
|
|
|
284
287
|
this._errorLog.push({timestamp:Date.now(), message:message})
|
|
285
|
-
this.
|
|
288
|
+
this._error=true
|
|
289
|
+
this.emit("error", true)
|
|
286
290
|
}
|
|
287
291
|
|
|
288
292
|
//Instance Initialization functions
|
|
@@ -327,7 +331,7 @@ class BTSensor extends EventEmitter {
|
|
|
327
331
|
description: this.getGATTDescription(),
|
|
328
332
|
type:"object",
|
|
329
333
|
properties:{
|
|
330
|
-
useGATT: {title: "Use GATT connection", type: "boolean", default:
|
|
334
|
+
useGATT: {title: "Use GATT connection", type: "boolean", default: true },
|
|
331
335
|
pollFreq: { type: "number", title: "Polling frequency in seconds"}
|
|
332
336
|
}
|
|
333
337
|
}
|
|
@@ -349,16 +353,21 @@ class BTSensor extends EventEmitter {
|
|
|
349
353
|
|
|
350
354
|
}
|
|
351
355
|
async init(){
|
|
356
|
+
this.setState("INITIALIZING")
|
|
357
|
+
|
|
352
358
|
this.currentProperties = await this.constructor.getDeviceProps(this.device)
|
|
353
359
|
await this.initSchema()
|
|
354
360
|
|
|
355
361
|
this.initListen()
|
|
362
|
+
this.setState("DORMANT")
|
|
363
|
+
|
|
356
364
|
}
|
|
357
365
|
|
|
358
366
|
initListen(){
|
|
359
367
|
this.listen()
|
|
360
368
|
}
|
|
361
|
-
activate(config, plugin){
|
|
369
|
+
async activate(config, plugin){
|
|
370
|
+
this.setState("ACTIVATING")
|
|
362
371
|
if (config.paths){
|
|
363
372
|
this.createPaths(config,plugin.id)
|
|
364
373
|
this.initPaths(config,plugin.id)
|
|
@@ -366,13 +375,16 @@ class BTSensor extends EventEmitter {
|
|
|
366
375
|
}
|
|
367
376
|
if (this.usingGATT()){
|
|
368
377
|
try {
|
|
369
|
-
this.activateGATT()
|
|
378
|
+
await this.activateGATT()
|
|
370
379
|
} catch (e) {
|
|
371
|
-
this.setError(`GATT services unavailable
|
|
372
|
-
|
|
380
|
+
this.setError(`GATT services unavailable.`)
|
|
381
|
+
throw new Error(`GATT services unavailable for ${this.getName()}. Reason: ${e}`)
|
|
373
382
|
}
|
|
383
|
+
} else {
|
|
384
|
+
this.setState("ACTIVE")
|
|
374
385
|
}
|
|
375
|
-
this.
|
|
386
|
+
this._active = true
|
|
387
|
+
|
|
376
388
|
this._propertiesChanged(this.currentProperties)
|
|
377
389
|
|
|
378
390
|
}
|
|
@@ -383,23 +395,17 @@ class BTSensor extends EventEmitter {
|
|
|
383
395
|
return this._gattServer
|
|
384
396
|
}
|
|
385
397
|
async activateGATT(isReconnecting=false){
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
catch(e) {
|
|
395
|
-
this.debug(`Unable to activate GATT connection for ${this.getName()} (${this.getMacAddress()}): ${e}`)
|
|
396
|
-
}
|
|
398
|
+
this.setState("ACTIVATING GATT")
|
|
399
|
+
await this.initGATTConnection(isReconnecting)
|
|
400
|
+
if (this.pollFreq)
|
|
401
|
+
await this.initGATTInterval()
|
|
402
|
+
else
|
|
403
|
+
await this.initGATTNotifications()
|
|
404
|
+
|
|
397
405
|
}
|
|
398
406
|
|
|
399
|
-
async
|
|
400
|
-
if (this.
|
|
401
|
-
this.debug(`(${this.getName()}) disconnecting from GATT server`)
|
|
402
|
-
if (this._gattServer) { //getGATTServer() was called which calls node-ble's Device::gatt() which needs cleaning up after
|
|
407
|
+
async stopAllGATTNotifications(){
|
|
408
|
+
if (this._gattServer) { //getGATTServer() was called which calls node-ble's Device::gatt() which needs cleaning up after
|
|
403
409
|
(await this._gattServer.services()).forEach(async (uuid) => {
|
|
404
410
|
await this._gattServer.getPrimaryService(uuid).then(async (service) => {
|
|
405
411
|
(await service.characteristics()).forEach(async (uuid) => {
|
|
@@ -409,8 +415,12 @@ class BTSensor extends EventEmitter {
|
|
|
409
415
|
});
|
|
410
416
|
this._gattServer.helper.removeListeners();
|
|
411
417
|
});
|
|
412
|
-
|
|
413
|
-
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async deactivateGATT(){
|
|
421
|
+
if (this.device) {
|
|
422
|
+
this.debug(`Disconnecting from GATT server...`)
|
|
423
|
+
await this.deviceDisconnect()
|
|
414
424
|
}
|
|
415
425
|
}
|
|
416
426
|
|
|
@@ -528,7 +538,7 @@ class BTSensor extends EventEmitter {
|
|
|
528
538
|
for (let attempts = 0; attempts<retries; attempts++) {
|
|
529
539
|
try
|
|
530
540
|
{
|
|
531
|
-
this.debug( `
|
|
541
|
+
this.debug( `Trying to connect (attempt # ${attempts +1}) to Bluetooth device.` );
|
|
532
542
|
await this.deviceConnect(isReconnecting);
|
|
533
543
|
return this.device
|
|
534
544
|
}
|
|
@@ -536,43 +546,56 @@ class BTSensor extends EventEmitter {
|
|
|
536
546
|
catch (e){
|
|
537
547
|
if (attempts==retries)
|
|
538
548
|
throw new Error (`(${this.getName}) Unable to connect to Bluetooth device after ${attempts} attempts`)
|
|
539
|
-
this.debug(`
|
|
549
|
+
this.debug(`Error connecting to device. Retrying... `);
|
|
540
550
|
await new Promise((r) => setTimeout(r, retryInterval*1000));
|
|
541
551
|
|
|
542
552
|
}
|
|
543
553
|
}
|
|
544
554
|
}
|
|
545
555
|
setConnected(state){
|
|
546
|
-
this.
|
|
547
|
-
this.emit("connected", this._connected)
|
|
556
|
+
this.setState(state?"CONNECTED":"DISCONNECTED")
|
|
548
557
|
}
|
|
549
|
-
deviceConnect(isReconnecting=false, autoReconnect=false) {
|
|
550
558
|
|
|
559
|
+
isError(){
|
|
560
|
+
return this._error
|
|
561
|
+
}
|
|
562
|
+
deviceConnect(isReconnecting=false, autoReconnect=false) {
|
|
551
563
|
|
|
552
564
|
return connectQueue.enqueue( async ()=>{
|
|
553
565
|
this.debug(`Connecting... ${this.getName()}`)
|
|
566
|
+
this.setState("CONNECTING")
|
|
567
|
+
if (!isReconnecting){
|
|
568
|
+
this.device.on("disconnect", () => {
|
|
569
|
+
this.debug("Device disconnected.")
|
|
570
|
+
this.setConnected(false)
|
|
571
|
+
})
|
|
572
|
+
this.device.on("connect", () => {
|
|
573
|
+
this.debug("Device connected.")
|
|
574
|
+
this.setConnected(true)
|
|
575
|
+
})
|
|
576
|
+
}
|
|
554
577
|
await this.device.helper.callMethod('Connect')
|
|
578
|
+
this.setConnected(true)
|
|
555
579
|
|
|
556
580
|
this.debug(`Connected to ${this.getName()}`)
|
|
557
581
|
if (!isReconnecting) {
|
|
558
582
|
this.device.helper.on(
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
583
|
+
"PropertiesChanged",
|
|
584
|
+
(propertiesChanged) => {
|
|
585
|
+
if ("Connected" in propertiesChanged) {
|
|
586
|
+
const { value } = propertiesChanged.Connected;
|
|
587
|
+
if (value) {
|
|
588
|
+
this.device.emit("connect", { connected: true });
|
|
589
|
+
} else {
|
|
590
|
+
this.device.emit("disconnect", { connected: false });
|
|
591
|
+
}
|
|
592
|
+
}
|
|
569
593
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
this._connected = false;
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
if (autoReconnect){
|
|
597
|
+
this.device.on("disconnect", async () => {
|
|
598
|
+
|
|
576
599
|
if (this.isActive()) {
|
|
577
600
|
this.debug(
|
|
578
601
|
`Device disconnected. Attempting to reconnect to ${this.getName()}`
|
|
@@ -583,16 +606,16 @@ class BTSensor extends EventEmitter {
|
|
|
583
606
|
this.debug(`(${this.getName()}) Device reconnected.`);
|
|
584
607
|
} catch (e) {
|
|
585
608
|
this.setError(
|
|
586
|
-
`Error while reconnecting
|
|
609
|
+
`Error while reconnecting: ${
|
|
587
610
|
e.message
|
|
588
611
|
}`
|
|
589
612
|
);
|
|
590
613
|
this.debug(
|
|
591
|
-
`Error while reconnecting
|
|
614
|
+
`Error while reconnecting: ${
|
|
592
615
|
e.message
|
|
593
616
|
}`
|
|
594
617
|
);
|
|
595
|
-
this.debug(e);
|
|
618
|
+
this._app.debug(e);
|
|
596
619
|
}
|
|
597
620
|
}
|
|
598
621
|
});
|
|
@@ -628,36 +651,51 @@ class BTSensor extends EventEmitter {
|
|
|
628
651
|
|
|
629
652
|
})
|
|
630
653
|
|
|
631
|
-
}
|
|
654
|
+
}
|
|
655
|
+
async deviceDisconnect(){
|
|
656
|
+
await this.stopAllGATTNotifications()
|
|
657
|
+
await this.device.disconnect()
|
|
658
|
+
this.setConnected(false)
|
|
659
|
+
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
async stopGATTNotifications(gattCharacteristic) {
|
|
663
|
+
if (gattCharacteristic){
|
|
664
|
+
gattCharacteristic.removeAllListeners()
|
|
632
665
|
|
|
666
|
+
try{
|
|
667
|
+
if (await gattCharacteristic.isNotifying())
|
|
668
|
+
await gattCharacteristic.stopNotifications();
|
|
669
|
+
} catch (e){
|
|
670
|
+
this.debug(`Error stopping notifications: ${e.message}`)
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
633
674
|
/**
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
* This function is only called when the property pollFreq is set to > 0
|
|
637
|
-
* The function calls #emitGATT() at the specified interval then disconnects
|
|
638
|
-
* from the device.
|
|
675
|
+
* The function calls #emitGATT() at the specified interval then calls deactivateGATT()
|
|
676
|
+
* which disconnects from the device.
|
|
639
677
|
*/
|
|
640
678
|
|
|
641
|
-
initGATTInterval(){
|
|
642
|
-
this.
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
catch(error) {
|
|
649
|
-
this.debug(error)
|
|
650
|
-
throw new Error(`unable to emit values for device ${this.getName()}:${error}`)
|
|
651
|
-
}
|
|
652
|
-
finally{
|
|
653
|
-
this.deactivateGATT().catch(
|
|
654
|
-
(e)=>{
|
|
655
|
-
this.debug(`(${this.getName()}) Error deactivating GATT Connection: ${e.message}`)
|
|
656
|
-
})
|
|
657
|
-
}
|
|
679
|
+
async initGATTInterval(){
|
|
680
|
+
await this.deviceDisconnect()
|
|
681
|
+
|
|
682
|
+
this.intervalID = setInterval( async () => {
|
|
683
|
+
try {
|
|
684
|
+
await this.initGATTConnection(true)
|
|
685
|
+
await this.emitGATT()
|
|
658
686
|
}
|
|
659
|
-
|
|
660
|
-
|
|
687
|
+
catch(error) {
|
|
688
|
+
this.debug(error)
|
|
689
|
+
this.setError(`Unable to emit values for device: ${error.message}`)
|
|
690
|
+
}
|
|
691
|
+
finally{
|
|
692
|
+
await this.deactivateGATT().catch( (e)=>{
|
|
693
|
+
this.debug(`Error deactivating GATT Connection: ${e.message}`)
|
|
694
|
+
})
|
|
695
|
+
this.setState("WAITING")
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
, this.pollFreq*1000)
|
|
661
699
|
}
|
|
662
700
|
|
|
663
701
|
/**
|
|
@@ -828,7 +866,7 @@ class BTSensor extends EventEmitter {
|
|
|
828
866
|
}
|
|
829
867
|
|
|
830
868
|
isActive(){
|
|
831
|
-
return this
|
|
869
|
+
return this?._active??false
|
|
832
870
|
}
|
|
833
871
|
getBars(){
|
|
834
872
|
const ss = this.getSignalStrength()
|
|
@@ -903,9 +941,7 @@ class BTSensor extends EventEmitter {
|
|
|
903
941
|
emitData(tag, buffer, ...args){
|
|
904
942
|
const md = this.getPath(tag)
|
|
905
943
|
if (md && md.read)
|
|
906
|
-
this.emit(tag, md.read(buffer, ...args))
|
|
907
|
-
|
|
908
|
-
|
|
944
|
+
this.emit(tag, md.read(buffer, ...args))
|
|
909
945
|
}
|
|
910
946
|
|
|
911
947
|
emitValuesFrom(buffer){
|
|
@@ -963,12 +999,11 @@ class BTSensor extends EventEmitter {
|
|
|
963
999
|
this.device.helper.removeListeners()
|
|
964
1000
|
|
|
965
1001
|
if (this.intervalID){
|
|
966
|
-
this.debug(`${this.getName()}::stopListening called clearInterval()`)
|
|
967
1002
|
clearInterval(this.intervalID)
|
|
968
1003
|
}
|
|
969
1004
|
if( this.usingGATT() )
|
|
970
1005
|
await this.deactivateGATT()
|
|
971
|
-
this.setState("
|
|
1006
|
+
this.setState("DORMANT")
|
|
972
1007
|
}
|
|
973
1008
|
//END Sensor listen-to-changes functions
|
|
974
1009
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Bluetooth Sensors for [Signal K](http://www.signalk.org)
|
|
2
2
|
|
|
3
3
|
## WHAT'S NEW
|
|
4
|
+
|
|
5
|
+
# Version 1.2.6-beta-6
|
|
6
|
+
- Funny you should ask...
|
|
7
|
+
|
|
8
|
+
# Version 1.2.6-beta-5
|
|
9
|
+
|
|
10
|
+
- JikongBMS fixes
|
|
11
|
+
|
|
4
12
|
# Version 1.2.6-beta-4
|
|
5
13
|
|
|
6
14
|
- Improved reconnect logic for connected devices
|
|
@@ -111,12 +119,12 @@ It's pretty easy to write and deploy your own sensor class for any currently uns
|
|
|
111
119
|
|Redodo| Rebranded LiTime |
|
|
112
120
|
|Kilovault| [Kilovault HLX+ smart batteries ](https://sunwatts.com/content/manual/KiloVault_HLX_PLUS_Datasheet_06252021%20%281%29.pdf?srsltid=AfmBOooY-cGnC_Qm6V1T9Vg5oZzBCJurS0AOGoWqWeyy-dwz2vA-l1Jb) (Note: Kilovault appears to be out of business as of March 2024) |
|
|
113
121
|
|[Lancol](www.Lancol.com)| [Micro 10C 12V Car Battery Monitor](https://www.lancol.com/product/12v-bluetooth-4-0-battery-tester-micro-10-c/)|
|
|
122
|
+
|[Jikong](https://jikongbms.com/)| https://jikongbms.com/product/ |
|
|
114
123
|
|[Junctek](https://www.junteks.com)|[Junctek BMS](https://www.junteks.com/pages/product/index) |
|
|
115
124
|
|[Remoran](https://remoran.eu)| [Remoran Wave.3](https://remoran.eu/wave.html)|
|
|
116
125
|
|[AC DC Systems](https://marinedcac.com) | [Bank Manager] hybrid (Pb and Li) charger(https://marinedcac.com/pages/bankmanager)|
|
|
117
126
|
|[Ective](https://ective.de/)| Also Topband(?), Skanbatt and others |
|
|
118
127
|
|
|
119
|
-
|
|
120
128
|
### Environmental
|
|
121
129
|
| Manufacturer | Devices |
|
|
122
130
|
|--------------|----------|
|
package/index.js
CHANGED
|
@@ -85,6 +85,9 @@ class MissingSensor {
|
|
|
85
85
|
isActive(){
|
|
86
86
|
return false
|
|
87
87
|
}
|
|
88
|
+
isConnected(){return false}
|
|
89
|
+
|
|
90
|
+
|
|
88
91
|
elapsedTimeSinceLastContact(){
|
|
89
92
|
return NaN
|
|
90
93
|
}
|
|
@@ -94,6 +97,12 @@ class MissingSensor {
|
|
|
94
97
|
prepareConfig(){
|
|
95
98
|
|
|
96
99
|
}
|
|
100
|
+
getErrorLog(){
|
|
101
|
+
return []
|
|
102
|
+
}
|
|
103
|
+
getDebugLog(){
|
|
104
|
+
return []
|
|
105
|
+
}
|
|
97
106
|
|
|
98
107
|
}
|
|
99
108
|
module.exports = function (app) {
|
|
@@ -247,9 +256,9 @@ module.exports = function (app) {
|
|
|
247
256
|
options, async () => {
|
|
248
257
|
res.status(200).json({message: "Sensor updated"})
|
|
249
258
|
if (sensor) {
|
|
250
|
-
removeSensorFromList(sensor)
|
|
251
259
|
if (sensor.isActive())
|
|
252
260
|
await sensor.stopListening()
|
|
261
|
+
removeSensorFromList(sensor)
|
|
253
262
|
}
|
|
254
263
|
initConfiguredDevice(req.body)
|
|
255
264
|
}
|
|
@@ -355,6 +364,7 @@ module.exports = function (app) {
|
|
|
355
364
|
class: sensor.constructor.name,
|
|
356
365
|
domain: sensor.getDomain().name,
|
|
357
366
|
state: sensor.getState(),
|
|
367
|
+
error: sensor.isError(),
|
|
358
368
|
errorLog: sensor.getErrorLog(),
|
|
359
369
|
debugLog: sensor.getDebugLog(),
|
|
360
370
|
RSSI: sensor.getRSSI(),
|
|
@@ -406,12 +416,29 @@ module.exports = function (app) {
|
|
|
406
416
|
}
|
|
407
417
|
|
|
408
418
|
function removeSensorFromList(sensor){
|
|
419
|
+
sensor.removeAllListeners("state")
|
|
420
|
+
sensor.removeAllListeners("connected")
|
|
421
|
+
sensor.removeAllListeners("error")
|
|
422
|
+
sensor.removeAllListeners("debug")
|
|
423
|
+
|
|
409
424
|
sensorMap.delete(sensor.getMacAddress())
|
|
410
425
|
channel.broadcast({mac:sensor.getMacAddress()},"removesensor")
|
|
411
426
|
}
|
|
412
427
|
|
|
413
428
|
function addSensorToList(sensor){
|
|
414
429
|
sensorMap.set(sensor.getMacAddress(),sensor)
|
|
430
|
+
sensor.on("state", (state)=>{
|
|
431
|
+
updateSensor(sensor)
|
|
432
|
+
})
|
|
433
|
+
sensor.on("connected", (state)=>{
|
|
434
|
+
updateSensor(sensor)
|
|
435
|
+
})
|
|
436
|
+
sensor.on("error",(error)=>{
|
|
437
|
+
updateSensor(sensor)
|
|
438
|
+
})
|
|
439
|
+
sensor.on("debug", ()=>{
|
|
440
|
+
updateSensor(sensor)
|
|
441
|
+
})
|
|
415
442
|
channel.broadcast(sensorToJSON(sensor),"newsensor");
|
|
416
443
|
}
|
|
417
444
|
function deviceNameAndAddress(config){
|
|
@@ -460,19 +487,10 @@ module.exports = function (app) {
|
|
|
460
487
|
device.once("deviceFound",async (device)=>{
|
|
461
488
|
s.device=device
|
|
462
489
|
s.listen()
|
|
463
|
-
s.activate(config, plugin)
|
|
490
|
+
await s.activate(config, plugin)
|
|
464
491
|
removeSensorFromList(s)
|
|
465
492
|
addSensorToList(s)
|
|
466
493
|
})
|
|
467
|
-
s.on("state", (state)=>{
|
|
468
|
-
channel.broadcast(getSensorInfo(s), "sensorchanged")
|
|
469
|
-
})
|
|
470
|
-
s.on("error",(error)=>{
|
|
471
|
-
channel.broadcast(getSensorInfo(s), "sensorchanged")
|
|
472
|
-
})
|
|
473
|
-
s.on("debug", ()=>{
|
|
474
|
-
channel.broadcast(getSensorInfo(s), "sensorchanged")
|
|
475
|
-
})
|
|
476
494
|
addSensorToList(s)
|
|
477
495
|
resolve(s)
|
|
478
496
|
}
|
|
@@ -528,11 +546,13 @@ module.exports = function (app) {
|
|
|
528
546
|
return sensor
|
|
529
547
|
}
|
|
530
548
|
catch(error){
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
549
|
+
if (!config.unconfigured) {
|
|
550
|
+
const msg = `Unable to instantiate ${await BTSensor.getDeviceProp(device,"Address")}: ${error.message} `
|
|
551
|
+
plugin.debug(msg)
|
|
552
|
+
plugin.debug(error)
|
|
553
|
+
if (config.active)
|
|
554
|
+
plugin.setError(msg)
|
|
555
|
+
}
|
|
536
556
|
return null
|
|
537
557
|
}
|
|
538
558
|
|
|
@@ -543,19 +563,23 @@ module.exports = function (app) {
|
|
|
543
563
|
plugin.setStatusText(`Initializing ${deviceNameAndAddress(deviceConfig)}`);
|
|
544
564
|
if (!deviceConfig.discoveryTimeout)
|
|
545
565
|
deviceConfig.discoveryTimeout = options.discoveryTimeout
|
|
546
|
-
createSensor(adapter, deviceConfig).then((sensor)=>{
|
|
566
|
+
createSensor(adapter, deviceConfig).then(async (sensor)=>{
|
|
547
567
|
if (startNumber != starts ) {
|
|
548
568
|
return
|
|
549
569
|
}
|
|
550
570
|
if (deviceConfig.active && !(sensor.device instanceof OutOfRangeDevice) ) {
|
|
551
571
|
plugin.setStatusText(`Listening to ${++foundConfiguredDevices} sensors.`);
|
|
552
|
-
|
|
572
|
+
try {
|
|
573
|
+
await sensor.activate(deviceConfig, plugin)
|
|
574
|
+
} catch (e){
|
|
575
|
+
sensor.setError(`Unable to activate sensor. Reason: ${e.message}`)
|
|
576
|
+
}
|
|
553
577
|
}
|
|
554
578
|
|
|
555
579
|
})
|
|
556
580
|
.catch((error)=>
|
|
557
581
|
{
|
|
558
|
-
if (deviceConfig
|
|
582
|
+
if (deviceConfig?.unconfigured??false) return
|
|
559
583
|
if (startNumber != starts ) {
|
|
560
584
|
return
|
|
561
585
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bt-sensors-plugin-sk",
|
|
3
|
-
"version": "1.2.6-beta-
|
|
3
|
+
"version": "1.2.6-beta-6",
|
|
4
4
|
"description": "Bluetooth Sensors for Signalk - see https://www.npmjs.com/package/bt-sensors-plugin-sk#supported-sensors for a list of supported sensors",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"@rjsf/validator-ajv8": "^5.24.11",
|
|
11
11
|
"better-sse": "^0.14.1",
|
|
12
12
|
"buffer": "^6.0.3",
|
|
13
|
-
"dbus-next": "^0.10.
|
|
13
|
+
"@jellybrick/dbus-next": "^0.10.3",
|
|
14
14
|
"int24": "^0.0.1",
|
|
15
15
|
"kaitai-struct": "^0.10.0",
|
|
16
16
|
"node-ble": "^1.13.0",
|
package/public/847.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[847],{9337:()=>{},62995:(e,t,n)=>{"use strict";n.r(t),n.d(t,{BTConfig:()=>k,default:()=>C});var a=n(73490),s=n(74810),r=n(40334),o=n(86528),c=n.n(o),i=n(11363),l=n(97493),u=n(27606),m=n(82096),d=n(3768),g=n(71431),f=n(39676),h=n(47041),p=n(86038),E=n(95027),w=n(43540),y=n(38250),S=n(31008),b=n(20455),v=n(23399);const A=e=>console.log.bind(console,e);function k(e){const t=(0,m.A)((e=>({root:{"& > *":{margin:e.spacing(1)}}}))),[n,k]=(0,o.useState)({}),[C,D]=(0,o.useState)({}),[_
|
|
1
|
+
(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[847],{9337:()=>{},62995:(e,t,n)=>{"use strict";n.r(t),n.d(t,{BTConfig:()=>k,default:()=>C});var a=n(73490),s=n(74810),r=n(40334),o=n(86528),c=n.n(o),i=n(11363),l=n(97493),u=n(27606),m=n(82096),d=n(3768),g=n(71431),f=n(39676),h=n(47041),p=n(86038),E=n(95027),w=n(43540),y=n(38250),S=n(31008),b=n(20455),v=n(23399);const A=e=>console.log.bind(console,e);function k(e){const t=(0,m.A)((e=>({root:{"& > *":{margin:e.spacing(1)}}}))),[n,k]=(0,o.useState)({}),[C,D]=(0,o.useState)({}),[$,_]=(0,o.useState)({}),[x,N]=(0,o.useState)({"ui:options":{label:!1},paths:{enableMarkdownInDescription:!0},title:{"ui:widget":"hidden"}}),[O,T]=(0,o.useState)(),[j,M]=(0,o.useState)(!1),[U,J]=(0,o.useState)(!0),[L,R]=(0,o.useState)(new Map),[I,P]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[K,B]=(0,o.useState)("unknown"),[G,W]=(0,o.useState)(),[F,H]=(0,o.useState)(!1),[z,Y]=(0,o.useState)(""),q=t();function Q(e,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 V(e,t={}){let n;try{const a=Object.keys(t).length?"?"+new URLSearchParams(t).toString():"";n=await fetch(`/plugins/bt-sensors-plugin-sk/${e}${a}`,{credentials:"include",method:"GET"})}catch(e){n={status:500,statusText:e.toString()}}return n}function X(e){return Object.keys(e.configCopy).length>0}function Z(e){const t=X(e);return c().createElement(b.A,{action:!0,onClick:()=>{e.config.mac_address=e.info.mac,_(e.schema),T(e.config)}},c().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}`,c().createElement("div",{class:"d-flex justify-content-between "},`${e.info.state} ${e.info.error?" (ERROR)":""}`,c().createElement("div",{class:"d-flex justify-content-between "},function(e){return null==e.info.lastContactDelta||e.info.lastContactDelta>e.config.discoveryTimeout?c().createElement(d.A,null):e.info.signalStrength>80?c().createElement(g.A,null):e.info.signalStrength>60?c().createElement(f.A,null):e.info.signalStrength>40?c().createElement(h.A,null):e.info.signalStrength>20?c().createElement(p.A,null):c().createElement(E.A,null)}(e)))));var n}function ee(e){window.open(e,"_blank","noreferrer")}return(0,o.useEffect)((()=>{let e=null;return V("getPluginState").then((async t=>{if(404==t.status)throw B("unknown"),new Error("unable to get plugin state");const n=await t.json();e=new EventSource("/plugins/bt-sensors-plugin-sk/sse",{withCredentials:!0}),e.addEventListener("newsensor",(e=>{!function(e){let t=JSON.parse(e.data);console.log(`New sensor: ${t.info.mac}`),R((e=>(e.set(t.info.mac,t),new Map(e))))}(e)})),e.addEventListener("sensorchanged",(e=>{!function(e){console.log("sensorchanged");const t=JSON.parse(e.data);console.log(t),R((e=>{const n=e.get(t.mac);return n&&Object.assign(n.info,t),new Map(e)}))}(e)})),e.addEventListener("progress",(e=>{const t=JSON.parse(e.data);P(t)})),e.addEventListener("pluginstate",(e=>{const t=JSON.parse(e.data);B(t.state)})),B(n.state),(async()=>{const e=await async function(){const e=await V("getSensors");if(200!=e.status)throw new Error(`Unable get sensor data: ${e.statusText} (${e.status}) `);return await e.json()}();R(new Map(e.map((e=>[e.info.mac,e]))))})()})).catch((e=>{W(e.message)})),()=>{console.log("Closing connection to SSE"),e.close()}}),[]),(0,o.useEffect)((()=>{if(!j)return;if(!O||!L)return;const e=L.get(O.mac_address);e&&$&&O&&Object.hasOwn(O,"params")&&"UNKNOWN"==e.info.class&&O.params.sensorClass&&"UNKNOWN"!=O.params.sensorClass&&(J(!1),Y(`Please wait. Fetching schema for ${O.params.sensorClass}...`),async function(e,t){const n=await V("getSensorInfo",{mac_address:e,class:t});if(200!=n.status)throw new Error(`Unable get sensor info: ${n.statusText} (${n.status}) `);return await n.json()}(O.mac_address,O.params.sensorClass).then((e=>{_(e.schema)})).catch((e=>{alert(e.message)})).finally((()=>{Y(""),J(!0),M(!1)})))}),[j]),(0,o.useEffect)((()=>{H(""!=z)}),[z]),(0,o.useEffect)((()=>{"started"==K?(async function(){const e=await V("getBaseData");if(200!=e.status)throw new Error(`Unable to get base data: ${e.statusText} (${e.status}) `);const t=await e.json();return t.schema.htmlDescription=c().createElement("div",null,(0,r.Ay)(t.schema.htmlDescription),c().createElement("p",null)),t}().then((e=>{k(e.schema),D(e.data)})).catch((e=>{W(e.message)})),async function(){const e=await V("getProgress");if(200!=e.status)throw new Error(`Unable to get progress: ${e.statusText} (${e.status}) `);return await e.json()}().then((e=>{P(e)})).catch((e=>{W(e.message)}))):(k({}),D({}))}),[K]),"stopped"==K||"unknown"==K?c().createElement("h3",null,"Enable plugin to see configuration"):c().createElement("div",null,c().createElement(i.A,{anchorOrigin:{horizontal:"center",vertical:"bottom"},onClose:()=>H(!1),open:F,message:z,key:"snackbar"}),c().createElement("div",{className:q.root},c().createElement(l.A,{variant:"contained",onClick:()=>{ee("https://github.com/naugehyde/bt-sensors-plugin-sk/tree/1.2.0-beta#configuration")}},"Documentation"),c().createElement(l.A,{variant:"contained",onClick:()=>{ee("https://github.com/naugehyde/bt-sensors-plugin-sk/issues/new/choose")}},"Report Issue"),c().createElement(l.A,{variant:"contained",onClick:()=>{ee("https://discord.com/channels/1170433917761892493/1295425963466952725")}},"Discord Thread"),c().createElement("p",null),c().createElement("p",null)),c().createElement("hr",{style:{width:"100%",height:"1px",color:"gray","background-color":"gray","text-align":"left","margin-left":0}}),G?c().createElement("h2",{style:{color:"red"}},G):"",c().createElement(a.Ay,{schema:n,validator:s.Ay,uiSchema:{"ui:field":"LayoutGridField","ui:layoutGrid":{"ui:row":[{"ui:row":{className:"row",children:[{"ui:columns":{className:"col-xs-4",children:["adapter","transport","duplicateData","discoveryTimeout","discoveryInterval"]}}]}}]}},onChange:e=>D(e.formData),onSubmit:({formData:e},t)=>{var n;n=e,R(new Map),Q("updateBaseData",n).then((e=>{200!=e.status&&W(`Unable to update base data: ${e.statusText} (${e.status})`)})),_({})},onError:A("errors"),formData:C}),c().createElement("hr",{style:{width:"100%",height:"1px",color:"gray","background-color":"gray","text-align":"left","margin-left":0}}),c().createElement("p",null),c().createElement("p",null),I.deviceCount<I.totalDevices?c().createElement(v.A,{max:I.maxTimeout,now:I.progress}):"",c().createElement("p",null),c().createElement(y.A,{defaultActiveKey:"_configured",id:"domain-tabs",className:"mb-3"},function(){const e=[...new Set(L.entries().map((e=>e[1].info.domain)))].sort(),t=Array.from(L.entries()).filter((e=>X(e[1])));let n={};return n._configured=0==t.length?"Select a device from its domain tab (Electrical etc.) and configure it.":t.map((e=>Z(L.get(e[0])))),e.forEach((e=>{var t;n[e]=(t=e,Array.from(L.entries()).filter((e=>e[1].info.domain===t))).map((e=>Z(L.get(e[0]))))})),Object.keys(n).map((e=>function(e,t){let n=e.slice("_"===e.charAt(0)?1:0);return c().createElement(S.A,{eventKey:e,title:`${n.charAt(0).toUpperCase()}${n.slice(1)}${"string"==typeof t?"":" ("+t.length+")"}`},c().createElement(w.A,{style:{maxHeight:"300px",overflowY:"auto"}},t))}(e,n[e])))}()),c().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys($).length?"none":""}},c().createElement(u.A,{container:!0,direction:"column",style:{spacing:5}},c().createElement(u.A,{item:!0},c().createElement("h2",null,$?.title),c().createElement("p",null)),c().createElement(u.A,{item:!0},(0,r.Ay)($?.htmlDescription))),c().createElement("fieldset",{disabled:!U},c().createElement(a.Ay,{schema:$,validator:s.Ay,uiSchema:x,onChange:(e,t)=>{const n=L.get(e.formData.mac_address);n&&(n._changesMade=!0,n.config=e.formData,T(e.formData)),"root_params_sensorClass"==t&&M(!0)},onSubmit:({formData:e},t)=>{var n;Q("updateSensorData",n=e).then((e=>{if(200!=e.status)throw new Error(e.statusText);R((e=>(e.delete(n.mac_address),new Map(e)))),_({})})),alert("Changes saved")},onError:A("errors"),formData:O},c().createElement("div",{className:q.root},c().createElement(l.A,{type:"submit",color:"primary",variant:"contained"},"Save"),c().createElement(l.A,{variant:"contained",onClick:()=>{var e;e=O.mac_address,L.get(e)._changesMade=!1,L.get(e).config=JSON.parse(JSON.stringify(L.get(e).configCopy)),T(L.get(e).config)}},"Undo"),c().createElement(l.A,{variant:"contained",color:"secondary",onClick:e=>function(e){const t=L.get(e);(!X(t)||window.confirm(`Delete configuration for ${t.info.name}?`))&&function(e){try{Q("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),R((t=>(t.delete(e),new Map(t)))),_({})}catch{}}(e)}(O.mac_address)},"Delete"))))))}const C=k}}]);
|