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.
- package/BTSensor.js +77 -38
- package/DistanceManager.js +249 -0
- package/Mixin.js +19 -0
- package/OutOfRangeDevice.js +46 -0
- package/README.md +20 -6
- package/classLoader.js +7 -2
- package/connectUUID.exp +26 -0
- package/index.js +54 -11
- package/package.json +8 -6
- package/public/159.js +1 -1
- package/public/540.js +1 -1
- package/public/681.js +3 -9
- package/public/681.js.LICENSE.txt +2 -0
- package/public/764.js +1 -0
- package/public/images/ATC.jpeg +0 -0
- package/public/images/Aranet4.webp +0 -0
- package/public/images/BP108B.webp +0 -0
- package/public/images/GoveeH5074.jpg +0 -0
- package/public/images/GoveeH5075.webp +0 -0
- package/public/images/GoveeH510x.jpg +0 -0
- package/public/images/InkbirdTH3.webp +0 -0
- package/public/images/JBDBMS.webp +0 -0
- package/public/images/Junctek.webp +0 -0
- package/public/images/KilovaultHLXPlus.jpg +0 -0
- package/public/images/LancolVoltageMeter.webp +0 -0
- package/public/images/LiTimeLiFePo4Battery.avif +0 -0
- package/public/images/MercurySmartcraft.jpg +0 -0
- package/public/images/MopekaTankSensor.jpg +0 -0
- package/public/images/RemoranWave3.jpeg +0 -0
- package/public/images/RenogyInverter.jpg +0 -0
- package/public/images/RenogyRoverClient.jpg +0 -0
- package/public/images/RenogySmartLiFePo4Battery.webp +0 -0
- package/public/images/RuuviTag.jpg +0 -0
- package/public/images/ShellyBLUHT.webp +0 -0
- package/public/images/ShellyBLUMotion.webp +0 -0
- package/public/images/ShellyBluDoorWindow.webp +0 -0
- package/public/images/Skanbatt.jpg +0 -0
- package/public/images/SmartBatteryProtect.webp +0 -0
- package/public/images/SmartBatterySense.webp +0 -0
- package/public/images/SwitchBotMeterPlus.webp +0 -0
- package/public/images/SwitchBotTH.webp +0 -0
- package/public/images/TopbandBattery.webp +0 -0
- package/public/images/Ultrasonic.jpg +0 -0
- package/public/images/VictronBlueSmartACCharger.jpg +0 -0
- package/public/images/VictronBlueSolarMPPT.jpeg +0 -0
- package/public/images/VictronCerboGX.webp +0 -0
- package/public/images/VictronInverterRS.webp +0 -0
- package/public/images/VictronLynxSmartBMS.webp +0 -0
- package/public/images/VictronMultiPlus-II.webp +0 -0
- package/public/images/VictronOrionTrIsolated.webp +0 -0
- package/public/images/VictronOrionTrNonIsolated.webp +0 -0
- package/public/images/VictronPhoenixInverter.webp +0 -0
- package/public/images/VictronPhoenixSmart1600.webp +0 -0
- package/public/images/VictronSmartBatteryProtect.jpg +0 -0
- package/public/images/VictronSmartIP43.webp +0 -0
- package/public/images/VictronSmartLithiumBattery.jpg +0 -0
- package/public/images/VictronSmartSolarMPPT.webp +0 -0
- package/public/images/VictronVEBus.webp +0 -0
- package/public/images/iBeacon.jpg +0 -0
- package/public/main.js +1 -1
- package/public/remoteEntry.js +1 -1
- package/readUUID.exp +23 -0
- package/sensor_classes/ATC.js +3 -2
- package/sensor_classes/Aranet2.js +3 -1
- package/sensor_classes/Aranet4.js +1 -2
- package/sensor_classes/BankManager.js +1 -1
- package/sensor_classes/Beacon/AbstractBeaconMixin.js +85 -0
- package/sensor_classes/Beacon/Eddystone.js +77 -0
- package/sensor_classes/Beacon/iBeacon.js +58 -0
- package/sensor_classes/EctiveBMS.js +270 -0
- package/sensor_classes/FeasyComBeacon.js +68 -0
- package/sensor_classes/GobiusCTankMeter.js +4 -3
- package/sensor_classes/GoveeH5074.js +2 -0
- package/sensor_classes/GoveeH5075.js +2 -0
- package/sensor_classes/GoveeH510x.js +1 -0
- package/sensor_classes/Inkbird.js +1 -0
- package/sensor_classes/JBDBMS.js +1 -0
- package/sensor_classes/Junctek.js +14 -6
- package/sensor_classes/KilovaultHLXPlus.js +1 -0
- package/sensor_classes/LancolVoltageMeter.js +2 -0
- package/sensor_classes/MercurySmartcraft.js +1 -0
- package/sensor_classes/MopekaTankSensor.js +7 -204
- package/sensor_classes/RemoranWave3.js +2 -0
- package/sensor_classes/Renogy/RenogySensor.js +1 -0
- package/sensor_classes/RenogyBattery.js +3 -4
- package/sensor_classes/RenogyInverter.js +3 -6
- package/sensor_classes/RenogyRoverClient.js +3 -0
- package/sensor_classes/RuuviTag.js +11 -8
- package/sensor_classes/ShellySBDW002C.js +3 -1
- package/sensor_classes/ShellySBHT003C.js +7 -0
- package/sensor_classes/ShellySBMO003Z.js +3 -2
- package/sensor_classes/ShenzhenLiOnBMS.js +4 -0
- package/sensor_classes/SwitchBotMeterPlus.js +1 -1
- package/sensor_classes/SwitchBotTH.js +2 -1
- package/sensor_classes/UNKNOWN.js +2 -1
- package/sensor_classes/UltrasonicWindMeter.js +3 -0
- package/sensor_classes/Victron/VictronConstants.js +2 -0
- package/sensor_classes/Victron/VictronIdentifier.js +24 -0
- package/sensor_classes/Victron/VictronSensor.js +59 -49
- package/sensor_classes/VictronACCharger.js +1 -6
- package/sensor_classes/VictronBatteryMonitor.js +37 -26
- package/sensor_classes/VictronDCDCConverter.js +1 -4
- package/sensor_classes/VictronDCEnergyMeter.js +1 -4
- package/sensor_classes/VictronGXDevice.js +1 -4
- package/sensor_classes/VictronInverter.js +2 -3
- package/sensor_classes/VictronInverterRS.js +2 -4
- package/sensor_classes/VictronLynxSmartBMS.js +1 -4
- package/sensor_classes/VictronOrionXS.js +1 -3
- package/sensor_classes/VictronSmartBatteryProtect.js +1 -4
- package/sensor_classes/VictronSmartLithium.js +1 -4
- package/sensor_classes/VictronSolarCharger.js +1 -3
- package/sensor_classes/VictronVEBus.js +1 -4
- package/sensor_classes/XiaomiMiBeacon.js +5 -2
- package/sensor_classes/iBeaconSensor.js +40 -0
- package/src/components/PluginConfigurationPanel.js +134 -173
- package/Screenshot 2025-06-12 at 9.33.57/342/200/257AM.png +0 -0
- package/bt-sensors-plugin-sk copy.json +0 -170
- package/bt-sensors-plugin-sk.json.bak +0 -121
- package/public/847.js +0 -1
- package/sensor_classes/IBeacon.js +0 -45
- package/vsl_patch_17_06_25.patch +0 -13
- /package/public/images/{Aranet2_HOME_F_900x900_90OVA5J.original.webp → Aranet2.webp} +0 -0
- /package/public/images/{Bank Manager All-in-onewc.webp → BankManager.webp} +0 -0
- /package/public/images/{Gobius_C.png → GobiusCTankMeter.png} +0 -0
- /package/public/images/{Victron-SmartShunt.jpg → VictronSmartShunt.jpg} +0 -0
- /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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
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
|
-
|
|
175
|
-
|
|
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
|
-
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
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
|
-
|
|
393
|
+
cd.map((entry) => {
|
|
401
394
|
return createListGroupItem(sensorMap.get(entry[0]))
|
|
402
395
|
})
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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(
|
|
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
|
-
|
|
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)}${
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
|
524
|
-
|
|
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
|
|
Binary file
|
|
@@ -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
|
-
}
|