bt-sensors-plugin-sk 1.1.0-beta.2.1.1 → 1.1.0-beta.2.1.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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  ## WHAT IT IS
5
5
 
6
- BT Sensors Plugin for Signalk is a lightweight BLE (Bluetooth Low Energy) framework for connecting to Bluetooth sensors on your boat and sending deltas to Signalk paths with the values the sensors reports. <br>
6
+ BT Sensors Plugin for Signalk is a lightweight BLE (Bluetooth Low Energy) framework for listening and connecting to Bluetooth sensors on your boat and sending deltas to Signalk paths with the values the sensors reports. <br>
7
7
 
8
8
  The Plugin currently supports every documented Victron device (AC Charger, Battery Monitor, DC-DC Converter, DC Energy Meter, GX Device, Inverter, Inverter RS, Lynx Smart BMS, Orion XS, Smart Battery Protect, Smart Lithium and VE Bus), Xiaomi devices, [ATC devices](https://github.com/atc1441/ATC_MiThermometer), RuuviTags and Inkbird thermometers.
9
9
 
@@ -71,7 +71,7 @@ Then press the + button to add a sensor. Your screen should look something like
71
71
 
72
72
  <br><br>
73
73
 
74
- Select the sensor you want to connect to from the drop down.<br>
74
+ Select the sensor you want Signalk to listen to from the drop down.<br>
75
75
 
76
76
  If you don't see your device and you know that it's on and nearby to the server, it may not be currently supported. But fear not, you can add custom sensor classes yourself. (Check out [the development section](#development).). <br><br>
77
77
 
package/index.js CHANGED
@@ -48,8 +48,8 @@ class MissingSensor {
48
48
  getDisplayName(){
49
49
  return `OUT OF RANGE DEVICE (${this.getName()} ${this.getMacAddress()})`
50
50
  }
51
- disconnect(){}
52
- connect(){}
51
+ stopListening(){}
52
+ listen(){}
53
53
  }
54
54
  module.exports = function (app) {
55
55
  const adapterID = 'hci0'
@@ -159,7 +159,7 @@ module.exports = function (app) {
159
159
  plugin.schema = {
160
160
  type: "object",
161
161
  description: "NOTE: \n 1) Plugin must be enabled to configure your sensors. \n"+
162
- "2) You will have to wait until the scanner has found and connected to your device before seeing your device's config fields and saving the configuration. \n"+
162
+ "2) You will have to wait until the scanner has found your device before seeing your device's config fields and saving the configuration. \n"+
163
163
  "3) To refresh the list of available devices and their configurations, just open and close the config screen by clicking on the arrow symbol in the config's top bar. \n"+
164
164
  "4) If you submit and get errors it may be because the configured devices have not yet all been discovered.",
165
165
  required:["discoveryTimeout", "discoveryInterval"],
@@ -310,7 +310,7 @@ module.exports = function (app) {
310
310
  })
311
311
  .catch((e)=>{
312
312
  if (s)
313
- s.disconnect()
313
+ s.stopListening()
314
314
  app.debug(`Unable to communicate with device ${deviceNameAndAddress(config)} Reason: ${e?.message??e}`)
315
315
  reject( e?.message??e )
316
316
  })})
@@ -346,22 +346,24 @@ module.exports = function (app) {
346
346
  if (deviceConfig.active) {
347
347
  createPaths(deviceConfig)
348
348
  initPaths(deviceConfig)
349
- const result = Promise.resolve(deviceConfig.sensor.connect())
349
+ const result = Promise.resolve(deviceConfig.sensor.listen())
350
350
  result.then(() => {
351
- app.debug(`Connected to ${deviceConfig.sensor.getDisplayName()}`);
352
- app.setPluginStatus(`Initial scan complete. Connected to ${++found} sensors.`);
351
+ app.debug(`Listening for changes from ${deviceConfig.sensor.getDisplayName()}`);
352
+ app.setPluginStatus(`Initial scan complete. Listening to ${++found} sensors.`);
353
353
  })
354
354
  }
355
355
 
356
356
  })
357
357
  .catch((error)=>
358
358
  {
359
+
359
360
  const msg =`Sensor at ${deviceConfig.mac_address} unavailable. Reason: ${error}`
360
361
  app.debug(msg)
361
362
  app.debug(error)
362
363
  app.setPluginError(msg)
363
364
  deviceConfig.sensor=new MissingSensor(deviceConfig)
364
365
  addSensorToList(deviceConfig.sensor) //add sensor to list with known options
366
+
365
367
  })
366
368
  }
367
369
  function findDevices (discoveryTimeout) {
@@ -439,13 +441,15 @@ module.exports = function (app) {
439
441
  plugin.stopped=true
440
442
  plugin.uiSchema.peripherals['ui:disabled']=true
441
443
  if ((sensorMap)){
444
+ plugin.schema.properties.peripherals.items.properties.mac_address.enum=[]
445
+ plugin.schema.properties.peripherals.items.properties.mac_address.enumNames=[]
442
446
  sensorMap.forEach(async (sensor, mac)=> {
443
447
  try{
444
- await sensor.disconnect()
445
- app.debug(`Disconnected from ${mac}`)
448
+ await sensor.stopListening()
449
+ app.debug(`No longer listening to ${mac}`)
446
450
  }
447
451
  catch (e){
448
- app.debug(`Error disconnecting from ${mac}: ${e.message}`)
452
+ app.debug(`Error stopping listening to ${mac}: ${e.message}`)
449
453
  }
450
454
  })
451
455
  }
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.1",
3
+ "version": "1.1.0-beta.2.1.3",
4
4
  "description": "Bluetooth Sensors for Signalk -- support for Victron devices, RuuviTag, Xiaomi, ATC and Inkbird",
5
5
  "main": "index.js",
6
6
  "dependencies": {
@@ -1,6 +1,12 @@
1
1
  const BTSensor = require("../BTSensor");
2
2
  class ATC extends BTSensor{
3
-
3
+
4
+ constructor(device, config={}){
5
+ super(device,config)
6
+ if (config.parser){
7
+ this.parser=config.parser
8
+ }
9
+ }
4
10
  static async identify(device){
5
11
  try{
6
12
  const regex = /^ATC_[A-Fa-f0-9]{6}$/
@@ -15,22 +21,48 @@ class ATC extends BTSensor{
15
21
  }
16
22
 
17
23
  async init() {
18
- await super.init()
19
- this.addMetadatum('temp','K', 'temperature',
20
- (buff,offset)=>{return ((buff.readInt16LE(offset))/100) + 273.1})
21
- this.addMetadatum('humidity','ratio', 'humidity',
22
- (buff,offset)=>{return ((buff.readUInt16LE(offset))/10000)})
23
- this.addMetadatum('voltage', 'V', 'sensor battery voltage',
24
- (buff,offset)=>{return ((buff.readUInt16LE(offset))/1000)})
24
+ await super.init()
25
+ const md=this.addMetadatum('parser','','data parsing strategy')
26
+ md.isParam=true
27
+ md.enum=["ATC-LE","ATC-BE"]
28
+ if (!this.parser){
29
+ this.parser="ATC-LE"
30
+ }
31
+ this.initMetadata()
32
+ }
33
+ initMetadata(){
34
+ if (this.parser=="ATC-LE"){
35
+ this.addMetadatum('voltage', 'V', 'sensor battery voltage',
36
+ (buff)=>{return ((buff.readUInt16LE(10))/1000)})
37
+ this.addMetadatum('batteryStrength', 'ratio', 'sensor battery strength',
38
+ (buff)=>{return ((buff.readUInt8(12))/100)})
39
+ this.addMetadatum('temp','K', 'temperature',
40
+ (buff)=>{return parseFloat((273.15+(buff.readInt16LE(6))/100).toFixed(2))})
41
+ this.addMetadatum('humidity','ratio', 'humidity',
42
+ (buff)=>{return ((buff.readUInt16LE(8))/10000)})
43
+
44
+ } else{
45
+ this.addMetadatum('voltage', 'V', 'sensor battery voltage',
46
+ (buff)=>{return ((buff.readUInt16BE(10))/1000)})
47
+ this.addMetadatum('batteryStrength', 'ratio', 'sensor battery strength',
48
+ (buff)=>{return ((buff.readUInt8(9))/100)})
49
+ this.addMetadatum('temp','K', 'temperature',
50
+ (buff)=>{return parseFloat((273.15+(buff.readInt16BE(6))/100).toFixed(2))})
51
+ this.addMetadatum('humidity','ratio', 'humidity',
52
+ (buff)=>{return ((buff.readUInt8(8))/100)})
53
+
54
+ }
25
55
  }
26
56
  propertiesChanged(props){
27
57
  super.propertiesChanged(props)
28
58
  const buff = this.getServiceData("0000181a-0000-1000-8000-00805f9b34fb")
29
59
  if (!buff)
30
60
  throw new Error("Unable to get service data for "+this.getDisplayName())
31
- this.emitData("temp", buff, 6)
32
- this.emitData("humidity", buff, 8)
33
- this.emitData("voltage", buff, 10)
61
+ this.emitData("temp", buff)
62
+ this.emitData("humidity", buff)
63
+ this.emitData("voltage", buff)
64
+ this.emitData("batteryStrength", buff)
65
+
34
66
  }
35
67
  getManufacturer(){
36
68
  return "ATC1441 (custom firmware see: https://github.com/atc1441)"
@@ -12,7 +12,13 @@ class BLACKLISTED extends BTSensor{
12
12
  reasonForBlacklisting() {
13
13
  switch ( this.getManufacturerID()){
14
14
  case (0x004C): return "Randomized MAC address"
15
+ case (0x02e1): return "Device is using VE.Smart" //NOTE: Victron/VictronSensor class
16
+ //determines if a device is using VE.Smart
17
+ //in identify(). If so, identify() returns
18
+ //BlackListedDevice
19
+
15
20
  default: return ""
21
+
16
22
  }
17
23
 
18
24
  }
@@ -36,7 +36,7 @@ class Inkbird extends BTSensor{
36
36
  const data = this.getManufacturerData(key)
37
37
  if (!data)
38
38
  throw new Error("Unable to get manufacturer data for "+this.getDisplayName())
39
- this.emit("temp", (parseInt(key)/100) + 273.1);
39
+ this.emit("temp", parseFloat((273.15+parseInt(key)/100).toFixed(2))) ;
40
40
  this.emit('battery', data[5]/100)
41
41
  if (this.getMetadata().has('humidity')){
42
42
  this.emit("temp", data.readUInt16LE(0)/100);
@@ -40,10 +40,10 @@ class RuuviTag extends BTSensor{
40
40
  **/
41
41
  _initModeV5(){
42
42
  this.addMetadatum("temp","K","temperature in Kelvin",
43
- (buffer)=>{ return (buffer.readInt16BE(1)*.005).toFixed(3)+273.15}
43
+ (buffer)=>{ return parseFloat((273.15+buffer.readInt16BE(1)*.005).toFixed(3))}
44
44
  )
45
45
  this.addMetadatum("humidity","ratio","humidity",
46
- (buffer)=>{ return ((buffer.readUInt16BE(3)*.0025)/100).toFixed(2)}
46
+ (buffer)=>{ return parseFloat(((buffer.readUInt16BE(3)*.0025)/100).toFixed(2))}
47
47
  )
48
48
  this.addMetadatum("pressure","Pa","atmospheric pressure",
49
49
  (buffer)=>{ return buffer.readUInt16BE(5)+50000}
@@ -58,7 +58,7 @@ class RuuviTag extends BTSensor{
58
58
  (buffer)=>{ return buffer.readInt16BE(11)}
59
59
  )
60
60
  this.addMetadatum("battV","V","battery voltage",
61
- (buffer)=>{ return 1.6+(buffer.readUInt16BE(13)>>5)/1000}
61
+ (buffer)=>{ return parseFloat((1.6+(buffer.readUInt16BE(13)>>5)/1000).toFixed(2))}
62
62
  )
63
63
  this.addMetadatum("mc","","movement counter",
64
64
  (buffer)=>{ return buffer.readUInt16BE(13) && 0x1F}
@@ -126,6 +126,8 @@ module.exports = {
126
126
  0xA06F: "BlueSolar MPPT 150|45 rev2",
127
127
  0xA070: "BlueSolar MPPT 150|60 rev2",
128
128
  0xA071: "BlueSolar MPPT 150|70 rev2",
129
+ 0xA0F0: "Smart Lithium Battery 4 cells 12v 330AH",
130
+ 0xA0EE: "Smart Lithium Battery",
129
131
  0xA102: "SmartSolar MPPT VE.Can 150/70",
130
132
  0xA103: "SmartSolar MPPT VE.Can 150/45",
131
133
  0xA104: "SmartSolar MPPT VE.Can 150/60",
@@ -193,6 +195,8 @@ module.exports = {
193
195
  0xA2A1: "Phoenix Inverter 12V 3000VA 230V",
194
196
  0xA2A2: "Phoenix Inverter 24V 3000VA 230V",
195
197
  0xA2A4: "Phoenix Inverter 48V 3000VA 230V",
198
+ 0xA31A: "Blue Smart AC Charger IP67",
199
+ 0xA33C: "Blue Smart AC Charger IP65",
196
200
  0xA340: "Phoenix Smart IP43 Charger 12|50 (1+1)",
197
201
  0xA341: "Phoenix Smart IP43 Charger 12|50 (3)",
198
202
  0xA342: "Phoenix Smart IP43 Charger 24|25 (1+1)",
@@ -201,6 +205,7 @@ module.exports = {
201
205
  0xA345: "Phoenix Smart IP43 Charger 12|30 (3)",
202
206
  0xA346: "Phoenix Smart IP43 Charger 24|16 (1+1)",
203
207
  0xA347: "Phoenix Smart IP43 Charger 24|16 (3)",
208
+ 0xA350: "Phoenix Smart IP43 Charger 12|50 (1+1) 120-240V A350",
204
209
  0xA381: "BMV-712 Smart",
205
210
  0xA382: "BMV-710H Smart",
206
211
  0xA383: "BMV-712 Smart Rev2",
@@ -2,7 +2,8 @@ const BTSensor = require("../../BTSensor.js");
2
2
  const crypto = require('node:crypto');
3
3
  const int24 = require('int24')
4
4
  const util = require('util')
5
- const VC = require('./VictronConstants.js')
5
+ const VC = require('./VictronConstants.js');
6
+ const BLACKLISTED = require("../BlackListedDevice.js");
6
7
 
7
8
  class VictronSensor extends BTSensor{
8
9
 
@@ -17,10 +18,14 @@ const VC = require('./VictronConstants.js')
17
18
  const md = await this.getDeviceProp(device,'ManufacturerData')
18
19
  if (!md) return null
19
20
  const data = md[0x2e1]
21
+ if (data.value[0]==0x2) { //VE.Smart is on
22
+ return BLACKLISTED
23
+ }
20
24
  if (data && data.value[0]==0x10 && data.value[4]==mode)
21
25
  return this
22
- else
26
+ else {
23
27
  return null
28
+ }
24
29
  } catch (e){
25
30
  console.log(e)
26
31
  return null
@@ -28,20 +33,6 @@ const VC = require('./VictronConstants.js')
28
33
 
29
34
  }
30
35
 
31
- getAuxModeAndCurrent(offset, decData=null){
32
- if (decData==null){
33
- decData=this.getManufacturerData(0x2e1)
34
- if (this.encryptionKey)
35
- decData=this.decrypt(decData)
36
- else
37
- return {current:NaN, auxMode:NaN}
38
- }
39
- const auxModeAndCurrent = int24.readInt24LE(decData,offset)
40
- return {
41
- current : (this.NaNif(auxModeAndCurrent >> 2,0x3FFFFF))/1000,
42
- auxMode : auxModeAndCurrent & 0b11
43
- }
44
- }
45
36
 
46
37
  async init(){
47
38
  await super.init()
@@ -85,17 +76,21 @@ const VC = require('./VictronConstants.js')
85
76
  propertiesChanged(props){
86
77
  super.propertiesChanged(props)
87
78
  if (this.usingGATT()) return
79
+
88
80
  try{
89
- const buff = this.getManufacturerData(0x2e1)
90
- const decData=this.decrypt(buff)
91
- this.emitValuesFrom(decData)
81
+ const md = this.getManufacturerData(0x2e1)
82
+ if (md.length && md[0]==0x10){
83
+ const buff = this.getManufacturerData(0x2e1)
84
+ const decData=this.decrypt(buff)
85
+ this.emitValuesFrom(decData)
86
+ }
92
87
  }
93
88
  catch (error) {
94
89
  throw new Error(`Unable to read data from ${ this.getDisplayName()}: ${error}` )
95
90
  }
96
91
  }
97
92
 
98
- initGATT(){
93
+ initGATTConnection(){
99
94
  throw new Error( "GATT Connection unimplemented for "+this.getDisplayName())
100
95
  }
101
96
 
@@ -30,34 +30,37 @@ class VictronACCharger extends VictronSensor{
30
30
 
31
31
  async init(){
32
32
  await super.init()
33
+ this.initMetadata()
34
+ }
35
+ initMetadata(){
33
36
  this.addMetadatum('state','', 'device state',
34
37
  (buff)=>{return VC.OperationMode.get(buff.readUInt8(0))})
35
38
  this.addMetadatum('error','', 'error code',
36
39
  (buff)=>{return VC.ChargerError.get(buff.readUInt8(1))})
37
40
 
38
41
  this.addMetadatum('batt1','V', 'battery 1 voltage',
39
- (buff)=>{return this.NaNif((buff.readUInt16BE(2)>>3), 0x1FFF)/100})
42
+ (buff)=>{return this.NaNif((buff.readUInt16LE(2)&0x1FFF), 0x1FFF)/100})
40
43
 
41
44
  this.addMetadatum('curr1','A', 'battery 1 current',
42
45
  (buff)=>{return this.NaNif(buff.readUInt16BE(3)&0x7FF,0x7FF)/10})
43
46
 
44
47
  this.addMetadatum('batt2','V', 'battery 2 voltage',
45
- (buff)=>{return this.NaNif((buff.readUInt16BE(5)>>3), 0x1FFF)/100})
48
+ (buff)=>{return this.NaNif((buff.readUInt16LE(5)&0x1FFF), 0x1FFF)/100})
46
49
 
47
50
  this.addMetadatum('curr2','A', 'battery 2 current',
48
51
  (buff)=>{return this.NaNif(buff.readUInt16BE(7)&0x7FF,0x7FF)/10})
49
52
 
50
53
  this.addMetadatum('batt3','V', 'battery 3 voltage',
51
- (buff)=>{return this.NaNif((buff.readUInt16BE(8)>>3), 0x1FFF)/100})
54
+ (buff)=>{return this.NaNif((buff.readUInt16LE(8)&0x1FFF), 0x1FFF)/100})
52
55
 
53
56
  this.addMetadatum('curr3','A', 'battery 3 current',
54
57
  (buff)=>{return this.NaNif(buff.readUInt16BE(9)&0x7FF,0x7FF)/10})
55
58
 
56
59
  this.addMetadatum('temp', 'K', 'battery temperature',
57
- (buff)=>{return this.NaNif(buff.readUInt8(11)>>1,0x7F)+233.15}) //-40 plus K conversion
60
+ (buff)=>{return this.NaNif(buff.readUInt8(11)&0x7F,0x7F)+233.15}) //-40 plus K conversion
58
61
 
59
62
  this.addMetadatum('acCurr','A', 'AC current',
60
- (buff)=>{return this.NaNif((buff.readInt16BE(11))&0x1FFF,0x1FFF)})
63
+ (buff)=>{return this.NaNif((buff.readUInt16BE(11)&0x1FF),0x1FF)/10})
61
64
  }
62
65
  }
63
66
  module.exports=VictronACCharger
@@ -1,15 +1,45 @@
1
+ /**
2
+
3
+ */
4
+
1
5
  const VictronSensor = require("./Victron/VictronSensor.js");
2
6
  const VC=require("./Victron/VictronConstants.js")
7
+ const int24 = require('int24')
3
8
  class VictronBatteryMonitor extends VictronSensor{
4
9
 
5
10
 
6
11
  static async identify(device){
7
12
  return await this.identifyMode(device, 0x02)
8
13
  }
14
+ static _test(data, key){
15
+ var b = Buffer.from(data.replaceAll(" ",""),"hex")
16
+ const d = new this()
17
+
18
+ if (key) {
19
+ d.encryptionKey = key
20
+
21
+ }
22
+ d.currentProperties = {}
23
+ d.currentProperties.ManufacturerData={}
24
+ d.currentProperties.ManufacturerData[0x02e1]=b
25
+ d.initMetadata()
26
+ d.getPathMetadata().forEach((datum,tag)=>{
27
+ d.on(tag,(v)=>console.log(`${tag}=${v}`))
28
+ })
29
+ b = d.decrypt(b)
30
+ console.log(b)
31
+ d.emitValuesFrom(b)
32
+ d.removeAllListeners()
33
+
34
+ }
9
35
 
10
36
  characteristics=[]
11
37
  async init(){
12
38
  await super.init()
39
+ this.initMetadata()
40
+ }
41
+
42
+ initMetadata(){
13
43
  this.addMetadatum('current', 'A', 'house battery amperage',
14
44
  (buff,offset=0)=>{return buff.readInt32LE(offset)/1000},
15
45
  '6597ed8c-4bda-4c1e-af4b-551c4cf74769')
@@ -33,9 +63,13 @@ class VictronBatteryMonitor extends VictronSensor{
33
63
 
34
64
  this.addMetadatum( 'ttg','s','time to go',
35
65
  (buff,offset=0)=>{return this.NaNif(buff.readUInt16LE(offset),0xFFFF)*60},
36
- '65970ffe-4bda-4c1e-af4b-551c4cf74769')
37
- const modecurrent = this.getAuxModeAndCurrent()
38
- this.auxMode= modecurrent.auxMode
66
+ '65970ffe-4bda-4c1e-af4b-551c4cf74769')
67
+ if (this.encryptionKey){
68
+ const decData = this.decrypt(this.getManufacturerData(0x02e1))
69
+ if (decData)
70
+ this.auxMode=decData.readInt8(8)&0x3
71
+ }
72
+
39
73
  switch(this.auxMode){
40
74
  case VC.AuxMode.STARTER_VOLTAGE:
41
75
  this.addMetadatum('starterVoltage','V', 'starter battery voltage',
@@ -50,14 +84,14 @@ class VictronBatteryMonitor extends VictronSensor{
50
84
 
51
85
  case VC.AuxMode.TEMPERATURE:
52
86
  this.addMetadatum('temperature','K', 'House battery temperature',
53
- (buff,offset=0)=>{return buff.readInt16LE(offset)/100},
87
+ (buff,offset=0)=>{return (buff.readInt16LE(offset)/1000)+273.15},
54
88
  '6597ed7d-4bda-4c1e-af4b-551c4cf74769')
55
89
  break;
56
90
  default:
57
91
  break
58
92
  }
59
93
  }
60
-
94
+
61
95
  emitValuesFrom(decData){
62
96
  this.emitData("ttg",decData,0)
63
97
  this.emitData("voltage",decData,2);
@@ -65,10 +99,8 @@ class VictronBatteryMonitor extends VictronSensor{
65
99
  if (alarm>0){
66
100
  this.emit(
67
101
  `ALARM #${alarm} from ${this.getDisplayName()})`,
68
- { message: AlarmReason.get(alarm), state: 'alert'})
102
+ { message: VC.AlarmReason.get(alarm), state: 'alert'})
69
103
  }
70
-
71
- this.emit("current", (this.getAuxModeAndCurrent(8,decData)).current)
72
104
  switch(this.auxMode){
73
105
  case VC.AuxMode.STARTER_VOLTAGE:
74
106
  this.emitData("starterVoltage",decData,6);
@@ -81,17 +113,19 @@ class VictronBatteryMonitor extends VictronSensor{
81
113
  break;
82
114
  default:
83
115
  break
84
- }
85
- this.emit("consumed",decData.readInt16LE(11) / 10 ); //TODO this ain't right
86
- var soc = decData.readUInt16LE(13)
87
- this.emit("soc", ((soc & 0x3FFF) >> 4) / 1000)
116
+ }
117
+ this.emit("current", (this.NaNif(int24.readInt24LE(decData, 8)>>2,0x3FFFFF))/1000)
118
+ this.emit("consumed",(this.NaNif(int24.readInt24LE(decData, 11)&0xFFFFF,0xFFFFF)) / 10) ;
119
+ this.emit("soc", this.NaNif(((decData.readUInt16LE(13)& 0x3FFF)>>4),0x3FF)/1000)
120
+
88
121
  }
89
122
 
90
- initGATT() {
123
+ initGATTConnection() {
91
124
  return new Promise((resolve,reject )=>{
92
125
  if (!this.valueIfVariant(this.currentProperties.Paired))
93
126
  reject(`${this.getName()} must be paired with the Signalk server to use GATT protocol`)
94
127
  this.device.connect().then(async ()=>{
128
+ this.debug(`${this.getName()} connected.`)
95
129
  if (!this.gattServer) {
96
130
  this.gattServer = await this.device.gatt()
97
131
  this.gattService= await this.gattServer.getPrimaryService("65970000-4bda-4c1e-af4b-551c4cf74769")
@@ -133,9 +167,7 @@ class VictronBatteryMonitor extends VictronSensor{
133
167
  }})
134
168
  resolve(this)})
135
169
  }
136
- propertiesChanged(props){
137
- super.propertiesChanged(props)
138
- }
170
+
139
171
  hasGATT(){
140
172
  return true
141
173
  }
@@ -144,14 +176,14 @@ class VictronBatteryMonitor extends VictronSensor{
144
176
  return "To use the GATT connection the SignalK server computer and the Smart Shunt must first be paired."
145
177
  }
146
178
 
147
- async disconnect(){
148
- super.disconnect()
179
+ async stopListening(){
180
+ super.stopListening()
149
181
  for (var c of this.characteristics){
150
182
  await c.stopNotifications()
151
183
  }
152
184
  if (await this.device.isConnected()){
153
- console.log(`Disconnecting from ${ this.getMacAddress()}`)
154
185
  await this.device.disconnect()
186
+ this.debug(`Disconnected from ${ this.getName()}`)
155
187
  }
156
188
  }
157
189
  }
@@ -27,7 +27,7 @@ TBD
27
27
  }
28
28
 
29
29
  async init() {
30
- super.init()
30
+ await super.init()
31
31
  this.addMetadatum('voltage','V', 'channel #1 voltage',
32
32
  (buff)=>{return this.NaNif(buff.readInt16LE(0),0xFFFF)/100})
33
33
  this.addMetadatum('pvPower','W','DC input power in watts',
@@ -27,6 +27,9 @@ class VictronSmartLithium extends VictronSensor{
27
27
 
28
28
  async init() {
29
29
  await super.init()
30
+ this.initMetadata()
31
+ }
32
+ initMetadata(){
30
33
  function _toCellVoltage(val){
31
34
  return val==0x7F?NaN:2.6+(val/100)
32
35
  }
@@ -34,29 +37,29 @@ class VictronSmartLithium extends VictronSensor{
34
37
  (buff)=>{return buff.readUInt32BE(0)})
35
38
 
36
39
  this.addMetadatum('smartLithiumErrors','', 'Smart Lithium Errors Flags',
37
- (buff)=>{return buff.readUInt16BE(3)})
40
+ (buff)=>{return buff.readUInt16BE(4)})
38
41
  this.addMetadatum('cell1Voltage','V', 'cell #1 voltage',
39
- (buff)=>{return _toCellVoltage((buff.readUInt8(5))>>1)})
42
+ (buff)=>{return _toCellVoltage((buff.readUInt8(6))>>1)})
40
43
  this.addMetadatum('cell2Voltage','V', 'cell #2 voltage',
41
- (buff)=>{return _toCellVoltage((buff.subarray(5,7).readUInt16BE())&0x01fe>>2)})
44
+ (buff)=>{return _toCellVoltage(((buff.readUInt16BE(6))&0x01Fe)>>2)})
42
45
  this.addMetadatum('cell3Voltage','V', 'cell #3 voltage',
43
- (buff)=>{return _toCellVoltage(((buff.subarray(6,8).readUInt16BE())&0x03fe)>>3)})
46
+ (buff)=>{return _toCellVoltage(((buff.readUInt16BE(7))&0x03Fe)>>3)})
44
47
  this.addMetadatum('cell4Voltage','V', 'cell #4 voltage',
45
- (buff)=>{return _toCellVoltage(((buff.subarray(7,9).readUInt16BE())&0x07fe)>>4)})
48
+ (buff)=>{return _toCellVoltage(((buff.readUInt16BE(8))&0x07fe)>>4)})
46
49
  this.addMetadatum('cell5Voltage','V', 'cell #5 voltage',
47
- (buff)=>{return _toCellVoltage(((buff.subarray(8,10).readUInt16BE())&0x0ffe)>>5)})
50
+ (buff)=>{return _toCellVoltage(((buff.readUInt16BE(9))&0x0ffe)>>5)})
48
51
  this.addMetadatum('cell6Voltage','V', 'cell #6 voltage',
49
- (buff)=>{return _toCellVoltage(((buff.subarray(9,11).readUInt16BE())&0x1ffe)>>6)})
52
+ (buff)=>{return _toCellVoltage(((buff.readUInt16BE(10))&0x1ffe)>>6)})
50
53
  this.addMetadatum('cell7Voltage','V', 'cell #7 voltage',
51
- (buff)=>{return _toCellVoltage(((buff.subarray(10,12).readUInt16BE())&0x3ffe)>>7)})
54
+ (buff)=>{return _toCellVoltage(((buff.readUInt16BE(11))&0x3ffe)>>7)})
52
55
  this.addMetadatum('cell8Voltage','V', 'cell #8 voltage',
53
- (buff)=>{return _toCellVoltage((buff.readUInt8(11))&0x7f)})
56
+ (buff)=>{return _toCellVoltage((buff.readUInt8(12))&0x7e)})
54
57
  this.addMetadatum('batteryVoltage','V', 'battery voltage',
55
- (buff)=>{return this.NaNif((buff.readUInt16BE(14)>>4),0xFFF)/100})
58
+ (buff)=>{return this.NaNif((buff.readUInt16LE(13)&0xFFF),0xFFF)/100})
56
59
  this.addMetadatum('balancerStatus','', 'balancer status', //TODO
57
- (buff)=>{return this.NaNif((buff.readUInt16BE(14)&0xf),0xF)})
60
+ (buff)=>{return this.NaNif((buff.readUInt8(14)&0xf),0xF)})
58
61
  this.addMetadatum('batteryTemp','K', 'battery temperature',
59
- (buff)=>{return this.NaNif((buff.readInt8(15)>>1),0x7F)+233.15})
62
+ (buff)=>{return this.NaNif((buff.readUInt8(15)&0x7F),0x7F)+233.15})
60
63
  }
61
64
  }
62
65
  module.exports=VictronSmartLithium
@@ -8,22 +8,23 @@ class VictronSolarCharger extends VictronSensor{
8
8
 
9
9
  async init() {
10
10
  await super.init()
11
-
12
- this.addMetadatum('chargeState','', 'charge state',
13
- (buff)=>{return VC.OperationMode.get(buff.readUInt8(0))})
14
- this.addMetadatum('chargerError','', 'charger error',
15
- (buff)=>{return VC.ChargerError.get(buff.readUInt8(1))})
16
- this.addMetadatum('voltage','V', 'charger battery voltage',
17
- (buff)=>{return this.NaNif(buff.readInt16LE(2),0x7FFF)/100})
18
- this.addMetadatum('current','A','charger battery current',
19
- (buff)=>{return this.NaNif(buff.readInt16LE(4),0x7FFF)/10})
20
- this.addMetadatum('yield','Wh', 'yield today in Watt-hours',
21
- (buff)=>{return this.NaNif(buff.readUInt16LE(6),0xFFFF)*10})
22
- this.addMetadatum('solarPower','W', 'solar power',
23
- (buff)=>{return this.NaNif(buff.readUInt16LE(8),0xFFFF)})
24
- this.addMetadatum('externalDeviceLoad','A', 'external device load',
25
- (buff)=>{return this.NaNif(buff.readUInt16BE(10)>>7,0x1FF)})
26
- }
27
-
11
+ this.initMetadata()
12
+ }
13
+ initMetadata() {
14
+ this.addMetadatum('chargeState','', 'charge state',
15
+ (buff)=>{return VC.OperationMode.get(buff.readUInt8(0))})
16
+ this.addMetadatum('chargerError','', 'charger error',
17
+ (buff)=>{return VC.ChargerError.get(buff.readUInt8(1))})
18
+ this.addMetadatum('voltage','V', 'charger battery voltage',
19
+ (buff)=>{return this.NaNif(buff.readInt16LE(2),0x7FFF)/100})
20
+ this.addMetadatum('current','A','charger battery current',
21
+ (buff)=>{return this.NaNif(buff.readInt16LE(4),0x7FFF)/10})
22
+ this.addMetadatum('yield','Wh', 'yield today in Watt-hours',
23
+ (buff)=>{return this.NaNif(buff.readUInt16LE(6),0xFFFF)*10})
24
+ this.addMetadatum('solarPower','W', 'solar power',
25
+ (buff)=>{return this.NaNif(buff.readUInt16LE(8),0xFFFF)})
26
+ this.addMetadatum('externalDeviceLoad','A', 'external device load',
27
+ (buff)=>{return this.NaNif(buff.readUInt16BE(10)>>7,0x1FF)})
28
+ }
28
29
  }
29
30
  module.exports=VictronSolarCharger
@@ -105,7 +105,7 @@ class XiaomiMiBeacon extends BTSensor{
105
105
  getGATTDescription() {
106
106
  return this.GATTwarning
107
107
  }
108
- initGATT(){
108
+ initGATTConnection(){
109
109
  if (!this?.gattWarningDelivered) {
110
110
  this.debug(this.GATTwarning.toUpperCase())
111
111
  this.gattWarningDelivered=true
@@ -212,15 +212,15 @@ class XiaomiMiBeacon extends BTSensor{
212
212
  return this?.name??`${dt.name} ${dt.model}`
213
213
  }
214
214
 
215
- async disconnectGattCharacteristic(){
215
+ async disconnectGATTCharacteristic(){
216
216
  if (this.gattCharacteristic && await this.gattCharacteristic.isNotifying()) {
217
217
  await this.gattCharacteristic.stopNotifications()
218
218
  this.gattCharacteristic=null
219
219
  }
220
220
  }
221
- async disconnect(){
222
- super.disconnect()
223
- await this.disconnectGattCharacteristic()
221
+ async stopListening(){
222
+ super.stopListening()
223
+ await this.disconnectGATTCharacteristic()
224
224
 
225
225
  if (await this.device.isConnected()){
226
226
  await this.device.disconnect()