bt-sensors-plugin-sk 1.1.0-beta.2.2.2 → 1.1.0-beta.2.2.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/README.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Bluetooth Sensors for [Signal K](http://www.signalk.org)
2
2
 
3
+ ## BETA 2.2.4
4
+ ### What's New
5
+ Fix to 2.2.3 scan and connect issues. Added Transport option to Config page. Default is Bluetooth LE (was Auto in 2.2.3).
6
+
7
+ ## BETA 2.2.3
8
+ ### What's New
9
+ Support for [JBD/Jiabaida/Xiaoxiang Battery management systems](https://jiabaida-bms.com/), IBeacon and clone devices courtesy of [Arjen R](https://github.com/ArjenR).
10
+
11
+ ### What's New for Developers
12
+ Runtime loading of external device modules. See (https://github.com/naugehyde/bt-sensors-plugin-sk/discussions/26)
3
13
  ## BETA 2.2.2
4
14
  ### What's New
5
15
  Support for Lancol Battery Meters, Kilovault HLX+ smart batteries courtesy of [sdlee1963](https://github.com/sdlee1963) and baseline support for BTHome devices as well as support for the ShellySBHT003C enviromental sensor courtesy of [Sebastian Haas](https://github.com/sebastianhaas)
package/index.js CHANGED
@@ -4,13 +4,14 @@ const path = require('path')
4
4
  const packageInfo = require("./package.json")
5
5
 
6
6
  const {createBluetooth} = require('node-ble')
7
+ const { Variant } = require('dbus-next')
7
8
  const {bluetooth, destroy} = createBluetooth()
8
9
 
9
10
  const BTSensor = require('./BTSensor.js')
10
11
  const BLACKLISTED = require('./sensor_classes/BlackListedDevice.js')
11
12
 
12
13
  class MissingSensor {
13
-
14
+
14
15
 
15
16
  constructor(config){
16
17
  this.Metadatum = BTSensor.Metadatum
@@ -53,8 +54,10 @@ class MissingSensor {
53
54
  stopListening(){}
54
55
  listen(){}
55
56
  }
56
- module.exports = function (app) {
57
- const adapterID = 'hci0'
57
+ module.exports = function (app) {
58
+ var adapterID = 'hci0'
59
+
60
+
58
61
  var deviceConfigs
59
62
  var starts=0
60
63
  var classMap
@@ -66,6 +69,8 @@ module.exports = function (app) {
66
69
  plugin.name = 'BT Sensors plugin';
67
70
  plugin.description = 'Plugin to communicate with and update paths to BLE Sensors in Signalk';
68
71
 
72
+
73
+
69
74
  //Try and load utilities-sk NOTE: should be installed from App Store--
70
75
  //But there's a fail safe because I'm a reasonable man.
71
76
 
@@ -162,10 +167,19 @@ module.exports = function (app) {
162
167
  }
163
168
 
164
169
  function loadClassMap() {
165
- const _classMap = utilities_sk.loadClasses(path.join(__dirname, 'sensor_classes'))
166
- classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
167
- classMap.get('UNKNOWN').classMap=new Map([...classMap].filter(([k, v]) => !v.isSystem )) // share the classMap with Unknown for configuration purposes
168
-
170
+ import(app.config.appPath+"/lib/modules.js").then( (modulesjs)=>{
171
+ const _classMap = utilities_sk.loadClasses(path.join(__dirname, 'sensor_classes'))
172
+ classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
173
+ const { default:defaultExport} = modulesjs
174
+ const modules = defaultExport.modulesWithKeyword(app.config, "signalk-bt-sensor-class")
175
+ modules.forEach((module)=>{
176
+ module.metadata.classFiles.forEach((classFile)=>{
177
+ const cls = require(module.location+module.module+"/"+classFile);
178
+ classMap.set(cls.name, cls);
179
+ })
180
+ })
181
+ classMap.get('UNKNOWN').classMap=new Map([...classMap].sort().filter(([k, v]) => !v.isSystem )) // share the classMap with Unknown for configuration purposes
182
+ })
169
183
  }
170
184
 
171
185
  app.debug(`Loading plugin ${packageInfo.version}`)
@@ -180,12 +194,15 @@ module.exports = function (app) {
180
194
  properties: {
181
195
  adapter: {title: "Bluetooth adapter",
182
196
  type: "string", default: "hci0"},
197
+ transport: {title: "Transport ",
198
+ type: "string", enum: ["auto","le","bredr"], default: "le", enumNames:["Auto", "LE-Bluetooth Low Energy", "BR/EDR Bluetooth basic rate/enhanced data rate"]},
183
199
 
184
200
  discoveryTimeout: {title: "Default device discovery timeout (in seconds)",
185
201
  type: "integer", default: 30,
186
202
  minimum: 10,
187
203
  maximum: 3600
188
204
  },
205
+
189
206
  discoveryInterval: {title: "Scan for new devices interval (in seconds-- 0 for no new device scanning)",
190
207
  type: "integer",
191
208
  default: 10,
@@ -335,23 +352,41 @@ module.exports = function (app) {
335
352
  })})
336
353
  }
337
354
 
338
- async function startScanner() {
355
+ async function startScanner(transport) {
339
356
 
340
357
  app.debug("Starting scan...");
341
- try{ await adapter.stopDiscovery() } catch(error){}
342
- try{ await adapter.startDiscovery() } catch(error){}
358
+ //Use adapter.helper directly to get around Adapter::startDiscovery()
359
+ //filter options which can cause issues with Device::Connect()
360
+ //turning off Discovery
361
+ //try {await adapter.startDiscovery()}
362
+ try{
363
+ if (transport) {
364
+ app.debug(`Setting Bluetooth transport option to ${transport}`)
365
+ await adapter.helper.callMethod('SetDiscoveryFilter', {
366
+ Transport: new Variant('s', transport)
367
+ })
368
+ }
369
+ await adapter.helper.callMethod('StartDiscovery')
370
+ }
371
+ catch (error){
372
+ app.debug(error)
373
+ }
374
+
343
375
  }
344
376
 
345
377
  const sensorMap=new Map()
346
- var adapter
347
378
 
348
379
  plugin.started=false
349
380
 
350
381
  loadClassMap()
351
382
  var discoveryIntervalID
352
-
383
+ var adapter
384
+ var adapterPower
353
385
  plugin.start = async function (options, restartPlugin) {
354
-
386
+ plugin.started=true
387
+
388
+ var adapterID=options.adapter
389
+
355
390
  function getDeviceConfig(mac){
356
391
  return deviceConfigs.find((p)=>p.mac_address==mac)
357
392
  }
@@ -381,7 +416,8 @@ module.exports = function (app) {
381
416
  const msg =`Sensor at ${deviceConfig.mac_address} unavailable. Reason: ${error}`
382
417
  app.debug(msg)
383
418
  app.debug(error)
384
- app.setPluginError(msg)
419
+ if (deviceConfig.active)
420
+ app.setPluginError(msg)
385
421
  deviceConfig.sensor=new MissingSensor(deviceConfig)
386
422
  addSensorToList(deviceConfig.sensor) //add sensor to list with known options
387
423
 
@@ -420,25 +456,63 @@ module.exports = function (app) {
420
456
  discoveryIntervalID = setInterval( findDevices, discoveryInterval*1000, discoveryTimeout)
421
457
  }
422
458
 
423
- plugin.started=true
459
+
460
+ if (!adapterID || adapterID=="")
461
+ adapterID = "hci0"
462
+ //Check if Adapter has changed since last start()
463
+ if (adapter) {
464
+ const n = await adapter.getName()
465
+ if (n!=adapterID) {
466
+ adapter.helper.removeAllListeners()
467
+ adapter=null
468
+ }
469
+ }
470
+ //Connect to adapter
471
+
472
+ if (!adapter){
473
+ app.debug(`Connecting to bluetooth adapter ${adapterID}`);
474
+
475
+ adapter = await bluetooth.getAdapter(adapterID)
476
+
477
+ //Set up DBUS listener to monitor Powered status of current adapter
478
+
479
+ await adapter.helper._prepare()
480
+ adapter.helper._propsProxy.on('PropertiesChanged', async (iface,changedProps,invalidated) => {
481
+ if (Object.hasOwn(changedProps,"Powered")){
482
+ if (changedProps.Powered.value==false) {
483
+ if (plugin.started){ //only call stop() if plugin is started
484
+ app.setPluginStatus(`Bluetooth Adapter ${adapterID} turned off. Plugin disabled.`)
485
+ await plugin.stop()
486
+ adapterPower=false
487
+ }
488
+ } else {
489
+ if (!adapterPower) { //only call start() once
490
+ adapterPower=true
491
+ await plugin.start(options,restartPlugin)
492
+ }
493
+ }
494
+ }
495
+ })
496
+ if (!await adapter.isPowered()) {
497
+ app.debug(`Bluetooth Adapter ${adapterID} not powered on.`)
498
+ app.setPluginError(`Bluetooth Adapter ${adapterID} not powered on.`)
499
+ adapterPower=false
500
+ await plugin.stop()
501
+ return
502
+ }
503
+ }
504
+ adapterPower=true
505
+
424
506
  plugin.uiSchema.peripherals['ui:disabled']=false
425
507
  sensorMap.clear()
426
508
  deviceConfigs=options?.peripherals??[]
427
509
 
428
-
429
-
430
510
  if (plugin.stopped) {
431
511
  await sleep(5000) //Make sure plugin.stop() completes first
432
512
  //plugin.start is called asynchronously for some reason
433
513
  //and does not wait for plugin.stop to complete
434
514
  plugin.stopped=false
435
515
  }
436
- var adapterID=options.adapter
437
-
438
- if (!adapterID || adapterID==="")
439
- adapterID = "hci0"
440
-
441
- app.debug(`Connecting to bluetooth adapter ${adapterID}`);
442
516
 
443
517
  const activeAdapters = await bluetooth.activeAdapters()
444
518
  plugin.schema.properties.adapter.enum=[]
@@ -450,8 +524,8 @@ module.exports = function (app) {
450
524
 
451
525
  plugin.uiSchema.adapter={'ui:disabled': (activeAdapters.length==1)}
452
526
 
453
- adapter = await bluetooth.getAdapter(adapterID)
454
- await startScanner()
527
+
528
+ await startScanner(options.transport)
455
529
  if (starts>0){
456
530
  app.debug(`Plugin ${packageInfo.version} restarting...`);
457
531
  if (plugin.schema.properties.peripherals.items.dependencies)
@@ -479,6 +553,7 @@ module.exports = function (app) {
479
553
  plugin.stop = async function () {
480
554
  app.debug("Stopping plugin")
481
555
  plugin.stopped=true
556
+ plugin.started=false
482
557
  plugin.uiSchema.peripherals['ui:disabled']=true
483
558
  if ((sensorMap)){
484
559
  plugin.schema.properties.peripherals.items.properties.mac_address.enum=[]
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "bt-sensors-plugin-sk",
3
- "version": "1.1.0-beta.2.2.2",
3
+ "version": "1.1.0-beta.2.2.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": {
7
7
  "dbus-next": "^0.10.2",
8
- "node-ble": "^1.12.0",
8
+ "node-ble": "^1.13.0",
9
9
  "int24":"^0.0.1",
10
10
  "kaitai-struct": "^0.10.0"
11
11
  },
@@ -1,31 +1,33 @@
1
1
  const BTSensor = require("../BTSensor");
2
- class BLACKLISTED extends BTSensor{
3
- static isSystem = true
4
- static async identify(device){
5
- const md = await this.getDeviceProp(device,'ManufacturerData')
6
- if (md){
7
- const keys = Object.keys(md)
8
- if (keys.length==1 && keys[0]==0x004C)
9
- return this
2
+ class BLACKLISTED extends BTSensor {
3
+ static isSystem = true;
4
+ static async identify(device) {
5
+ const md = await this.getDeviceProp(device, "ManufacturerData");
6
+ if (md && Object.hasOwn(md, 0x004c)){
7
+ if (md[0x004c].value.slice(0,2).join() != [0x02, 0x15].join()){ // iBeacons are exempt
8
+ return this;
9
+ }
10
+ return null;
10
11
  }
11
- return null
12
12
  }
13
- async init(){
14
- await super.init()
15
- this.currentProperties.Name= `Unsupported device from ${this.getManufacturer()}`
13
+
14
+ async init() {
15
+ await super.init();
16
+ this.currentProperties.Name = `Unsupported device from ${this.getManufacturer()}`;
16
17
  }
17
18
  reasonForBlacklisting() {
18
- switch ( this.getManufacturerID()){
19
- case (0x004C): return "Randomized MAC address (Apple)"
20
- case (0x02e1): return "Device is using VE.Smart" //NOTE: Victron/VictronSensor class
21
- //determines if a device is using VE.Smart
22
- //in identify(). If so, identify() returns
23
- //BlackListedDevice
24
-
25
- default: return ""
26
-
27
- }
19
+ switch (this.getManufacturerID()) {
20
+ case 0x004c:
21
+ return "Randomized MAC address (Apple)";
22
+ case 0x02e1:
23
+ return "Device is using VE.Smart"; //NOTE: Victron/VictronSensor class
24
+ //determines if a device is using VE.Smart
25
+ //in identify(). If so, identify() returns
26
+ //BlackListedDevice
28
27
 
28
+ default:
29
+ return "";
30
+ }
29
31
  }
30
32
  }
31
- module.exports=BLACKLISTED
33
+ module.exports = BLACKLISTED;
@@ -0,0 +1,42 @@
1
+ const BTSensor = require("../BTSensor");
2
+
3
+ class IBeacon extends BTSensor {
4
+ static isSystem = true;
5
+
6
+ static async identify(device) {
7
+ const md = await this.getDeviceProp(device,'ManufacturerData');
8
+ if (md && Object.hasOwn(md, 0x004c)) {
9
+ if (md[0x004c].value.slice(0,2).join() == [0x02, 0x15].join()) {
10
+ return this
11
+ }
12
+ }
13
+ return null
14
+ }
15
+
16
+ async init() {
17
+ await super.init();
18
+ this.initMetadata();
19
+ }
20
+
21
+ initMetadata(){
22
+ this.addMetadatum('battery','ratio', 'Battery charge state', (buffer)=>{return buffer[6]})
23
+ }
24
+
25
+ propertiesChanged(props){
26
+ super.propertiesChanged(props);
27
+ const buff = this.getServiceData("0000356e-0000-1000-8000-00805f9b34fb");
28
+ if (!buff)
29
+ throw new Error("Unable to get service data for " + this.getDisplayName());
30
+ this.emitData("battery", buff);
31
+ }
32
+
33
+ getManufacturer(){
34
+ return "Apple Inc. or clone";
35
+ }
36
+
37
+ getDescription(){
38
+ return `${this.getName()} iBeacon from Apple Inc. or a clone`
39
+ }
40
+ }
41
+
42
+ module.exports = IBeacon;
@@ -0,0 +1,170 @@
1
+ const BTSensor = require("../BTSensor");
2
+ function sleep(ms) {
3
+ return new Promise((resolve) => {
4
+ setTimeout(resolve, ms);
5
+ });
6
+ }
7
+ class JBDBMS extends BTSensor {
8
+
9
+ static TX_RX_SERVICE = "0000ff00-0000-1000-8000-00805f9b34fb"
10
+ static NOTIFY_CHAR_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"
11
+ static WRITE_CHAR_UUID = "0000ff02-0000-1000-8000-00805f9b34fb"
12
+
13
+ constructor(device,config,gattConfig){
14
+ super(device,config,gattConfig)
15
+ this.emitterFunctions=
16
+ [this.getAndEmitBatteryInfo.bind(this),
17
+ this.getAndEmitCellVoltages.bind(this)]
18
+
19
+ }
20
+ static identify(device){
21
+ return null
22
+ }
23
+ jbdCommand(command) {
24
+ return [0xDD, 0xA5, command, 0x00, 0xFF, 0xFF - (command - 1), 0x77]
25
+ }
26
+
27
+ async sendReadFunctionRequest( command ){
28
+ return await this.txChar.writeValueWithResponse(Buffer.from(this.jbdCommand(command)))
29
+
30
+ }
31
+ async init(){
32
+ await super.init()
33
+ this.addMetadatum('voltage', 'V', 'Total battery voltage',
34
+ (buffer)=>{return buffer.readUInt16BE(4) / 100})
35
+ this.addMetadatum('current', 'A', 'Current flow',
36
+ (buffer)=>{return buffer.readInt16BE(6) / 100} )
37
+ this.addMetadatum('remainingCapacity', 'Ah', 'Remaining battery capacity',
38
+ (buffer)=>{return buffer.readUInt16BE(8) / 100} )
39
+ this.addMetadatum('capacity', 'Ah', 'Battery capacity',
40
+ (buffer)=>{return buffer.readUInt16BE(10) / 100} )
41
+ this.addMetadatum('cycles', '', 'cycles',
42
+ (buffer)=>{return buffer.readUInt16BE(12)} )
43
+ this.addMetadatum('protectionStatus', '', 'Protection Status',
44
+ (buffer)=>{return buffer.readUInt16BE(20)} )
45
+
46
+ this.addMetadatum('SOC', 'ratio', 'State of Charge',
47
+ (buffer)=>{return buffer.readUInt8(23)/100} )
48
+
49
+ this.addMetadatum('FET', '', 'FET Control',
50
+ (buffer)=>{return buffer.readUInt8(24)} )
51
+
52
+ await this.device.connect()
53
+ await this.initCharacteristics()
54
+ const cellsAndTemps = await this.getNumberOfCellsAndTemps()
55
+ this.numberOfCells=cellsAndTemps.cells
56
+ this.numberOfTemps=cellsAndTemps.temps
57
+
58
+ for (let i=0; i<this.numberOfTemps; i++){
59
+ this.addMetadatum(`temp${i}`, 'K', `Temperature${i+1} reading`,
60
+ (buffer)=>{
61
+ return buffer.readUInt16BE(27+(i*2))/10
62
+ })
63
+ }
64
+
65
+ for (let i=0; i<this.numberOfCells; i++){
66
+ this.addMetadatum(`cell${i}Voltage`, 'V', `Cell ${i+1} voltage`,
67
+ (buffer)=>{return buffer.readUInt16BE((4+(i*2)))/1000} )
68
+ this.addMetadatum(`cell${i}Balance`, 'V', `Cell ${i+1} balance` )
69
+ }
70
+
71
+
72
+ }
73
+ hasGATT(){
74
+ return true
75
+ }
76
+ initCharacteristics(){
77
+ return new Promise((resolve,reject )=>{ this.device.connect().then(async ()=>{
78
+ const gattServer = await this.device.gatt()
79
+ const txRxService= await gattServer.getPrimaryService(this.constructor.TX_RX_SERVICE)
80
+ this.rxChar = await txRxService.getCharacteristic(this.constructor.NOTIFY_CHAR_UUID)
81
+ this.txChar = await txRxService.getCharacteristic(this.constructor.WRITE_CHAR_UUID)
82
+ await this.rxChar.startNotifications()
83
+ resolve(this)
84
+ }) .catch((e)=>{ reject(e.message) }) })
85
+ }
86
+
87
+ async initGATTNotifications(){
88
+ this.intervalID = setInterval(()=>{
89
+ this.emitGATT()
90
+ }, 1000*(this?.pollFreq??60) )
91
+ }
92
+
93
+ emitGATT(){
94
+ this.getAndEmitBatteryInfo()
95
+ setTimeout(()=>{this.getAndEmitCellVoltages()}, 5000)
96
+ }
97
+
98
+ async getNumberOfCellsAndTemps(){
99
+ var b = await this.getBuffer(0x3)
100
+ return {cells:b[25], temps:b[26]}
101
+ }
102
+
103
+ getBuffer(command){
104
+
105
+ return new Promise( async ( resolve, reject )=>{
106
+ const r = await this.sendReadFunctionRequest(command)
107
+ const result = Buffer.alloc(256)
108
+ var offset = 0
109
+
110
+ const timer = setTimeout(() => {
111
+ clearTimeout(timer)
112
+ reject(new Error(`Response timed out from JBDBMS device ${this.getName()}. `));
113
+ }, 30000);
114
+
115
+ const valChanged = async (buffer) => {
116
+ this.debug(buffer)
117
+ buffer.copy(result,offset)
118
+ if (buffer[buffer.length-1]==0x77){
119
+ this.rxChar.removeAllListeners()
120
+ clearTimeout(timer)
121
+ resolve(result)
122
+ }
123
+ offset+=buffer.length
124
+ }
125
+
126
+
127
+ this.rxChar.on('valuechanged', valChanged )
128
+ })
129
+ }
130
+
131
+ async initGATTConnection() {
132
+ return this
133
+ }
134
+
135
+ getAndEmitBatteryInfo(){
136
+ this.getBuffer(0x03).then((buffer)=>{
137
+ (["current", "voltage", "remainingCapacity", "capacity","cycles", "protectionStatus", "SOC","FET",]).forEach((tag) =>
138
+ this.emitData( tag, buffer )
139
+ )
140
+ for (let i = 0; i<this.numberOfTemps; i++){
141
+ this.emitData(`temp${i}`,buffer)
142
+ }
143
+ const balances = buffer.readUInt32BE(16)
144
+
145
+ for (let i = 0; i<this.numberOfCells; i++){
146
+ this.emit(`cell${i}Balance`,(1<<i & balances)?1:0)
147
+ }
148
+ })
149
+ }
150
+
151
+ getAndEmitCellVoltages(){
152
+ this.getBuffer(0x4).then((buffer)=>{
153
+ for (let i=0; i<this.numberOfCells; i++){
154
+ this.emitData(`cell${i}Voltage`,buffer)
155
+ }})
156
+ }
157
+
158
+ initGATTInterval(){
159
+ this.initGATTNotifications()
160
+ }
161
+
162
+ async stopListening(){
163
+ super.stopListening()
164
+ this.rxChar.stopNotifications()
165
+ await this.device.disconnect()
166
+ }
167
+
168
+ }
169
+
170
+ module.exports = JBDBMS;
@@ -77,8 +77,8 @@ class RenogyBattery extends RenogySensor {
77
77
 
78
78
 
79
79
  this.readChar.once('valuechanged', (buffer) => {
80
- ["current", "voltage", "remainingCharge", "capacity"].forEach(tag)
81
- this.emitData( tag, buffer )
80
+ ["current", "voltage", "remainingCharge", "capacity"].forEach((tag)=>
81
+ this.emitData( tag, buffer ))
82
82
 
83
83
  resolve(this)
84
84
  })
@@ -87,7 +87,7 @@ class RenogyBattery extends RenogySensor {
87
87
 
88
88
  getAndEmitCellVoltages(){
89
89
  return new Promise( async ( resolve, reject )=>{
90
- this.sendReadFunctionRequest(0x1388,0x11)
90
+ await this.sendReadFunctionRequest(0x1388,0x11)
91
91
 
92
92
  this.readChar.once('valuechanged', (buffer) => {
93
93
  for (let i = 0; i++ ; i < this.numberOfCells)
@@ -99,7 +99,7 @@ class RenogyBattery extends RenogySensor {
99
99
 
100
100
  getAndEmitCellTemperatures(){
101
101
  return new Promise( async ( resolve, reject )=>{
102
- this.sendReadFunctionRequest(0x1399,0x22)
102
+ await this.sendReadFunctionRequest(0x1399,0x22)
103
103
 
104
104
  this.readChar.once('valuechanged', buffer => {
105
105
  for (let i = 0; i++ ; i < this.numberOfCells)
@@ -63,8 +63,8 @@ class RenogyInverter extends RenogySensor {
63
63
  await this.sendReadFunctionRequest(0xfa0, 0x8)
64
64
 
65
65
  this.readChar.once('valuechanged', (buffer) => {
66
- ["ueiVoltage","ueiCurrent", "voltage", "loadCurrent", "frequency","temperature"].forEach(tag)
67
- this.emitData( tag, buffer )
66
+ ["ueiVoltage","ueiCurrent", "voltage", "loadCurrent", "frequency","temperature"].forEach((tag)=>
67
+ this.emitData( tag, buffer ))
68
68
 
69
69
  resolve(this)
70
70
  })
@@ -77,8 +77,8 @@ class RenogyInverter extends RenogySensor {
77
77
  await this.sendReadFunctionRequest(0x10e9, 0x5)
78
78
 
79
79
  this.readChar.once('valuechanged', (buffer) => {
80
- ["solarVoltage","solarCurrent", "solarPower", "solarChargingStatus", "solarChargingPower"].forEach(tag)
81
- this.emitData( tag, buffer )
80
+ ["solarVoltage","solarCurrent", "solarPower", "solarChargingStatus", "solarChargingPower"].forEach((tag)=>
81
+ this.emitData( tag, buffer ))
82
82
 
83
83
  resolve(this)
84
84
  })
@@ -91,8 +91,8 @@ class RenogyInverter extends RenogySensor {
91
91
  await this.sendReadFunctionRequest(0x113a, 0x2)
92
92
 
93
93
  this.readChar.once('valuechanged', (buffer) => {
94
- ["loadPower", "chargingCurrent"].forEach(tag)
95
- this.emitData( tag, buffer )
94
+ ["loadPower", "chargingCurrent"].forEach((tag)=>
95
+ this.emitData( tag, buffer ))
96
96
 
97
97
  resolve(this)
98
98
  })
@@ -2,7 +2,6 @@ const BTSensor = require("../BTSensor");
2
2
 
3
3
  const crypto = require('crypto');
4
4
  const util = require('util');
5
- const { isGeneratorFunction } = require("util/types");
6
5
 
7
6
  const DEVICE_TYPES = new Map([
8
7
  [0x0C3C, { name: "Alarm Clock", model: "CGC1" }],