bt-sensors-plugin-sk 1.3.2 → 1.3.4-beta

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.
@@ -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',
@@ -45,9 +44,9 @@ class VictronSmartBatteryProtect extends VictronSensor{
45
44
  }
46
45
  emitValuesFrom(decData){
47
46
  super.emitValuesFrom(decData)
48
- const alarm = this.getPath("alarm").read(decData)
47
+ const alarm = this.getPath("alarmReason").read(decData)
49
48
  if (alarm>0)
50
- this.emitAlarm("alarm",alarm)
49
+ this.emitAlarm("alarmReason",alarm)
51
50
  }
52
51
 
53
52
  }
@@ -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()