bt-sensors-plugin-sk 1.2.4-4 → 1.2.5-1
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 +4 -1
- package/README.md +15 -8
- package/bt-sensors-plugin-sk copy.json +170 -0
- package/diff.txt +2860 -0
- package/index.js +31 -15
- package/package.json +1 -1
- package/public/847.js +1 -1
- package/sensor_classes/MopekaTankSensor.js +5 -5
- package/sensor_classes/RuuviTag.js +5 -5
- package/sensor_classes/Victron/VictronSensor.js +29 -8
- package/src/components/PluginConfigurationPanel.js +86 -155
|
@@ -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,9 +19,7 @@ import { ListGroupItem } from 'react-bootstrap';
|
|
|
20
19
|
|
|
21
20
|
import ProgressBar from 'react-bootstrap/ProgressBar';
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export default function BTConfig (props) {
|
|
22
|
+
export function BTConfig (props) {
|
|
26
23
|
|
|
27
24
|
const _uiSchema= {
|
|
28
25
|
"ui:options": {label: false},
|
|
@@ -71,10 +68,9 @@ const useStyles = makeStyles((theme) => ({
|
|
|
71
68
|
|
|
72
69
|
const [schema, setSchema] = useState({})
|
|
73
70
|
const [ uiSchema, setUISchema] = useState(_uiSchema )
|
|
74
|
-
const [sensorList, setSensorList] = useState([])
|
|
75
71
|
|
|
76
72
|
const [sensorData, setSensorData] = useState()
|
|
77
|
-
const [sensorMap, setSensorMap ] = useState(new Map()
|
|
73
|
+
const [sensorMap, setSensorMap ] = useState(new Map())
|
|
78
74
|
|
|
79
75
|
const [progress, setProgress ] = useState({
|
|
80
76
|
"progress":0, "maxTimeout": 100,
|
|
@@ -89,8 +85,6 @@ const useStyles = makeStyles((theme) => ({
|
|
|
89
85
|
|
|
90
86
|
function sendJSONData(cmd, data){
|
|
91
87
|
|
|
92
|
-
console.log(`sending ${cmd}`)
|
|
93
|
-
console.log(data)
|
|
94
88
|
const headers = new Headers();
|
|
95
89
|
headers.append("Content-Type", "application/json");
|
|
96
90
|
return fetch(`/plugins/bt-sensors-plugin-sk/${cmd}`, {
|
|
@@ -102,7 +96,6 @@ const useStyles = makeStyles((theme) => ({
|
|
|
102
96
|
}
|
|
103
97
|
|
|
104
98
|
async function fetchJSONData(path){
|
|
105
|
-
console.log(`fetching ${path}`)
|
|
106
99
|
var result
|
|
107
100
|
try {
|
|
108
101
|
result = fetch(`/plugins/bt-sensors-plugin-sk/${path}`, {
|
|
@@ -119,72 +112,53 @@ const useStyles = makeStyles((theme) => ({
|
|
|
119
112
|
}
|
|
120
113
|
|
|
121
114
|
async function getSensors(){
|
|
122
|
-
console.log("getSensors")
|
|
123
115
|
const response = await fetchJSONData("getSensors")
|
|
124
116
|
if (response.status!=200){
|
|
125
117
|
throw new Error(`Unable get sensor data: ${response.statusText} (${response.status}) `)
|
|
126
118
|
}
|
|
127
119
|
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
|
-
//}
|
|
132
|
-
return json
|
|
133
120
|
|
|
134
|
-
}
|
|
135
|
-
async function getDomains(){
|
|
136
|
-
console.log("getDomains")
|
|
137
|
-
const response = await fetchJSONData("getDomains")
|
|
138
|
-
if (response.status!=200){
|
|
139
|
-
throw new Error(`Unable get domain data: ${response.statusText} (${response.status}) `)
|
|
140
|
-
}
|
|
141
|
-
const json = await response.json()
|
|
142
|
-
console.log(json)
|
|
143
121
|
return json
|
|
144
122
|
|
|
145
123
|
}
|
|
124
|
+
|
|
146
125
|
async function getBaseData(){
|
|
147
|
-
console.log("getBaseData")
|
|
148
126
|
const response = await fetchJSONData("getBaseData")
|
|
149
127
|
if (response.status!=200){
|
|
150
128
|
throw new Error(`Unable to get base data: ${response.statusText} (${response.status}) `)
|
|
151
129
|
}
|
|
152
130
|
const json = await response.json()
|
|
153
|
-
console.log(json)
|
|
154
131
|
json.schema.htmlDescription=<div>{ReactHtmlParser(json.schema.htmlDescription)}<p></p></div>
|
|
155
132
|
return json
|
|
156
133
|
}
|
|
134
|
+
|
|
157
135
|
async function getProgress(){
|
|
158
|
-
console.log("getProgress")
|
|
159
136
|
const response = await fetchJSONData("getProgress")
|
|
160
137
|
if (response.status!=200){
|
|
161
138
|
throw new Error(`Unable to get progress: ${response.statusText} (${response.status}) `)
|
|
162
139
|
}
|
|
163
140
|
const json = await response.json()
|
|
164
|
-
console.log(json)
|
|
165
141
|
return json
|
|
166
142
|
}
|
|
167
143
|
|
|
168
144
|
function updateSensorData(data){
|
|
169
|
-
console.log("updateSensorData")
|
|
170
145
|
sendJSONData("updateSensorData", data).then((response)=>{
|
|
171
146
|
if (response.status != 200) {
|
|
172
147
|
throw new Error(response.statusText)
|
|
173
148
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
149
|
+
setSensorMap((sm)=>{sm.delete(data.mac_address); return new Map(sm) })
|
|
150
|
+
setSchema( {} )
|
|
151
|
+
|
|
177
152
|
})
|
|
178
153
|
}
|
|
179
154
|
|
|
180
155
|
function undoChanges(mac) {
|
|
181
|
-
console.log("undoChanges")
|
|
182
156
|
sensorMap.get(mac)._changesMade = false
|
|
157
|
+
sensorMap.get(mac).config = JSON.parse(JSON.stringify(sensorMap.get(mac).configCopy))
|
|
183
158
|
setSensorData( sensorMap.get(mac).config )
|
|
184
159
|
}
|
|
185
160
|
|
|
186
161
|
function removeSensorData(mac){
|
|
187
|
-
console.log("removeSensorData")
|
|
188
162
|
|
|
189
163
|
try{
|
|
190
164
|
|
|
@@ -193,10 +167,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
193
167
|
throw new Error(response.statusText)
|
|
194
168
|
}
|
|
195
169
|
})
|
|
196
|
-
|
|
197
|
-
_sensorMap.delete(mac)
|
|
198
|
-
|
|
199
|
-
setSensorMap(new Map(_sensorMap))
|
|
170
|
+
setSensorMap((sm)=>{sm.delete(mac); return new Map(sm) })
|
|
200
171
|
setSchema( {} )
|
|
201
172
|
} catch {(e)=>
|
|
202
173
|
setError( new Error(`Couldn't remove ${mac}: ${e}`))
|
|
@@ -206,88 +177,80 @@ const useStyles = makeStyles((theme) => ({
|
|
|
206
177
|
|
|
207
178
|
|
|
208
179
|
function updateBaseData(data){
|
|
209
|
-
|
|
210
|
-
|
|
180
|
+
setSensorMap(new Map())
|
|
181
|
+
//setSensorList({})
|
|
211
182
|
sendJSONData("updateBaseData", data).then( (response )=>{
|
|
212
183
|
if (response.status != 200) {
|
|
213
184
|
setError(new Error(`Unable to update base data: ${response.statusText} (${response.status})`))
|
|
214
|
-
}
|
|
215
|
-
getProgress().then((json)=>{
|
|
216
|
-
setProgress(json)
|
|
217
|
-
}).catch((e)=>{
|
|
218
|
-
setError(e)
|
|
219
|
-
})
|
|
220
|
-
}*/
|
|
185
|
+
}
|
|
221
186
|
})
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
function refreshSensors(){
|
|
226
|
-
console.log('refreshing sensor map')
|
|
227
187
|
|
|
228
|
-
getSensors().then((sensors)=>{
|
|
229
|
-
setSensorMap (new Map(sensors.map((sensor)=>[sensor.info.mac,sensor])));
|
|
230
|
-
})
|
|
231
|
-
.catch((e)=>{
|
|
232
|
-
setError(e)
|
|
233
|
-
})
|
|
234
188
|
}
|
|
189
|
+
|
|
190
|
+
|
|
235
191
|
|
|
236
192
|
|
|
237
193
|
useEffect(()=>{
|
|
238
|
-
console.log("useEffect([])")
|
|
239
194
|
let eventSource=null
|
|
240
|
-
|
|
241
195
|
fetchJSONData("getPluginState").then( async (response)=> {
|
|
196
|
+
|
|
197
|
+
function newSensorEvent(event){
|
|
198
|
+
let json = JSON.parse(event.data)
|
|
199
|
+
console.log(`New sensor: ${json.info.mac}`)
|
|
200
|
+
setSensorMap( (_sm)=> {
|
|
201
|
+
//if (!_sm.has(json.info.mac))
|
|
202
|
+
_sm.set(json.info.mac, json)
|
|
203
|
+
|
|
204
|
+
return new Map(_sm)
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
function sensorChangedEvent(event){
|
|
209
|
+
console.log("sensorchanged")
|
|
210
|
+
const json = JSON.parse(event.data)
|
|
211
|
+
|
|
212
|
+
setSensorMap( (_sm) => {
|
|
213
|
+
const sensor = _sm.get(json.mac)
|
|
214
|
+
if (sensor)
|
|
215
|
+
Object.assign(sensor.info, json )
|
|
216
|
+
return new Map(_sm)
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
242
221
|
if (response.status==404) {
|
|
243
222
|
setPluginState("unknown")
|
|
244
223
|
throw new Error("unable to get plugin state")
|
|
245
224
|
}
|
|
246
225
|
const json = await response.json()
|
|
247
|
-
console.log("Setting up eventsource")
|
|
248
226
|
eventSource = new EventSource("/plugins/bt-sensors-plugin-sk/sse", { withCredentials: true })
|
|
249
227
|
|
|
250
|
-
setPluginState(json.state)
|
|
251
|
-
|
|
252
|
-
_sensorDomains = await getDomains()
|
|
253
|
-
|
|
254
228
|
eventSource.addEventListener("newsensor", (event) => {
|
|
255
|
-
|
|
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
|
-
}
|
|
229
|
+
newSensorEvent(event)
|
|
262
230
|
});
|
|
263
231
|
|
|
264
232
|
eventSource.addEventListener("sensorchanged", (event) => {
|
|
265
|
-
|
|
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
|
-
}
|
|
233
|
+
sensorChangedEvent(event)
|
|
275
234
|
});
|
|
235
|
+
|
|
276
236
|
eventSource.addEventListener("progress", (event) => {
|
|
277
|
-
console.log("progress")
|
|
278
237
|
const json = JSON.parse(event.data)
|
|
279
238
|
setProgress(json)
|
|
280
|
-
console.log(json)
|
|
281
239
|
});
|
|
282
240
|
|
|
283
241
|
eventSource.addEventListener("pluginstate", (event) => {
|
|
284
|
-
console.log("pluginstate")
|
|
285
242
|
const json = JSON.parse(event.data)
|
|
286
243
|
setPluginState(json.state)
|
|
287
244
|
});
|
|
288
|
-
|
|
289
|
-
|
|
245
|
+
|
|
246
|
+
setPluginState(json.state);
|
|
290
247
|
|
|
248
|
+
(async ()=>{
|
|
249
|
+
const sensors = await getSensors()
|
|
250
|
+
setSensorMap ( new Map(sensors.map((sensor)=>[sensor.info.mac,sensor])) )
|
|
251
|
+
})()
|
|
252
|
+
|
|
253
|
+
})
|
|
291
254
|
.catch( (e) => {
|
|
292
255
|
setError(e)
|
|
293
256
|
}
|
|
@@ -296,13 +259,11 @@ const useStyles = makeStyles((theme) => ({
|
|
|
296
259
|
console.log("Closing connection to SSE")
|
|
297
260
|
eventSource.close()
|
|
298
261
|
};
|
|
262
|
+
|
|
299
263
|
},[])
|
|
300
264
|
|
|
301
265
|
useEffect(()=>{
|
|
302
|
-
|
|
303
|
-
if (pluginState=="started"){
|
|
304
|
-
refreshSensors()
|
|
305
|
-
|
|
266
|
+
if (pluginState=="started") {
|
|
306
267
|
getBaseData().then((json) => {
|
|
307
268
|
setBaseSchema(json.schema);
|
|
308
269
|
setBaseData(json.data);
|
|
@@ -317,7 +278,6 @@ useEffect(()=>{
|
|
|
317
278
|
})
|
|
318
279
|
|
|
319
280
|
} else{
|
|
320
|
-
setSensorMap(new Map())
|
|
321
281
|
setBaseSchema({})
|
|
322
282
|
setBaseData({})
|
|
323
283
|
}
|
|
@@ -325,9 +285,10 @@ useEffect(()=>{
|
|
|
325
285
|
},[pluginState])
|
|
326
286
|
|
|
327
287
|
|
|
328
|
-
|
|
329
288
|
function confirmDelete(mac){
|
|
330
|
-
|
|
289
|
+
|
|
290
|
+
const sensor = sensorMap.get(mac)
|
|
291
|
+
const result = !hasConfig(sensor) || window.confirm(`Delete configuration for ${sensor.info.name}?`)
|
|
331
292
|
if (result)
|
|
332
293
|
removeSensorData(mac)
|
|
333
294
|
}
|
|
@@ -352,7 +313,7 @@ function signalStrengthIcon(sensor){
|
|
|
352
313
|
|
|
353
314
|
}
|
|
354
315
|
function hasConfig(sensor){
|
|
355
|
-
return Object.keys(sensor.
|
|
316
|
+
return Object.keys(sensor.configCopy).length>0;
|
|
356
317
|
}
|
|
357
318
|
|
|
358
319
|
function createListGroupItem(sensor){
|
|
@@ -376,60 +337,43 @@ function createListGroupItem(sensor){
|
|
|
376
337
|
</ListGroupItem>
|
|
377
338
|
}
|
|
378
339
|
|
|
379
|
-
function configuredDevices(){
|
|
380
|
-
return Array.from(sensorMap.entries()).filter((entry)=>hasConfig(entry[1]))
|
|
381
|
-
}
|
|
382
340
|
|
|
383
341
|
function devicesInDomain(domain){
|
|
342
|
+
|
|
384
343
|
return Array.from(sensorMap.entries()).filter((entry)=>entry[1].info.domain===domain)
|
|
385
344
|
}
|
|
386
345
|
|
|
387
|
-
|
|
388
|
-
useEffect(()=>{
|
|
389
|
-
console.log("useEffect([sensorMap])")
|
|
390
|
-
|
|
391
|
-
_sensorMap = sensorMap
|
|
392
|
-
|
|
393
|
-
const _sensorDomains = new Set(sensorMap.entries().map((entry)=>{ return entry[1].info.domain}))
|
|
394
|
-
const sl = {
|
|
395
|
-
_configured: configuredDevices().map((entry) => {
|
|
396
|
-
return createListGroupItem(sensorMap.get(entry[0]))
|
|
397
|
-
})
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
_sensorDomains.forEach((d)=>{
|
|
401
|
-
sl[d]=devicesInDomain(d).map((entry) => {
|
|
402
|
-
return createListGroupItem(sensorMap.get(entry[0]))
|
|
403
|
-
})
|
|
404
|
-
})
|
|
405
|
-
_sensorList=sl
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
},[sensorMap]
|
|
409
|
-
)
|
|
410
|
-
|
|
411
346
|
function ifNullNaN(value){
|
|
412
347
|
return value==null? NaN : value
|
|
413
348
|
}
|
|
414
349
|
|
|
415
|
-
function getSensorList(domain){
|
|
416
|
-
return _sensorList[domain]
|
|
417
|
-
}
|
|
418
|
-
|
|
419
350
|
function getTabs(){
|
|
351
|
+
const sensorDomains = [... (new Set(sensorMap.entries().map((entry)=>{ return entry[1].info.domain})))].sort()
|
|
352
|
+
const cd = Array.from(sensorMap.entries()).filter((entry)=>hasConfig(entry[1]))
|
|
353
|
+
let sensorList={}
|
|
354
|
+
sensorList["_configured"]=
|
|
355
|
+
cd.length==0?
|
|
356
|
+
"Select a device from its domain tab (Electrical etc.) and configure it.":
|
|
357
|
+
cd.map((entry) => {
|
|
358
|
+
return createListGroupItem(sensorMap.get(entry[0]))
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
sensorDomains.forEach((d)=>{
|
|
362
|
+
sensorList[d]=devicesInDomain(d).map((entry) => {
|
|
363
|
+
return createListGroupItem(sensorMap.get(entry[0]))
|
|
364
|
+
})
|
|
365
|
+
})
|
|
420
366
|
|
|
421
|
-
return Object.keys(
|
|
367
|
+
return Object.keys(sensorList).map((domain)=> {return getTab(domain, sensorList[domain])})
|
|
422
368
|
}
|
|
423
|
-
// <div style={{paddingBottom: 20}} class="d-flex flex-wrap justify-content-start align-items-start">
|
|
424
|
-
// <div class="d-flex flex-column" >
|
|
425
369
|
|
|
426
|
-
function getTab(key){
|
|
427
|
-
|
|
370
|
+
function getTab(key, sensorList){
|
|
371
|
+
let title = key.slice(key.charAt(0)==="_"?1:0)
|
|
428
372
|
|
|
429
|
-
return <Tab eventKey={key} title={title.charAt(0).toUpperCase()
|
|
373
|
+
return <Tab eventKey={key} title={`${title.charAt(0).toUpperCase()}${title.slice(1)}${typeof sensorList=='string'?'':' ('+sensorList.length+')'}` } >
|
|
430
374
|
|
|
431
375
|
<ListGroup style={{ maxHeight: '300px', overflowY: 'auto' }}>
|
|
432
|
-
{
|
|
376
|
+
{sensorList}
|
|
433
377
|
</ListGroup>
|
|
434
378
|
|
|
435
379
|
|
|
@@ -441,22 +385,6 @@ useEffect(()=>{
|
|
|
441
385
|
window.open(url, "_blank", "noreferrer");
|
|
442
386
|
}
|
|
443
387
|
|
|
444
|
-
function CustomFieldTemplate(props) {
|
|
445
|
-
const { id, classNames, style, label, help, required, description, errors, children } = props;
|
|
446
|
-
return (
|
|
447
|
-
<div className={classNames} style={style}>
|
|
448
|
-
<Grid container xs={12} direction="row" spacing="1">
|
|
449
|
-
<Grid item xs={1} sm container direction="column">
|
|
450
|
-
<Grid item ><label htmlFor={id}>{label}{required ? '*' : null}</label></Grid>
|
|
451
|
-
<Grid item> {description}</Grid>
|
|
452
|
-
</Grid>
|
|
453
|
-
<Grid item>{children}</Grid>
|
|
454
|
-
</Grid>
|
|
455
|
-
{errors}
|
|
456
|
-
{help}
|
|
457
|
-
</div>
|
|
458
|
-
);
|
|
459
|
-
}
|
|
460
388
|
|
|
461
389
|
if (pluginState=="stopped" || pluginState=="unknown")
|
|
462
390
|
return (<h3>Enable plugin to see configuration</h3>)
|
|
@@ -498,7 +426,7 @@ useEffect(()=>{
|
|
|
498
426
|
defaultActiveKey="_configured"
|
|
499
427
|
id="domain-tabs"
|
|
500
428
|
className="mb-3"
|
|
501
|
-
|
|
429
|
+
|
|
502
430
|
>
|
|
503
431
|
{getTabs()}
|
|
504
432
|
</Tabs>
|
|
@@ -514,13 +442,15 @@ useEffect(()=>{
|
|
|
514
442
|
uiSchema={uiSchema}
|
|
515
443
|
onChange={(e) => {
|
|
516
444
|
const s = sensorMap.get(e.formData.mac_address)
|
|
517
|
-
s
|
|
518
|
-
|
|
445
|
+
if(s) {
|
|
446
|
+
s._changesMade=true
|
|
447
|
+
s.config = e.formData
|
|
448
|
+
setSensorData(e.formData)
|
|
449
|
+
}
|
|
519
450
|
}
|
|
520
451
|
}
|
|
521
452
|
onSubmit={({ formData }, e) => {
|
|
522
453
|
updateSensorData(formData)
|
|
523
|
-
setSchema({})
|
|
524
454
|
alert("Changes saved")
|
|
525
455
|
}}
|
|
526
456
|
onError={log('errors')}
|
|
@@ -538,4 +468,5 @@ useEffect(()=>{
|
|
|
538
468
|
)
|
|
539
469
|
|
|
540
470
|
|
|
541
|
-
}
|
|
471
|
+
}
|
|
472
|
+
export default BTConfig
|