bt-sensors-plugin-sk 1.2.5 → 1.2.6-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.
Files changed (126) hide show
  1. package/BTSensor.js +77 -38
  2. package/DistanceManager.js +249 -0
  3. package/Mixin.js +19 -0
  4. package/OutOfRangeDevice.js +46 -0
  5. package/README.md +20 -6
  6. package/classLoader.js +7 -2
  7. package/connectUUID.exp +26 -0
  8. package/index.js +54 -11
  9. package/package.json +8 -6
  10. package/public/159.js +1 -1
  11. package/public/540.js +1 -1
  12. package/public/681.js +3 -9
  13. package/public/681.js.LICENSE.txt +2 -0
  14. package/public/764.js +1 -0
  15. package/public/images/ATC.jpeg +0 -0
  16. package/public/images/Aranet4.webp +0 -0
  17. package/public/images/BP108B.webp +0 -0
  18. package/public/images/GoveeH5074.jpg +0 -0
  19. package/public/images/GoveeH5075.webp +0 -0
  20. package/public/images/GoveeH510x.jpg +0 -0
  21. package/public/images/InkbirdTH3.webp +0 -0
  22. package/public/images/JBDBMS.webp +0 -0
  23. package/public/images/Junctek.webp +0 -0
  24. package/public/images/KilovaultHLXPlus.jpg +0 -0
  25. package/public/images/LancolVoltageMeter.webp +0 -0
  26. package/public/images/LiTimeLiFePo4Battery.avif +0 -0
  27. package/public/images/MercurySmartcraft.jpg +0 -0
  28. package/public/images/MopekaTankSensor.jpg +0 -0
  29. package/public/images/RemoranWave3.jpeg +0 -0
  30. package/public/images/RenogyInverter.jpg +0 -0
  31. package/public/images/RenogyRoverClient.jpg +0 -0
  32. package/public/images/RenogySmartLiFePo4Battery.webp +0 -0
  33. package/public/images/RuuviTag.jpg +0 -0
  34. package/public/images/ShellyBLUHT.webp +0 -0
  35. package/public/images/ShellyBLUMotion.webp +0 -0
  36. package/public/images/ShellyBluDoorWindow.webp +0 -0
  37. package/public/images/Skanbatt.jpg +0 -0
  38. package/public/images/SmartBatteryProtect.webp +0 -0
  39. package/public/images/SmartBatterySense.webp +0 -0
  40. package/public/images/SwitchBotMeterPlus.webp +0 -0
  41. package/public/images/SwitchBotTH.webp +0 -0
  42. package/public/images/TopbandBattery.webp +0 -0
  43. package/public/images/Ultrasonic.jpg +0 -0
  44. package/public/images/VictronBlueSmartACCharger.jpg +0 -0
  45. package/public/images/VictronBlueSolarMPPT.jpeg +0 -0
  46. package/public/images/VictronCerboGX.webp +0 -0
  47. package/public/images/VictronInverterRS.webp +0 -0
  48. package/public/images/VictronLynxSmartBMS.webp +0 -0
  49. package/public/images/VictronMultiPlus-II.webp +0 -0
  50. package/public/images/VictronOrionTrIsolated.webp +0 -0
  51. package/public/images/VictronOrionTrNonIsolated.webp +0 -0
  52. package/public/images/VictronPhoenixInverter.webp +0 -0
  53. package/public/images/VictronPhoenixSmart1600.webp +0 -0
  54. package/public/images/VictronSmartBatteryProtect.jpg +0 -0
  55. package/public/images/VictronSmartIP43.webp +0 -0
  56. package/public/images/VictronSmartLithiumBattery.jpg +0 -0
  57. package/public/images/VictronSmartSolarMPPT.webp +0 -0
  58. package/public/images/VictronVEBus.webp +0 -0
  59. package/public/images/iBeacon.jpg +0 -0
  60. package/public/main.js +1 -1
  61. package/public/remoteEntry.js +1 -1
  62. package/readUUID.exp +23 -0
  63. package/sensor_classes/ATC.js +3 -2
  64. package/sensor_classes/Aranet2.js +3 -1
  65. package/sensor_classes/Aranet4.js +1 -2
  66. package/sensor_classes/BankManager.js +1 -1
  67. package/sensor_classes/Beacon/AbstractBeaconMixin.js +85 -0
  68. package/sensor_classes/Beacon/Eddystone.js +77 -0
  69. package/sensor_classes/Beacon/iBeacon.js +58 -0
  70. package/sensor_classes/EctiveBMS.js +270 -0
  71. package/sensor_classes/FeasyComBeacon.js +68 -0
  72. package/sensor_classes/GobiusCTankMeter.js +4 -3
  73. package/sensor_classes/GoveeH5074.js +2 -0
  74. package/sensor_classes/GoveeH5075.js +2 -0
  75. package/sensor_classes/GoveeH510x.js +1 -0
  76. package/sensor_classes/Inkbird.js +1 -0
  77. package/sensor_classes/JBDBMS.js +1 -0
  78. package/sensor_classes/Junctek.js +14 -6
  79. package/sensor_classes/KilovaultHLXPlus.js +1 -0
  80. package/sensor_classes/LancolVoltageMeter.js +2 -0
  81. package/sensor_classes/MercurySmartcraft.js +1 -0
  82. package/sensor_classes/MopekaTankSensor.js +7 -204
  83. package/sensor_classes/RemoranWave3.js +2 -0
  84. package/sensor_classes/Renogy/RenogySensor.js +1 -0
  85. package/sensor_classes/RenogyBattery.js +3 -4
  86. package/sensor_classes/RenogyInverter.js +3 -6
  87. package/sensor_classes/RenogyRoverClient.js +3 -0
  88. package/sensor_classes/RuuviTag.js +11 -8
  89. package/sensor_classes/ShellySBDW002C.js +3 -1
  90. package/sensor_classes/ShellySBHT003C.js +7 -0
  91. package/sensor_classes/ShellySBMO003Z.js +3 -2
  92. package/sensor_classes/ShenzhenLiOnBMS.js +4 -0
  93. package/sensor_classes/SwitchBotMeterPlus.js +1 -1
  94. package/sensor_classes/SwitchBotTH.js +2 -1
  95. package/sensor_classes/UNKNOWN.js +2 -1
  96. package/sensor_classes/UltrasonicWindMeter.js +3 -0
  97. package/sensor_classes/Victron/VictronConstants.js +2 -0
  98. package/sensor_classes/Victron/VictronIdentifier.js +24 -0
  99. package/sensor_classes/Victron/VictronSensor.js +59 -49
  100. package/sensor_classes/VictronACCharger.js +1 -6
  101. package/sensor_classes/VictronBatteryMonitor.js +37 -26
  102. package/sensor_classes/VictronDCDCConverter.js +1 -4
  103. package/sensor_classes/VictronDCEnergyMeter.js +1 -4
  104. package/sensor_classes/VictronGXDevice.js +1 -4
  105. package/sensor_classes/VictronInverter.js +2 -3
  106. package/sensor_classes/VictronInverterRS.js +2 -4
  107. package/sensor_classes/VictronLynxSmartBMS.js +1 -4
  108. package/sensor_classes/VictronOrionXS.js +1 -3
  109. package/sensor_classes/VictronSmartBatteryProtect.js +1 -4
  110. package/sensor_classes/VictronSmartLithium.js +1 -4
  111. package/sensor_classes/VictronSolarCharger.js +1 -3
  112. package/sensor_classes/VictronVEBus.js +1 -4
  113. package/sensor_classes/XiaomiMiBeacon.js +5 -2
  114. package/sensor_classes/iBeaconSensor.js +40 -0
  115. package/src/components/PluginConfigurationPanel.js +134 -173
  116. package/Screenshot 2025-06-12 at 9.33.57/342/200/257AM.png +0 -0
  117. package/bt-sensors-plugin-sk copy.json +0 -170
  118. package/bt-sensors-plugin-sk.json.bak +0 -121
  119. package/public/847.js +0 -1
  120. package/sensor_classes/IBeacon.js +0 -45
  121. package/vsl_patch_17_06_25.patch +0 -13
  122. /package/public/images/{Aranet2_HOME_F_900x900_90OVA5J.original.webp → Aranet2.webp} +0 -0
  123. /package/public/images/{Bank Manager All-in-onewc.webp → BankManager.webp} +0 -0
  124. /package/public/images/{Gobius_C.png → GobiusCTankMeter.png} +0 -0
  125. /package/public/images/{Victron-SmartShunt.jpg → VictronSmartShunt.jpg} +0 -0
  126. /package/public/images/{smartsolarMPPT7515.png → VictronSmartSolarMPPT7515.png} +0 -0
@@ -1,8 +1,7 @@
1
1
  import Form from '@rjsf/core' ;
2
2
  import validator from '@rjsf/validator-ajv8';
3
- import React from "react";
4
3
  import ReactHtmlParser from 'react-html-parser';
5
-
4
+ import React from 'react'
6
5
  import {useEffect, useState} from 'react'
7
6
 
8
7
  import {Button, Grid } from '@material-ui/core';
@@ -20,13 +19,14 @@ import { ListGroupItem } from 'react-bootstrap';
20
19
 
21
20
  import ProgressBar from 'react-bootstrap/ProgressBar';
22
21
 
23
- var _sensorMap, _sensorDomains={}, _sensorList={}
24
-
25
- export default function BTConfig (props) {
22
+ export function BTConfig (props) {
26
23
 
27
24
  const _uiSchema= {
28
25
  "ui:options": {label: false},
29
- 'title': { 'ui:widget': 'hidden' }
26
+ "paths":{
27
+ enableMarkdownInDescription:true
28
+ },
29
+ 'title': { 'ui:widget': 'hidden' },
30
30
  }
31
31
 
32
32
  const baseUISchema =
@@ -71,10 +71,9 @@ const useStyles = makeStyles((theme) => ({
71
71
 
72
72
  const [schema, setSchema] = useState({})
73
73
  const [ uiSchema, setUISchema] = useState(_uiSchema )
74
- const [sensorList, setSensorList] = useState([])
75
74
 
76
75
  const [sensorData, setSensorData] = useState()
77
- const [sensorMap, setSensorMap ] = useState(new Map() )
76
+ const [sensorMap, setSensorMap ] = useState(new Map())
78
77
 
79
78
  const [progress, setProgress ] = useState({
80
79
  "progress":0, "maxTimeout": 100,
@@ -89,8 +88,6 @@ const useStyles = makeStyles((theme) => ({
89
88
 
90
89
  function sendJSONData(cmd, data){
91
90
 
92
- console.log(`sending ${cmd}`)
93
- console.log(data)
94
91
  const headers = new Headers();
95
92
  headers.append("Content-Type", "application/json");
96
93
  return fetch(`/plugins/bt-sensors-plugin-sk/${cmd}`, {
@@ -100,91 +97,83 @@ const useStyles = makeStyles((theme) => ({
100
97
  headers:headers
101
98
  })
102
99
  }
103
-
104
- async function fetchJSONData(path){
105
- console.log(`fetching ${path}`)
106
- var result
107
- try {
108
- result = fetch(`/plugins/bt-sensors-plugin-sk/${path}`, {
109
- credentials: 'include'
110
- })
111
- } catch (e) {
112
- result=
113
- {
114
- status: 500,
115
- statusText: e.toString()
116
- }
117
- }
118
- return result
100
+ async function fetchJSONData(path, data = {}) {
101
+ let result;
102
+ try {
103
+ // Convert data object to query string
104
+ const query = Object.keys(data).length
105
+ ? '?' + new URLSearchParams(data).toString()
106
+ : '';
107
+ result = await fetch(`/plugins/bt-sensors-plugin-sk/${path}${query}`, {
108
+ credentials: 'include',
109
+ method: 'GET'
110
+ });
111
+ } catch (e) {
112
+ result = {
113
+ status: 500,
114
+ statusText: e.toString()
115
+ };
119
116
  }
120
-
117
+ return result;
118
+ }
121
119
  async function getSensors(){
122
- console.log("getSensors")
123
120
  const response = await fetchJSONData("getSensors")
124
121
  if (response.status!=200){
125
122
  throw new Error(`Unable get sensor data: ${response.statusText} (${response.status}) `)
126
123
  }
127
124
  const json = await response.json()
128
- console.log(json)
129
- //for (let i=0;i<json.length;i++){
130
- // json[i].schema.htmlDescription=<div>{ReactHtmlParser(json[i].schema.htmlDescription)}<p></p></div>
131
- //}
125
+
132
126
  return json
133
127
 
134
128
  }
135
- async function getDomains(){
136
- console.log("getDomains")
137
- const response = await fetchJSONData("getDomains")
129
+
130
+
131
+ async function getSensorInfo(mac, sensorClass){
132
+ const response = await fetchJSONData("getSensorInfo",{mac_address: mac, class: sensorClass})
138
133
  if (response.status!=200){
139
- throw new Error(`Unable get domain data: ${response.statusText} (${response.status}) `)
134
+ throw new Error(`Unable get sensor info: ${response.statusText} (${response.status}) `)
140
135
  }
141
136
  const json = await response.json()
142
- console.log(json)
143
137
  return json
144
-
145
138
  }
139
+
146
140
  async function getBaseData(){
147
- console.log("getBaseData")
148
141
  const response = await fetchJSONData("getBaseData")
149
142
  if (response.status!=200){
150
143
  throw new Error(`Unable to get base data: ${response.statusText} (${response.status}) `)
151
144
  }
152
145
  const json = await response.json()
153
- console.log(json)
154
146
  json.schema.htmlDescription=<div>{ReactHtmlParser(json.schema.htmlDescription)}<p></p></div>
155
147
  return json
156
148
  }
149
+
157
150
  async function getProgress(){
158
- console.log("getProgress")
159
151
  const response = await fetchJSONData("getProgress")
160
152
  if (response.status!=200){
161
153
  throw new Error(`Unable to get progress: ${response.statusText} (${response.status}) `)
162
154
  }
163
155
  const json = await response.json()
164
- console.log(json)
165
156
  return json
166
157
  }
167
158
 
168
159
  function updateSensorData(data){
169
- console.log("updateSensorData")
170
160
  sendJSONData("updateSensorData", data).then((response)=>{
171
161
  if (response.status != 200) {
172
162
  throw new Error(response.statusText)
173
163
  }
174
- sensorMap.get(data.mac_address)._changesMade=false
175
- sensorMap.get(data.mac_address).config = data
176
-
164
+ setSensorMap((sm)=>{sm.delete(data.mac_address); return new Map(sm) })
165
+ setSchema( {} )
166
+
177
167
  })
178
168
  }
179
169
 
180
170
  function undoChanges(mac) {
181
- console.log("undoChanges")
182
171
  sensorMap.get(mac)._changesMade = false
172
+ sensorMap.get(mac).config = JSON.parse(JSON.stringify(sensorMap.get(mac).configCopy))
183
173
  setSensorData( sensorMap.get(mac).config )
184
174
  }
185
175
 
186
176
  function removeSensorData(mac){
187
- console.log("removeSensorData")
188
177
 
189
178
  try{
190
179
 
@@ -193,10 +182,7 @@ const useStyles = makeStyles((theme) => ({
193
182
  throw new Error(response.statusText)
194
183
  }
195
184
  })
196
-
197
- _sensorMap.delete(mac)
198
-
199
- setSensorMap(new Map(_sensorMap))
185
+ setSensorMap((sm)=>{sm.delete(mac); return new Map(sm) })
200
186
  setSchema( {} )
201
187
  } catch {(e)=>
202
188
  setError( new Error(`Couldn't remove ${mac}: ${e}`))
@@ -206,88 +192,80 @@ const useStyles = makeStyles((theme) => ({
206
192
 
207
193
 
208
194
  function updateBaseData(data){
209
- console.log("updateBaseData")
210
-
195
+ setSensorMap(new Map())
196
+ //setSensorList({})
211
197
  sendJSONData("updateBaseData", data).then( (response )=>{
212
198
  if (response.status != 200) {
213
199
  setError(new Error(`Unable to update base data: ${response.statusText} (${response.status})`))
214
- } /*else {
215
- getProgress().then((json)=>{
216
- setProgress(json)
217
- }).catch((e)=>{
218
- setError(e)
219
- })
220
- }*/
200
+ }
221
201
  })
222
- }
223
-
224
202
 
225
- function refreshSensors(){
226
- console.log('refreshing sensor map')
227
-
228
- getSensors().then((sensors)=>{
229
- setSensorMap (new Map(sensors.map((sensor)=>[sensor.info.mac,sensor])));
230
- })
231
- .catch((e)=>{
232
- setError(e)
233
- })
234
203
  }
204
+
205
+
235
206
 
236
207
 
237
208
  useEffect(()=>{
238
- console.log("useEffect([])")
239
209
  let eventSource=null
240
-
241
210
  fetchJSONData("getPluginState").then( async (response)=> {
211
+
212
+ function newSensorEvent(event){
213
+ let json = JSON.parse(event.data)
214
+ console.log(`New sensor: ${json.info.mac}`)
215
+ setSensorMap( (_sm)=> {
216
+ //if (!_sm.has(json.info.mac))
217
+ _sm.set(json.info.mac, json)
218
+
219
+ return new Map(_sm)
220
+ }
221
+ )
222
+ }
223
+ function sensorChangedEvent(event){
224
+ console.log("sensorchanged")
225
+ const json = JSON.parse(event.data)
226
+
227
+ setSensorMap( (_sm) => {
228
+ const sensor = _sm.get(json.mac)
229
+ if (sensor)
230
+ Object.assign(sensor.info, json )
231
+ return new Map(_sm)
232
+ })
233
+ }
234
+
235
+
242
236
  if (response.status==404) {
243
237
  setPluginState("unknown")
244
238
  throw new Error("unable to get plugin state")
245
239
  }
246
240
  const json = await response.json()
247
- console.log("Setting up eventsource")
248
241
  eventSource = new EventSource("/plugins/bt-sensors-plugin-sk/sse", { withCredentials: true })
249
242
 
250
- setPluginState(json.state)
251
-
252
- _sensorDomains = await getDomains()
253
-
254
243
  eventSource.addEventListener("newsensor", (event) => {
255
- console.log("newsensor")
256
- let json = JSON.parse(event.data)
257
-
258
- if (!_sensorMap.has(json.info.mac)) {
259
- console.log(`New sensor: ${json.info.mac}`)
260
- setSensorMap(new Map(_sensorMap.set(json.info.mac, json)))
261
- }
244
+ newSensorEvent(event)
262
245
  });
263
246
 
264
247
  eventSource.addEventListener("sensorchanged", (event) => {
265
- let json = JSON.parse(event.data)
266
- console.log("sensorchanged")
267
- console.log(json)
268
-
269
- if (_sensorMap.has(json.mac)) {
270
- let sensor = _sensorMap.get(json.mac)
271
-
272
- Object.assign(sensor.info, json )
273
- setSensorMap(new Map ( _sensorMap ))
274
- }
248
+ sensorChangedEvent(event)
275
249
  });
250
+
276
251
  eventSource.addEventListener("progress", (event) => {
277
- console.log("progress")
278
252
  const json = JSON.parse(event.data)
279
253
  setProgress(json)
280
- console.log(json)
281
254
  });
282
255
 
283
256
  eventSource.addEventListener("pluginstate", (event) => {
284
- console.log("pluginstate")
285
257
  const json = JSON.parse(event.data)
286
258
  setPluginState(json.state)
287
259
  });
288
-
289
- })
260
+
261
+ setPluginState(json.state);
290
262
 
263
+ (async ()=>{
264
+ const sensors = await getSensors()
265
+ setSensorMap ( new Map(sensors.map((sensor)=>[sensor.info.mac,sensor])) )
266
+ })()
267
+
268
+ })
291
269
  .catch( (e) => {
292
270
  setError(e)
293
271
  }
@@ -296,13 +274,32 @@ const useStyles = makeStyles((theme) => ({
296
274
  console.log("Closing connection to SSE")
297
275
  eventSource.close()
298
276
  };
277
+
299
278
  },[])
300
279
 
301
- useEffect(()=>{
302
- console.log("useEffect([pluginState])")
303
- if (pluginState=="started"){
304
- refreshSensors()
280
+
281
+ useEffect(()=>{
282
+
283
+ if (!(sensorData && sensorMap) ) return
284
+
285
+ const _sensor = sensorMap.get(sensorData.mac_address)
286
+ if (_sensor && schema && sensorData &&
287
+ Object.hasOwn(sensorData,"params" )){
305
288
 
289
+ if (_sensor.info.class == "UNKNOWN" && sensorData.params.sensorClass && sensorData.params.sensorClass != "UNKNOWN") {
290
+ getSensorInfo(sensorData.mac_address, sensorData.params.sensorClass).then((json)=>{
291
+ debugger
292
+ setSchema(json.schema)
293
+ })
294
+ }
295
+
296
+ }
297
+
298
+ },[sensorData])
299
+
300
+
301
+ useEffect(()=>{
302
+ if (pluginState=="started") {
306
303
  getBaseData().then((json) => {
307
304
  setBaseSchema(json.schema);
308
305
  setBaseData(json.data);
@@ -317,7 +314,6 @@ useEffect(()=>{
317
314
  })
318
315
 
319
316
  } else{
320
- setSensorMap(new Map())
321
317
  setBaseSchema({})
322
318
  setBaseData({})
323
319
  }
@@ -325,9 +321,10 @@ useEffect(()=>{
325
321
  },[pluginState])
326
322
 
327
323
 
328
-
329
324
  function confirmDelete(mac){
330
- const result = window.confirm(`Delete configuration for ${mac}?`)
325
+
326
+ const sensor = sensorMap.get(mac)
327
+ const result = !hasConfig(sensor) || window.confirm(`Delete configuration for ${sensor.info.name}?`)
331
328
  if (result)
332
329
  removeSensorData(mac)
333
330
  }
@@ -352,7 +349,7 @@ function signalStrengthIcon(sensor){
352
349
 
353
350
  }
354
351
  function hasConfig(sensor){
355
- return Object.keys(sensor.config).length>0;
352
+ return Object.keys(sensor.configCopy).length>0;
356
353
  }
357
354
 
358
355
  function createListGroupItem(sensor){
@@ -376,66 +373,43 @@ function createListGroupItem(sensor){
376
373
  </ListGroupItem>
377
374
  }
378
375
 
379
- function configuredDevices(){
380
- return Array.from(sensorMap.entries()).filter((entry)=>hasConfig(entry[1]))
381
- }
382
376
 
383
377
  function devicesInDomain(domain){
384
- if (domain==="_configured")
385
- return configuredDevices()
386
- else
378
+
387
379
  return Array.from(sensorMap.entries()).filter((entry)=>entry[1].info.domain===domain)
388
380
  }
389
381
 
382
+ function ifNullNaN(value){
383
+ return value==null? NaN : value
384
+ }
390
385
 
391
- useEffect(()=>{
392
- console.log("useEffect([sensorMap])")
393
-
394
- _sensorMap = sensorMap
395
-
396
- const _sensorDomains = [... (new Set(sensorMap.entries().map((entry)=>{ return entry[1].info.domain})))].sort()
397
- const sl = {
398
- _configured: configuredDevices().length==0?
386
+ function getTabs(){
387
+ const sensorDomains = [... (new Set(sensorMap.entries().map((entry)=>{ return entry[1].info.domain})))].sort()
388
+ const cd = Array.from(sensorMap.entries()).filter((entry)=>hasConfig(entry[1]))
389
+ let sensorList={}
390
+ sensorList["_configured"]=
391
+ cd.length==0?
399
392
  "Select a device from its domain tab (Electrical etc.) and configure it.":
400
- configuredDevices().map((entry) => {
393
+ cd.map((entry) => {
401
394
  return createListGroupItem(sensorMap.get(entry[0]))
402
395
  })
403
- }
404
-
405
- _sensorDomains.forEach((d)=>{
406
- sl[d]=devicesInDomain(d).map((entry) => {
396
+
397
+ sensorDomains.forEach((d)=>{
398
+ sensorList[d]=devicesInDomain(d).map((entry) => {
407
399
  return createListGroupItem(sensorMap.get(entry[0]))
408
400
  })
409
- })
410
- _sensorList=sl
411
-
412
-
413
- },[sensorMap]
414
- )
415
-
416
- function ifNullNaN(value){
417
- return value==null? NaN : value
418
- }
419
-
420
- function getSensorList(domain){
421
- return _sensorList[domain]
422
- }
423
-
424
- function getTabs(){
401
+ })
425
402
 
426
- return Object.keys(_sensorList).map((domain)=> {return getTab(domain)})
403
+ return Object.keys(sensorList).map((domain)=> {return getTab(domain, sensorList[domain])})
427
404
  }
428
- // <div style={{paddingBottom: 20}} class="d-flex flex-wrap justify-content-start align-items-start">
429
- // <div class="d-flex flex-column" >
430
405
 
431
- function getTab(key){
432
- var title = key.slice(key.charAt(0)==="_"?1:0)
433
- let sl = getSensorList(key)
406
+ function getTab(key, sensorList){
407
+ let title = key.slice(key.charAt(0)==="_"?1:0)
434
408
 
435
- return <Tab eventKey={key} title={`${title.charAt(0).toUpperCase()}${title.slice(1)}${devicesInDomain(key).length==0?'':' ('+devicesInDomain(key).length+')'}` } >
409
+ return <Tab eventKey={key} title={`${title.charAt(0).toUpperCase()}${title.slice(1)}${typeof sensorList=='string'?'':' ('+sensorList.length+')'}` } >
436
410
 
437
411
  <ListGroup style={{ maxHeight: '300px', overflowY: 'auto' }}>
438
- {sl}
412
+ {sensorList}
439
413
  </ListGroup>
440
414
 
441
415
 
@@ -447,22 +421,6 @@ useEffect(()=>{
447
421
  window.open(url, "_blank", "noreferrer");
448
422
  }
449
423
 
450
- function CustomFieldTemplate(props) {
451
- const { id, classNames, style, label, help, required, description, errors, children } = props;
452
- return (
453
- <div className={classNames} style={style}>
454
- <Grid container xs={12} direction="row" spacing="1">
455
- <Grid item xs={1} sm container direction="column">
456
- <Grid item ><label htmlFor={id}>{label}{required ? '*' : null}</label></Grid>
457
- <Grid item> {description}</Grid>
458
- </Grid>
459
- <Grid item>{children}</Grid>
460
- </Grid>
461
- {errors}
462
- {help}
463
- </div>
464
- );
465
- }
466
424
 
467
425
  if (pluginState=="stopped" || pluginState=="unknown")
468
426
  return (<h3>Enable plugin to see configuration</h3>)
@@ -504,7 +462,7 @@ useEffect(()=>{
504
462
  defaultActiveKey="_configured"
505
463
  id="domain-tabs"
506
464
  className="mb-3"
507
- onClick={()=>{setSchema({})}}
465
+
508
466
  >
509
467
  {getTabs()}
510
468
  </Tabs>
@@ -520,13 +478,15 @@ useEffect(()=>{
520
478
  uiSchema={uiSchema}
521
479
  onChange={(e) => {
522
480
  const s = sensorMap.get(e.formData.mac_address)
523
- s._changesMade=true
524
- setSensorData(e.formData)
481
+ if(s) {
482
+ s._changesMade=true
483
+ s.config = e.formData
484
+ setSensorData(e.formData)
485
+ }
525
486
  }
526
487
  }
527
488
  onSubmit={({ formData }, e) => {
528
489
  updateSensorData(formData)
529
- setSchema({})
530
490
  alert("Changes saved")
531
491
  }}
532
492
  onError={log('errors')}
@@ -544,4 +504,5 @@ useEffect(()=>{
544
504
  )
545
505
 
546
506
 
547
- }
507
+ }
508
+ export default BTConfig
@@ -1,170 +0,0 @@
1
- {
2
- "configuration": {
3
- "discoveryInterval": 10,
4
- "peripherals": [
5
- {
6
- "active": true,
7
- "discoveryTimeout": 30,
8
- "params": {
9
- "name": "ATC_9FF77E",
10
- "zone": "inside.cabin",
11
- "parser": "ATC-LE",
12
- "sensorClass": "ATC"
13
- },
14
- "paths": {
15
- "RSSI": "sensors.{macAndName}.RSSI",
16
- "batteryStrength": "sensors.{macAndName}.battery.strength",
17
- "voltage": "sensors.{macAndName}.battery.voltage",
18
- "temp": "environment.{zone}.temperature",
19
- "humidity": "environment.{zone}.humidity"
20
- },
21
- "mac_address": "A4:C1:38:9F:F7:7E"
22
- },
23
- {
24
- "active": true,
25
- "discoveryTimeout": 30,
26
- "params": {
27
- "name": "tps",
28
- "zone": "inside.refrigerator",
29
- "sensorClass": "Inkbird"
30
- },
31
- "paths": {
32
- "RSSI": "sensors.{macAndName}.RSSI",
33
- "temp": "environment.{zone}.temperature",
34
- "battery": "sensors.{macAndName}.battery.strength"
35
- },
36
- "mac_address": "49:22:05:17:2B:AE"
37
- },
38
- {
39
- "active": true,
40
- "discoveryTimeout": 30,
41
- "params": {
42
- "name": "Ruuvi BC7E",
43
- "zone": "inside.navdesk",
44
- "sensorClass": "RuuviTag"
45
- },
46
- "paths": {
47
- "RSSI": "sensors.{macAndName}.RSSI",
48
- "temp": "environment.{zone}.temperature",
49
- "humidity": "environment.{zone}.humidity",
50
- "pressure": "environment.{zone}.pressure",
51
- "accX": "sensors.{macAndName}.accX",
52
- "accY": "sensors.{macAndName}.accY",
53
- "accZ": "sensors.{macAndName}.accZ",
54
- "battV": "sensors.{macAndName}.battery.voltage",
55
- "mc": "sensors.{macAndName}.movementCounter",
56
- "msc": "sensors.{macAndName}.measurementSequenceCounter"
57
- },
58
- "mac_address": "F9:B0:6E:63:BC:7E"
59
- },
60
- {
61
- "active": true,
62
- "discoveryTimeout": 30,
63
- "params": {
64
- "name": "SBMO-003Z-db1b",
65
- "zone": "inside",
66
- "sensorClass": "ShellySBMO003Z"
67
- },
68
- "paths": {
69
- "RSSI": "sensors.{macAndName}.RSSI",
70
- "motion": "environment.{zone}.motion",
71
- "illuminance": "environment.{zone}.illuminance",
72
- "battery": "sensors.{macAndName}.battery.strength",
73
- "button": "sensors.{macAndName}.button"
74
- },
75
- "mac_address": "E8:E0:7E:97:DB:1B"
76
- },
77
- {
78
- "active": true,
79
- "discoveryTimeout": 30,
80
- "params": {
81
- "name": "LYWSD03MMC",
82
- "zone": "inside.vberth",
83
- "encryptionKey": "3985f4ebc032f276cc316f1f6ecea085",
84
- "sensorClass": "XiaomiMiBeacon"
85
- },
86
- "paths": {
87
- "RSSI": "sensors.{macAndName}.RSSI",
88
- "temp": "environment.{zone}.temperature",
89
- "humidity": "environment.{zone}.humidity",
90
- "batteryStrength": "sensors.{macAndName}.battery.strength",
91
- "voltage": "sensors.{macAndName}.battery.voltage"
92
- },
93
- "gattParams": {
94
- "useGATT": false
95
- },
96
- "mac_address": "A4:C1:38:3E:7E:94"
97
- },
98
- {
99
- "active": true,
100
- "discoveryTimeout": 30,
101
- "params": {
102
- "name": "SmartShunt HQ2204C2GHD",
103
- "batteryID": "house",
104
- "encryptionKey": "8cce8529307cf9dd0c85611c4fef42d9",
105
- "sensorClass": "VictronBatteryMonitor"
106
- },
107
- "paths": {
108
- "RSSI": "sensors.{macAndName}.RSSI",
109
- "current": "electrical.batteries.{batteryID}.current",
110
- "power": "electrical.batteries.{batteryID}.power",
111
- "voltage": "electrical.batteries.{batteryID}.voltage",
112
- "alarm": "electrical.batteries.{batteryID}.alarm",
113
- "consumed": "electrical.batteries.{batteryID}.capacity.ampHoursConsumed",
114
- "soc": "electrical.batteries.{batteryID}.capacity.stateOfCharge",
115
- "ttg": "electrical.batteries.{batteryID}.capacity.timeRemaining",
116
- "starterVoltage": "electrical.batteries.secondary.voltage"
117
- },
118
- "gattParams": {
119
- "useGATT": false
120
- },
121
- "mac_address": "D4:50:46:39:38:C5"
122
- },
123
- {
124
- "active": true,
125
- "discoveryTimeout": 90,
126
- "params": {
127
- "name": "aft propane tank",
128
- "medium": "PROPANE",
129
- "tankHeight": "325",
130
- "id": "propane",
131
- "sensorClass": "MopekaTankSensor"
132
- },
133
- "paths": {
134
- "RSSI": "sensors.{macAndName}.RSSI",
135
- "battVolt": "sensors.{macAndName}.battery.voltage",
136
- "battStrength": "sensors.{macAndName}.battery.strength",
137
- "temp": "tanks.{id}.temperature",
138
- "tankLevel": "tanks.{id}.currentLevel",
139
- "readingQuality": "sensors.{macAndName}.readingQuality",
140
- "accX": "sensors.{macAndName}.accelerationXAxis",
141
- "accY": "sensors.{macAndName}.accelerationYAxis"
142
- },
143
- "mac_address": "D4:40:59:BE:2A:8C"
144
- },
145
- {
146
- "active": true,
147
- "discoveryTimeout": 30,
148
- "params": {
149
- "name": "SBHT-003C",
150
- "zone": "outside.deck",
151
- "sensorClass": "ShellySBHT003C"
152
- },
153
- "paths": {
154
- "RSSI": "sensors.{macAndName}.RSSI",
155
- "battery": "sensors.{macAndName}.battery.strength",
156
- "temp": "environment.{zone}.temperature",
157
- "humidity": "environment.{zone}.humidity",
158
- "button": "sensors.{macAndName}.button"
159
- },
160
- "mac_address": "7C:C6:B6:AF:49:5F"
161
- }
162
- ],
163
- "adapter": "hci0",
164
- "transport": "le",
165
- "duplicateData": false,
166
- "discoveryTimeout": 30
167
- },
168
- "enabled": true,
169
- "enableDebug": false
170
- }