bt-sensors-plugin-sk 1.1.0-beta.2.1.4.2 → 1.1.0-beta.2.1.4.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/index.js CHANGED
@@ -3,7 +3,7 @@ const util = require('util')
3
3
  const path = require('path')
4
4
  const {createBluetooth} = require('node-ble')
5
5
  const {bluetooth, destroy} = createBluetooth()
6
-
6
+ const packageInfo = require("./package.json")
7
7
  const BTSensor = require('./BTSensor.js')
8
8
  const BLACKLISTED = require('./sensor_classes/BlackListedDevice.js')
9
9
 
@@ -152,7 +152,7 @@ module.exports = function (app) {
152
152
  classMap = utilities_sk.loadClasses(path.join(__dirname, 'sensor_classes'))
153
153
  }
154
154
 
155
- app.debug('Loading plugin')
155
+ app.debug(`Loading plugin ${packageInfo.version}`)
156
156
 
157
157
  plugin.schema = {
158
158
  type: "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bt-sensors-plugin-sk",
3
- "version": "1.1.0-beta.2.1.4.2",
3
+ "version": "1.1.0-beta.2.1.4.4",
4
4
  "description": "Bluetooth Sensors for Signalk -- support for Victron devices, RuuviTag, Xiaomi, ATC and Inkbird, Ultrasonic, Mopeka tank reader and preliminary support for Govee GVH51xx temp sensors",
5
5
  "main": "index.js",
6
6
  "dependencies": {
@@ -36,6 +36,7 @@ class GoveeTH extends BTSensor{
36
36
 
37
37
  async init(){
38
38
  await super.init()
39
+ this.initMetadata()
39
40
  }
40
41
  initMetadata(){
41
42
  this.addMetadatum('temp','K', 'temperature')
@@ -63,4 +64,4 @@ class GoveeTH extends BTSensor{
63
64
  }
64
65
  }
65
66
  }
66
- module.exports=GoveeTH
67
+ module.exports=GoveeTH
@@ -258,20 +258,22 @@ class MopekaTankSensor extends BTSensor{
258
258
  const md = this.valueIfVariant(this.getManufacturerData(this.constructor.manufacturerID))
259
259
  this.modelID = md[0]
260
260
  this.initMetadata()
261
-
262
261
  }
263
262
 
264
263
  getMedium(){
265
264
  return Media[this?.medium??'PROPANE']
266
265
  }
266
+ getTankHeight(){
267
+ return this?.tankHeight??304.8 //Assume a foot
268
+ }
267
269
 
268
270
  _tankLevel( rawLevel ){
269
271
  const coefs= this.getMedium().coefficients
270
- return rawLevel * (coefs[0] + (coefs[1] * (this.temp-273.15)) + (coefs[2] * ((this.temp-273.15)^2)))
272
+ return rawLevel * (coefs[0] + (coefs[1] * (this.temp-233.15)) + (coefs[2] * ((this.temp-233.15)^2)))
271
273
  }
272
274
 
273
275
  initMetadata(){
274
- const md = this.addMetadatum("medium","","type of liquid in tank")
276
+ var md = this.addMetadatum("medium","","type of liquid in tank")
275
277
  md.isParam=true
276
278
  md.enum=Object.keys(Media)
277
279
 
@@ -293,8 +295,8 @@ class MopekaTankSensor extends BTSensor{
293
295
  return this.temp
294
296
  }).bind(this)
295
297
  )
296
- this.addMetadatum("tankLevel","m","tank level",
297
- (buffer)=>{ return this._tankLevel(((buffer.readUInt16LE(3))&0x3FFF))}
298
+ this.addMetadatum("tankLevel","ratio","tank level",
299
+ (buffer)=>{ return (this._tankLevel(((buffer.readUInt16LE(3))&0x3FFF)))/this.getTankHeight()}
298
300
  )
299
301
  this.addMetadatum("readingQuality","","quality of read",
300
302
  (buffer)=>{ return buffer.readUInt8(4)>>6}
@@ -312,6 +314,7 @@ class MopekaTankSensor extends BTSensor{
312
314
  if (props.ManufacturerData)
313
315
  this.emitValuesFrom( this.getManufacturerData(this.constructor.manufacturerID) )
314
316
  }
317
+
315
318
  getName(){
316
319
  if (this.name)
317
320
  return this.name
File without changes
@@ -0,0 +1,107 @@
1
+ const BTSensor = require("../../BTSensor.js");
2
+ const VC = require('./RenogyConstants.js');
3
+ function sleep(x) {
4
+ return new Promise((resolve) => {
5
+ setTimeout(() => {
6
+ resolve(x);
7
+ }, x);
8
+ });
9
+ }
10
+ class RenogySensor extends BTSensor{
11
+
12
+ constructor(device,config,gattConfig){
13
+ super(device,config,gattConfig)
14
+ this.encryptionKey = config?.encryptionKey
15
+ }
16
+
17
+ static async identifyMode(device, mode){
18
+
19
+ var md = await this.getDeviceProp(device,'ManufacturerData')
20
+ if (md==undefined || !Object.hasOwn(md,0x2e1))
21
+ return null
22
+ else {
23
+
24
+ if (md[0x2e1].value[0]==0x10) {
25
+ if (md[0x2e1].value[4]==mode)
26
+ return this
27
+ else
28
+ return null
29
+ }
30
+
31
+ var hasDataPacket=false
32
+ device.helper._prepare()
33
+ device.helper.on("PropertiesChanged",
34
+ (props)=> {
35
+ if (Object.hasOwn(props,'ManufacturerData')){
36
+ md = props['ManufacturerData'].value
37
+ hasDataPacket=md[0x2e1].value[0]==0x10
38
+ }
39
+ })
40
+ while (!hasDataPacket) {
41
+ await sleep(500)
42
+ }
43
+ device.helper.removeListeners()
44
+ if (md[0x2e1].value[4]==mode)
45
+ return this
46
+ else
47
+ return null
48
+ }
49
+ }
50
+
51
+ async init(){
52
+ await super.init()
53
+ }
54
+ alarmReason(alarmValue){
55
+ return this.constructor.AlarmReason[alarmValue]
56
+ }
57
+ getModelName(){
58
+ return VC?.MODEL_ID_MAP[this.model_id]??this.constructor.name+" (Model ID:"+this.model_id+")"
59
+ }
60
+
61
+ decrypt(data){
62
+ if (!this.encryptionKey)
63
+ throw Error("Unable to decrypt: no encryption key set")
64
+
65
+ const encMethod = 'aes-128-ctr';
66
+ const iv = data.readUInt16LE(5);
67
+ const key = Buffer.from(this.encryptionKey,'hex')
68
+ const ivBuffer = Buffer.alloc(16); // 128 bits = 16 bytes
69
+
70
+ ivBuffer.writeUInt16LE(iv)
71
+
72
+ var encData = Buffer.from([...data.slice(8)])
73
+
74
+ const decipher = crypto.createDecipheriv(encMethod, key, ivBuffer)
75
+
76
+ const decData=decipher.update(encData)
77
+
78
+ return Buffer.from(decData)
79
+
80
+ }
81
+ getName(){
82
+ return `Victron ${this.getModelName()}`
83
+ }
84
+ propertiesChanged(props){
85
+ super.propertiesChanged(props)
86
+ if (this.usingGATT()) return
87
+
88
+ try{
89
+ const md = this.getManufacturerData(0x2e1)
90
+ if (md && md.length && md[0]==0x10){
91
+ const decData=this.decrypt(md)
92
+ this.emitValuesFrom(decData)
93
+ }
94
+ }
95
+ catch (error) {
96
+ throw new Error(`Unable to read data from ${ this.getDisplayName()}: ${error}` )
97
+ }
98
+ }
99
+
100
+ initGATTConnection(){
101
+ throw new Error( "GATT Connection unimplemented for "+this.getDisplayName())
102
+ }
103
+
104
+
105
+
106
+ }
107
+ module.exports=RenogySensor
@@ -1,11 +1,6 @@
1
1
  const BTSensor = require("../../BTSensor.js");
2
2
  const crypto = require('node:crypto');
3
- const int24 = require('int24')
4
- const util = require('util')
5
3
  const VC = require('./VictronConstants.js');
6
- const BLACKLISTED = require("../BlackListedDevice.js");
7
- const { resolve } = require("node:path");
8
- const { setMaxIdleHTTPParsers } = require("node:http");
9
4
  function sleep(x) {
10
5
  return new Promise((resolve) => {
11
6
  setTimeout(() => {
@@ -20,7 +15,6 @@ function sleep(x) {
20
15
  this.encryptionKey = config?.encryptionKey
21
16
  }
22
17
 
23
-
24
18
  static async identifyMode(device, mode){
25
19
 
26
20
  var md = await this.getDeviceProp(device,'ManufacturerData')
@@ -54,15 +48,10 @@ function sleep(x) {
54
48
  return null
55
49
  }
56
50
  }
57
-
58
-
59
51
 
60
52
  async init(){
61
53
  await super.init()
62
- var md = this.addMetadatum('encryptionKey','', "Encryption Key")
63
- md.isParam = true
64
- this.metadata = new Map(super.getMetadata())
65
- md = this.addMetadatum('encryptionKey','', "Encryption Key")
54
+ const md =this.addMetadatum('encryptionKey','', "Encryption Key")
66
55
  md.isParam = true
67
56
  this.model_id=this.getManufacturerData(0x2e1).readUInt16LE(2)
68
57
  }
@@ -35,7 +35,7 @@ class VictronACCharger extends VictronSensor{
35
35
  initMetadata(){
36
36
  this.addMetadatum('state','', 'device state',
37
37
  (buff)=>{return VC.OperationMode.get(buff.readUInt8(0))})
38
- this.addMetadatum('error','', 'error code',
38
+ this.addMetadatum('chargerError','', 'charger error code',
39
39
  (buff)=>{return VC.ChargerError.get(buff.readUInt8(1))})
40
40
 
41
41
  this.addMetadatum('batt1','V', 'battery 1 voltage')
@@ -70,4 +70,4 @@ class VictronACCharger extends VictronSensor{
70
70
  this.emit("acCurr", this.NaNif(br.read_unsigned_int(9),0x1FF)/10)
71
71
  }
72
72
  }
73
- module.exports=VictronACCharger
73
+ module.exports=VictronACCharger
@@ -16,10 +16,19 @@ Start Bit Nr of Bits Meaning Units Range NA Value Remark
16
16
  152 7 Battery temperature 1°C -40..86 °C 0x7F VE_REG_BAT_TEMPERATURE Temperature = Record value - 40
17
17
  159 1 Unused
18
18
  VE_REG_BATTERY_CELL_VOLTAGE 0x00 ( 0) when cell voltage < 2.61V 0x01 ( 1) when cell voltage == 2.61V 0x7D (125) when cell voltage == 3.85V 0x7E (126) when cell voltage > 3.85 0x7F (127) when cell voltage is not available / unknown
19
- */const VictronSensor = require ("./Victron/VictronSensor")
19
+ */
20
+
21
+ const VictronSensor = require ("./Victron/VictronSensor")
20
22
  const VC = require("./Victron/VictronConstants")
21
23
  const BitReader = require("./_BitReader")
22
24
 
25
+ const BALANCERSTATUS = {
26
+ 0:"Unknown",
27
+ 1:"Balanced",
28
+ 2:"Balancing",
29
+ 3:"Cell imbalance",
30
+ 0xF:"Not applicable"
31
+ }
23
32
  function _toCellVoltage(val){
24
33
  return val==0x7F?NaN:2.6+(val/100)
25
34
  }
@@ -51,15 +60,15 @@ class VictronSmartLithium extends VictronSensor{
51
60
  this.addMetadatum('batteryVoltage','V', 'battery voltage',
52
61
  (buff)=>{return this.NaNif((buff.readUInt16LE(13)&0xFFF),0xFFF)/100})
53
62
  this.addMetadatum('balancerStatus','', 'balancer status', //TODO
54
- (buff)=>{return this.NaNif((buff.readUInt8(14)>>4),0xF)})
63
+ (buff)=>{return BALANCERSTATUS[this.NaNif((buff.readUInt8(14)>>4),0xF)]})
55
64
  this.addMetadatum('batteryTemp','K', 'battery temperature',
56
65
  (buff)=>{return this.NaNif((buff.readUInt8(15)&0x7F),0x7F)+233.15})
57
66
  }
58
67
  emitValuesFrom(buffer){
59
68
  super.emitValuesFrom(buffer)
60
69
  const br = new BitReader(buffer.subarray(6,13))
61
- for (let i = 1; i<8; i++)
70
+ for (let i = 0; i<8; i++)
62
71
  this.emit(`cell${i+1}Voltage`,_toCellVoltage(br.read_unsigned_int(7)))
63
72
  }
64
73
  }
65
- module.exports=VictronSmartLithium
74
+ module.exports=VictronSmartLithium