bt-sensors-plugin-sk 1.2.0-beta.0.1.1 → 1.2.0-beta.0.1.2.a

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/BTSensor.js CHANGED
@@ -465,23 +465,24 @@ class BTSensor extends EventEmitter {
465
465
 
466
466
  deviceConnect() {
467
467
 
468
- /* CAUTION: HACK AHEAD
469
-
470
- Bluez for some cockamamie reason (It's 2025 for chrissake.
471
- BLUETOOTH ISN'T JUST FOR DESKTOPS ANYMORE, BLUEZ DEVS!)
472
- SUSPENDS scanning while connected to a device.
473
-
474
- The next line of code gives the scanner a kick in the arse,
475
- starting it up again so, I dunno, another device might be able
476
- to connect and sensor classes could maybe get beacon updates.
477
-
478
- You know, the little things.
479
- */
468
+
480
469
  return connectQueue.enqueue( async ()=>{
481
470
  this.debug(`Connecting to ${this.getName()}`)
482
471
  await this.device.connect()
483
472
  try {
484
473
 
474
+ /* CAUTION: HACK AHEAD
475
+
476
+ Bluez for some cockamamie reason (It's 2025 for chrissake.
477
+ BLUETOOTH ISN'T JUST FOR DESKTOPS ANYMORE, BLUEZ DEVS!)
478
+ SUSPENDS scanning while connected to a device.
479
+
480
+ The next line of code gives the scanner a kick in the arse,
481
+ starting it up again so, I dunno, another device might be able
482
+ to connect and sensor classes could maybe get beacon updates.
483
+
484
+ You know, the little things.
485
+ */
485
486
  await this._adapter.helper.callMethod('StopDiscovery')
486
487
  await this._adapter.helper.callMethod('SetDiscoveryFilter', {
487
488
  Transport: new Variant('s', this._adapter?._transport??"le")
@@ -492,9 +493,13 @@ class BTSensor extends EventEmitter {
492
493
  //probably ignorable error. probably.
493
494
  console.log(e)
494
495
  }
496
+ /* END HACK*/
497
+ this.device.on("disconnect", ()=>{
498
+ this.debug(`${this.macAndName()} disconnected`)
499
+ })
495
500
  })
496
- /* END HACK*/
497
- }
501
+
502
+ }
498
503
 
499
504
  /**
500
505
  *
@@ -771,7 +776,9 @@ class BTSensor extends EventEmitter {
771
776
 
772
777
  async stopListening(){
773
778
  this.removeAllListeners()
779
+ this.device.removeAllListeners()
774
780
  this.device.helper.removeListeners()
781
+
775
782
  if (this.intervalID){
776
783
  clearInterval(this.intervalID)
777
784
  }
package/README.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Bluetooth Sensors for [Signal K](http://www.signalk.org)
2
2
 
3
3
  ## What's New
4
+ ## 1.2.0-beta-0.1.2.a
5
+
6
+ Module load fix
7
+
8
+ ## 1.2.0-beta-0.1.2
9
+
10
+ SSE deregister fix (long story)
11
+
4
12
  ## 1.2.0-beta-0.1.1
5
13
 
6
14
  Gobius fix for inclination path, id parameter.
package/classLoader.js CHANGED
@@ -20,7 +20,7 @@ const semver = require('semver')
20
20
  const _classMap = loadClasses(path.join(__dirname, 'sensor_classes'))
21
21
  const classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
22
22
  const libPath = app.config.appPath +(
23
- semver.gt(app.config.version,"2.13.5")?"dist":"lib"
23
+ semver.gte(app.config.version,"2.13.5")?"dist":"lib"
24
24
  )
25
25
  import(libPath+"/modules.js").then( (modulesjs)=>{
26
26
  const { default:defaultExport} = modulesjs
package/index.js CHANGED
@@ -106,6 +106,7 @@ module.exports = function (app) {
106
106
  type: "string", default: "hci0"},
107
107
  transport: {title: "Transport ",
108
108
  type: "string", enum: ["auto","le","bredr"], default: "le", enumNames:["Auto", "LE-Bluetooth Low Energy", "BR/EDR Bluetooth basic rate/enhanced data rate"]},
109
+ duplicateData: {title: "Set scanner to report duplicate data", type: "boolean", default: false, },
109
110
  discoveryTimeout: {title: "Default device discovery timeout (in seconds)",
110
111
  type: "integer", default: 30,
111
112
  minimum: 10,
@@ -125,6 +126,7 @@ module.exports = function (app) {
125
126
  var discoveryIntervalID, progressID, progressTimeoutID, deviceHealthID
126
127
  var adapter
127
128
  const channel = createChannel()
129
+
128
130
  const classMap = loadClassMap(app)
129
131
  const sensorMap=new Map()
130
132
 
@@ -226,6 +228,7 @@ module.exports = function (app) {
226
228
  data: {
227
229
  adapter: options.adapter,
228
230
  transport: options.transport,
231
+ duplicateData: options.duplicateData,
229
232
  discoveryTimeout: options.discoveryTimeout,
230
233
  discoveryInterval: options.discoveryInterval
231
234
  }
@@ -248,17 +251,20 @@ module.exports = function (app) {
248
251
  });
249
252
 
250
253
  router.get('/getPluginState', async (req, res) => {
251
-
252
254
  res.status(200).json({
255
+ "connectionId": Date.now(),
253
256
  "state":(plugin.started?"started":"stopped")
254
257
  })
255
258
  });
256
259
  router.get("/sse", async (req, res) => {
257
- const session = await createSession(req, res);
260
+ const session = await createSession(req,res)
258
261
  channel.register(session)
259
- });
260
-
261
-
262
+ req.on("close", ()=>{
263
+ app.debug("deregistering session")
264
+ channel.deregister(session)
265
+ })
266
+ });
267
+
262
268
  };
263
269
 
264
270
  function sensorsToJSON(){
@@ -287,8 +293,11 @@ module.exports = function (app) {
287
293
  config: config?config:{}
288
294
  }
289
295
  }
290
- async function startScanner(transport) {
296
+
297
+ async function startScanner(options) {
291
298
 
299
+ const transport = options?.transport??"le"
300
+ const duplicateData = options?.duplicateData??false
292
301
  app.debug("Starting scan...");
293
302
  //Use adapter.helper directly to get around Adapter::startDiscovery()
294
303
  //filter options which can cause issues with Device::Connect()
@@ -296,9 +305,10 @@ module.exports = function (app) {
296
305
  //try {await adapter.startDiscovery()}
297
306
  try{
298
307
  if (transport) {
299
- app.debug(`Setting Bluetooth transport option to ${transport}`)
308
+ app.debug(`Setting Bluetooth transport option to ${transport}. DuplicateData to ${duplicateData}`)
300
309
  await adapter.helper.callMethod('SetDiscoveryFilter', {
301
- Transport: new Variant('s', transport)
310
+ Transport: new Variant('s', transport),
311
+ DuplicateData: new Variant('b', duplicateData)
302
312
  })
303
313
  }
304
314
  await adapter.helper.callMethod('StartDiscovery')
@@ -307,8 +317,7 @@ module.exports = function (app) {
307
317
  app.debug(error)
308
318
  }
309
319
 
310
- }
311
-
320
+ }
312
321
  function updateSensor(sensor){
313
322
  channel.broadcast(getSensorInfo(sensor), "sensorchanged")
314
323
  }
@@ -350,12 +359,12 @@ module.exports = function (app) {
350
359
  addSensorToList(s)
351
360
  s._lastRSSI=-1*Infinity
352
361
  s.on("RSSI",(()=>{
353
- if (Date.now()-s._lastRSSI > 20000) { //only update RSSI on client every 20 seconds
354
- //app.debug(`${s.getMacAddress()} ${Date.now()-s._lastRSSI}`)
362
+ if (Date.now()-s._lastRSSI > 30000) { //only update RSSI on client every 30 seconds
363
+ //app.debug(`Updating ${s.getMacAddress()} RSSI after ${Date.now()-s._lastRSSI} ms`)
364
+
355
365
  s._lastRSSI=Date.now()
356
366
 
357
367
  updateSensor(s)
358
- //app.debug(`Updated Sensor ${config.mac_address}`)
359
368
  }
360
369
 
361
370
  }))
@@ -528,8 +537,9 @@ module.exports = function (app) {
528
537
  }
529
538
 
530
539
  sensorMap.clear()
531
- if (channel)
540
+ if (channel){
532
541
  channel.broadcast({state:"started"},"pluginstate")
542
+ }
533
543
  deviceConfigs=options?.peripherals??[]
534
544
 
535
545
  if (plugin.stopped) {
@@ -544,7 +554,7 @@ module.exports = function (app) {
544
554
  plugin.schema.properties.adapter.enumNames.push(`${a.adapter} @ ${ await a.getAddress()} (${await a.getName()})`)
545
555
  }
546
556
 
547
- await startScanner(options.transport)
557
+ await startScanner(options)
548
558
  if (starts>0){
549
559
  app.debug(`Plugin ${packageInfo.version} restarting...`);
550
560
  } else {
@@ -554,7 +564,7 @@ module.exports = function (app) {
554
564
  starts++
555
565
  if (!await adapter.isDiscovering())
556
566
  try{
557
- await startScanner()
567
+ await startScanner(options)
558
568
  } catch (e){
559
569
  app.debug(`Error starting scan: ${e.message}`)
560
570
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bt-sensors-plugin-sk",
3
- "version": "1.2.0-beta.0.1.1",
3
+ "version": "1.2.0-beta.0.1.2.a",
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": {
package/public/159.js CHANGED
@@ -1 +1 @@
1
- "use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[159],{62995:(e,t,n)=>{n.r(t),n.d(t,{default:()=>A});var a=n(73490),s=n(74810),o=n(86528),r=n.n(o),l=n(27606),c=n(86452),i=n(3768),u=n(71431),g=n(39676),d=n(47041),m=n(86038),f=n(95027),p=n(43540),h=n(24712),E=n(75056),w=n(96890),S=n(23399);const v=e=>console.log.bind(console,e);var y,b={};const A=e=>{const[t,n]=(0,o.useState)({}),[A,D]=(0,o.useState)({}),[$,_]=(0,o.useState)({}),[k,x]=(0,o.useState)({"ui:submitButtonOptions":{props:{disabled:!1,className:"btn btn-info"},norender:!0,submitText:"Submit"}}),[C,T]=(0,o.useState)([]),[j,M]=(0,o.useState)(),[O,N]=(0,o.useState)(new Map),[B,U]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[J,L]=(0,o.useState)("unknown"),[P,K]=(0,o.useState)();function z(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(){console.log("getProgress");const e=await H("getProgress");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 R(){console.log("refreshing sensor map"),async function(){console.log("getSensors");const e=await H("getSensors");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=>{N(new Map(e.map((e=>[e.info.mac,e]))))})).catch((e=>{K(e)}))}function W(e){return Object.keys(e.config).length>0}function Y(e){const t=W(e);return r().createElement(w.A,{action:!0,onClick:()=>{e.config.mac_address=e.info.mac,_(e.schema),M(e.config)}},r().createElement("div",{class:"d-flex justify-content-between align-items-center",style:t?{fontWeight:"normal"}:{fontStyle:"italic"}},`${e._changesMade?"*":""}${e.info.name} MAC: ${e.info.mac} RSSI: ${n=e.info.RSSI,null==n?NaN:n}`,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(g.A,null):e.info.signalStrength>40?r().createElement(d.A,null):e.info.signalStrength>20?r().createElement(m.A,null):r().createElement(f.A,null)}(e))));var n}return(0,o.useEffect)((()=>{console.log("useEffect([])"),H("getPluginState").then((async e=>{if(404==e.status)throw L("unknown"),new Error("unable to get plugin state");const t=await e.json();L(t.state),await async function(){console.log("getDomains");const e=await H("getDomains");if(200!=e.status)throw new Error(`Unable get domain data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}(),console.log("Setting up eventsource");const n=new EventSource("/plugins/bt-sensors-plugin-sk/sse");return n.addEventListener("newsensor",(e=>{console.log("newsensor");let t=JSON.parse(e.data);y.has(t.info.mac)||(console.log(`New sensor: ${t.info.mac}`),N(new Map(y.set(t.info.mac,t))))})),n.addEventListener("sensorchanged",(e=>{let t=JSON.parse(e.data);if(console.log("sensorchanged"),console.log(t),y.has(t.mac)){let e=y.get(t.mac);Object.assign(e.info,t),N(new Map(y))}})),n.addEventListener("progress",(e=>{console.log("progress");const t=JSON.parse(e.data);U(t),console.log(t)})),n.addEventListener("pluginstate",(e=>{console.log("pluginstate");const t=JSON.parse(e.data);L(t.state)})),()=>n.close()})).catch((e=>{K(e)}))}),[]),(0,o.useEffect)((()=>{console.log("useEffect([pluginState])"),"started"==J?(R(),async function(){console.log("getBaseData");const e=await H("getBaseData");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),D(e.data)})).catch((e=>{K(e)})),I().then((e=>{U(e)})).catch((e=>{K(e)}))):(N(new Map),n({}),D({}))}),[J]),(0,o.useEffect)((()=>{console.log("useEffect([sensorMap])"),y=O;const e=new Set(O.entries().map((e=>e[1].info.domain))),t={_configured:Array.from(O.entries()).filter((e=>W(e[1]))).map((e=>Y(O.get(e[0]))))};e.forEach((e=>{var n;t[e]=(n=e,Array.from(O.entries()).filter((e=>e[1].info.domain===n))).map((e=>Y(O.get(e[0]))))})),b=t}),[O]),"stopped"==J||"unknown"==J?r().createElement("h1",null,"Enable plugin to see configuration (if plugin is Enabled and you're seeing this message, restart SignalK)"):r().createElement("div",null,P?r().createElement("h2",{style:"color: red;"},P):"",r().createElement(a.Ay,{schema:t,validator:s.Ay,onChange:e=>D(e.formData),onSubmit:({formData:e},t)=>{var n;n=e,console.log("updateBaseData"),z("updateBaseData",n).then((e=>{200!=e.status?K(new Error(`Unable to update base data: ${e.statusText} (${e.status})`)):(I().then((e=>{U(e)})).catch((e=>{K(e)})),R())})),_({})},onError:v("errors"),formData:A}),r().createElement("p",null),r().createElement("p",null),B.deviceCount<B.totalDevices?r().createElement(S.A,{max:B.maxTimeout,now:B.progress}):"",r().createElement("h2",null,O.size>0?"Bluetooth Devices - Select to configure":""),r().createElement("h2",null,O.size>0?"(* = sensor has unsaved changes)":""),r().createElement("p",null),r().createElement(h.A,{defaultActiveKey:"_configured",id:"domain-tabs",className:"mb-3"},Object.keys(b).map((e=>{return n=(t=e).slice("_"===t.charAt(0)?1:0),r().createElement(E.A,{eventKey:t,title:n.charAt(0).toUpperCase()+n.slice(1)},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"}},function(e){return b[e]}(t)),r().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys($).length?"none":""}},r().createElement(a.Ay,{schema:$,validator:s.Ay,uiSchema:k,onChange:e=>{O.get(e.formData.mac_address)._changesMade=!0,M(e.formData)},onSubmit:({formData:e},t)=>{var n;console.log(e),n=e,console.log("updateSensorData"),z("updateSensorData",n).then((e=>{if(200!=e.status)throw new Error(e.statusText);O.get(n.mac_address)._changesMade=!1,O.get(n.mac_address).config=n})),_({}),alert("Changes saved")},onError:v("errors"),formData:j},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=j.mac_address,console.log("undoChanges"),O.get(e)._changesMade=!1,M(O.get(e).config)}},"Undo"),r().createElement(c.A,{variant:"contained",color:"secondary",onClick:e=>{return t=j.mac_address,void(window.confirm(`Delete configuration for ${t}?`)&&function(e){console.log("removeSensorData");try{z("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),y.delete(e),N(new Map(y)),_({})}catch{}}(t));var t}},"Delete")))))));var t,n}))))}}}]);
1
+ "use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[159],{62995:(e,t,n)=>{n.r(t),n.d(t,{default:()=>A});var a=n(73490),s=n(74810),o=n(86528),r=n.n(o),l=n(27606),c=n(86452),i=n(3768),u=n(71431),g=n(39676),d=n(47041),m=n(86038),f=n(95027),p=n(43540),h=n(24712),E=n(75056),w=n(96890),S=n(23399);const v=e=>console.log.bind(console,e);var y,b={};const A=e=>{const[t,n]=(0,o.useState)({}),[A,D]=(0,o.useState)({}),[$,_]=(0,o.useState)({}),[k,C]=(0,o.useState)({"ui:submitButtonOptions":{props:{disabled:!1,className:"btn btn-info"},norender:!0,submitText:"Submit"}}),[x,T]=(0,o.useState)([]),[j,M]=(0,o.useState)(),[O,N]=(0,o.useState)(new Map),[B,U]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[J,L]=(0,o.useState)("unknown"),[P,K]=(0,o.useState)();function z(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(){console.log("getProgress");const e=await H("getProgress");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 R(){console.log("refreshing sensor map"),async function(){console.log("getSensors");const e=await H("getSensors");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=>{N(new Map(e.map((e=>[e.info.mac,e]))))})).catch((e=>{K(e)}))}function W(e){return Object.keys(e.config).length>0}function Y(e){const t=W(e);return r().createElement(w.A,{action:!0,onClick:()=>{e.config.mac_address=e.info.mac,_(e.schema),M(e.config)}},r().createElement("div",{class:"d-flex justify-content-between align-items-center",style:t?{fontWeight:"normal"}:{fontStyle:"italic"}},`${e._changesMade?"*":""}${e.info.name} MAC: ${e.info.mac} RSSI: ${n=e.info.RSSI,null==n?NaN:n}`,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(g.A,null):e.info.signalStrength>40?r().createElement(d.A,null):e.info.signalStrength>20?r().createElement(m.A,null):r().createElement(f.A,null)}(e))));var n}return(0,o.useEffect)((()=>{console.log("useEffect([])");let e=null;return H("getPluginState").then((async t=>{if(404==t.status)throw L("unknown"),new Error("unable to get plugin state");const n=await t.json();console.log("Setting up eventsource"),e=new EventSource("/plugins/bt-sensors-plugin-sk/sse",{withCredentials:!0}),L(n.state),await async function(){console.log("getDomains");const e=await H("getDomains");if(200!=e.status)throw new Error(`Unable get domain data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}(),e.addEventListener("newsensor",(e=>{console.log("newsensor");let t=JSON.parse(e.data);y.has(t.info.mac)||(console.log(`New sensor: ${t.info.mac}`),N(new Map(y.set(t.info.mac,t))))})),e.addEventListener("sensorchanged",(e=>{let t=JSON.parse(e.data);if(console.log("sensorchanged"),console.log(t),y.has(t.mac)){let e=y.get(t.mac);Object.assign(e.info,t),N(new Map(y))}})),e.addEventListener("progress",(e=>{console.log("progress");const t=JSON.parse(e.data);U(t),console.log(t)})),e.addEventListener("pluginstate",(e=>{console.log("pluginstate");const t=JSON.parse(e.data);L(t.state)}))})).catch((e=>{K(e)})),()=>{console.log("Closing connection to SSE"),e.close()}}),[]),(0,o.useEffect)((()=>{console.log("useEffect([pluginState])"),"started"==J?(R(),async function(){console.log("getBaseData");const e=await H("getBaseData");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),D(e.data)})).catch((e=>{K(e)})),I().then((e=>{U(e)})).catch((e=>{K(e)}))):(N(new Map),n({}),D({}))}),[J]),(0,o.useEffect)((()=>{console.log("useEffect([sensorMap])"),y=O;const e=new Set(O.entries().map((e=>e[1].info.domain))),t={_configured:Array.from(O.entries()).filter((e=>W(e[1]))).map((e=>Y(O.get(e[0]))))};e.forEach((e=>{var n;t[e]=(n=e,Array.from(O.entries()).filter((e=>e[1].info.domain===n))).map((e=>Y(O.get(e[0]))))})),b=t}),[O]),"stopped"==J||"unknown"==J?r().createElement("h1",null,"Enable plugin to see configuration (if plugin is Enabled and you're seeing this message, restart SignalK)"):r().createElement("div",null,P?r().createElement("h2",{style:"color: red;"},P):"",r().createElement(a.Ay,{schema:t,validator:s.Ay,onChange:e=>D(e.formData),onSubmit:({formData:e},t)=>{var n;n=e,console.log("updateBaseData"),z("updateBaseData",n).then((e=>{200!=e.status?K(new Error(`Unable to update base data: ${e.statusText} (${e.status})`)):(I().then((e=>{U(e)})).catch((e=>{K(e)})),R())})),_({})},onError:v("errors"),formData:A}),r().createElement("p",null),r().createElement("p",null),B.deviceCount<B.totalDevices?r().createElement(S.A,{max:B.maxTimeout,now:B.progress}):"",r().createElement("h2",null,O.size>0?"Bluetooth Devices - Select to configure":""),r().createElement("h2",null,O.size>0?"(* = sensor has unsaved changes)":""),r().createElement("p",null),r().createElement(h.A,{defaultActiveKey:"_configured",id:"domain-tabs",className:"mb-3"},Object.keys(b).map((e=>{return n=(t=e).slice("_"===t.charAt(0)?1:0),r().createElement(E.A,{eventKey:t,title:n.charAt(0).toUpperCase()+n.slice(1)},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"}},function(e){return b[e]}(t)),r().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys($).length?"none":""}},r().createElement(a.Ay,{schema:$,validator:s.Ay,uiSchema:k,onChange:e=>{O.get(e.formData.mac_address)._changesMade=!0,M(e.formData)},onSubmit:({formData:e},t)=>{var n;console.log(e),n=e,console.log("updateSensorData"),z("updateSensorData",n).then((e=>{if(200!=e.status)throw new Error(e.statusText);O.get(n.mac_address)._changesMade=!1,O.get(n.mac_address).config=n})),_({}),alert("Changes saved")},onError:v("errors"),formData:j},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=j.mac_address,console.log("undoChanges"),O.get(e)._changesMade=!1,M(O.get(e).config)}},"Undo"),r().createElement(c.A,{variant:"contained",color:"secondary",onClick:e=>{return t=j.mac_address,void(window.confirm(`Delete configuration for ${t}?`)&&function(e){console.log("removeSensorData");try{z("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),y.delete(e),N(new Map(y)),_({})}catch{}}(t));var t}},"Delete")))))));var t,n}))))}}}]);
@@ -25,7 +25,7 @@ class ATC extends BTSensor{
25
25
  title:'data parsing strategy',
26
26
  type: 'string',
27
27
  enum:["ATC-LE","ATC-BE"],
28
- default: ["ATC-LE"]
28
+ default: "ATC-LE"
29
29
  }
30
30
  )
31
31
  if (!this.parser){
@@ -66,9 +66,12 @@ class ATC extends BTSensor{
66
66
  super.propertiesChanged(props)
67
67
  if (!props.hasOwnProperty("ServiceData")) return
68
68
 
69
- const buff = this.getServiceData("0000181a-0000-1000-8000-00805f9b34fb")
69
+ var buff = this.getServiceData("0000181a-0000-1000-8000-00805f9b34fb")
70
70
  if (!buff)
71
- throw new Error("Unable to get service data for "+this.getDisplayName())
71
+ buff = this.getServiceData("0000fcd2-0000-1000-8000-00805f9b34fb")
72
+ if (!buff)
73
+ throw new Error("Unable to get service data for "+this.getDisplayName())
74
+
72
75
  this.emitData("temp", buff)
73
76
  this.emitData("humidity", buff)
74
77
  this.emitData("voltage", buff)
@@ -50,6 +50,7 @@ export default (props) => {
50
50
  const [pluginState, setPluginState ] = useState("unknown")
51
51
  const [error, setError ] = useState()
52
52
 
53
+
53
54
  function sendJSONData(cmd, data){
54
55
 
55
56
  console.log(`sending ${cmd}`)
@@ -188,20 +189,21 @@ export default (props) => {
188
189
 
189
190
  useEffect(()=>{
190
191
  console.log("useEffect([])")
192
+ let eventSource=null
193
+
191
194
  fetchJSONData("getPluginState").then( async (response)=> {
192
195
  if (response.status==404) {
193
196
  setPluginState("unknown")
194
197
  throw new Error("unable to get plugin state")
195
198
  }
196
199
  const json = await response.json()
197
- setPluginState(json.state)
200
+ console.log("Setting up eventsource")
201
+ eventSource = new EventSource("/plugins/bt-sensors-plugin-sk/sse", { withCredentials: true })
198
202
 
203
+ setPluginState(json.state)
199
204
 
200
205
  _sensorDomains = await getDomains()
201
206
 
202
- console.log("Setting up eventsource")
203
- const eventSource = new EventSource("/plugins/bt-sensors-plugin-sk/sse")
204
-
205
207
  eventSource.addEventListener("newsensor", (event) => {
206
208
  console.log("newsensor")
207
209
  let json = JSON.parse(event.data)
@@ -235,14 +237,18 @@ export default (props) => {
235
237
  const json = JSON.parse(event.data)
236
238
  setPluginState(json.state)
237
239
  });
238
- return () => eventSource.close();
240
+
239
241
  })
240
242
 
241
243
  .catch( (e) => {
242
244
  setError(e)
243
245
  }
244
- )
245
- },[])
246
+ )
247
+ return () => {
248
+ console.log("Closing connection to SSE")
249
+ eventSource.close()
250
+ };
251
+ },[])
246
252
 
247
253
  useEffect(()=>{
248
254
  console.log("useEffect([pluginState])")