bt-sensors-plugin-sk 1.2.0-beta.0.0.7 → 1.2.0-beta.0.0.8

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": []
7
+ }
package/BTSensor.js CHANGED
@@ -100,7 +100,6 @@ function preparePath(obj, str) {
100
100
  */
101
101
 
102
102
  class BTSensor extends EventEmitter {
103
- //static metadata=new Map()
104
103
 
105
104
  static DEFAULTS = require('./plugin_defaults.json');
106
105
 
@@ -318,6 +317,7 @@ class BTSensor extends EventEmitter {
318
317
 
319
318
  //create the 'name' parameter
320
319
  this.addDefaultParam("name")
320
+ .default=this?.currentProperties?.Name
321
321
 
322
322
  //create the 'location' parameter
323
323
 
package/README.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## What's New
4
4
 
5
+ ## 1.2.0-beta-0.0.8
6
+
7
+ Improved handling of changed state on config page.
8
+
9
+ Several small fixes to various sensor classes.
10
+
5
11
  ## 1.2.0-beta-0.0.7
6
12
 
7
13
  Added zone config param for environmental sensors. Removed location parameter.
package/index.js CHANGED
@@ -21,15 +21,13 @@ class MissingSensor {
21
21
  this.addPath=BTSensor.prototype.addPath.bind(this)
22
22
  this.addParameter=BTSensor.prototype.addParameter.bind(this)
23
23
  this.addDefaultPath=BTSensor.prototype.addDefaultPath.bind(this)
24
- this.addDefaultParam=BTSensor.prototype.addDefaultPath.bind(this)
25
- this.addDefaultParam=BTSensor.prototype.addDefaultPath.bind(this)
24
+ this.addDefaultParam=BTSensor.prototype.addDefaultParam.bind(this)
26
25
  this.getPath=BTSensor.prototype.getPath.bind(this)
27
26
 
28
27
  this.getJSONSchema = BTSensor.prototype.getJSONSchema.bind(this)
29
28
  this.initSchema = BTSensor.prototype.initSchema.bind(this)
30
29
 
31
30
  this.initSchema()
32
-
33
31
  var keys = Object.keys(config?.paths??{})
34
32
 
35
33
  keys.forEach((key)=>{
@@ -390,7 +388,6 @@ module.exports = function (app) {
390
388
  adapter.waitDevice(config.mac_address,(config?.discoveryTimeout??30)*1000)
391
389
  .then(async (device)=> {
392
390
  if (startNumber != starts ) {
393
- debugger
394
391
  return
395
392
  }
396
393
  //app.debug(`Found ${config.mac_address}`)
@@ -400,8 +397,13 @@ module.exports = function (app) {
400
397
  reject ( `Device is blacklisted (${s.reasonForBlacklisting()}).`)
401
398
  else{
402
399
  addSensorToList(s)
400
+ let _lastRSSI=-1*Infinity
403
401
  s.on("RSSI",(()=>{
404
- updateSensor(s)
402
+ if (Date.now()-_lastRSSI > 5000) { //only update RSSI on client every five seconds
403
+ _lastRSSI=Date.now()
404
+ updateSensor(s)
405
+ }
406
+
405
407
  }))
406
408
  resolve(s)
407
409
  }
@@ -443,7 +445,7 @@ module.exports = function (app) {
443
445
  app.setPluginError(msg)
444
446
  }
445
447
  //if we're here ain't got no class for the device
446
- var sensor
448
+ var sensor
447
449
  if (config.params?.sensorClass){
448
450
  var c = classMap.get(config.params.sensorClass)
449
451
  } else{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bt-sensors-plugin-sk",
3
- "version": "1.2.0-beta.0.0.7",
3
+ "version": "1.2.0-beta.0.0.8",
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": {
@@ -22,6 +22,7 @@
22
22
  "environment":{
23
23
  "temperature":
24
24
  {
25
+ "title":"Current zone's temperature",
25
26
  "unit":"K",
26
27
  "default": "environment.{zone}.temperature"
27
28
  },
@@ -32,15 +33,15 @@
32
33
  },
33
34
  "relativeHumidity":
34
35
  {
35
- "title":"Current relative humidity",
36
+ "title":"Current zone's relative humidity",
36
37
  "unit":"ratio",
37
- "default":"environment.{zone}.humidity"
38
+ "default":"environment.{zone}.relativeHumidity"
38
39
  },
39
40
  "pressure":
40
41
  {
41
- "title": "Current outside air ambient pressure",
42
+ "title": "Current zone's ambient air pressure",
42
43
  "unit":"Pa",
43
- "default":"environment.{zone}.humidity"
44
+ "default":"environment.{zone}.pressure"
44
45
  }
45
46
  },
46
47
  "electrical":{
package/public/893.js CHANGED
@@ -1 +1 @@
1
- "use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[893],{2995:(e,t,n)=>{n.r(t),n.d(t,{default:()=>v});var a=n(3490),s=n(4810),o=n(4147),r=n.n(o),l=n(7606),c=n(4952),i=n(3768),u=n(1431),d=n(9676),m=n(7041),f=n(3657),g=n(5027),p=n(7265),h=n(6890),E=n(8207);const w=e=>console.log.bind(console,e);var S;const v=e=>{const[t,n]=(0,o.useState)({}),[v,b]=(0,o.useState)({}),[y,A]=(0,o.useState)({}),[$,k]=(0,o.useState)({"ui:submitButtonOptions":{props:{disabled:!1,className:"btn btn-info"},norender:!0,submitText:"Submit"}}),[x,D]=(0,o.useState)([]),[C,T]=(0,o.useState)(),[j,_]=(0,o.useState)(new Map),[O,N]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[M,J]=(0,o.useState)("unknown"),[L,U]=(0,o.useState)();function B(e,t){console.log(`sending ${e}`),console.log(t);const n=new Headers;return n.append("Content-Type","application/json"),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include",method:"POST",body:JSON.stringify(t),headers:n})}async function H(e){return console.log(`fetching ${e}`),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include"})}async function I(){const e=await H("progress");if(200!=e.status)throw new Error(`Unable get progres: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}function P(){console.log("refreshing sensor map"),async function(){const e=await H("sensors");if(200!=e.status)throw new Error(`Unable get sensor data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{_(new Map(e.map((e=>[e.info.mac,e]))))})).catch((e=>{U(e)}))}return(0,o.useEffect)((()=>{H("sendPluginState").then((async e=>{const t=await e.json();J(t.state),console.log("Setting up eventsource");const n=new EventSource("/plugins/bt-sensors-plugin-sk/sse");return n.addEventListener("newsensor",(e=>{let t=JSON.parse(e.data);S.has(t.info.mac)||(console.log(`New sensor: ${t.info.mac}`),_(new Map(S.set(t.info.mac,t))))})),n.addEventListener("sensorchanged",(e=>{let t=JSON.parse(e.data);if(S.has(t.mac)){let e=S.get(t.mac);Object.assign(e.info,t),_(new Map(S))}})),n.addEventListener("progress",(e=>{const t=JSON.parse(e.data);N(t),console.log(t)})),n.addEventListener("pluginstate",(e=>{const t=JSON.parse(e.data);J(t.state)})),()=>n.close()})).catch((e=>{U(e)}))}),[]),(0,o.useEffect)((()=>{"started"==M?(P(),async function(){const e=await H("base");if(200!=e.status)throw new Error(`Unable get base data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{n(e.schema),b(e.data)})).catch((e=>{U(e)})),I().then((e=>{N(e)})).catch((e=>{U(e)}))):(_(new Map),n({}),b({}))}),[M]),(0,o.useEffect)((()=>{console.log(L)}),[L]),(0,o.useEffect)((()=>{S=j,D(Array.from(j.entries()).map((e=>{const t=j.get(e[0]),n=t.config,a=Object.keys(n).length>0;return r().createElement(h.A,{action:!0,onClick:()=>{t&&(n.mac_address=e[0],A(t.schema),T(n))}},r().createElement("div",{class:"d-flex justify-content-between align-items-center",style:a?{fontWeight:"normal"}:{fontStyle:"italic"}},`${t.info.name} MAC: ${t.info.mac} RSSI: ${s=t.info.RSSI,null==s?NaN:s}`,r().createElement("div",{class:"d-flex justify-content-between "},function(e){return null==e.info.lastContactDelta||e.info.lastContactDelta>e.config.discoveryTimeout?r().createElement(i.A,null):e.info.signalStrength>80?r().createElement(u.A,null):e.info.signalStrength>60?r().createElement(d.A,null):e.info.signalStrength>40?r().createElement(m.A,null):e.info.signalStrength>20?r().createElement(f.A,null):r().createElement(g.A,null)}(t))));var s})))}),[j]),"stopped"==M?r().createElement("h1",null,"Enable plugin to see configuration"):r().createElement("div",null,L?r().createElement("h2",{style:"color: red;"},L.message):"",r().createElement(a.Ay,{schema:t,validator:s.Ay,onChange:e=>b(e.formData),onSubmit:({formData:e},t)=>{T(null),B("sendBaseData",e).then((e=>{200!=e.status?U(new Error(`Unable to update base data: ${e.statusText} (${e.status})`)):(I().then((e=>{N(e)})).catch((e=>{U(e)})),P())}))},onError:w("errors"),formData:v}),r().createElement("p",null),r().createElement("p",null),O.deviceCount<O.totalDevices?r().createElement(E.A,{max:O.maxTimeout,now:O.progress}):"",r().createElement("h2",null,j.size>0?" Bluetooth Devices click to configure":""),r().createElement("p",null),r().createElement("div",{style:{paddingBottom:20},class:"d-flex flex-wrap justify-content-start align-items-start"},r().createElement(p.A,{style:{maxHeight:"300px",overflowY:"auto"}},x),r().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys(y).length?"none":""}},r().createElement(a.Ay,{schema:y,validator:s.Ay,uiSchema:$,onChange:e=>T(e.formData),onSubmit:({formData:e},t)=>{var n;console.log(e),B("sendSensorData",n=e).then((e=>{if(200!=e.status)throw new Error(e.statusText);j.get(n.mac_address).config=n})),A({}),alert("Changes saved")},onError:w("errors"),formData:C},r().createElement("div",null,r().createElement(l.A,{direction:"row",style:{spacing:5}},r().createElement(c.A,{type:"submit",color:"primary",variant:"contained"},"Save"),r().createElement(c.A,{variant:"contained",onClick:()=>{var e;e=C.mac_address,T(j.get(e).config)}},"Undo"),r().createElement(c.A,{variant:"contained",color:"secondary",onClick:e=>{return t=C.mac_address,void(window.confirm(`Delete configuration for ${t}?`)&&function(e){try{B("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),S.delete(e),_(new Map(S)),A({})}catch{}}(t));var t}},"Delete")))))))}}}]);
1
+ "use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[893],{2995:(e,t,n)=>{n.r(t),n.d(t,{default:()=>S});var a=n(3490),s=n(4810),o=n(4147),r=n.n(o),c=n(7606),l=n(4952),i=n(3768),u=n(1431),d=n(9676),m=n(7041),g=n(3657),f=n(5027),h=n(7265),p=n(6890),E=n(8207);const w=e=>console.log.bind(console,e);var v;const S=e=>{const[t,n]=(0,o.useState)({}),[S,b]=(0,o.useState)({}),[y,A]=(0,o.useState)({}),[$,D]=(0,o.useState)({"ui:submitButtonOptions":{props:{disabled:!1,className:"btn btn-info"},norender:!0,submitText:"Submit"}}),[_,k]=(0,o.useState)([]),[x,C]=(0,o.useState)(),[T,j]=(0,o.useState)(new Map),[M,O]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[N,J]=(0,o.useState)("unknown"),[L,U]=(0,o.useState)();function B(e,t){console.log(`sending ${e}`),console.log(t);const n=new Headers;return n.append("Content-Type","application/json"),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include",method:"POST",body:JSON.stringify(t),headers:n})}async function z(e){return console.log(`fetching ${e}`),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include"})}async function H(){const e=await z("progress");if(200!=e.status)throw new Error(`Unable get progres: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}function I(){console.log("refreshing sensor map"),async function(){const e=await z("sensors");if(200!=e.status)throw new Error(`Unable get sensor data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{j(new Map(e.map((e=>[e.info.mac,e]))))})).catch((e=>{U(e)}))}return(0,o.useEffect)((()=>{z("sendPluginState").then((async e=>{const t=await e.json();J(t.state),console.log("Setting up eventsource");const n=new EventSource("/plugins/bt-sensors-plugin-sk/sse");return n.addEventListener("newsensor",(e=>{let t=JSON.parse(e.data);v.has(t.info.mac)||(console.log(`New sensor: ${t.info.mac}`),j(new Map(v.set(t.info.mac,t))))})),n.addEventListener("sensorchanged",(e=>{let t=JSON.parse(e.data);if(v.has(t.mac)){let e=v.get(t.mac);Object.assign(e.info,t),j(new Map(v))}})),n.addEventListener("progress",(e=>{const t=JSON.parse(e.data);O(t),console.log(t)})),n.addEventListener("pluginstate",(e=>{const t=JSON.parse(e.data);J(t.state)})),()=>n.close()})).catch((e=>{U(e)}))}),[]),(0,o.useEffect)((()=>{"started"==N?(I(),async function(){const e=await z("base");if(200!=e.status)throw new Error(`Unable get base data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{n(e.schema),b(e.data)})).catch((e=>{U(e)})),H().then((e=>{O(e)})).catch((e=>{U(e)}))):(j(new Map),n({}),b({}))}),[N]),(0,o.useEffect)((()=>{console.log(L)}),[L]),(0,o.useEffect)((()=>{v=T,k(Array.from(T.entries()).map((e=>{const t=T.get(e[0]),n=t.config,a=Object.keys(n).length>0;return r().createElement(p.A,{action:!0,onClick:()=>{t&&(n.mac_address=e[0],A(t.schema),C(n))}},r().createElement("div",{class:"d-flex justify-content-between align-items-center",style:a?{fontWeight:"normal"}:{fontStyle:"italic"}},`${t._changesMade?"*":""}${t.info.name} MAC: ${t.info.mac} RSSI: ${s=t.info.RSSI,null==s?NaN:s}`,r().createElement("div",{class:"d-flex justify-content-between "},function(e){return null==e.info.lastContactDelta||e.info.lastContactDelta>e.config.discoveryTimeout?r().createElement(i.A,null):e.info.signalStrength>80?r().createElement(u.A,null):e.info.signalStrength>60?r().createElement(d.A,null):e.info.signalStrength>40?r().createElement(m.A,null):e.info.signalStrength>20?r().createElement(g.A,null):r().createElement(f.A,null)}(t))));var s})))}),[T]),"stopped"==N?r().createElement("h1",null,"Enable plugin to see configuration"):r().createElement("div",null,L?r().createElement("h2",{style:"color: red;"},L.message):"",r().createElement(a.Ay,{schema:t,validator:s.Ay,onChange:e=>b(e.formData),onSubmit:({formData:e},t)=>{C(null),B("sendBaseData",e).then((e=>{200!=e.status?U(new Error(`Unable to update base data: ${e.statusText} (${e.status})`)):(H().then((e=>{O(e)})).catch((e=>{U(e)})),I())}))},onError:w("errors"),formData:S}),r().createElement("p",null),r().createElement("p",null),M.deviceCount<M.totalDevices?r().createElement(E.A,{max:M.maxTimeout,now:M.progress}):"",r().createElement("h2",null,T.size>0?"Bluetooth Devices click to configure":""),r().createElement("h2",null,T.size>0?"(* means sensor has unsaved changes)":""),r().createElement("p",null),r().createElement("div",{style:{paddingBottom:20},class:"d-flex flex-wrap justify-content-start align-items-start"},r().createElement(h.A,{style:{maxHeight:"300px",overflowY:"auto"}},_),r().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys(y).length?"none":""}},r().createElement(a.Ay,{schema:y,validator:s.Ay,uiSchema:$,onChange:e=>{T.get(e.formData.mac_address)._changesMade=!0,C(e.formData)},onSubmit:({formData:e},t)=>{var n;console.log(e),B("sendSensorData",n=e).then((e=>{if(200!=e.status)throw new Error(e.statusText);T.get(n.mac_address)._changesMade=!1,T.get(n.mac_address).config=n})),A({}),alert("Changes saved")},onError:w("errors"),formData:x},r().createElement("div",null,r().createElement(c.A,{direction:"row",style:{spacing:5}},r().createElement(l.A,{type:"submit",color:"primary",variant:"contained"},"Save"),r().createElement(l.A,{variant:"contained",onClick:()=>{var e;e=x.mac_address,T.get(e)._changesMade=!1,C(T.get(e).config)}},"Undo"),r().createElement(l.A,{variant:"contained",color:"secondary",onClick:e=>{return t=x.mac_address,void(window.confirm(`Delete configuration for ${t}?`)&&function(e){try{B("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),v.delete(e),j(new Map(v)),A({})}catch{}}(t));var t}},"Delete")))))))}}}]);
@@ -31,7 +31,7 @@ class Aranet4 extends AranetSensor{
31
31
  this.addDefaultPath("pressure","environment.pressure")
32
32
  .read=(buff)=>{return ((buff.readUInt16LE(12)))/10}
33
33
 
34
- this.addDefaultPath('relativeHumidity','environment.relative')
34
+ this.addDefaultPath('relativeHumidity','environment.relativeHumidity')
35
35
  .read=(buff)=>{return ((buff.readUInt8(14))/100)}
36
36
 
37
37
  this.addMetadatum('color', '', 'Warning color (G Y R)',
@@ -19,6 +19,8 @@ class GoveeH50xx extends BTSensor {
19
19
 
20
20
  initSchema(){
21
21
  super.initSchema()
22
+ this.addDefaultParam("zone")
23
+
22
24
  this.addDefaultPath("temp","environment.temperature")
23
25
  .read= (buffer)=>{return 273.15+(buffer.readUInt16LE(1)/100) }
24
26
 
@@ -26,6 +26,7 @@ class VictronSmartBatteryProtect extends VictronSensor{
26
26
 
27
27
  initSchema(){
28
28
  super.initSchema()
29
+ this.addDefaultParam("id")
29
30
  this.addMetadatum('deviceState','', 'device state',
30
31
  (buff)=>{return VC.OperationMode.get(buff.readUInt8(1))})
31
32
  this.addMetadatum('outputStatus','', 'output status', //TODO
@@ -5,8 +5,7 @@ import {useEffect, useState} from 'react'
5
5
 
6
6
  import {Button, Grid} from '@material-ui/core';
7
7
 
8
-
9
- import { SignalCellular0Bar, SignalCellular1Bar, SignalCellular2Bar, SignalCellular3Bar, SignalCellular4Bar, SignalCellularConnectedNoInternet0Bar } from '@material-ui/icons';
8
+ import { SignalCellular0Bar, SignalCellular1Bar, SignalCellular2Bar, SignalCellular3Bar, SignalCellular4Bar, SignalCellularConnectedNoInternet0Bar } from '@material-ui/icons';
10
9
 
11
10
  const log = (type) => console.log.bind(console, type);
12
11
 
@@ -111,13 +110,14 @@ export default (props) => {
111
110
  if (response.status != 200) {
112
111
  throw new Error(response.statusText)
113
112
  }
114
- debugger
113
+ sensorMap.get(data.mac_address)._changesMade=false
115
114
  sensorMap.get(data.mac_address).config = data
116
115
 
117
116
  })
118
117
  }
119
118
 
120
119
  function undoChanges(mac) {
120
+ sensorMap.get(mac)._changesMade = false
121
121
  setSensorData( sensorMap.get(mac).config )
122
122
  }
123
123
 
@@ -289,7 +289,7 @@ useEffect(()=>{
289
289
  }
290
290
  }>
291
291
  <div class="d-flex justify-content-between align-items-center" style={hasConfig?{fontWeight:"normal"}:{fontStyle:"italic"}}>
292
- {`${sensor.info.name} MAC: ${sensor.info.mac} RSSI: ${ifNullNaN(sensor.info.RSSI)}` }
292
+ {`${sensor._changesMade?"*":""}${sensor.info.name} MAC: ${sensor.info.mac} RSSI: ${ifNullNaN(sensor.info.RSSI)}` }
293
293
  <div class="d-flex justify-content-between ">
294
294
  {
295
295
  signalStrengthIcon(sensor)
@@ -329,7 +329,8 @@ useEffect(()=>{
329
329
  now={progress.progress}
330
330
  />:""
331
331
  }
332
- <h2>{`${sensorMap.size>0?" Bluetooth Devices click to configure":""}`}</h2>
332
+ <h2>{`${sensorMap.size>0?"Bluetooth Devices click to configure" :""}`}</h2>
333
+ <h2>{`${sensorMap.size>0?"(* means sensor has unsaved changes)" :""}`}</h2>
333
334
  <p></p>
334
335
  <div style={{paddingBottom: 20}} class="d-flex flex-wrap justify-content-start align-items-start">
335
336
  <ListGroup style={{ maxHeight: '300px', overflowY: 'auto' }}>
@@ -340,7 +341,14 @@ useEffect(()=>{
340
341
  schema={schema}
341
342
  validator={validator}
342
343
  uiSchema={uiSchema}
343
- onChange={(e) => setSensorData(e.formData)}
344
+ onChange={(e) => {
345
+ const s = sensorMap.get(e.formData.mac_address)
346
+ s._changesMade=true
347
+ //s.config = e.formData;
348
+
349
+ setSensorData(e.formData)
350
+ }
351
+ }
344
352
  onSubmit={({ formData }, e) => {
345
353
  console.log(formData)
346
354
  updateSensorData(formData)