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
package/BTSensor.js
CHANGED
|
@@ -102,7 +102,14 @@ function preparePath(obj, str) {
|
|
|
102
102
|
class BTSensor extends EventEmitter {
|
|
103
103
|
|
|
104
104
|
static DEFAULTS = require('./plugin_defaults.json');
|
|
105
|
-
|
|
105
|
+
|
|
106
|
+
static SensorDomains={
|
|
107
|
+
unknown: { name: "unknown", description: "Unknown sensor domain "},
|
|
108
|
+
environmental: { name: "environmental", description: "Sensors that measure environmental conditions - air temperature, humidity etc."},
|
|
109
|
+
electrical: { name: "electrical", description: "Electrical sensor - chargers, batteries, inverters etc."},
|
|
110
|
+
tanks: { name: "tanks", description: "Sensors that measure level in tanks (gas, propane, water etc.) "}
|
|
111
|
+
}
|
|
112
|
+
static Domain = this.SensorDomains.unknown
|
|
106
113
|
/**
|
|
107
114
|
*
|
|
108
115
|
* @param {module:node-ble/Device} device
|
|
@@ -404,7 +411,8 @@ class BTSensor extends EventEmitter {
|
|
|
404
411
|
path.type="string"
|
|
405
412
|
|
|
406
413
|
if (!path.pattern)
|
|
407
|
-
path.pattern
|
|
414
|
+
path.pattern=//"^(?:[^{}\\s]*\\{[a-zA-Z0-9]+\\}[^{}\\s]*|[^{}\\s]*)$"
|
|
415
|
+
"^((\\{[a-zA-Z0-9]+\\}|[a-zA-Z0-9]+))(\\.(\\{[a-zA-Z0-9]+\\}|[a-zA-Z0-9]+))*$"
|
|
408
416
|
this._schema.properties.paths.properties[tag]=path
|
|
409
417
|
return this._schema.properties.paths.properties[tag]
|
|
410
418
|
}
|
|
@@ -644,6 +652,10 @@ class BTSensor extends EventEmitter {
|
|
|
644
652
|
return this._state
|
|
645
653
|
}
|
|
646
654
|
|
|
655
|
+
getDomain(){
|
|
656
|
+
return this.constructor.Domain
|
|
657
|
+
}
|
|
658
|
+
|
|
647
659
|
isActive(){
|
|
648
660
|
return this._state=="ACTIVE"
|
|
649
661
|
}
|
package/README.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# Bluetooth Sensors for [Signal K](http://www.signalk.org)
|
|
2
2
|
|
|
3
3
|
## What's New
|
|
4
|
+
## 1.2.0-beta-0.1.1
|
|
5
|
+
|
|
6
|
+
Gobius fix for inclination path, id parameter.
|
|
7
|
+
|
|
8
|
+
## 1.2.0-beta-0.1.0
|
|
9
|
+
|
|
10
|
+
Sensors on config page appear under tabs indicating their domain (Environmental, Electrical etc.)
|
|
11
|
+
|
|
12
|
+
Gobius C tank meter support added.
|
|
13
|
+
|
|
14
|
+
## 1.2.0-beta-0.0.10
|
|
15
|
+
|
|
16
|
+
Better handling of plugin config screen when Disabled
|
|
4
17
|
|
|
5
18
|
## 1.2.0-beta-0.0.9
|
|
6
19
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{
|
|
2
|
+
"configuration": {
|
|
3
|
+
"discoveryTimeout": 30,
|
|
4
|
+
"discoveryInterval": 0,
|
|
5
|
+
"peripherals": [
|
|
6
|
+
{
|
|
7
|
+
"active": true,
|
|
8
|
+
"mac_address": "D4:50:46:39:38:C5",
|
|
9
|
+
"discoveryTimeout": 30,
|
|
10
|
+
"params": {
|
|
11
|
+
"name": "Victron Smart Shunt",
|
|
12
|
+
"encryptionKey": "8cce8529307cf9dd0c85611c4fef42d9"
|
|
13
|
+
},
|
|
14
|
+
"paths": {
|
|
15
|
+
"RSSI": "sensors.smartshunt.rssi",
|
|
16
|
+
"current": "electrical.battery.house.current",
|
|
17
|
+
"power": "electrical.battery.house.power",
|
|
18
|
+
"voltage": "electrical.battery.house.voltage",
|
|
19
|
+
"alarm": "electrical.battery.house.alarm",
|
|
20
|
+
"consumed": "electrical.battery.house.consumedAh",
|
|
21
|
+
"soc": "electrical.battery.house.soc",
|
|
22
|
+
"ttg": "electrical.battery.house.ttg",
|
|
23
|
+
"starterVoltage": "electrical.battery.starter.voltage",
|
|
24
|
+
"__state__": "sensors.smartshunt.state"
|
|
25
|
+
},
|
|
26
|
+
"gattParams": {
|
|
27
|
+
"useGATT": false
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"active": true,
|
|
32
|
+
"mac_address": "F9:B0:6E:63:BC:7E",
|
|
33
|
+
"discoveryTimeout": 30,
|
|
34
|
+
"params": {
|
|
35
|
+
"name": "Ruuvi sensor for cabin"
|
|
36
|
+
},
|
|
37
|
+
"paths": {
|
|
38
|
+
"RSSI": "sensors.ruuviBC7E.rssi",
|
|
39
|
+
"temp": "environment.cabin.temperature",
|
|
40
|
+
"humidity": "environment.cabin.humidity",
|
|
41
|
+
"pressure": "environment.cabin.pressure",
|
|
42
|
+
"battV": "sensors.ruuviBC7E.voltage",
|
|
43
|
+
"mc": "sensors.ruuviBC7E.movementCounter",
|
|
44
|
+
"battery": "sensors.temperature.reefer.batterystrength",
|
|
45
|
+
"__state__": "sensors.ruuviBC7E.state"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"active": true,
|
|
50
|
+
"mac_address": "49:22:05:17:2B:AE",
|
|
51
|
+
"discoveryTimeout": 120,
|
|
52
|
+
"params": {
|
|
53
|
+
"name": "Inkbird temperature sensor"
|
|
54
|
+
},
|
|
55
|
+
"paths": {
|
|
56
|
+
"RSSI": "sensors.inkbird-th2.rssi",
|
|
57
|
+
"temp": "environment.refrigerator.temperature",
|
|
58
|
+
"battery": "sensors.inkbird-th2.battery",
|
|
59
|
+
"__state__": "sensors.inkbird-th2.state"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"active": true,
|
|
64
|
+
"mac_address": "A4:C1:38:9F:F7:7E",
|
|
65
|
+
"discoveryTimeout": 300,
|
|
66
|
+
"params": {
|
|
67
|
+
"name": "ATC Temp/Humidity sensor for Deck",
|
|
68
|
+
"parser": "ATC-LE"
|
|
69
|
+
},
|
|
70
|
+
"paths": {
|
|
71
|
+
"RSSI": "sensors.ATC_9FF77E.rssi",
|
|
72
|
+
"temp": "environment.deck.temperature",
|
|
73
|
+
"humidity": "environment.deck.humidity",
|
|
74
|
+
"voltage": "sensors.ATC_9FF77E.voltage",
|
|
75
|
+
"batteryStrength": "sensors.ATC_9FF77E.batteryStrength",
|
|
76
|
+
"__state__": "sensors.ATC_9FF77E.state"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"active": true,
|
|
81
|
+
"mac_address": "D4:40:59:BE:2A:8C",
|
|
82
|
+
"discoveryTimeout": 30,
|
|
83
|
+
"params": {
|
|
84
|
+
"medium": "PROPANE",
|
|
85
|
+
"tankHeight": "304.8",
|
|
86
|
+
"name": "Galley propane level"
|
|
87
|
+
},
|
|
88
|
+
"paths": {
|
|
89
|
+
"RSSI": "sensors.mopeka-59be8c.rssi",
|
|
90
|
+
"battVolt": "sensors.mopeka-59be8c.battery.voltage",
|
|
91
|
+
"battStrength": "sensors.mopeka-59be8c.battery.strength",
|
|
92
|
+
"temp": "sensors.mopeka-59be8c.temperature",
|
|
93
|
+
"tankLevel": "sensors.mopeka-59be8c.tankLevel",
|
|
94
|
+
"readingQuality": "sensors.mopeka-59be8c.quality",
|
|
95
|
+
"__state__": "sensors.mopeka-59be8c.state"
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"active": true,
|
|
100
|
+
"mac_address": "A4:C1:38:3E:7E:94",
|
|
101
|
+
"discoveryTimeout": 30,
|
|
102
|
+
"params": {
|
|
103
|
+
"encryptionKey": "3985f4ebc032f276cc316f1f6ecea085",
|
|
104
|
+
"__state__": "sensors.xiaomi.state"
|
|
105
|
+
},
|
|
106
|
+
"paths": {
|
|
107
|
+
"RSSI": "sensors.xiaomi.rssi",
|
|
108
|
+
"temp": "sensors.xiaomi.temp",
|
|
109
|
+
"humidity": "sensors.xiaomi.humidity",
|
|
110
|
+
"voltage": "sensors.xiaomi.voltage",
|
|
111
|
+
"__state__": "sensors.xiaomi.state"
|
|
112
|
+
},
|
|
113
|
+
"gattParams": {
|
|
114
|
+
"useGATT": false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
"enabled": true,
|
|
120
|
+
"enableDebug": true
|
|
121
|
+
}
|
package/classLoader.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const semver = require('semver')
|
|
4
|
+
|
|
5
|
+
function loadClasses (dir, ext='.js')
|
|
6
|
+
{
|
|
7
|
+
const classMap = new Map()
|
|
8
|
+
const classFiles = fs.readdirSync(dir)
|
|
9
|
+
.filter(file => file.endsWith(ext));
|
|
10
|
+
|
|
11
|
+
classFiles.forEach(file => {
|
|
12
|
+
const filePath = path.join(dir, file);
|
|
13
|
+
const cls = require(filePath);
|
|
14
|
+
classMap.set(cls.name, cls);
|
|
15
|
+
})
|
|
16
|
+
return classMap
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadClassMap(app) {
|
|
20
|
+
const _classMap = loadClasses(path.join(__dirname, 'sensor_classes'))
|
|
21
|
+
const classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
|
|
22
|
+
const libPath = app.config.appPath +(
|
|
23
|
+
semver.gt(app.config.version,"2.13.5")?"dist":"lib"
|
|
24
|
+
)
|
|
25
|
+
import(libPath+"/modules.js").then( (modulesjs)=>{
|
|
26
|
+
const { default:defaultExport} = modulesjs
|
|
27
|
+
const modules = defaultExport.modulesWithKeyword(app.config, "signalk-bt-sensor-class")
|
|
28
|
+
modules.forEach((module)=>{
|
|
29
|
+
module.metadata.classFiles.forEach((classFile)=>{
|
|
30
|
+
const cls = require(module.location+module.module+"/"+classFile);
|
|
31
|
+
classMap.set(cls.name, cls);
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
classMap.get('UNKNOWN').classMap=new Map([...classMap].sort().filter(([k, v]) => !v.isSystem )) // share the classMap with Unknown for configuration purposes
|
|
35
|
+
})
|
|
36
|
+
return classMap
|
|
37
|
+
}
|
|
38
|
+
module.exports=loadClassMap
|
package/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const util = require('util')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const semver = require('semver')
|
|
5
1
|
const packageInfo = require("./package.json")
|
|
6
2
|
|
|
7
3
|
const {createBluetooth} = require('node-ble')
|
|
@@ -12,10 +8,10 @@ const BTSensor = require('./BTSensor.js')
|
|
|
12
8
|
const BLACKLISTED = require('./sensor_classes/BlackListedDevice.js')
|
|
13
9
|
const { createChannel, createSession } = require("better-sse");
|
|
14
10
|
const { clearTimeout } = require('timers')
|
|
11
|
+
const loadClassMap = require('./classLoader.js')
|
|
15
12
|
|
|
16
13
|
class MissingSensor {
|
|
17
14
|
|
|
18
|
-
|
|
19
15
|
constructor(config){
|
|
20
16
|
this.config=config
|
|
21
17
|
this.addPath=BTSensor.prototype.addPath.bind(this)
|
|
@@ -27,6 +23,7 @@ class MissingSensor {
|
|
|
27
23
|
this.getJSONSchema = BTSensor.prototype.getJSONSchema.bind(this)
|
|
28
24
|
this.initSchema = BTSensor.prototype.initSchema.bind(this)
|
|
29
25
|
|
|
26
|
+
|
|
30
27
|
this.initSchema()
|
|
31
28
|
var keys = Object.keys(config?.paths??{})
|
|
32
29
|
|
|
@@ -62,6 +59,9 @@ class MissingSensor {
|
|
|
62
59
|
getMacAddress(){
|
|
63
60
|
return this.mac_address
|
|
64
61
|
}
|
|
62
|
+
getDomain(){
|
|
63
|
+
return BTSensor.SensorDomains.unknown
|
|
64
|
+
}
|
|
65
65
|
getDescription(){
|
|
66
66
|
return ""
|
|
67
67
|
}
|
|
@@ -88,66 +88,14 @@ class MissingSensor {
|
|
|
88
88
|
|
|
89
89
|
}
|
|
90
90
|
module.exports = function (app) {
|
|
91
|
-
var adapterID = 'hci0'
|
|
92
|
-
|
|
93
|
-
|
|
94
91
|
var deviceConfigs
|
|
95
92
|
var starts=0
|
|
96
|
-
var classMap
|
|
97
|
-
|
|
98
|
-
var utilities_sk
|
|
99
93
|
|
|
100
94
|
var plugin = {};
|
|
101
95
|
plugin.id = 'bt-sensors-plugin-sk';
|
|
102
96
|
plugin.name = 'BT Sensors plugin';
|
|
103
97
|
plugin.description = 'Plugin to communicate with and update paths to BLE Sensors in Signalk';
|
|
104
98
|
|
|
105
|
-
//Try and load utilities-sk NOTE: should be installed from App Store--
|
|
106
|
-
//But there's a fail safe because I'm a reasonable man.
|
|
107
|
-
|
|
108
|
-
utilities_sk = {
|
|
109
|
-
loadClasses: function(dir, ext='.js')
|
|
110
|
-
{
|
|
111
|
-
const classMap = new Map()
|
|
112
|
-
const classFiles = fs.readdirSync(dir)
|
|
113
|
-
.filter(file => file.endsWith(ext));
|
|
114
|
-
|
|
115
|
-
classFiles.forEach(file => {
|
|
116
|
-
const filePath = path.join(dir, file);
|
|
117
|
-
const cls = require(filePath);
|
|
118
|
-
classMap.set(cls.name, cls);
|
|
119
|
-
})
|
|
120
|
-
return classMap
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function sleep(x) {
|
|
125
|
-
return new Promise((resolve) => {
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
resolve(x);
|
|
128
|
-
}, x);
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function loadClassMap() {
|
|
133
|
-
const _classMap = utilities_sk.loadClasses(path.join(__dirname, 'sensor_classes'))
|
|
134
|
-
classMap = new Map([..._classMap].filter(([k, v]) => !k.startsWith("_") ))
|
|
135
|
-
const libPath = app.config.appPath +(
|
|
136
|
-
semver.gt(app.config.version,"2.13.5")?"dist":"lib"
|
|
137
|
-
)
|
|
138
|
-
import(libPath+"/modules.js").then( (modulesjs)=>{
|
|
139
|
-
const { default:defaultExport} = modulesjs
|
|
140
|
-
const modules = defaultExport.modulesWithKeyword(app.config, "signalk-bt-sensor-class")
|
|
141
|
-
modules.forEach((module)=>{
|
|
142
|
-
module.metadata.classFiles.forEach((classFile)=>{
|
|
143
|
-
const cls = require(module.location+module.module+"/"+classFile);
|
|
144
|
-
classMap.set(cls.name, cls);
|
|
145
|
-
})
|
|
146
|
-
})
|
|
147
|
-
classMap.get('UNKNOWN').classMap=new Map([...classMap].sort().filter(([k, v]) => !v.isSystem )) // share the classMap with Unknown for configuration purposes
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
|
|
151
99
|
app.debug(`Loading plugin ${packageInfo.version}`)
|
|
152
100
|
|
|
153
101
|
plugin.schema = {
|
|
@@ -171,17 +119,17 @@ module.exports = function (app) {
|
|
|
171
119
|
}
|
|
172
120
|
}
|
|
173
121
|
|
|
174
|
-
const sensorMap=new Map()
|
|
175
122
|
|
|
176
123
|
plugin.started=false
|
|
177
|
-
|
|
178
|
-
loadClassMap()
|
|
124
|
+
|
|
179
125
|
var discoveryIntervalID, progressID, progressTimeoutID, deviceHealthID
|
|
180
126
|
var adapter
|
|
181
|
-
var adapterPower
|
|
182
127
|
const channel = createChannel()
|
|
128
|
+
const classMap = loadClassMap(app)
|
|
129
|
+
const sensorMap=new Map()
|
|
183
130
|
|
|
184
|
-
|
|
131
|
+
|
|
132
|
+
/* plugin.registerWithRouter = function(router) {
|
|
185
133
|
router.get('/sendPluginState', async (req, res) => {
|
|
186
134
|
|
|
187
135
|
res.status(200).json({
|
|
@@ -193,15 +141,16 @@ module.exports = function (app) {
|
|
|
193
141
|
channel.register(session)
|
|
194
142
|
});
|
|
195
143
|
|
|
196
|
-
}
|
|
144
|
+
}*/
|
|
197
145
|
|
|
198
146
|
plugin.start = async function (options, restartPlugin) {
|
|
199
147
|
plugin.started=true
|
|
200
148
|
var adapterID=options.adapter
|
|
201
149
|
var foundConfiguredDevices=0
|
|
150
|
+
|
|
202
151
|
plugin.registerWithRouter = function(router) {
|
|
203
152
|
|
|
204
|
-
router.post('/
|
|
153
|
+
router.post('/updateSensorData', async (req, res) => {
|
|
205
154
|
app.debug(req.body)
|
|
206
155
|
const i = deviceConfigs.findIndex((p)=>p.mac_address==req.body.mac_address)
|
|
207
156
|
if (i<0){
|
|
@@ -222,13 +171,9 @@ module.exports = function (app) {
|
|
|
222
171
|
const sensor = sensorMap.get(req.body.mac_address)
|
|
223
172
|
if (sensor) {
|
|
224
173
|
removeSensorFromList(sensor)
|
|
225
|
-
if (sensor.isActive())
|
|
226
|
-
sensor.stopListening()
|
|
227
|
-
|
|
228
|
-
)
|
|
229
|
-
} else {
|
|
230
|
-
initConfiguredDevice(req.body)
|
|
231
|
-
}
|
|
174
|
+
if (sensor.isActive())
|
|
175
|
+
await sensor.stopListening()
|
|
176
|
+
initConfiguredDevice(req.body)
|
|
232
177
|
}
|
|
233
178
|
|
|
234
179
|
}
|
|
@@ -244,7 +189,7 @@ module.exports = function (app) {
|
|
|
244
189
|
if (sensorMap.has(req.body.mac_address))
|
|
245
190
|
sensorMap.delete(req.body.mac_address)
|
|
246
191
|
app.savePluginOptions(
|
|
247
|
-
options,
|
|
192
|
+
options, () => {
|
|
248
193
|
app.debug('Plugin options saved')
|
|
249
194
|
res.status(200).json({message: "Sensor updated"})
|
|
250
195
|
channel.broadcast({},"resetSensors")
|
|
@@ -253,7 +198,7 @@ module.exports = function (app) {
|
|
|
253
198
|
|
|
254
199
|
});
|
|
255
200
|
|
|
256
|
-
router.post('/
|
|
201
|
+
router.post('/updateBaseData', async (req, res) => {
|
|
257
202
|
|
|
258
203
|
app.debug(req.body)
|
|
259
204
|
Object.assign(options,req.body)
|
|
@@ -266,9 +211,14 @@ module.exports = function (app) {
|
|
|
266
211
|
}
|
|
267
212
|
)
|
|
268
213
|
});
|
|
214
|
+
router.get('/getDomains', (req, res) => {
|
|
215
|
+
|
|
216
|
+
res.status(200).json(
|
|
217
|
+
BTSensor.SensorDomains
|
|
218
|
+
);
|
|
219
|
+
})
|
|
269
220
|
|
|
270
|
-
|
|
271
|
-
router.get('/base', (req, res) => {
|
|
221
|
+
router.get('/getBaseData', (req, res) => {
|
|
272
222
|
|
|
273
223
|
res.status(200).json(
|
|
274
224
|
{
|
|
@@ -282,13 +232,13 @@ module.exports = function (app) {
|
|
|
282
232
|
}
|
|
283
233
|
);
|
|
284
234
|
})
|
|
285
|
-
router.get('/
|
|
235
|
+
router.get('/getSensors', (req, res) => {
|
|
286
236
|
app.debug("Sending sensors")
|
|
287
237
|
const t = sensorsToJSON()
|
|
288
238
|
res.status(200).json(t)
|
|
289
239
|
});
|
|
290
240
|
|
|
291
|
-
router.get('/
|
|
241
|
+
router.get('/getProgress', (req, res) => {
|
|
292
242
|
app.debug("Sending progress")
|
|
293
243
|
const json = {"progress":foundConfiguredDevices/deviceConfigs.length, "maxTimeout": 1,
|
|
294
244
|
"deviceCount":foundConfiguredDevices,
|
|
@@ -297,7 +247,7 @@ module.exports = function (app) {
|
|
|
297
247
|
|
|
298
248
|
});
|
|
299
249
|
|
|
300
|
-
router.get('/
|
|
250
|
+
router.get('/getPluginState', async (req, res) => {
|
|
301
251
|
|
|
302
252
|
res.status(200).json({
|
|
303
253
|
"state":(plugin.started?"started":"stopped")
|
|
@@ -320,12 +270,12 @@ module.exports = function (app) {
|
|
|
320
270
|
|
|
321
271
|
function getSensorInfo(sensor){
|
|
322
272
|
|
|
323
|
-
const etslc = sensor.elapsedTimeSinceLastContact()
|
|
324
273
|
return { mac: sensor.getMacAddress(),
|
|
325
274
|
name: sensor.getName(),
|
|
275
|
+
domain: sensor.getDomain().name,
|
|
326
276
|
RSSI: sensor.getRSSI(),
|
|
327
277
|
signalStrength: sensor.getSignalStrength(),
|
|
328
|
-
lastContactDelta:
|
|
278
|
+
lastContactDelta: sensor.elapsedTimeSinceLastContact()
|
|
329
279
|
}
|
|
330
280
|
}
|
|
331
281
|
|
|
@@ -335,7 +285,6 @@ module.exports = function (app) {
|
|
|
335
285
|
info: getSensorInfo(sensor),
|
|
336
286
|
schema: sensor.getJSONSchema(),
|
|
337
287
|
config: config?config:{}
|
|
338
|
-
|
|
339
288
|
}
|
|
340
289
|
}
|
|
341
290
|
async function startScanner(transport) {
|
|
@@ -369,7 +318,7 @@ module.exports = function (app) {
|
|
|
369
318
|
channel.broadcast({mac:sensor.getMacAddress()},"removesensor")
|
|
370
319
|
}
|
|
371
320
|
|
|
372
|
-
|
|
321
|
+
function addSensorToList(sensor){
|
|
373
322
|
app.debug(`adding sensor to list ${sensor.getMacAddress()}`)
|
|
374
323
|
if (sensorMap.has(sensor.getMacAddress()) )
|
|
375
324
|
debugger
|
|
@@ -380,7 +329,7 @@ module.exports = function (app) {
|
|
|
380
329
|
return `${config?.name??""}${config.name?" at ":""}${config.mac_address}`
|
|
381
330
|
}
|
|
382
331
|
|
|
383
|
-
|
|
332
|
+
function createSensor(adapter, config) {
|
|
384
333
|
return new Promise( ( resolve, reject )=>{
|
|
385
334
|
var s
|
|
386
335
|
const startNumber=starts
|
|
@@ -390,19 +339,23 @@ module.exports = function (app) {
|
|
|
390
339
|
if (startNumber != starts ) {
|
|
391
340
|
return
|
|
392
341
|
}
|
|
393
|
-
//app.debug(`Found ${config.mac_address}`)
|
|
394
342
|
s = await instantiateSensor(device,config)
|
|
395
|
-
|
|
343
|
+
//app.debug(`Instantiated ${config.mac_address}`)
|
|
344
|
+
|
|
396
345
|
if (s instanceof BLACKLISTED)
|
|
397
346
|
reject ( `Device is blacklisted (${s.reasonForBlacklisting()}).`)
|
|
398
347
|
else{
|
|
348
|
+
//app.debug(`Adding sensor to list ${config.mac_address}`)
|
|
349
|
+
|
|
399
350
|
addSensorToList(s)
|
|
400
351
|
s._lastRSSI=-1*Infinity
|
|
401
352
|
s.on("RSSI",(()=>{
|
|
402
|
-
if (Date.now()-s._lastRSSI > 20000) { //only update RSSI on client every
|
|
353
|
+
if (Date.now()-s._lastRSSI > 20000) { //only update RSSI on client every 20 seconds
|
|
403
354
|
//app.debug(`${s.getMacAddress()} ${Date.now()-s._lastRSSI}`)
|
|
404
355
|
s._lastRSSI=Date.now()
|
|
356
|
+
|
|
405
357
|
updateSensor(s)
|
|
358
|
+
//app.debug(`Updated Sensor ${config.mac_address}`)
|
|
406
359
|
}
|
|
407
360
|
|
|
408
361
|
}))
|
|
@@ -531,14 +484,15 @@ module.exports = function (app) {
|
|
|
531
484
|
setInterval( findDevices, discoveryInterval*1000, discoveryTimeout)
|
|
532
485
|
}
|
|
533
486
|
|
|
534
|
-
|
|
487
|
+
channel.broadcast({state:"started"},"pluginstate")
|
|
488
|
+
|
|
489
|
+
|
|
535
490
|
if (!adapterID || adapterID=="")
|
|
536
491
|
adapterID = "hci0"
|
|
537
492
|
//Check if Adapter has changed since last start()
|
|
538
493
|
if (adapter) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
adapter.helper.removeAllListeners()
|
|
494
|
+
if (adapter.adapter!=adapterID) {
|
|
495
|
+
adapter.helper._propsProxy.removeAllListeners()
|
|
542
496
|
adapter=null
|
|
543
497
|
}
|
|
544
498
|
}
|
|
@@ -568,12 +522,10 @@ module.exports = function (app) {
|
|
|
568
522
|
if (!await adapter.isPowered()) {
|
|
569
523
|
app.debug(`Bluetooth Adapter ${adapterID} not powered on.`)
|
|
570
524
|
app.setPluginError(`Bluetooth Adapter ${adapterID} not powered on.`)
|
|
571
|
-
adapterPower=false
|
|
572
525
|
await plugin.stop()
|
|
573
526
|
return
|
|
574
527
|
}
|
|
575
528
|
}
|
|
576
|
-
adapterPower=true
|
|
577
529
|
|
|
578
530
|
sensorMap.clear()
|
|
579
531
|
if (channel)
|
|
@@ -581,9 +533,6 @@ module.exports = function (app) {
|
|
|
581
533
|
deviceConfigs=options?.peripherals??[]
|
|
582
534
|
|
|
583
535
|
if (plugin.stopped) {
|
|
584
|
-
//await sleep(5000) //Make sure plugin.stop() completes first
|
|
585
|
-
//plugin.start is called asynchronously for some reason
|
|
586
|
-
//and does not wait for plugin.stop to complete
|
|
587
536
|
plugin.stopped=false
|
|
588
537
|
}
|
|
589
538
|
|
|
@@ -646,7 +595,7 @@ module.exports = function (app) {
|
|
|
646
595
|
const dt = config?.discoveryTimeout??options.discoveryTimeout
|
|
647
596
|
const lc=sensor.elapsedTimeSinceLastContact()
|
|
648
597
|
if (lc > dt) {
|
|
649
|
-
app.debug(`${sensor.getMacAddress()} not heard from in ${lc} seconds`)
|
|
598
|
+
//app.debug(`${sensor.getMacAddress()} not heard from in ${lc} seconds`)
|
|
650
599
|
channel.broadcast(getSensorInfo(sensor), "sensorchanged")
|
|
651
600
|
}
|
|
652
601
|
})
|
|
@@ -689,17 +638,20 @@ module.exports = function (app) {
|
|
|
689
638
|
}
|
|
690
639
|
}
|
|
691
640
|
sensorMap.clear()
|
|
692
|
-
|
|
641
|
+
|
|
642
|
+
if (adapter) {
|
|
643
|
+
adapter.helper._propsProxy.removeAllListeners()
|
|
644
|
+
if( await adapter.isDiscovering())
|
|
693
645
|
try{
|
|
694
646
|
await adapter.stopDiscovery()
|
|
695
647
|
app.debug('Scan stopped')
|
|
696
648
|
} catch (e){
|
|
697
649
|
app.debug(`Error stopping scan: ${e.message}`)
|
|
698
650
|
}
|
|
699
|
-
|
|
651
|
+
}
|
|
700
652
|
app.debug('BT Sensors plugin stopped')
|
|
701
653
|
|
|
702
654
|
}
|
|
703
655
|
|
|
704
656
|
return plugin;
|
|
705
|
-
}
|
|
657
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bt-sensors-plugin-sk",
|
|
3
|
-
"version": "1.2.0-beta.0.
|
|
3
|
+
"version": "1.2.0-beta.0.1.1",
|
|
4
4
|
"description": "Bluetooth Sensors for Signalk -- support for Victron devices, RuuviTag, Xiaomi, ATC and Inkbird, Ultrasonic wind meters, Mopeka tank readers, Renogy Battery and Solar Controllers, Aranet4 environment sensors, SwitchBot temp and humidity sensors, KilovaultHLXPlus smart batteries, and Govee GVH51xx temp sensors",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"better-sse": "^0.14.1",
|
|
11
11
|
"dbus-next": "^0.10.2",
|
|
12
12
|
"int24": "^0.0.1",
|
|
13
|
-
"kaitai-struct": "^0.10.0",
|
|
13
|
+
"kaitai-struct": "^0.10.0",
|
|
14
14
|
"node-ble": "^1.13.0",
|
|
15
15
|
"semver": "^7.7.1"
|
|
16
16
|
},
|
package/public/159.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
"use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[159,540],{5228:e=>{var r=Object.getOwnPropertySymbols,t=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var r={},t=0;t<10;t++)r["_"+String.fromCharCode(t)]=t;if("0123456789"!==Object.getOwnPropertyNames(r).map((function(e){return r[e]})).join(""))return!1;var n={};return"abcdefghijklmnopqrst".split("").forEach((function(e){n[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},n)).join("")}catch(e){return!1}}()?Object.assign:function(e,o){for(var u,c,f=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l<arguments.length;l++){for(var i in u=Object(arguments[l]))t.call(u,i)&&(f[i]=u[i]);if(r){c=r(u);for(var a=0;a<c.length;a++)n.call(u,c[a])&&(f[c[a]]=u[c[a]])}}return f}},5287:(e,r,t)=>{var n=t(5228),o="function"==typeof Symbol&&Symbol.for,u=o?Symbol.for("react.element"):60103,c=o?Symbol.for("react.portal"):60106,f=o?Symbol.for("react.fragment"):60107,l=o?Symbol.for("react.strict_mode"):60108,i=o?Symbol.for("react.profiler"):60114,a=o?Symbol.for("react.provider"):60109,s=o?Symbol.for("react.context"):60110,p=o?Symbol.for("react.forward_ref"):60112,y=o?Symbol.for("react.suspense"):60113,d=o?Symbol.for("react.memo"):60115,h=o?Symbol.for("react.lazy"):60116,b="function"==typeof Symbol&&Symbol.iterator;function v(e){for(var r="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t<arguments.length;t++)r+="&args[]="+encodeURIComponent(arguments[t]);return"Minified React error #"+e+"; visit "+r+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},_={};function g(e,r,t){this.props=e,this.context=r,this.refs=_,this.updater=t||m}function S(){}function k(e,r,t){this.props=e,this.context=r,this.refs=_,this.updater=t||m}g.prototype.isReactComponent={},g.prototype.setState=function(e,r){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(v(85));this.updater.enqueueSetState(this,e,r,"setState")},g.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},S.prototype=g.prototype;var w=k.prototype=new S;w.constructor=k,n(w,g.prototype),w.isPureReactComponent=!0;var j={current:null},O=Object.prototype.hasOwnProperty,C={key:!0,ref:!0,__self:!0,__source:!0};function $(e,r,t){var n,o={},c=null,f=null;if(null!=r)for(n in void 0!==r.ref&&(f=r.ref),void 0!==r.key&&(c=""+r.key),r)O.call(r,n)&&!C.hasOwnProperty(n)&&(o[n]=r[n]);var l=arguments.length-2;if(1===l)o.children=t;else if(1<l){for(var i=Array(l),a=0;a<l;a++)i[a]=arguments[a+2];o.children=i}if(e&&e.defaultProps)for(n in l=e.defaultProps)void 0===o[n]&&(o[n]=l[n]);return{$$typeof:u,type:e,key:c,ref:f,props:o,_owner:j.current}}function E(e){return"object"==typeof e&&null!==e&&e.$$typeof===u}var P=/\/+/g,x=[];function R(e,r,t,n){if(x.length){var o=x.pop();return o.result=e,o.keyPrefix=r,o.func=t,o.context=n,o.count=0,o}return{result:e,keyPrefix:r,func:t,context:n,count:0}}function A(e){e.result=null,e.keyPrefix=null,e.func=null,e.context=null,e.count=0,10>x.length&&x.push(e)}function I(e,r,t,n){var o=typeof e;"undefined"!==o&&"boolean"!==o||(e=null);var f=!1;if(null===e)f=!0;else switch(o){case"string":case"number":f=!0;break;case"object":switch(e.$$typeof){case u:case c:f=!0}}if(f)return t(n,e,""===r?"."+U(e,0):r),1;if(f=0,r=""===r?".":r+":",Array.isArray(e))for(var l=0;l<e.length;l++){var i=r+U(o=e[l],l);f+=I(o,i,t,n)}else if("function"==typeof(i=null===e||"object"!=typeof e?null:"function"==typeof(i=b&&e[b]||e["@@iterator"])?i:null))for(e=i.call(e),l=0;!(o=e.next()).done;)f+=I(o=o.value,i=r+U(o,l++),t,n);else if("object"===o)throw t=""+e,Error(v(31,"[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t,""));return f}function q(e,r,t){return null==e?0:I(e,"",r,t)}function U(e,r){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var r={"=":"=0",":":"=2"};return"$"+(""+e).replace(/[=:]/g,(function(e){return r[e]}))}(e.key):r.toString(36)}function F(e,r){e.func.call(e.context,r,e.count++)}function L(e,r,t){var n=e.result,o=e.keyPrefix;e=e.func.call(e.context,r,e.count++),Array.isArray(e)?M(e,n,t,(function(e){return e})):null!=e&&(E(e)&&(e=function(e,r){return{$$typeof:u,type:e.type,key:r,ref:e.ref,props:e.props,_owner:e._owner}}(e,o+(!e.key||r&&r.key===e.key?"":(""+e.key).replace(P,"$&/")+"/")+t)),n.push(e))}function M(e,r,t,n,o){var u="";null!=t&&(u=(""+t).replace(P,"$&/")+"/"),q(e,L,r=R(r,u,n,o)),A(r)}var N={current:null};function D(){var e=N.current;if(null===e)throw Error(v(321));return e}var T={ReactCurrentDispatcher:N,ReactCurrentBatchConfig:{suspense:null},ReactCurrentOwner:j,IsSomeRendererActing:{current:!1},assign:n};r.Children={map:function(e,r,t){if(null==e)return e;var n=[];return M(e,n,null,r,t),n},forEach:function(e,r,t){if(null==e)return e;q(e,F,r=R(null,null,r,t)),A(r)},count:function(e){return q(e,(function(){return null}),null)},toArray:function(e){var r=[];return M(e,r,null,(function(e){return e})),r},only:function(e){if(!E(e))throw Error(v(143));return e}},r.Component=g,r.Fragment=f,r.Profiler=i,r.PureComponent=k,r.StrictMode=l,r.Suspense=y,r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=T,r.cloneElement=function(e,r,t){if(null==e)throw Error(v(267,e));var o=n({},e.props),c=e.key,f=e.ref,l=e._owner;if(null!=r){if(void 0!==r.ref&&(f=r.ref,l=j.current),void 0!==r.key&&(c=""+r.key),e.type&&e.type.defaultProps)var i=e.type.defaultProps;for(a in r)O.call(r,a)&&!C.hasOwnProperty(a)&&(o[a]=void 0===r[a]&&void 0!==i?i[a]:r[a])}var a=arguments.length-2;if(1===a)o.children=t;else if(1<a){i=Array(a);for(var s=0;s<a;s++)i[s]=arguments[s+2];o.children=i}return{$$typeof:u,type:e.type,key:c,ref:f,props:o,_owner:l}},r.createContext=function(e,r){return void 0===r&&(r=null),(e={$$typeof:s,_calculateChangedBits:r,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null}).Provider={$$typeof:a,_context:e},e.Consumer=e},r.createElement=$,r.createFactory=function(e){var r=$.bind(null,e);return r.type=e,r},r.createRef=function(){return{current:null}},r.forwardRef=function(e){return{$$typeof:p,render:e}},r.isValidElement=E,r.lazy=function(e){return{$$typeof:h,_ctor:e,_status:-1,_result:null}},r.memo=function(e,r){return{$$typeof:d,type:e,compare:void 0===r?null:r}},r.useCallback=function(e,r){return D().useCallback(e,r)},r.useContext=function(e,r){return D().useContext(e,r)},r.useDebugValue=function(){},r.useEffect=function(e,r){return D().useEffect(e,r)},r.useImperativeHandle=function(e,r,t){return D().useImperativeHandle(e,r,t)},r.useLayoutEffect=function(e,r){return D().useLayoutEffect(e,r)},r.useMemo=function(e,r){return D().useMemo(e,r)},r.useReducer=function(e,r,t){return D().useReducer(e,r,t)},r.useRef=function(e){return D().useRef(e)},r.useState=function(e){return D().useState(e)},r.version="16.14.0"},6540:(e,r,t)=>{e.exports=t(5287)}}]);
|
|
1
|
+
"use strict";(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[159],{62995:(e,t,n)=>{n.r(t),n.d(t,{default:()=>A});var a=n(73490),s=n(74810),o=n(86528),r=n.n(o),l=n(27606),c=n(86452),i=n(3768),u=n(71431),g=n(39676),d=n(47041),m=n(86038),f=n(95027),p=n(43540),h=n(24712),E=n(75056),w=n(96890),S=n(23399);const v=e=>console.log.bind(console,e);var y,b={};const A=e=>{const[t,n]=(0,o.useState)({}),[A,D]=(0,o.useState)({}),[$,_]=(0,o.useState)({}),[k,x]=(0,o.useState)({"ui:submitButtonOptions":{props:{disabled:!1,className:"btn btn-info"},norender:!0,submitText:"Submit"}}),[C,T]=(0,o.useState)([]),[j,M]=(0,o.useState)(),[O,N]=(0,o.useState)(new Map),[B,U]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[J,L]=(0,o.useState)("unknown"),[P,K]=(0,o.useState)();function z(e,t){console.log(`sending ${e}`),console.log(t);const n=new Headers;return n.append("Content-Type","application/json"),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include",method:"POST",body:JSON.stringify(t),headers:n})}async function H(e){return console.log(`fetching ${e}`),fetch(`/plugins/bt-sensors-plugin-sk/${e}`,{credentials:"include"})}async function I(){console.log("getProgress");const e=await H("getProgress");if(200!=e.status)throw new Error(`Unable get progres: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}function R(){console.log("refreshing sensor map"),async function(){console.log("getSensors");const e=await H("getSensors");if(200!=e.status)throw new Error(`Unable get sensor data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{N(new Map(e.map((e=>[e.info.mac,e]))))})).catch((e=>{K(e)}))}function W(e){return Object.keys(e.config).length>0}function Y(e){const t=W(e);return r().createElement(w.A,{action:!0,onClick:()=>{e.config.mac_address=e.info.mac,_(e.schema),M(e.config)}},r().createElement("div",{class:"d-flex justify-content-between align-items-center",style:t?{fontWeight:"normal"}:{fontStyle:"italic"}},`${e._changesMade?"*":""}${e.info.name} MAC: ${e.info.mac} RSSI: ${n=e.info.RSSI,null==n?NaN:n}`,r().createElement("div",{class:"d-flex justify-content-between "},function(e){return null==e.info.lastContactDelta||e.info.lastContactDelta>e.config.discoveryTimeout?r().createElement(i.A,null):e.info.signalStrength>80?r().createElement(u.A,null):e.info.signalStrength>60?r().createElement(g.A,null):e.info.signalStrength>40?r().createElement(d.A,null):e.info.signalStrength>20?r().createElement(m.A,null):r().createElement(f.A,null)}(e))));var n}return(0,o.useEffect)((()=>{console.log("useEffect([])"),H("getPluginState").then((async e=>{if(404==e.status)throw L("unknown"),new Error("unable to get plugin state");const t=await e.json();L(t.state),await async function(){console.log("getDomains");const e=await H("getDomains");if(200!=e.status)throw new Error(`Unable get domain data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}(),console.log("Setting up eventsource");const n=new EventSource("/plugins/bt-sensors-plugin-sk/sse");return n.addEventListener("newsensor",(e=>{console.log("newsensor");let t=JSON.parse(e.data);y.has(t.info.mac)||(console.log(`New sensor: ${t.info.mac}`),N(new Map(y.set(t.info.mac,t))))})),n.addEventListener("sensorchanged",(e=>{let t=JSON.parse(e.data);if(console.log("sensorchanged"),console.log(t),y.has(t.mac)){let e=y.get(t.mac);Object.assign(e.info,t),N(new Map(y))}})),n.addEventListener("progress",(e=>{console.log("progress");const t=JSON.parse(e.data);U(t),console.log(t)})),n.addEventListener("pluginstate",(e=>{console.log("pluginstate");const t=JSON.parse(e.data);L(t.state)})),()=>n.close()})).catch((e=>{K(e)}))}),[]),(0,o.useEffect)((()=>{console.log("useEffect([pluginState])"),"started"==J?(R(),async function(){console.log("getBaseData");const e=await H("getBaseData");if(200!=e.status)throw new Error(`Unable get base data: ${e.statusText} (${e.status}) `);const t=await e.json();return console.log(t),t}().then((e=>{n(e.schema),D(e.data)})).catch((e=>{K(e)})),I().then((e=>{U(e)})).catch((e=>{K(e)}))):(N(new Map),n({}),D({}))}),[J]),(0,o.useEffect)((()=>{console.log("useEffect([sensorMap])"),y=O;const e=new Set(O.entries().map((e=>e[1].info.domain))),t={_configured:Array.from(O.entries()).filter((e=>W(e[1]))).map((e=>Y(O.get(e[0]))))};e.forEach((e=>{var n;t[e]=(n=e,Array.from(O.entries()).filter((e=>e[1].info.domain===n))).map((e=>Y(O.get(e[0]))))})),b=t}),[O]),"stopped"==J||"unknown"==J?r().createElement("h1",null,"Enable plugin to see configuration (if plugin is Enabled and you're seeing this message, restart SignalK)"):r().createElement("div",null,P?r().createElement("h2",{style:"color: red;"},P):"",r().createElement(a.Ay,{schema:t,validator:s.Ay,onChange:e=>D(e.formData),onSubmit:({formData:e},t)=>{var n;n=e,console.log("updateBaseData"),z("updateBaseData",n).then((e=>{200!=e.status?K(new Error(`Unable to update base data: ${e.statusText} (${e.status})`)):(I().then((e=>{U(e)})).catch((e=>{K(e)})),R())})),_({})},onError:v("errors"),formData:A}),r().createElement("p",null),r().createElement("p",null),B.deviceCount<B.totalDevices?r().createElement(S.A,{max:B.maxTimeout,now:B.progress}):"",r().createElement("h2",null,O.size>0?"Bluetooth Devices - Select to configure":""),r().createElement("h2",null,O.size>0?"(* = sensor has unsaved changes)":""),r().createElement("p",null),r().createElement(h.A,{defaultActiveKey:"_configured",id:"domain-tabs",className:"mb-3"},Object.keys(b).map((e=>{return n=(t=e).slice("_"===t.charAt(0)?1:0),r().createElement(E.A,{eventKey:t,title:n.charAt(0).toUpperCase()+n.slice(1)},r().createElement("div",{style:{paddingBottom:20},class:"d-flex flex-wrap justify-content-start align-items-start"},r().createElement(p.A,{style:{maxHeight:"300px",overflowY:"auto"}},function(e){return b[e]}(t)),r().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys($).length?"none":""}},r().createElement(a.Ay,{schema:$,validator:s.Ay,uiSchema:k,onChange:e=>{O.get(e.formData.mac_address)._changesMade=!0,M(e.formData)},onSubmit:({formData:e},t)=>{var n;console.log(e),n=e,console.log("updateSensorData"),z("updateSensorData",n).then((e=>{if(200!=e.status)throw new Error(e.statusText);O.get(n.mac_address)._changesMade=!1,O.get(n.mac_address).config=n})),_({}),alert("Changes saved")},onError:v("errors"),formData:j},r().createElement("div",null,r().createElement(l.A,{direction:"row",style:{spacing:5}},r().createElement(c.A,{type:"submit",color:"primary",variant:"contained"},"Save"),r().createElement(c.A,{variant:"contained",onClick:()=>{var e;e=j.mac_address,console.log("undoChanges"),O.get(e)._changesMade=!1,M(O.get(e).config)}},"Undo"),r().createElement(c.A,{variant:"contained",color:"secondary",onClick:e=>{return t=j.mac_address,void(window.confirm(`Delete configuration for ${t}?`)&&function(e){console.log("removeSensorData");try{z("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),y.delete(e),N(new Map(y)),_({})}catch{}}(t));var t}},"Delete")))))));var t,n}))))}}}]);
|