bt-sensors-plugin-sk 1.2.0-beta.0.0.9 → 1.2.0-beta.0.1.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 +14 -2
- package/README.md +13 -0
- package/bt-sensors-plugin-sk.json.bak +121 -0
- package/classLoader.js +38 -0
- package/index.js +51 -99
- package/package.json +2 -2
- package/public/159.js +1 -2
- package/public/239.js +14 -0
- package/public/540.js +1 -1
- package/public/778.js +2 -0
- package/public/main.js +1 -1
- package/public/remoteEntry.js +1 -1
- package/sensor_classes/ATC.js +1 -0
- package/sensor_classes/Aranet/AranetSensor.js +1 -0
- package/sensor_classes/GobiusCTankMeter.js +363 -0
- package/sensor_classes/GoveeH50xx.js +1 -1
- package/sensor_classes/GoveeH510x.js +1 -1
- package/sensor_classes/IBeacon.js +9 -2
- package/sensor_classes/Inkbird.js +1 -1
- package/sensor_classes/JBDBMS.js +1 -0
- package/sensor_classes/KilovaultHLXPlus.js +2 -0
- package/sensor_classes/LancolVoltageMeter.js +1 -0
- package/sensor_classes/MopekaTankSensor.js +7 -3
- package/sensor_classes/Renogy/RenogySensor.js +1 -1
- package/sensor_classes/RuuviTag.js +1 -0
- package/sensor_classes/ShellySBHT003C.js +2 -5
- package/sensor_classes/SwitchBotMeterPlus.js +2 -1
- package/sensor_classes/SwitchBotTH.js +2 -0
- package/sensor_classes/UltrasonicWindMeter.js +2 -0
- package/sensor_classes/Victron/VictronSensor.js +1 -0
- package/sensor_classes/VictronInverterRS.js +2 -2
- package/sensor_classes/XiaomiMiBeacon.js +2 -1
- package/src/components/PluginConfigurationPanel.js +140 -81
- package/.vscode/launch.json +0 -7
- package/public/30.js +0 -8
- package/public/893.js +0 -1
- package/testqueue.js +0 -64
- /package/public/{30.js.LICENSE.txt → 239.js.LICENSE.txt} +0 -0
- /package/public/{159.js.LICENSE.txt → 778.js.LICENSE.txt} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const BTSensor = require("../BTSensor");
|
|
2
2
|
class RuuviTag extends BTSensor{
|
|
3
3
|
static manufacturerID = 0x0499
|
|
4
|
+
static Domain = BTSensor.SensorDomains.environmental
|
|
4
5
|
static async identify(device){
|
|
5
6
|
if (await this.getManufacturerID(device)==this.manufacturerID)
|
|
6
7
|
return this
|
|
@@ -7,17 +7,14 @@ const AbstractBTHomeSensor = require("./BTHome/AbstractBTHomeSensor");
|
|
|
7
7
|
* This sensor is publishing data utilising the BTHome format and inherits from {@link AbstractBTHomeSensor}.
|
|
8
8
|
*/
|
|
9
9
|
class ShellySBHT003C extends AbstractBTHomeSensor {
|
|
10
|
+
static Domain = AbstractBTHomeSensor.SensorDomains.environmental
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* The shortened local name as advertised by the Shelly BLU H&T.
|
|
12
14
|
* @type {string}
|
|
13
15
|
*/
|
|
14
16
|
static SHORTENED_LOCAL_NAME = "SBHT-003C";
|
|
15
17
|
|
|
16
|
-
async init() {
|
|
17
|
-
await super.init();
|
|
18
|
-
this.initMetadata();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
18
|
/**
|
|
22
19
|
* @typedef ButtonPressEvent {string}
|
|
23
20
|
*/
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const BTSensor = require("../BTSensor");
|
|
2
2
|
|
|
3
3
|
class SwitchBotTH extends BTSensor {
|
|
4
|
+
static Domain = BTSensor.SensorDomains.environmental
|
|
5
|
+
|
|
4
6
|
static async test(){
|
|
5
7
|
|
|
6
8
|
const p = {[this.ID.toString()]: [0xd8, 0x35, 0x34, 0x38, 0x4f, 0x70, 0x07, 0x02, 0x04, 0x96, 0x2c, 0x00]}
|
|
@@ -19,13 +19,13 @@ class VictronInverterRS extends VictronSensor{
|
|
|
19
19
|
|
|
20
20
|
const md = this.addMetadatum('chargerError','', 'charger error',
|
|
21
21
|
(buff)=>{return VC.ChargerError(buff.readIntU8(1))})
|
|
22
|
-
.default='electrical.inverters.{id}.error'
|
|
22
|
+
md.default='electrical.inverters.{id}.error'
|
|
23
23
|
md.notify=true
|
|
24
24
|
|
|
25
25
|
this.addMetadatum('batteryVoltage','V', 'battery voltage',
|
|
26
26
|
(buff)=>{return this.NaNif(buff.readInt16LE(2),0x7FFF)/100})
|
|
27
27
|
.default='electrical.inverters.{id}.battery.voltage'
|
|
28
|
-
|
|
28
|
+
.
|
|
29
29
|
this.addMetadatum('pvPower','W', 'PV power',
|
|
30
30
|
(buff)=>{return this.NaNif(buff.readUInt16LE(4), 0xffff)})
|
|
31
31
|
.default='electrical.inverters.{id}.power'
|
|
@@ -71,7 +71,8 @@ const DEVICE_TYPES = new Map([
|
|
|
71
71
|
]);
|
|
72
72
|
|
|
73
73
|
class XiaomiMiBeacon extends BTSensor{
|
|
74
|
-
|
|
74
|
+
static Domain = BTSensor.SensorDomains.environmental
|
|
75
|
+
|
|
75
76
|
constructor(device, config, gattConfig){
|
|
76
77
|
super(device, config, gattConfig)
|
|
77
78
|
this.encryptionKey = config?.encryptionKey
|
|
@@ -10,12 +10,14 @@ import { SignalCellular0Bar, SignalCellular1Bar, SignalCellular2Bar, SignalCellu
|
|
|
10
10
|
const log = (type) => console.log.bind(console, type);
|
|
11
11
|
|
|
12
12
|
import ListGroup from 'react-bootstrap/ListGroup';
|
|
13
|
+
import Tabs from 'react-bootstrap/Tabs';
|
|
14
|
+
import Tab from 'react-bootstrap/Tab';
|
|
13
15
|
import { ListGroupItem } from 'react-bootstrap';
|
|
14
16
|
|
|
15
17
|
import ProgressBar from 'react-bootstrap/ProgressBar';
|
|
16
18
|
|
|
17
19
|
|
|
18
|
-
var _sensorMap
|
|
20
|
+
var _sensorMap, _sensorDomains={}, _sensorList={}
|
|
19
21
|
|
|
20
22
|
export default (props) => {
|
|
21
23
|
|
|
@@ -47,7 +49,6 @@ export default (props) => {
|
|
|
47
49
|
|
|
48
50
|
const [pluginState, setPluginState ] = useState("unknown")
|
|
49
51
|
const [error, setError ] = useState()
|
|
50
|
-
|
|
51
52
|
|
|
52
53
|
function sendJSONData(cmd, data){
|
|
53
54
|
|
|
@@ -65,16 +66,16 @@ export default (props) => {
|
|
|
65
66
|
|
|
66
67
|
async function fetchJSONData(path){
|
|
67
68
|
console.log(`fetching ${path}`)
|
|
68
|
-
|
|
69
|
+
|
|
69
70
|
return fetch(`/plugins/bt-sensors-plugin-sk/${path}`, {
|
|
70
71
|
credentials: 'include'
|
|
71
72
|
})
|
|
72
73
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
async function
|
|
76
|
-
console.log("
|
|
77
|
-
const response = await fetchJSONData("
|
|
76
|
+
async function getSensors(){
|
|
77
|
+
console.log("getSensors")
|
|
78
|
+
const response = await fetchJSONData("getSensors")
|
|
78
79
|
if (response.status!=200){
|
|
79
80
|
throw new Error(`Unable get sensor data: ${response.statusText} (${response.status}) `)
|
|
80
81
|
}
|
|
@@ -83,10 +84,20 @@ export default (props) => {
|
|
|
83
84
|
return json
|
|
84
85
|
|
|
85
86
|
}
|
|
87
|
+
async function getDomains(){
|
|
88
|
+
console.log("getDomains")
|
|
89
|
+
const response = await fetchJSONData("getDomains")
|
|
90
|
+
if (response.status!=200){
|
|
91
|
+
throw new Error(`Unable get domain data: ${response.statusText} (${response.status}) `)
|
|
92
|
+
}
|
|
93
|
+
const json = await response.json()
|
|
94
|
+
console.log(json)
|
|
95
|
+
return json
|
|
86
96
|
|
|
97
|
+
}
|
|
87
98
|
async function getBaseData(){
|
|
88
99
|
console.log("getBaseData")
|
|
89
|
-
const response = await fetchJSONData("
|
|
100
|
+
const response = await fetchJSONData("getBaseData")
|
|
90
101
|
if (response.status!=200){
|
|
91
102
|
throw new Error(`Unable get base data: ${response.statusText} (${response.status}) `)
|
|
92
103
|
}
|
|
@@ -96,7 +107,7 @@ export default (props) => {
|
|
|
96
107
|
}
|
|
97
108
|
async function getProgress(){
|
|
98
109
|
console.log("getProgress")
|
|
99
|
-
const response = await fetchJSONData("
|
|
110
|
+
const response = await fetchJSONData("getProgress")
|
|
100
111
|
if (response.status!=200){
|
|
101
112
|
throw new Error(`Unable get progres: ${response.statusText} (${response.status}) `)
|
|
102
113
|
}
|
|
@@ -107,7 +118,7 @@ export default (props) => {
|
|
|
107
118
|
|
|
108
119
|
function updateSensorData(data){
|
|
109
120
|
console.log("updateSensorData")
|
|
110
|
-
sendJSONData("
|
|
121
|
+
sendJSONData("updateSensorData", data).then((response)=>{
|
|
111
122
|
if (response.status != 200) {
|
|
112
123
|
throw new Error(response.statusText)
|
|
113
124
|
}
|
|
@@ -148,7 +159,7 @@ export default (props) => {
|
|
|
148
159
|
function updateBaseData(data){
|
|
149
160
|
console.log("updateBaseData")
|
|
150
161
|
|
|
151
|
-
sendJSONData("
|
|
162
|
+
sendJSONData("updateBaseData", data).then( (response )=>{
|
|
152
163
|
if (response.status != 200) {
|
|
153
164
|
setError(new Error(`Unable to update base data: ${response.statusText} (${response.status})`))
|
|
154
165
|
} else {
|
|
@@ -166,7 +177,7 @@ export default (props) => {
|
|
|
166
177
|
function refreshSensors(){
|
|
167
178
|
console.log('refreshing sensor map')
|
|
168
179
|
|
|
169
|
-
|
|
180
|
+
getSensors().then((sensors)=>{
|
|
170
181
|
setSensorMap (new Map(sensors.map((sensor)=>[sensor.info.mac,sensor])));
|
|
171
182
|
})
|
|
172
183
|
.catch((e)=>{
|
|
@@ -177,9 +188,17 @@ export default (props) => {
|
|
|
177
188
|
|
|
178
189
|
useEffect(()=>{
|
|
179
190
|
console.log("useEffect([])")
|
|
180
|
-
fetchJSONData("
|
|
191
|
+
fetchJSONData("getPluginState").then( async (response)=> {
|
|
192
|
+
if (response.status==404) {
|
|
193
|
+
setPluginState("unknown")
|
|
194
|
+
throw new Error("unable to get plugin state")
|
|
195
|
+
}
|
|
181
196
|
const json = await response.json()
|
|
182
197
|
setPluginState(json.state)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
_sensorDomains = await getDomains()
|
|
201
|
+
|
|
183
202
|
console.log("Setting up eventsource")
|
|
184
203
|
const eventSource = new EventSource("/plugins/bt-sensors-plugin-sk/sse")
|
|
185
204
|
|
|
@@ -251,10 +270,7 @@ useEffect(()=>{
|
|
|
251
270
|
|
|
252
271
|
},[pluginState])
|
|
253
272
|
|
|
254
|
-
|
|
255
|
-
console.log("useEffect([error])")
|
|
256
|
-
console.log(error)
|
|
257
|
-
},[error])
|
|
273
|
+
|
|
258
274
|
|
|
259
275
|
function confirmDelete(mac){
|
|
260
276
|
const result = window.confirm(`Delete configuration for ${mac}?`)
|
|
@@ -281,29 +297,21 @@ function signalStrengthIcon(sensor){
|
|
|
281
297
|
return <SignalCellular0Bar/>
|
|
282
298
|
|
|
283
299
|
}
|
|
284
|
-
|
|
285
|
-
|
|
300
|
+
function hasConfig(sensor){
|
|
301
|
+
return Object.keys(sensor.config).length>0;
|
|
302
|
+
}
|
|
286
303
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
Array.from(sensorMap.entries()).map((entry) => {
|
|
292
|
-
const sensor = sensorMap.get(entry[0]);
|
|
293
|
-
const config= sensor.config
|
|
294
|
-
const hasConfig = Object.keys(config).length>0;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return <ListGroupItem action
|
|
304
|
+
function createListGroupItem(sensor){
|
|
305
|
+
|
|
306
|
+
const config = hasConfig(sensor)
|
|
307
|
+
return <ListGroupItem action
|
|
298
308
|
onClick={()=>{
|
|
299
|
-
|
|
300
|
-
config.mac_address=entry[0]
|
|
309
|
+
sensor.config.mac_address=sensor.info.mac
|
|
301
310
|
setSchema(sensor.schema)
|
|
302
|
-
setSensorData(config)
|
|
303
|
-
}
|
|
311
|
+
setSensorData(sensor.config)
|
|
304
312
|
}
|
|
305
313
|
}>
|
|
306
|
-
<div class="d-flex justify-content-between align-items-center" style={
|
|
314
|
+
<div class="d-flex justify-content-between align-items-center" style={config?{fontWeight:"normal"}:{fontStyle:"italic"}}>
|
|
307
315
|
{`${sensor._changesMade?"*":""}${sensor.info.name} MAC: ${sensor.info.mac} RSSI: ${ifNullNaN(sensor.info.RSSI)}` }
|
|
308
316
|
<div class="d-flex justify-content-between ">
|
|
309
317
|
{
|
|
@@ -312,9 +320,37 @@ useEffect(()=>{
|
|
|
312
320
|
</div>
|
|
313
321
|
</div>
|
|
314
322
|
</ListGroupItem>
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function configuredDevices(){
|
|
326
|
+
return Array.from(sensorMap.entries()).filter((entry)=>hasConfig(entry[1]))
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function devicesInDomain(domain){
|
|
330
|
+
return Array.from(sensorMap.entries()).filter((entry)=>entry[1].info.domain===domain)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
useEffect(()=>{
|
|
335
|
+
console.log("useEffect([sensorMap])")
|
|
336
|
+
|
|
337
|
+
_sensorMap = sensorMap
|
|
338
|
+
|
|
339
|
+
const _sensorDomains = new Set(sensorMap.entries().map((entry)=>{ return entry[1].info.domain}))
|
|
340
|
+
const sl = {
|
|
341
|
+
_configured: configuredDevices().map((entry) => {
|
|
342
|
+
return createListGroupItem(sensorMap.get(entry[0]))
|
|
343
|
+
})
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
_sensorDomains.forEach((d)=>{
|
|
347
|
+
sl[d]=devicesInDomain(d).map((entry) => {
|
|
348
|
+
return createListGroupItem(sensorMap.get(entry[0]))
|
|
349
|
+
})
|
|
350
|
+
})
|
|
351
|
+
_sensorList=sl
|
|
352
|
+
|
|
353
|
+
|
|
318
354
|
},[sensorMap]
|
|
319
355
|
)
|
|
320
356
|
|
|
@@ -322,18 +358,71 @@ useEffect(()=>{
|
|
|
322
358
|
return value==null? NaN : value
|
|
323
359
|
}
|
|
324
360
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
361
|
+
function getSensorList(domain){
|
|
362
|
+
return _sensorList[domain]
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function getTabs(){
|
|
366
|
+
|
|
367
|
+
return Object.keys(_sensorList).map((domain)=> {return getTab(domain)})
|
|
368
|
+
}
|
|
369
|
+
function getTab(key){
|
|
370
|
+
var title = key.slice(key.charAt(0)==="_"?1:0)
|
|
371
|
+
|
|
372
|
+
return <Tab eventKey={key} title={title.charAt(0).toUpperCase()+title.slice(1) }>
|
|
373
|
+
|
|
374
|
+
<div style={{paddingBottom: 20}} class="d-flex flex-wrap justify-content-start align-items-start">
|
|
375
|
+
<ListGroup style={{ maxHeight: '300px', overflowY: 'auto' }}>
|
|
376
|
+
{getSensorList(key)}
|
|
377
|
+
</ListGroup>
|
|
378
|
+
|
|
379
|
+
<div style= {{ paddingLeft: 10, paddingTop: 10, display: (Object.keys(schema).length==0)? "none" :"" }} >
|
|
380
|
+
|
|
381
|
+
<Form
|
|
382
|
+
schema={schema}
|
|
383
|
+
validator={validator}
|
|
384
|
+
uiSchema={uiSchema}
|
|
385
|
+
onChange={(e) => {
|
|
386
|
+
const s = sensorMap.get(e.formData.mac_address)
|
|
387
|
+
s._changesMade=true
|
|
388
|
+
setSensorData(e.formData)
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
onSubmit={({ formData }, e) => {
|
|
392
|
+
console.log(formData)
|
|
393
|
+
updateSensorData(formData)
|
|
394
|
+
setSchema({})
|
|
395
|
+
alert("Changes saved")
|
|
396
|
+
}}
|
|
397
|
+
onError={log('errors')}
|
|
398
|
+
formData={sensorData}>
|
|
399
|
+
<div>
|
|
400
|
+
<Grid direction="row" style={{spacing:5}}>
|
|
401
|
+
<Button type='submit' color="primary" variant="contained">Save</Button>
|
|
402
|
+
<Button variant="contained" onClick={()=>{undoChanges(sensorData.mac_address)}}>Undo</Button>
|
|
403
|
+
<Button variant="contained" color="secondary" onClick={(e)=>confirmDelete(sensorData.mac_address)}>Delete</Button>
|
|
404
|
+
|
|
405
|
+
</Grid>
|
|
406
|
+
</div>
|
|
407
|
+
</Form>
|
|
408
|
+
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
</Tab>
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (pluginState=="stopped" || pluginState=="unknown")
|
|
415
|
+
return (<h1 >Enable plugin to see configuration (if plugin is Enabled and you're seeing this message, restart SignalK)</h1>)
|
|
328
416
|
else
|
|
329
417
|
return(
|
|
418
|
+
|
|
330
419
|
<div>
|
|
331
|
-
{error?<h2 style="color: red;">{error
|
|
420
|
+
{error?<h2 style="color: red;">{error}</h2>:""}
|
|
332
421
|
<Form
|
|
333
422
|
schema={baseSchema}
|
|
334
423
|
validator={validator}
|
|
335
424
|
onChange={(e) => setBaseData(e.formData)}
|
|
336
|
-
onSubmit={ ({ formData }, e) => {
|
|
425
|
+
onSubmit={ ({ formData }, e) => { updateBaseData(formData); setSchema({}) } }
|
|
337
426
|
onError={log('errors')}
|
|
338
427
|
formData={baseData}
|
|
339
428
|
/>
|
|
@@ -344,46 +433,16 @@ useEffect(()=>{
|
|
|
344
433
|
now={progress.progress}
|
|
345
434
|
/>:""
|
|
346
435
|
}
|
|
347
|
-
<h2>{`${sensorMap.size>0?"Bluetooth Devices
|
|
348
|
-
<h2>{`${sensorMap.size>0?"(*
|
|
436
|
+
<h2>{`${sensorMap.size>0?"Bluetooth Devices - Select to configure" :""}`}</h2>
|
|
437
|
+
<h2>{`${sensorMap.size>0?"(* = sensor has unsaved changes)" :""}`}</h2>
|
|
349
438
|
<p></p>
|
|
350
|
-
<
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
validator={validator}
|
|
358
|
-
uiSchema={uiSchema}
|
|
359
|
-
onChange={(e) => {
|
|
360
|
-
const s = sensorMap.get(e.formData.mac_address)
|
|
361
|
-
s._changesMade=true
|
|
362
|
-
//s.config = e.formData;
|
|
363
|
-
|
|
364
|
-
setSensorData(e.formData)
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
onSubmit={({ formData }, e) => {
|
|
368
|
-
console.log(formData)
|
|
369
|
-
updateSensorData(formData)
|
|
370
|
-
setSchema({})
|
|
371
|
-
alert("Changes saved")
|
|
372
|
-
}}
|
|
373
|
-
onError={log('errors')}
|
|
374
|
-
formData={sensorData}>
|
|
375
|
-
<div>
|
|
376
|
-
<Grid direction="row" style={{spacing:5}}>
|
|
377
|
-
<Button type='submit' color="primary" variant="contained">Save</Button>
|
|
378
|
-
<Button variant="contained" onClick={()=>{undoChanges(sensorData.mac_address)}}>Undo</Button>
|
|
379
|
-
<Button variant="contained" color="secondary" onClick={(e)=>confirmDelete(sensorData.mac_address)}>Delete</Button>
|
|
380
|
-
|
|
381
|
-
</Grid>
|
|
382
|
-
</div>
|
|
383
|
-
</Form>
|
|
384
|
-
|
|
385
|
-
</div>
|
|
386
|
-
</div>
|
|
439
|
+
<Tabs
|
|
440
|
+
defaultActiveKey="_configured"
|
|
441
|
+
id="domain-tabs"
|
|
442
|
+
className="mb-3"
|
|
443
|
+
>
|
|
444
|
+
{getTabs()}
|
|
445
|
+
</Tabs>
|
|
387
446
|
</div>
|
|
388
447
|
)
|
|
389
448
|
|
package/.vscode/launch.json
DELETED