bt-sensors-plugin-sk 1.2.0-beta.0.0.2 → 1.2.0-beta.0.0.4
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 +27 -16
- package/Queue.js +48 -0
- package/package.json +1 -1
- package/sensor_classes/JBDBMS.js +3 -5
- package/testqueue.js +64 -0
package/BTSensor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Variant } = require('dbus-next');
|
|
2
2
|
const { log } = require('node:console');
|
|
3
3
|
const EventEmitter = require('node:events');
|
|
4
|
-
|
|
4
|
+
const AutoQueue = require("./Queue.js")
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @author Andrew Gerngross <oh.that.andy@gmail.com>
|
|
@@ -12,6 +12,7 @@ var {exec} = require('child_process');
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
const BTCompanies = require('./bt_co.json');
|
|
15
|
+
const connectQueue = new AutoQueue()
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* @global A map of company names keyed by their Bluetooth ID
|
|
@@ -450,8 +451,7 @@ class BTSensor extends EventEmitter {
|
|
|
450
451
|
throw new Error("::initGATTNotifications() should be implemented by the BTSensor subclass")
|
|
451
452
|
}
|
|
452
453
|
|
|
453
|
-
|
|
454
|
-
await this.device.connect()
|
|
454
|
+
deviceConnect() {
|
|
455
455
|
|
|
456
456
|
/* CAUTION: HACK AHEAD
|
|
457
457
|
|
|
@@ -465,16 +465,23 @@ class BTSensor extends EventEmitter {
|
|
|
465
465
|
|
|
466
466
|
You know, the little things.
|
|
467
467
|
*/
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
468
|
+
return connectQueue.enqueue( async ()=>{
|
|
469
|
+
this.debug(`Connecting to ${this.getName()}`)
|
|
470
|
+
await this.device.connect()
|
|
471
|
+
try {
|
|
472
|
+
|
|
473
|
+
await this._adapter.helper.callMethod('StopDiscovery')
|
|
474
|
+
await this._adapter.helper.callMethod('SetDiscoveryFilter', {
|
|
475
|
+
Transport: new Variant('s', this._adapter?._transport??"le")
|
|
476
|
+
})
|
|
477
|
+
await this._adapter.helper.callMethod('StartDiscovery')
|
|
478
|
+
|
|
479
|
+
} catch (e){
|
|
480
|
+
//probably ignorable error. probably.
|
|
481
|
+
console.log(e)
|
|
482
|
+
}
|
|
483
|
+
})
|
|
484
|
+
/* END HACK*/
|
|
478
485
|
}
|
|
479
486
|
|
|
480
487
|
/**
|
|
@@ -767,12 +774,15 @@ class BTSensor extends EventEmitter {
|
|
|
767
774
|
//End instance utility functions
|
|
768
775
|
|
|
769
776
|
createPaths(config, id){
|
|
777
|
+
// const source = `${this.getName()} (${id})`
|
|
778
|
+
|
|
770
779
|
Object.keys(this.getPaths()).forEach((tag)=>{
|
|
771
780
|
const pathMeta=this.getPath(tag)
|
|
772
781
|
const path = config.paths[tag]
|
|
773
782
|
if (!(path===undefined))
|
|
774
783
|
this.app.handleMessage(id,
|
|
775
784
|
{
|
|
785
|
+
// $source: source,
|
|
776
786
|
updates:
|
|
777
787
|
[{ meta: [{path: preparePath(this, path), value: { units: pathMeta?.unit }}]}]
|
|
778
788
|
})
|
|
@@ -780,6 +790,7 @@ class BTSensor extends EventEmitter {
|
|
|
780
790
|
}
|
|
781
791
|
|
|
782
792
|
initPaths(deviceConfig, id){
|
|
793
|
+
const source = this.getName()
|
|
783
794
|
Object.keys(this.getPaths()).forEach((tag)=>{
|
|
784
795
|
const pathMeta=this.getPath(tag)
|
|
785
796
|
const path = deviceConfig.paths[tag];
|
|
@@ -788,14 +799,14 @@ class BTSensor extends EventEmitter {
|
|
|
788
799
|
if (pathMeta.notify){
|
|
789
800
|
this.app.notify(tag, val, id )
|
|
790
801
|
} else {
|
|
791
|
-
this.updatePath(preparePath(this,path),val,id)
|
|
802
|
+
this.updatePath(preparePath(this,path),val, id, source)
|
|
792
803
|
}
|
|
793
804
|
})
|
|
794
805
|
}
|
|
795
806
|
})
|
|
796
807
|
}
|
|
797
|
-
updatePath(path, val,id){
|
|
798
|
-
this.app.handleMessage(id, {updates: [ { values: [ {path: path, value: val }] } ] })
|
|
808
|
+
updatePath(path, val, id, source){
|
|
809
|
+
this.app.handleMessage(id, {updates: [ { $source: source, values: [ { path: path, value: val }] } ] })
|
|
799
810
|
}
|
|
800
811
|
elapsedTimeSinceLastContact(){
|
|
801
812
|
return (Date.now()-this?._lastContact??Date.now())/1000
|
package/Queue.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
see: https://stackoverflow.com/questions/53540348/js-async-await-tasks-queue
|
|
3
|
+
*/
|
|
4
|
+
class Queue {
|
|
5
|
+
constructor() { this._items = []; }
|
|
6
|
+
enqueue(item) { this._items.push(item); }
|
|
7
|
+
dequeue() { return this._items.shift(); }
|
|
8
|
+
get size() { return this._items.length; }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class AutoQueue extends Queue {
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
this._pendingPromise = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
enqueue(action) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
super.enqueue({ action, resolve, reject });
|
|
20
|
+
this.dequeue();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async dequeue() {
|
|
25
|
+
if (this._pendingPromise) return false;
|
|
26
|
+
|
|
27
|
+
let item = super.dequeue();
|
|
28
|
+
|
|
29
|
+
if (!item) return false;
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
this._pendingPromise = true;
|
|
33
|
+
|
|
34
|
+
let payload = await item.action(this);
|
|
35
|
+
|
|
36
|
+
this._pendingPromise = false;
|
|
37
|
+
item.resolve(payload);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
this._pendingPromise = false;
|
|
40
|
+
item.reject(e);
|
|
41
|
+
} finally {
|
|
42
|
+
this.dequeue();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
module.exports = AutoQueue
|
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.0.4",
|
|
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": {
|
package/sensor_classes/JBDBMS.js
CHANGED
|
@@ -73,15 +73,13 @@ class JBDBMS extends BTSensor {
|
|
|
73
73
|
hasGATT(){
|
|
74
74
|
return true
|
|
75
75
|
}
|
|
76
|
-
initCharacteristics(){
|
|
77
|
-
return new Promise( async (resolve,reject )=>{
|
|
76
|
+
async initCharacteristics(){
|
|
78
77
|
const gattServer = await this.device.gatt()
|
|
79
78
|
const txRxService= await gattServer.getPrimaryService(this.constructor.TX_RX_SERVICE)
|
|
80
79
|
this.rxChar = await txRxService.getCharacteristic(this.constructor.NOTIFY_CHAR_UUID)
|
|
81
80
|
this.txChar = await txRxService.getCharacteristic(this.constructor.WRITE_CHAR_UUID)
|
|
82
81
|
await this.rxChar.startNotifications()
|
|
83
|
-
|
|
84
|
-
.catch((e)=>{ reject(e.message) }) })
|
|
82
|
+
return this
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
async initGATTNotifications(){
|
|
@@ -92,7 +90,7 @@ class JBDBMS extends BTSensor {
|
|
|
92
90
|
|
|
93
91
|
emitGATT(){
|
|
94
92
|
this.getAndEmitBatteryInfo()
|
|
95
|
-
setTimeout(()=>{this.getAndEmitCellVoltages()},
|
|
93
|
+
setTimeout(()=>{this.getAndEmitCellVoltages()}, 10000)
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
async getNumberOfCellsAndTemps(){
|
package/testqueue.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import {createBluetooth} from 'node-ble'
|
|
4
|
+
|
|
5
|
+
import {AutoQueue} from "./Queue.js"
|
|
6
|
+
import {Variant} from 'dbus-next'
|
|
7
|
+
|
|
8
|
+
const {bluetooth, destroy} = createBluetooth()
|
|
9
|
+
const connectQueue = new AutoQueue()
|
|
10
|
+
const adapter = await bluetooth.getAdapter("hci0")
|
|
11
|
+
await adapter.startDiscovery()
|
|
12
|
+
|
|
13
|
+
function deviceConnect(mac) {
|
|
14
|
+
|
|
15
|
+
/* CAUTION: HACK AHEAD
|
|
16
|
+
|
|
17
|
+
Bluez for some cockamamie reason (It's 2025 for chrissake.
|
|
18
|
+
BLUETOOTH ISN'T JUST FOR DESKTOPS ANYMORE, BLUEZ DEVS!)
|
|
19
|
+
SUSPENDS scanning while connected to a device.
|
|
20
|
+
|
|
21
|
+
The next line of code gives the scanner a kick in the arse,
|
|
22
|
+
starting it up again so, I dunno, another device might be able
|
|
23
|
+
to connect and sensor classes could maybe get beacon updates.
|
|
24
|
+
|
|
25
|
+
You know, the little things.
|
|
26
|
+
*/
|
|
27
|
+
adapter.waitDevice(mac,(30000)).then((device) =>{
|
|
28
|
+
|
|
29
|
+
return connectQueue.enqueue( async ()=>{
|
|
30
|
+
console.log("Connecting to "+mac)
|
|
31
|
+
try {await device.connect()} catch {(e)=>console.log(e)}
|
|
32
|
+
try {
|
|
33
|
+
console.log("Connected to "+mac)
|
|
34
|
+
console.log("Stopping discovery for "+mac)
|
|
35
|
+
|
|
36
|
+
await adapter.helper.callMethod('StopDiscovery')
|
|
37
|
+
console.log("Discovery stopped for "+mac)
|
|
38
|
+
await adapter.helper.callMethod('SetDiscoveryFilter', {
|
|
39
|
+
Transport: new Variant('s', "le")
|
|
40
|
+
})
|
|
41
|
+
console.log("Starting discovery for "+mac)
|
|
42
|
+
await adapter.helper.callMethod('StartDiscovery')
|
|
43
|
+
console.log("Discovery started for "+mac)
|
|
44
|
+
|
|
45
|
+
} catch (e){
|
|
46
|
+
//probably ignorable error. probably.
|
|
47
|
+
console.log(e)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
/* END HACK*/
|
|
52
|
+
}
|
|
53
|
+
setInterval( ()=>{
|
|
54
|
+
deviceConnect("D1:06:00:C6:16:4A")
|
|
55
|
+
}, 5000)
|
|
56
|
+
setInterval( ()=>{
|
|
57
|
+
|
|
58
|
+
for (const mac of (["D1:06:01:46:49:39","A4:C1:38:3E:7E:94"])){
|
|
59
|
+
try { deviceConnect(mac) } catch { (e)=>console.log(e) }
|
|
60
|
+
}
|
|
61
|
+
}, 10000)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|