bt-sensors-plugin-sk 1.1.0-beta.2.2.1.5 → 1.1.0-beta.2.2.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 +13 -1
- package/index.js +84 -23
- package/package.json +4 -3
- package/sensor_classes/BTHome/AbstractBTHomeSensor.js +199 -0
- package/sensor_classes/BTHome/BTHomeServiceData.js +2289 -0
- package/sensor_classes/BlackListedDevice.js +25 -23
- package/sensor_classes/IBeacon.js +42 -0
- package/sensor_classes/JBDBMS.js +170 -0
- package/sensor_classes/LancolVoltageMeter.js +39 -0
- package/sensor_classes/RenogyBattery.js +4 -4
- package/sensor_classes/RenogyInverter.js +6 -6
- package/sensor_classes/ShellySBHT003C.js +109 -0
- package/sensor_classes/VictronBatteryMonitor.js +3 -3
- package/sensor_classes/XiaomiMiBeacon.js +0 -1
|
@@ -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,
|
|
6
|
-
if (md){
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
async init() {
|
|
15
|
+
await super.init();
|
|
16
|
+
this.currentProperties.Name = `Unsupported device from ${this.getManufacturer()}`;
|
|
16
17
|
}
|
|
17
18
|
reasonForBlacklisting() {
|
|
18
|
-
switch (
|
|
19
|
-
case
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const BTSensor = require("../BTSensor");
|
|
2
|
+
|
|
3
|
+
class LancolVoltageMeter extends BTSensor{
|
|
4
|
+
|
|
5
|
+
static async identify(device){
|
|
6
|
+
|
|
7
|
+
const name = await this.getDeviceProp(device,"Name")
|
|
8
|
+
const regex = /^Lancol *[0-9]{1,3}\.[0-9]{1,2}V/
|
|
9
|
+
|
|
10
|
+
if (name && name.match(regex))
|
|
11
|
+
return this
|
|
12
|
+
else
|
|
13
|
+
return null
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async init(){
|
|
18
|
+
await super.init()
|
|
19
|
+
this.addMetadatum('voltage','V', 'battery voltage')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getManufacturer(){
|
|
23
|
+
return "Lancol"
|
|
24
|
+
}
|
|
25
|
+
async propertiesChanged(props){
|
|
26
|
+
super.propertiesChanged(props)
|
|
27
|
+
|
|
28
|
+
if (props.Name) {
|
|
29
|
+
const regex = /[+-]?([0-9]*[.])?[0-9]+/
|
|
30
|
+
const r = this.valueIfVariant(props.Name).match(regex)
|
|
31
|
+
if (r) {
|
|
32
|
+
this.emit("voltage",parseFloat([...r][0]))
|
|
33
|
+
} else {
|
|
34
|
+
this.debug(`Unable to parse Name property for ${this.getName()}: ${props.Name}`)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
module.exports=LancolVoltageMeter
|
|
@@ -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
|
})
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const BTHomeServiceData = require("./BTHome/BTHomeServiceData");
|
|
2
|
+
const AbstractBTHomeSensor = require("./BTHome/AbstractBTHomeSensor");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sensor class representing the Shelly BLU H&T.
|
|
6
|
+
*
|
|
7
|
+
* This sensor is publishing data utilising the BTHome format and inherits from {@link AbstractBTHomeSensor}.
|
|
8
|
+
*/
|
|
9
|
+
class ShellySBHT003C extends AbstractBTHomeSensor {
|
|
10
|
+
/**
|
|
11
|
+
* The shortened local name as advertised by the Shelly BLU H&T.
|
|
12
|
+
* @type {string}
|
|
13
|
+
*/
|
|
14
|
+
static SHORTENED_LOCAL_NAME = "SBHT-003C";
|
|
15
|
+
|
|
16
|
+
async init() {
|
|
17
|
+
await super.init();
|
|
18
|
+
this.initMetadata();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef ButtonPressEvent {string}
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The Shelly BLU H&T only supports single press and hold press options.
|
|
26
|
+
* @type {Readonly<{PRESS: string, HOLD_PRESS: string}>}
|
|
27
|
+
*/
|
|
28
|
+
static ButtonPressEvent = Object.freeze({
|
|
29
|
+
PRESS: "press",
|
|
30
|
+
HOLD_PRESS: "hold_press",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Returns the `ShellySBHT003C` sensor class if the specified device has been identified as Shelly BLU H&T.
|
|
35
|
+
*
|
|
36
|
+
* @param device The Bluetooth device to be identified.
|
|
37
|
+
* @returns {Promise<ShellySBHT003C|null>} Returns the sensor class if the device has been identified, or null.
|
|
38
|
+
*/
|
|
39
|
+
static async identify(device) {
|
|
40
|
+
if (
|
|
41
|
+
(await ShellySBHT003C.hasBtHomeServiceData(device)) &&
|
|
42
|
+
(await ShellySBHT003C.hasName(
|
|
43
|
+
device,
|
|
44
|
+
ShellySBHT003C.SHORTENED_LOCAL_NAME,
|
|
45
|
+
))
|
|
46
|
+
) {
|
|
47
|
+
return ShellySBHT003C;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Parses the relevant button press events for the Shelly BLU H&T from the specified BTHome data. This device only
|
|
54
|
+
* uses a subset of all available BTHome button press events.
|
|
55
|
+
*
|
|
56
|
+
* @param btHomeData {BTHomeServiceData.BthomeServiceData} The BTHome data provided by the device.
|
|
57
|
+
* @returns {ShellySBHT003C.ButtonPressEvent|null} The device's button state.
|
|
58
|
+
* @see https://shelly-api-docs.shelly.cloud/docs-ble/Devices/ht/#button-press-events
|
|
59
|
+
* @see https://bthome.io/format/
|
|
60
|
+
*/
|
|
61
|
+
static parseShellySBHT003CButton(btHomeData) {
|
|
62
|
+
const buttonEvent = ShellySBHT003C.parseButton(btHomeData);
|
|
63
|
+
if (buttonEvent) {
|
|
64
|
+
if (buttonEvent === BTHomeServiceData.ButtonEventType.PRESS) {
|
|
65
|
+
return ShellySBHT003C.ButtonPressEvent.PRESS;
|
|
66
|
+
/*
|
|
67
|
+
* Prior to firmware version 1.0.20, the hold press event is indicated by 0xFE, which does
|
|
68
|
+
* not conform with the BTHome standard.
|
|
69
|
+
*/
|
|
70
|
+
}
|
|
71
|
+
if (
|
|
72
|
+
buttonEvent === BTHomeServiceData.ButtonEventType.HOLD_PRESS ||
|
|
73
|
+
buttonEvent === 0xfe
|
|
74
|
+
) {
|
|
75
|
+
return ShellySBHT003C.ButtonPressEvent.HOLD_PRESS;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
initMetadata() {
|
|
82
|
+
this.addMetadatum(
|
|
83
|
+
"battery",
|
|
84
|
+
"ratio",
|
|
85
|
+
"battery level",
|
|
86
|
+
ShellySBHT003C.parseBatteryLevel,
|
|
87
|
+
);
|
|
88
|
+
this.addMetadatum(
|
|
89
|
+
"temp",
|
|
90
|
+
"K",
|
|
91
|
+
"temperature",
|
|
92
|
+
ShellySBHT003C.parseTemperature,
|
|
93
|
+
);
|
|
94
|
+
this.addMetadatum(
|
|
95
|
+
"humidity",
|
|
96
|
+
"ratio",
|
|
97
|
+
"humidity",
|
|
98
|
+
ShellySBHT003C.parseHumidity,
|
|
99
|
+
);
|
|
100
|
+
this.addMetadatum(
|
|
101
|
+
"button",
|
|
102
|
+
"enum",
|
|
103
|
+
"button",
|
|
104
|
+
ShellySBHT003C.parseShellySBHT003CButton,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = ShellySBHT003C;
|
|
@@ -78,13 +78,13 @@ class VictronBatteryMonitor extends VictronSensor{
|
|
|
78
78
|
break;
|
|
79
79
|
case VC.AuxMode.MIDPOINT_VOLTAGE:
|
|
80
80
|
this.addMetadatum('midpointVoltage','V', 'midpoint battery voltage',
|
|
81
|
-
(buff,offset=0)=>{return buff.
|
|
81
|
+
(buff,offset=0)=>{return buff.readUInt16LE(offset)/100},
|
|
82
82
|
'6597ed7d-4bda-4c1e-af4b-551c4cf74769')
|
|
83
83
|
break;
|
|
84
84
|
|
|
85
85
|
case VC.AuxMode.TEMPERATURE:
|
|
86
86
|
this.addMetadatum('temperature','K', 'House battery temperature',
|
|
87
|
-
(buff,offset=0)=>{return (buff.
|
|
87
|
+
(buff,offset=0)=>{return (buff.readUInt16LE(offset)/100)},
|
|
88
88
|
'6597ed7d-4bda-4c1e-af4b-551c4cf74769')
|
|
89
89
|
break;
|
|
90
90
|
default:
|
|
@@ -114,7 +114,7 @@ class VictronBatteryMonitor extends VictronSensor{
|
|
|
114
114
|
default:
|
|
115
115
|
break
|
|
116
116
|
}
|
|
117
|
-
this.emit("current", (this.NaNif(int24.readInt24LE(decData, 8)>>2,
|
|
117
|
+
this.emit("current", (this.NaNif(int24.readInt24LE(decData, 8)>>2,0x1FFFFF))/1000)
|
|
118
118
|
this.emit("consumed",(this.NaNif(int24.readInt24LE(decData, 11)&0xFFFFF,0xFFFFF)) / 10) ;
|
|
119
119
|
this.emit("soc", this.NaNif(((decData.readUInt16LE(13)& 0x3FFF)>>4),0x3FF)/1000)
|
|
120
120
|
|