bt-sensors-plugin-sk 1.3.2-1 → 1.3.3
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 +10 -7
- package/README.md +7 -0
- package/index.js +11 -13
- package/package.json +1 -1
- package/pairing.md +147 -0
- package/sensor_classes/JikongBMS.js +1 -1
- package/sensor_classes/VictronBatteryMonitor.js +0 -3
- package/sensor_classes/VictronDCEnergyMeter.js +0 -1
- package/sensor_classes/VictronInverter.js +0 -1
- package/sensor_classes/VictronInverterRS.js +0 -1
- package/sensor_classes/VictronSmartBatteryProtect.js +0 -1
- package/sensor_classes/XiaomiMiBeacon.js +52 -24
- package/VictronSmartBatteryProtect.js +0 -54
- package/VictronSmartBatteryProtect.js.1 +0 -54
package/BTSensor.js
CHANGED
|
@@ -3,7 +3,7 @@ const { log } = require('node:console');
|
|
|
3
3
|
const EventEmitter = require('node:events');
|
|
4
4
|
const AutoQueue = require("./Queue.js")
|
|
5
5
|
const DistanceManager = require("./DistanceManager")
|
|
6
|
-
|
|
6
|
+
const OutOfRangeDevice = require("./OutOfRangeDevice.js")
|
|
7
7
|
/**
|
|
8
8
|
* @author Andrew Gerngross <oh.that.andy@gmail.com>
|
|
9
9
|
*/
|
|
@@ -278,7 +278,7 @@ class BTSensor extends EventEmitter {
|
|
|
278
278
|
|
|
279
279
|
unsetError(){
|
|
280
280
|
this._error=false
|
|
281
|
-
this.emit("
|
|
281
|
+
this.emit("errorDetected", false)
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
setError(message){
|
|
@@ -292,7 +292,7 @@ class BTSensor extends EventEmitter {
|
|
|
292
292
|
|
|
293
293
|
this._errorLog.push({timestamp:Date.now(), message:message})
|
|
294
294
|
this._error=true
|
|
295
|
-
this.emit("
|
|
295
|
+
this.emit("errorDetected", true)
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
//Instance Initialization functions
|
|
@@ -365,7 +365,10 @@ class BTSensor extends EventEmitter {
|
|
|
365
365
|
await this.initSchema()
|
|
366
366
|
|
|
367
367
|
this.initListen()
|
|
368
|
-
this.
|
|
368
|
+
if ( this.device instanceof OutOfRangeDevice)
|
|
369
|
+
this.setState("OUT OF RANGE")
|
|
370
|
+
else
|
|
371
|
+
this.setState("DORMANT")
|
|
369
372
|
|
|
370
373
|
}
|
|
371
374
|
|
|
@@ -1059,11 +1062,11 @@ class BTSensor extends EventEmitter {
|
|
|
1059
1062
|
if (!(path === undefined)) {
|
|
1060
1063
|
let preparedPath = this.preparePath(path)
|
|
1061
1064
|
this.on(tag, (val)=>{
|
|
1062
|
-
if (pathMeta.notify){
|
|
1065
|
+
/* if (pathMeta.notify){
|
|
1063
1066
|
this._app.notify(tag, val, id )
|
|
1064
|
-
} else {
|
|
1067
|
+
} else {*/
|
|
1065
1068
|
this.updatePath(preparedPath,val, id, source)
|
|
1066
|
-
}
|
|
1069
|
+
//}
|
|
1067
1070
|
})
|
|
1068
1071
|
}
|
|
1069
1072
|
})
|
package/README.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# Bluetooth Sensors for [Signal K](http://www.signalk.org)
|
|
2
2
|
|
|
3
3
|
## WHAT'S NEW
|
|
4
|
+
|
|
5
|
+
# Version 1.3.3
|
|
6
|
+
|
|
7
|
+
- Support for additional Xiaomi environmental sensors
|
|
8
|
+
- Out Of Range device automatic retry
|
|
9
|
+
- Pairing guide
|
|
10
|
+
|
|
4
11
|
# Version 1.3.2-1
|
|
5
12
|
|
|
6
13
|
- VictronSmartBatteryProtect fix
|
package/index.js
CHANGED
|
@@ -445,7 +445,7 @@ module.exports = function (app) {
|
|
|
445
445
|
sensor.on("connected", (state)=>{
|
|
446
446
|
updateSensor(sensor)
|
|
447
447
|
})
|
|
448
|
-
sensor.on("
|
|
448
|
+
sensor.on("errorDetected",(error)=>{
|
|
449
449
|
updateSensor(sensor)
|
|
450
450
|
})
|
|
451
451
|
sensor.on("debug", ()=>{
|
|
@@ -492,19 +492,17 @@ module.exports = function (app) {
|
|
|
492
492
|
s.stopListening()
|
|
493
493
|
else{
|
|
494
494
|
const device = new OutOfRangeDevice(adapter, config)
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
s
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
removeSensorFromList(s)
|
|
503
|
-
addSensorToList(s)
|
|
504
|
-
})
|
|
495
|
+
s = await instantiateSensor(device,config)
|
|
496
|
+
device.once("deviceFound",async (device)=>{
|
|
497
|
+
s.device=device
|
|
498
|
+
s.listen()
|
|
499
|
+
if (config.active)
|
|
500
|
+
await s.activate(config, plugin)
|
|
501
|
+
removeSensorFromList(s)
|
|
505
502
|
addSensorToList(s)
|
|
506
|
-
|
|
507
|
-
|
|
503
|
+
})
|
|
504
|
+
addSensorToList(s)
|
|
505
|
+
resolve(s)
|
|
508
506
|
}
|
|
509
507
|
if (startNumber == starts ) {
|
|
510
508
|
const errorTxt = `Unable to communicate with device ${deviceNameAndAddress(config)} Reason: ${e?.message??e}`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bt-sensors-plugin-sk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
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": {
|
package/pairing.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Bluetooth Device Pairing using bluetoothctl
|
|
2
|
+
|
|
3
|
+
This guide provides a step-by-step procedure for pairing, trusting, and connecting a new Bluetooth device using the bluetoothctl command-line utility, which is the official Bluetooth client for BlueZ (the Linux Bluetooth stack).
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- A running Linux system (e.g., Debian, Ubuntu, Fedora, Arch).
|
|
8
|
+
- The bluez package installed (which includes bluetoothctl).
|
|
9
|
+
- The Bluetooth service (bluetooth.service) is running.
|
|
10
|
+
- Your local Bluetooth adapter is enabled and powered on.
|
|
11
|
+
|
|
12
|
+
## The Pairing Process
|
|
13
|
+
|
|
14
|
+
Follow these steps within your terminal:
|
|
15
|
+
|
|
16
|
+
### Step 1: Launch bluetoothctl
|
|
17
|
+
|
|
18
|
+
Open your terminal and run the command to enter the interactive bluetoothctl prompt.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
bluetoothctl
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
(The prompt should change to [bluetooth]#)
|
|
27
|
+
|
|
28
|
+
### Step 2: Check Controller Status (Optional but recommended)Ensure your adapter is powered on and set to discoverable/pairable mode.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
[bluetooth]# show
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If the Powered field is listed as no, power the adapter on:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
[bluetooth]# power on
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Step 3: Start Scanning for Devices
|
|
45
|
+
|
|
46
|
+
Put your target Bluetooth device into pairing mode (see device instructions). Then, start the scanning process:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
[bluetooth]# scan on
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
You will see a list of discovered devices scrolling by with their MAC addresses and names.
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Discovery started
|
|
59
|
+
[CHG] Device 12:34:56:78:90:AB Name: My Bluetooth Headphones
|
|
60
|
+
[NEW] Device AB:CD:EF:12:34:56 Name: Wireless Mouse
|
|
61
|
+
...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Step 4: Identify and Stop Scanning
|
|
66
|
+
|
|
67
|
+
Once you see the name of your device, copy its MAC Address (e.g., AB:CD:EF:12:34:56) and stop the scan to save battery and reduce clutter:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
[bluetooth]# scan off
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
Step 5: Trust the Device
|
|
77
|
+
|
|
78
|
+
Trusting the device is crucial. It allows the device to reconnect automatically after a reboot or disconnection without needing to re-pair. Replace [MAC_ADDRESS] with your device's MAC address.
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
[bluetooth]# trust [MAC_ADDRESS]
|
|
83
|
+
|
|
84
|
+
Attempting to trust AB:CD:EF:12:34:56
|
|
85
|
+
[CHG] Device AB:CD:EF:12:34:56 Trusted: yes
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Step 6: Connect the Device
|
|
91
|
+
|
|
92
|
+
This step attempts to establish the active connection.
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
[bluetooth]# connect [MAC_ADDRESS]
|
|
97
|
+
|
|
98
|
+
Attempting to connect to AB:CD:EF:12:34:56
|
|
99
|
+
[CHG] Device AB:CD:EF:12:34:56 Connected: yes
|
|
100
|
+
Connection successful
|
|
101
|
+
...
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Step 7: Pair the Device
|
|
105
|
+
|
|
106
|
+
If the connection attempt in Step 6 did not automatically handle the key exchange, or if you prefer to explicitly perform the key exchange first, use the pair command. This initiates the actual pairing sequence. If your device requires a PIN or Passkey, bluetoothctl will prompt you to enter it (or confirm it). NOTE: Check your device's manual for setting the device's pairing mode.
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
[bluetooth]# pair [MAC_ADDRESS]
|
|
111
|
+
Attempting to pair with AB:CD:EF:12:34:56
|
|
112
|
+
[CHG] Device AB:CD:EF:12:34:56 Paired: yes
|
|
113
|
+
Pairing successful
|
|
114
|
+
...
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
(If prompted, enter or confirm the Passkey. If this command succeeds, you may need to run connect (Step 6) again to establish the active link.)
|
|
119
|
+
|
|
120
|
+
### Step 8: Exit
|
|
121
|
+
|
|
122
|
+
Once the connection is established, you can exit the interactive utility.
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
[bluetooth]# exit
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Summary of Essential Commands
|
|
131
|
+
|
|
132
|
+
| **Command** | **Purpose** |
|
|
133
|
+
| :--- | :--- |
|
|
134
|
+
| `bluetoothctl` | Enter the interactive prompt. |
|
|
135
|
+
| `power on` | Power on the local Bluetooth adapter. |
|
|
136
|
+
| `scan on` | Start discovering nearby devices. |
|
|
137
|
+
| `scan off` | Stop device discovery. |
|
|
138
|
+
| `trust [MAC]` | Mark the device as trusted for auto-reconnection. **(Crucial)** |
|
|
139
|
+
| `connect [MAC]` | Establish a connection to the device (may implicitly trigger pairing). |
|
|
140
|
+
| `pair [MAC]` | Explicitly initiate the pairing process (key exchange). |
|
|
141
|
+
| `exit` | Exit the `bluetoothctl` utility. |
|
|
142
|
+
|
|
143
|
+
### Troubleshooting Tips
|
|
144
|
+
|
|
145
|
+
* **Adapter Issues:** If `show` or `list` commands don't show an adapter, ensure your Bluetooth hardware is properly recognized by the system (check kernel logs or `rfkill list`).
|
|
146
|
+
|
|
147
|
+
* **Device Out of Range:** Ensure the device is close to the computer and is fully charged.
|
|
@@ -257,7 +257,7 @@ class JikongBMS extends BTSensor {
|
|
|
257
257
|
|
|
258
258
|
this.addMetadatum("cycleCapacity", "number", "Cycle capacity", (buffer) => {
|
|
259
259
|
return buffer.readUInt32LE(154 + this.offset * 2) / 1000;
|
|
260
|
-
}).default = "electrical.batteries.{batteryID}.
|
|
260
|
+
}).default = "electrical.batteries.{batteryID}.cycleCapacity";
|
|
261
261
|
|
|
262
262
|
this.addMetadatum(
|
|
263
263
|
"balanceAction",
|
|
@@ -62,7 +62,6 @@ class VictronBatteryMonitor extends VictronSensor{
|
|
|
62
62
|
const alarmMD = this.addMetadatum('alarm','', 'alarm',
|
|
63
63
|
(buff,offset=0)=>{return buff.readInt16LE(offset)})
|
|
64
64
|
alarmMD.default='electrical.batteries.{batteryID}.alarm'
|
|
65
|
-
alarmMD.notify=true
|
|
66
65
|
|
|
67
66
|
this.addMetadatum( 'consumed','Ah', 'amp-hours consumed',
|
|
68
67
|
(buff,offset=0)=>{return buff.readInt32LE(offset)/10},
|
|
@@ -78,8 +77,6 @@ class VictronBatteryMonitor extends VictronSensor{
|
|
|
78
77
|
.read=(buff,offset=0)=>{return this.NaNif(buff.readUInt16LE(offset),0xFFFF)*60}
|
|
79
78
|
this.getPath("ttg").gatt='65970ffe-4bda-4c1e-af4b-551c4cf74769';
|
|
80
79
|
|
|
81
|
-
this.auxMode=VC.AuxMode.STARTER_VOLTAGE
|
|
82
|
-
|
|
83
80
|
if (this.auxMode==undefined){
|
|
84
81
|
const md=await this.constructor.getDataPacket(this.device, this.getManufacturerData(this.constructor.ManufacturerID))
|
|
85
82
|
try {
|
|
@@ -55,7 +55,6 @@ class VictronDCEnergyMeter extends VictronSensor{
|
|
|
55
55
|
this.addMetadatum('alarm','', 'alarm',
|
|
56
56
|
(buff)=>{return buff.readUInt16LE(4)})
|
|
57
57
|
.default="electrical.meters.{id}.alarm"
|
|
58
|
-
this.getPath("alarm").notify=true
|
|
59
58
|
this.addMetadatum('current','A', 'current')
|
|
60
59
|
.default="electrical.meters.{id}.current"
|
|
61
60
|
|
|
@@ -17,7 +17,6 @@ class VictronInverter extends VictronSensor{
|
|
|
17
17
|
const md = this.addMetadatum('alarmReason','', 'reason for alarm',
|
|
18
18
|
(buff)=>{return buff.readIntU16LE(1)})
|
|
19
19
|
.default="electrical.inverters.{id}.alarm"
|
|
20
|
-
md.notify=true
|
|
21
20
|
|
|
22
21
|
this.addDefaultPath('dcVoltage','electrical.inverters.dc.voltage')
|
|
23
22
|
.read=(buff)=>{return this.NaNif(buff.readInt16LE(3),0x7FFF)/100}
|
|
@@ -18,7 +18,6 @@ class VictronInverterRS extends VictronSensor{
|
|
|
18
18
|
const md = this.addMetadatum('chargerError','', 'charger error',
|
|
19
19
|
(buff)=>{return VC.ChargerError(buff.readIntU8(1))})
|
|
20
20
|
md.default='electrical.inverters.{id}.error'
|
|
21
|
-
md.notify=true
|
|
22
21
|
|
|
23
22
|
this.addMetadatum('batteryVoltage','V', 'battery voltage',
|
|
24
23
|
(buff)=>{return this.NaNif(buff.readInt16LE(2),0x7FFF)/100})
|
|
@@ -33,7 +33,6 @@ class VictronSmartBatteryProtect extends VictronSensor{
|
|
|
33
33
|
(buff)=>{return VC.ChargerError.get(buff.readUInt8(3))})
|
|
34
34
|
this.addMetadatum('alarmReason','', 'alarm reason',
|
|
35
35
|
(buff)=>{return buff.readUInt16LE(4)})
|
|
36
|
-
this.getPath("alarmReason").notify=true
|
|
37
36
|
this.addMetadatum('warningReason','', 'warning reason', //TODO
|
|
38
37
|
(buff)=>{return (buff.readUInt16LE(5))})
|
|
39
38
|
this.addMetadatum('channel1Voltage','V', 'channel one voltage',
|
|
@@ -100,7 +100,7 @@ class XiaomiMiBeacon extends BTSensor{
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
getDescription(){
|
|
103
|
-
return `<div><p><img src="../bt-sensors-plugin-sk/images/LYWSD03MMC-Device.jpg" alt=LYWSD03MMC image" style="float: left; margin-right: 10px;" /> The LYWSD03MMC temperature and humidity sensor is an inexpensive environmental sensor from Xiaomi Inc. <p>
|
|
103
|
+
return `<div><p><img src="../bt-sensors-plugin-sk/images/LYWSD03MMC-Device.jpg" alt=LYWSD03MMC image" style="float: left; margin-right: 10px;" /> The LYWSD03MMC temperature and humidity sensor is an inexpensive environmental sensor from Xiaomi Inc. <p> Follow the instructions <a href=https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor/?tab=readme-ov-file#linux--home-assistant-in-ssh--web-terminal target="_blank">here</a> to get your device's encryption key.<div>`
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
getManufacturer(){
|
|
@@ -131,19 +131,18 @@ class XiaomiMiBeacon extends BTSensor{
|
|
|
131
131
|
})
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
decryptV2and3(data){
|
|
134
|
+
decryptV2and3(data, index=11){
|
|
135
135
|
const encryptedPayload = data.subarray(-4);
|
|
136
|
-
const
|
|
137
|
-
const nonce = Buffer.concat([data.subarray(0, 5), data.subarray(-4,-1), xiaomi_mac.subarray(-1)]);
|
|
136
|
+
const nonce = Buffer.concat([data.subarray(0, 5), data.subarray(-4,-1), (this._mac_reversed)]);
|
|
138
137
|
const cipher = crypto.createDecipheriv('aes-128-ccm', Buffer.from(this.encryptionKey,"hex"), nonce, { authTagLength: 4});
|
|
139
138
|
cipher.setAAD(Buffer.from('11', 'hex'), { plaintextLength: encryptedPayload.length });
|
|
140
139
|
|
|
141
140
|
return cipher.update(encryptedPayload)
|
|
142
141
|
}
|
|
143
|
-
decryptV4and5(data){
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
const nonce = Buffer.concat([
|
|
142
|
+
decryptV4and5(data, index=11){
|
|
143
|
+
|
|
144
|
+
const encryptedPayload = data.subarray(index,-7);
|
|
145
|
+
const nonce = Buffer.concat([(this._mac_reversed), data.subarray(2, 5), data.subarray(-7,-4)]);
|
|
147
146
|
const cipher = crypto.createDecipheriv('aes-128-ccm', Buffer.from(this.encryptionKey,"hex"), nonce, { authTagLength: 4});
|
|
148
147
|
cipher.setAAD(Buffer.from('11', 'hex'), { plaintextLength: encryptedPayload.length });
|
|
149
148
|
cipher.setAuthTag(data.subarray(-4))
|
|
@@ -151,7 +150,7 @@ class XiaomiMiBeacon extends BTSensor{
|
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
hasGATT(){
|
|
154
|
-
return
|
|
153
|
+
return false
|
|
155
154
|
}
|
|
156
155
|
|
|
157
156
|
propertiesChanged(props){
|
|
@@ -160,35 +159,64 @@ class XiaomiMiBeacon extends BTSensor{
|
|
|
160
159
|
if (!props.hasOwnProperty("ServiceData")) return
|
|
161
160
|
|
|
162
161
|
const data = this.getServiceData(this.constructor.SERVICE_MIBEACON)
|
|
163
|
-
|
|
162
|
+
if (data.length<12) return
|
|
163
|
+
|
|
164
|
+
let dec=[]
|
|
165
|
+
let dataIndex=5
|
|
166
|
+
|
|
167
|
+
const frameControl = data.readUInt16LE(0)
|
|
168
|
+
const isEncrypted = (frameControl >> 3) & 1
|
|
169
|
+
const encryptionVersion = frameControl >> 12
|
|
170
|
+
const mesh = (frameControl >> 7) & 1; // mesh device
|
|
171
|
+
const authMode = (frameControl >> 10) & 3;
|
|
172
|
+
const solicited = (frameControl >> 9) & 1;
|
|
173
|
+
const registered = (frameControl >> 8) & 1;
|
|
174
|
+
const objectInclude = (frameControl >> 6) & 1; // object/payload data present
|
|
175
|
+
const capabilityInclude = (frameControl >> 5) & 1; // capability byte present
|
|
176
|
+
const macInclude = (frameControl >> 4) & 1; // MAC address included in payload
|
|
177
|
+
const requestTiming = frameControl & 1;
|
|
178
|
+
|
|
164
179
|
if (!this.encryptionKey){
|
|
165
180
|
throw new Error(`${this.getNameAndAddress()} requires an encryption key.`)
|
|
166
181
|
}
|
|
167
|
-
if (
|
|
168
|
-
dec = this.decryptV4and5(data)
|
|
182
|
+
if (encryptionVersion >= 4) {
|
|
183
|
+
dec = this.decryptV4and5(data, macInclude?11:5)
|
|
169
184
|
} else {
|
|
170
|
-
if(
|
|
171
|
-
dec=this.decryptV2and3(data)
|
|
185
|
+
if(encryptionVersion>=2){
|
|
186
|
+
dec=this.decryptV2and3(data, macInclude?11:5)
|
|
172
187
|
}
|
|
173
188
|
}
|
|
174
189
|
if (dec.length==0)
|
|
175
190
|
throw new Error(`${this.getNameAndAddress()} received empty decrypted packet. Check that the bind/encryption key in config is correct.`)
|
|
176
191
|
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
const objCode = dec.readUInt16LE(0)
|
|
193
|
+
|
|
194
|
+
switch(objCode){
|
|
195
|
+
case 0x100D:
|
|
179
196
|
this.emitData("temp",dec,3)
|
|
180
197
|
this.emitData("humidity",dec,5)
|
|
181
198
|
break
|
|
182
199
|
|
|
183
|
-
case
|
|
200
|
+
case 0x100A:
|
|
184
201
|
this.emitData("batteryStrength",dec,3)
|
|
185
202
|
break
|
|
186
|
-
case
|
|
203
|
+
case 0x1004:
|
|
187
204
|
this.emitData("temp",dec,3)
|
|
188
205
|
break
|
|
189
|
-
case
|
|
206
|
+
case 0x1006:
|
|
190
207
|
this.emitData("humidity",dec,3)
|
|
191
208
|
break
|
|
209
|
+
case 0x4C01:
|
|
210
|
+
this.emit("temp",dec.readFloatLE(3)+273.15)
|
|
211
|
+
break
|
|
212
|
+
|
|
213
|
+
case 0x4C02:
|
|
214
|
+
this.emit("humidity",dec[3]/100)
|
|
215
|
+
break
|
|
216
|
+
case 0x4C03:
|
|
217
|
+
this.emit("batteryStrength",dec[3]/100)
|
|
218
|
+
break
|
|
219
|
+
|
|
192
220
|
default:
|
|
193
221
|
throw new Error(`${this.getNameAndAddress()} unable to parse decrypted service data (${util.inspect(dec)})`)
|
|
194
222
|
|
|
@@ -198,13 +226,13 @@ class XiaomiMiBeacon extends BTSensor{
|
|
|
198
226
|
async init(){
|
|
199
227
|
|
|
200
228
|
await super.init()
|
|
229
|
+
this._mac_reversed = (Buffer.from(this.getMacAddress().replaceAll(":",""), "hex")).reverse()
|
|
201
230
|
const data = this.getServiceData(this.constructor.SERVICE_MIBEACON)
|
|
202
231
|
if (!data || data.length<4)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.encryptionVersion = frameControl >> 12
|
|
232
|
+
this.setError(`Service Data ${this.constructor.SERVICE_MIBEACON} not available for ${this.getName()}`)
|
|
233
|
+
else
|
|
234
|
+
this.deviceID = data[2] + (data[3] << 8)
|
|
235
|
+
|
|
208
236
|
}
|
|
209
237
|
initSchema(){
|
|
210
238
|
super.initSchema()
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Smart Battery Protect
|
|
3
|
-
Start
|
|
4
|
-
bit
|
|
5
|
-
Nr of
|
|
6
|
-
bits Meaning Units Range NA
|
|
7
|
-
value Remark
|
|
8
|
-
8 8 Device state 0 .. 0xFE 0xFF VE_REG_DEVICE_STATE
|
|
9
|
-
16 8 Output state 0 .. 0xFE 0xFF VE_REG_DC_OUTPUT_STATUS
|
|
10
|
-
24 8 Error code 0 .. 0xFE 0xFF VE_REG_CHR_ERROR_CODE
|
|
11
|
-
32 16 Alarm reason 0 .. 0xFFFF - VE_REG_ALARM_REASON
|
|
12
|
-
48 16 Warning reason 0 .. 0xFFFF - VE_REG_WARNING_REASON
|
|
13
|
-
64 16 Input voltage 0.01 V 327.68 .. 327.66 V 0x7FFF VE_REG_DC_CHANNEL1_VOLTAGE
|
|
14
|
-
80 16 Output voltage 0.01 V 0 .. 655.34 V 0xFFFF VE_REG_DC_OUTPUT_VOLTAGE
|
|
15
|
-
96 32 Off reason 0 .. 0xFFFFFFFF - VE_REG_DEVICE_OFF_REASON_2
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const VictronSensor = require ("./Victron/VictronSensor.js")
|
|
19
|
-
const VC = require("./Victron/VictronConstants.js")
|
|
20
|
-
class VictronSmartBatteryProtect extends VictronSensor{
|
|
21
|
-
|
|
22
|
-
static ImageFile="VictronSmartBatteryProte.jpg"
|
|
23
|
-
|
|
24
|
-
initSchema(){
|
|
25
|
-
super.initSchema()
|
|
26
|
-
this.addDefaultParam("id")
|
|
27
|
-
this.addMetadatum('deviceState','', 'device state',
|
|
28
|
-
(buff)=>{return VC.OperationMode.get(buff.readUInt8(1))})
|
|
29
|
-
this.addMetadatum('outputStatus','', 'output status', //TODO
|
|
30
|
-
(buff)=>{return (buff.readUInt8(2))})
|
|
31
|
-
|
|
32
|
-
this.addMetadatum('chargerError','', 'charger error',
|
|
33
|
-
(buff)=>{return VC.ChargerError.get(buff.readUInt8(3))})
|
|
34
|
-
this.addMetadatum('alarmReason','', 'alarm reason',
|
|
35
|
-
(buff)=>{return buff.readUInt16LE(4)})
|
|
36
|
-
this.getPath("alarmReason").notify=true
|
|
37
|
-
this.addMetadatum('warningReason','', 'warning reason', //TODO
|
|
38
|
-
(buff)=>{return (buff.readUInt16LE(5))})
|
|
39
|
-
this.addMetadatum('channel1Voltage','V', 'channel one voltage',
|
|
40
|
-
(buff)=>{return this.NaNif(buff.readInt16LE(7),0x7FFF)/100})
|
|
41
|
-
this.addMetadatum('outputVoltage','V', 'output voltage',
|
|
42
|
-
(buff)=>{return this.NaNif(buff.readUInt16LE(9),0xFFFF)/100})
|
|
43
|
-
this.addMetadatum('offReason','', 'off reason',
|
|
44
|
-
(buff)=>{return this.offReasonText(buff.readUInt32LE(11))})
|
|
45
|
-
}
|
|
46
|
-
emitValuesFrom(decData){
|
|
47
|
-
super.emitValuesFrom(decData)
|
|
48
|
-
const alarm = this.getPath("alarmReason").read(decData)
|
|
49
|
-
if (alarm>0)
|
|
50
|
-
this.emitAlarm("alarmReason",alarm)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
module.exports=VictronSmartBatteryProtect
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Smart Battery Protect
|
|
3
|
-
Start
|
|
4
|
-
bit
|
|
5
|
-
Nr of
|
|
6
|
-
bits Meaning Units Range NA
|
|
7
|
-
value Remark
|
|
8
|
-
8 8 Device state 0 .. 0xFE 0xFF VE_REG_DEVICE_STATE
|
|
9
|
-
16 8 Output state 0 .. 0xFE 0xFF VE_REG_DC_OUTPUT_STATUS
|
|
10
|
-
24 8 Error code 0 .. 0xFE 0xFF VE_REG_CHR_ERROR_CODE
|
|
11
|
-
32 16 Alarm reason 0 .. 0xFFFF - VE_REG_ALARM_REASON
|
|
12
|
-
48 16 Warning reason 0 .. 0xFFFF - VE_REG_WARNING_REASON
|
|
13
|
-
64 16 Input voltage 0.01 V 327.68 .. 327.66 V 0x7FFF VE_REG_DC_CHANNEL1_VOLTAGE
|
|
14
|
-
80 16 Output voltage 0.01 V 0 .. 655.34 V 0xFFFF VE_REG_DC_OUTPUT_VOLTAGE
|
|
15
|
-
96 32 Off reason 0 .. 0xFFFFFFFF - VE_REG_DEVICE_OFF_REASON_2
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const VictronSensor = require ("./Victron/VictronSensor.js")
|
|
19
|
-
const VC = require("./Victron/VictronConstants.js")
|
|
20
|
-
class VictronSmartBatteryProtect extends VictronSensor{
|
|
21
|
-
|
|
22
|
-
static ImageFile="VictronSmartBatteryProte.jpg"
|
|
23
|
-
|
|
24
|
-
initSchema(){
|
|
25
|
-
super.initSchema()
|
|
26
|
-
this.addDefaultParam("id")
|
|
27
|
-
this.addMetadatum('deviceState','', 'device state',
|
|
28
|
-
(buff)=>{return VC.OperationMode.get(buff.readUInt8(1))})
|
|
29
|
-
this.addMetadatum('outputStatus','', 'output status', //TODO
|
|
30
|
-
(buff)=>{return (buff.readUInt8(2))})
|
|
31
|
-
|
|
32
|
-
this.addMetadatum('chargerError','', 'charger error',
|
|
33
|
-
(buff)=>{return VC.ChargerError.get(buff.readUInt8(3))})
|
|
34
|
-
this.addMetadatum('alarmReason','', 'alarm reason',
|
|
35
|
-
(buff)=>{return buff.readUInt16LE(4)})
|
|
36
|
-
this.getPath("alarmReason").notify=true
|
|
37
|
-
this.addMetadatum('warningReason','', 'warning reason', //TODO
|
|
38
|
-
(buff)=>{return (buff.readUInt16LE(5))})
|
|
39
|
-
this.addMetadatum('channel1Voltage','V', 'channel one voltage',
|
|
40
|
-
(buff)=>{return this.NaNif(buff.readInt16LE(7),0x7FFF)/100})
|
|
41
|
-
this.addMetadatum('outputVoltage','V', 'output voltage',
|
|
42
|
-
(buff)=>{return this.NaNif(buff.readUInt16LE(9),0xFFFF)/100})
|
|
43
|
-
this.addMetadatum('offReason','', 'off reason',
|
|
44
|
-
(buff)=>{return this.offReasonText(buff.readUInt32LE(11))})
|
|
45
|
-
}
|
|
46
|
-
emitValuesFrom(decData){
|
|
47
|
-
super.emitValuesFrom(decData)
|
|
48
|
-
const alarm = this.getPath("alarmReason").read(decData)
|
|
49
|
-
if (alarm>0)
|
|
50
|
-
this.emitAlarm("alarmReason",alarm)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
module.exports=VictronSmartBatteryProtect
|