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 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("error", false)
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("error", true)
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.setState("DORMANT")
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("error",(error)=>{
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
- const c = await getClassFor(device,config)
496
- if (c.domain==BTSensor.SensorDomains.beacons || c.IsRoaming){
497
- s = await instantiateSensor(device,config)
498
- device.once("deviceFound",async (device)=>{
499
- s.device=device
500
- s.listen()
501
- await s.activate(config, plugin)
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
- resolve(s)
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.2-1",
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}.discharging";
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> WARNING: If you use the GATT connection, you won't need an encrypytion//bind key to get your data but the energy cost of maintaining a GATT connection is high and will drain your battery in about 2 weeks of persistent use. Instead 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>`
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 xiaomi_mac = data.subarray(5,11)
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
- const encryptedPayload = data.subarray(11,-7);
145
- const xiaomi_mac = data.subarray(5,11)
146
- const nonce = Buffer.concat([xiaomi_mac, data.subarray(2, 5), data.subarray(-7,-4)]);
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 true
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
- var dec
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 (this.encryptionVersion >= 4) {
168
- dec = this.decryptV4and5(data)
182
+ if (encryptionVersion >= 4) {
183
+ dec = this.decryptV4and5(data, macInclude?11:5)
169
184
  } else {
170
- if(this.encryptionVersion>=2){
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
- switch(dec[0]){
178
- case 0x0D:
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 0x0A:
200
+ case 0x100A:
184
201
  this.emitData("batteryStrength",dec,3)
185
202
  break
186
- case 0x04:
203
+ case 0x1004:
187
204
  this.emitData("temp",dec,3)
188
205
  break
189
- case 0x06:
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
- throw new Error(`Service Data ${this.constructor.SERVICE_MIBEACON} not available for ${this.getName()}`)
204
- const frameControl = data[0] + (data[1] << 8)
205
- this.deviceID = data[2] + (data[3] << 8)
206
- this.isEncrypted = (frameControl >> 3) & 1
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