bt-sensors-plugin-sk 1.3.4 → 1.3.6-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 +108 -10
- package/README.md +12 -0
- package/development/TestData/Jikong.json +14 -0
- package/diff.txt +1 -1
- package/index.js +28 -8
- package/package.json +7 -6
- package/plugin_defaults.json +14 -1
- package/public/143.js +1 -0
- package/public/{998.js → 834.js} +5 -5
- package/public/images/Mikrotik-TG-BT5-OUT.png +0 -0
- package/public/remoteEntry.js +1 -1
- package/sensor_classes/Aranet/AranetSensor.js +1 -0
- package/sensor_classes/Aranet2.js +1 -1
- package/sensor_classes/BTHome/AbstractBTHomeSensor.js +1 -0
- package/sensor_classes/Beacon/AbstractBeaconMixin.js +45 -6
- package/sensor_classes/FeasyComBeacon.js +11 -0
- package/sensor_classes/Govee/GoveeSensor.js +1 -0
- package/sensor_classes/Inkbird.js +1 -0
- package/sensor_classes/JBDBMS.js +14 -0
- package/sensor_classes/JikongBMS.js +3 -2
- package/sensor_classes/MikrotikTag.js +83 -0
- package/sensor_classes/MopekaTankSensor.js +2 -0
- package/sensor_classes/ShellySBMO003Z.js +1 -1
- package/sensor_classes/SwitchBotMeterPlus.js +1 -0
- package/sensor_classes/SwitchBotTH.js +1 -1
- package/sensor_classes/XiaomiMiBeacon.js +1 -0
- package/src/components/PluginConfigurationPanel.js +47 -7
- package/public/847.js +0 -1
- package/sensor_classes/TestData/Jikong.json +0 -36
- /package/public/{998.js.LICENSE.txt → 834.js.LICENSE.txt} +0 -0
package/BTSensor.js
CHANGED
|
@@ -87,7 +87,11 @@ class BTSensor extends EventEmitter {
|
|
|
87
87
|
tanks: { name: "tanks", description: "Sensors that measure level in tanks (gas, propane, water etc.) "},
|
|
88
88
|
beacons: { name: "beacons", description: "iBeacon/Eddystone sensor tags"}
|
|
89
89
|
}
|
|
90
|
+
static batteryStrengthTag="batteryStrength"
|
|
91
|
+
|
|
90
92
|
static Domain = this.SensorDomains.unknown
|
|
93
|
+
|
|
94
|
+
_currentValues = {}
|
|
91
95
|
/**
|
|
92
96
|
*
|
|
93
97
|
* @param {module:node-ble/Device} device
|
|
@@ -315,11 +319,17 @@ class BTSensor extends EventEmitter {
|
|
|
315
319
|
type: "integer", default:30,
|
|
316
320
|
minimum: 10,
|
|
317
321
|
maximum: 600 },
|
|
318
|
-
|
|
322
|
+
|
|
319
323
|
params:{
|
|
320
324
|
title:`Device parameters`,
|
|
321
325
|
type:"object",
|
|
322
|
-
properties:{
|
|
326
|
+
properties:{
|
|
327
|
+
noContactThreshold: {title: "If no contact (in seconds), raise warning. Set to 0 to disable",
|
|
328
|
+
type: "integer",
|
|
329
|
+
minimum: 0,
|
|
330
|
+
maximum: 600,
|
|
331
|
+
default: 2*(this?.discoveryTimeout??30) },
|
|
332
|
+
}
|
|
323
333
|
},
|
|
324
334
|
paths:{
|
|
325
335
|
title:"Signalk Paths",
|
|
@@ -955,6 +965,19 @@ class BTSensor extends EventEmitter {
|
|
|
955
965
|
throw new Error("Subclass must implement ::emitGATT function")
|
|
956
966
|
}
|
|
957
967
|
|
|
968
|
+
getCurrentValue(tag){
|
|
969
|
+
return this._currentValues[tag]
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
setCurrentValue(tag,value){
|
|
973
|
+
this._currentValues[tag]=value
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
emit(tag, value){
|
|
977
|
+
super.emit(tag, value)
|
|
978
|
+
this.setCurrentValue(tag,value)
|
|
979
|
+
}
|
|
980
|
+
|
|
958
981
|
emitData(tag, buffer, ...args){
|
|
959
982
|
const md = this.getPath(tag)
|
|
960
983
|
if (md && md.read)
|
|
@@ -1048,7 +1071,7 @@ class BTSensor extends EventEmitter {
|
|
|
1048
1071
|
this._app.handleMessage(id,
|
|
1049
1072
|
{
|
|
1050
1073
|
updates:
|
|
1051
|
-
[{ meta: [{path: this.preparePath(path), value: { units: pathMeta?.unit }}]}]
|
|
1074
|
+
[{ meta: [{path: this.preparePath(path), value: { units: pathMeta?.unit, zones:pathMeta?.zones } }]}]
|
|
1052
1075
|
})
|
|
1053
1076
|
}
|
|
1054
1077
|
})
|
|
@@ -1062,11 +1085,7 @@ class BTSensor extends EventEmitter {
|
|
|
1062
1085
|
if (!(path === undefined)) {
|
|
1063
1086
|
let preparedPath = this.preparePath(path)
|
|
1064
1087
|
this.on(tag, (val)=>{
|
|
1065
|
-
|
|
1066
|
-
this._app.notify(tag, val, id )
|
|
1067
|
-
} else {*/
|
|
1068
|
-
this.updatePath(preparedPath,val, id, source)
|
|
1069
|
-
//}
|
|
1088
|
+
this.updatePath(preparedPath,val, id, source)
|
|
1070
1089
|
})
|
|
1071
1090
|
}
|
|
1072
1091
|
})
|
|
@@ -1075,7 +1094,10 @@ class BTSensor extends EventEmitter {
|
|
|
1075
1094
|
this._app.handleMessage(id, {updates: [ { $source: source, values: [ { path: path, value: val }] } ] })
|
|
1076
1095
|
}
|
|
1077
1096
|
elapsedTimeSinceLastContact(){
|
|
1078
|
-
|
|
1097
|
+
if (this.device instanceof OutOfRangeDevice)
|
|
1098
|
+
return Infinity
|
|
1099
|
+
else
|
|
1100
|
+
return (Date.now()-this?._lastContact??Date.now())/1000
|
|
1079
1101
|
}
|
|
1080
1102
|
|
|
1081
1103
|
prepareConfig(config){
|
|
@@ -1116,7 +1138,83 @@ class BTSensor extends EventEmitter {
|
|
|
1116
1138
|
return resultString || str; // Return original string if no replacements were made
|
|
1117
1139
|
}
|
|
1118
1140
|
|
|
1141
|
+
notifyUnableToCommunicate(){
|
|
1142
|
+
this._app.handleMessage('bt-sensors-plugin-sk',
|
|
1143
|
+
{
|
|
1144
|
+
updates: [{
|
|
1145
|
+
$source: this.getName(),
|
|
1146
|
+
timestamp: (new Date()).toISOString(),
|
|
1147
|
+
values: [{
|
|
1148
|
+
path: `notifications.sensors.${this.macAndName()}`,
|
|
1149
|
+
value: {
|
|
1150
|
+
state: "warn",
|
|
1151
|
+
message: "Unable to communicate with sensor",
|
|
1152
|
+
method: ["visual", "sound"]
|
|
1153
|
+
}
|
|
1154
|
+
}]
|
|
1155
|
+
}]
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
clearUnableToCommunicate(){
|
|
1162
|
+
this._app.handleMessage('bt-sensors-plugin-sk',
|
|
1163
|
+
{
|
|
1164
|
+
updates: [{
|
|
1165
|
+
$source: this.getName(),
|
|
1166
|
+
timestamp: (new Date()).toISOString(),
|
|
1167
|
+
values: [{
|
|
1168
|
+
path: `notifications.sensors.${this.macAndName()}`,
|
|
1169
|
+
value: null
|
|
1170
|
+
}]
|
|
1171
|
+
}]
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
notifyNoContact(){
|
|
1177
|
+
this._app.handleMessage('bt-sensors-plugin-sk',
|
|
1178
|
+
{
|
|
1179
|
+
updates: [{
|
|
1180
|
+
$source: this.getName(),
|
|
1181
|
+
timestamp: (new Date()).toISOString(),
|
|
1182
|
+
values: [{
|
|
1183
|
+
path: `notifications.sensors.${this.macAndName()}`,
|
|
1184
|
+
value: {
|
|
1185
|
+
state: "warn",
|
|
1186
|
+
message: `No contact with sensor for ${this.elapsedTimeSinceLastContact()} seconds`,
|
|
1187
|
+
method: ["visual", "sound"]
|
|
1188
|
+
}
|
|
1189
|
+
}]
|
|
1190
|
+
}]
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
clearNoContact(){
|
|
1196
|
+
this._app.handleMessage('bt-sensors-plugin-sk',
|
|
1197
|
+
{
|
|
1198
|
+
updates: [{
|
|
1199
|
+
$source: this.getName(),
|
|
1200
|
+
timestamp: (new Date()).toISOString(),
|
|
1201
|
+
values: [{
|
|
1202
|
+
path: `notifications.sensors.${this.macAndName()}`,
|
|
1203
|
+
value: {
|
|
1204
|
+
state: "normal",
|
|
1205
|
+
message: `Communication with sensor normal`,
|
|
1206
|
+
method: []
|
|
1207
|
+
}
|
|
1208
|
+
}]
|
|
1209
|
+
}]
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
);
|
|
1213
|
+
}
|
|
1119
1214
|
|
|
1215
|
+
getBatteryStrength(){
|
|
1216
|
+
return this.getCurrentValue(this.constructor.batteryStrengthTag)
|
|
1217
|
+
}
|
|
1120
1218
|
}
|
|
1121
1219
|
|
|
1122
|
-
module.exports = BTSensor
|
|
1220
|
+
module.exports = BTSensor
|
package/README.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## WHAT'S NEW
|
|
4
4
|
|
|
5
|
+
# Version 1.3.6
|
|
6
|
+
|
|
7
|
+
- New sensor parameter: no contact threshhold.
|
|
8
|
+
- Notification if no contact threshhold exceeded for sensor
|
|
9
|
+
- Smaller install footprint (moved rjsf dependencies to dev)
|
|
10
|
+
|
|
11
|
+
# Version 1.3.5
|
|
12
|
+
|
|
13
|
+
- Battery strength notification for supported sensors
|
|
14
|
+
- Battery strength value/icon displayed on config page
|
|
15
|
+
- MicrotikTag TG-BT5 environment sensor support
|
|
5
16
|
|
|
6
17
|
# Version 1.3.4
|
|
7
18
|
|
|
@@ -157,6 +168,7 @@ It's pretty easy to write and deploy your own sensor class for any currently uns
|
|
|
157
168
|
|[BTHome](https://bthome.io/)| NOTE: Framework for IOT sensor devices. |
|
|
158
169
|
|[Inkbird](https://inkbird.com/)| TH-2 Temp and Humidity Sensor |
|
|
159
170
|
|[SensorPush](https://www.sensorpush.com/)| Temperature, Humidity and Atmospheric Pressure sensor|
|
|
171
|
+
|[MicrotikTag](https://mikrotik.com/products/group/iot-products)| TG-BT5 Temperature and Humidity and sensor|
|
|
160
172
|
|
|
161
173
|
|
|
162
174
|
### Tanks
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"delay":100,
|
|
3
|
+
"data":
|
|
4
|
+
{
|
|
5
|
+
"0x96": [
|
|
6
|
+
"55 aa eb 90 10 e0 ac d0 00 00 28 a0 00 00 5a a0 00 00 42 e0 00 00 78 d0 00 00 50 00 00 00 79 d0 00 00 50 a0 00 00 7a d0 00 00 16 d0 00 00 ba 90 00 00 20 bf 20 00 30 00 00 00 3c 00 00 00 20 bf 20 00 2c 10 00 00 3c 00 00 00 1e 00 00 00 d0 70 00 00 bc 20 00 00 58 20 00 00 bc 20 00 00 58 20 00 00 9c ff ff ff 00 00 00 00 20 30 00 00 bc 20 00 00 40 00 00 00 10 00 00 00 10 00 00 00 10 00 00 00 f0 ba 40 00 50 ","00 00 00 5c d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 20 a1 70 00 90 18 f6 00 18 fe ff ff ff 1f a9 6f e0 00 dd e2 00 7b" ],
|
|
7
|
+
"0x97":[
|
|
8
|
+
"55 aa eb 90 00 3 c4 4a 4b 5f 42 32 41 38 53 32 30 50 00 0 00 0 00 00 00 31 31 2e 58 57 00 00 00 31 31 2e 32 36 31 00 00 68 96 c1 03 18 00 00 00 48 42 31 5f 42 34 00 00 00 00 00 00 00 00 00 00 31 32 33 34 00 00 00 00 00 00 00 00 00 00 00 00 32 33 30 38 31 34 00 00 33 30 32 32 38 34 34 32 36 37 00 30 30 30 30 00 49 6e 70 75 74 20 55 73 65 72 64 61 74 61 00 00 31 32 33 33 32 31 00 00 00 00",
|
|
9
|
+
"00 00 00 00 00 00 49 6e 70 75 74 20 55 73 65 72 64 61 74 61 00 00",
|
|
10
|
+
"7c f8 ff ff 1f 0d 00 00 00 00 00 00 90 0f 00 00 00 00 c0 d8 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
11
|
+
"00 00 00 00 00 00 00 00 00 fe 2f 00 00 00 00 00 00 00 00 00 00 bf"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
}
|
package/diff.txt
CHANGED
|
@@ -1209,7 +1209,7 @@ index 0000000..473e8f1
|
|
|
1209
1209
|
+ })*/
|
|
1210
1210
|
+ }
|
|
1211
1211
|
+ initGATTConnection(){
|
|
1212
|
-
+ return new Promise((resolve,reject )=>{ this.
|
|
1212
|
+
+ return new Promise((resolve,reject )=>{ this.).then(async ()=>{
|
|
1213
1213
|
+ if (!this.gattServer) {
|
|
1214
1214
|
+ this.gattServer = await this.device.gatt()
|
|
1215
1215
|
+ this.battService = await this.gattServer.getPrimaryService("0000fff0-0000-1000-8000-00805f9b34fb")
|
package/index.js
CHANGED
|
@@ -77,6 +77,9 @@ class MissingSensor {
|
|
|
77
77
|
getRSSI(){
|
|
78
78
|
return NaN
|
|
79
79
|
}
|
|
80
|
+
getBatteryStrength(){
|
|
81
|
+
return NaN
|
|
82
|
+
}
|
|
80
83
|
getState(){
|
|
81
84
|
return "OUT_OF_RANGE"
|
|
82
85
|
}
|
|
@@ -386,6 +389,7 @@ module.exports = function (app) {
|
|
|
386
389
|
debugLog: sensor.getDebugLog(),
|
|
387
390
|
RSSI: sensor.getRSSI(),
|
|
388
391
|
signalStrength: sensor.getSignalStrength(),
|
|
392
|
+
batteryStrength: sensor.getBatteryStrength(),
|
|
389
393
|
connected: sensor.isConnected(),
|
|
390
394
|
lastContactDelta: sensor.elapsedTimeSinceLastContact()
|
|
391
395
|
}
|
|
@@ -457,9 +461,12 @@ module.exports = function (app) {
|
|
|
457
461
|
sensor.on("debug", ()=>{
|
|
458
462
|
updateSensor(sensor)
|
|
459
463
|
})
|
|
464
|
+
sensor.on(sensor.constructor.batteryStrengthTag,()=>{
|
|
465
|
+
updateSensor(sensor)
|
|
466
|
+
})
|
|
460
467
|
sensor._lastRSSI=-1*Infinity
|
|
461
468
|
sensor.on("RSSI",(()=>{
|
|
462
|
-
if (Date.now()-sensor._lastRSSI >
|
|
469
|
+
if (Date.now()-sensor._lastRSSI > 10000) { //only update RSSI on client every 10 seconds
|
|
463
470
|
|
|
464
471
|
sensor._lastRSSI=Date.now()
|
|
465
472
|
|
|
@@ -502,8 +509,10 @@ module.exports = function (app) {
|
|
|
502
509
|
device.once("deviceFound",async (device)=>{
|
|
503
510
|
s.device=device
|
|
504
511
|
s.listen()
|
|
505
|
-
if (config.active)
|
|
512
|
+
if (config.active) {
|
|
513
|
+
s.clearUnableToCommunicate()
|
|
506
514
|
await s.activate(config, plugin)
|
|
515
|
+
}
|
|
507
516
|
else {
|
|
508
517
|
s.unsetError()
|
|
509
518
|
s.setState("DORMANT")
|
|
@@ -516,15 +525,18 @@ module.exports = function (app) {
|
|
|
516
525
|
}
|
|
517
526
|
if (startNumber == starts ) {
|
|
518
527
|
const errorTxt = `Unable to communicate with device ${deviceNameAndAddress(config)} Reason: ${e?.message??e}`
|
|
519
|
-
|
|
520
|
-
{
|
|
521
|
-
s
|
|
522
|
-
|
|
523
|
-
|
|
528
|
+
|
|
529
|
+
if (config.active) {
|
|
530
|
+
if(s) {
|
|
531
|
+
s.setError(errorTxt)
|
|
532
|
+
s.notifyUnableToCommunicate()
|
|
533
|
+
}
|
|
534
|
+
else
|
|
524
535
|
plugin.setError(errorTxt)
|
|
525
536
|
}
|
|
537
|
+
plugin.debug(errorTxt)
|
|
526
538
|
plugin.debug(e)
|
|
527
|
-
|
|
539
|
+
|
|
528
540
|
reject( e?.message??e )
|
|
529
541
|
}
|
|
530
542
|
})})
|
|
@@ -776,6 +788,14 @@ module.exports = function (app) {
|
|
|
776
788
|
if (lc > dt) {
|
|
777
789
|
updateSensor(sensor)
|
|
778
790
|
}
|
|
791
|
+
if (sensor.noContactThreshold && lc>sensor.noContactThreshold){
|
|
792
|
+
if (sensor.isActive())
|
|
793
|
+
sensor.notifyNoContact()
|
|
794
|
+
}
|
|
795
|
+
else{
|
|
796
|
+
if (sensor.isActive())
|
|
797
|
+
sensor.clearNoContact()
|
|
798
|
+
}
|
|
779
799
|
})
|
|
780
800
|
if (sensorMap.size && options.inactivityTimeout && lastContactDelta > options.inactivityTimeout)
|
|
781
801
|
{
|
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bt-sensors-plugin-sk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.6-1",
|
|
4
4
|
"description": "Bluetooth Sensors for Signalk - see https://www.npmjs.com/package/bt-sensors-plugin-sk#supported-sensors for a list of supported sensors",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
|
|
8
|
-
"@rjsf/core": "^5.24.11",
|
|
9
|
-
"@rjsf/utils": "^5.24.11",
|
|
10
|
-
"@rjsf/validator-ajv8": "^5.24.11",
|
|
7
|
+
|
|
11
8
|
"better-sse": "^0.14.1",
|
|
12
9
|
"buffer": "^6.0.3",
|
|
13
10
|
"@jellybrick/dbus-next": "^0.10.3",
|
|
@@ -18,6 +15,10 @@
|
|
|
18
15
|
"lru-cache": "^11.1.0"
|
|
19
16
|
},
|
|
20
17
|
"devDependencies": {
|
|
18
|
+
"@rjsf/bootstrap-4": "^5.24.12",
|
|
19
|
+
"@rjsf/core": "^5.24.11",
|
|
20
|
+
"@rjsf/utils": "^5.24.11",
|
|
21
|
+
"@rjsf/validator-ajv8": "^5.24.11",
|
|
21
22
|
"@babel/core": "^7.11.6",
|
|
22
23
|
"@babel/preset-react": "^7.10.4",
|
|
23
24
|
"@fortawesome/fontawesome-free": "^5.15.1",
|
|
@@ -26,10 +27,10 @@
|
|
|
26
27
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
|
27
28
|
"@material-ui/core": "^4.12.4",
|
|
28
29
|
"@material-ui/icons": "^4.11.3",
|
|
30
|
+
"react-battery-gauge": "^1.0.7",
|
|
29
31
|
"babel-loader": "^8.1.0",
|
|
30
32
|
"chai": "^4.2.0",
|
|
31
33
|
"css-loader": "^5.0.0",
|
|
32
|
-
"d3": "^6.2.0",
|
|
33
34
|
"file-loader": "^6.1.1",
|
|
34
35
|
"font-awesome": "^4.7.0",
|
|
35
36
|
"mocha": "^8.0.1",
|
package/plugin_defaults.json
CHANGED
|
@@ -167,6 +167,19 @@
|
|
|
167
167
|
"title": "Battery Strength",
|
|
168
168
|
"unit":"ratio",
|
|
169
169
|
"default":"sensors.{macAndName}.battery.strength",
|
|
170
|
+
"zones":[
|
|
171
|
+
{ "upper": 0.5,
|
|
172
|
+
"lower": 0.3,
|
|
173
|
+
"state": "alert",
|
|
174
|
+
"message": "Battery low - change soon"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"upper": 0.3,
|
|
178
|
+
"lower": 0,
|
|
179
|
+
"state": "warn",
|
|
180
|
+
"message": "Battery very low - change now"
|
|
181
|
+
}
|
|
182
|
+
],
|
|
170
183
|
"description":"Sensor battery strength"
|
|
171
184
|
},
|
|
172
185
|
|
|
@@ -180,4 +193,4 @@
|
|
|
180
193
|
|
|
181
194
|
}
|
|
182
195
|
|
|
183
|
-
}
|
|
196
|
+
}
|
package/public/143.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(self.webpackChunkbt_sensors_plugin_sk=self.webpackChunkbt_sensors_plugin_sk||[]).push([[143],{9337:()=>{},62995:(e,t,n)=>{"use strict";n.r(t),n.d(t,{BTConfig:()=>$,default:()=>D});var a=n(73490),s=n(74810),r=n(40334),o=n(86528),i=n.n(o),c=n(11363),l=n(97493),u=n(27606),m=n(82096),d=n(55877),f=n(3768),g=n(71431),h=n(39676),p=n(47041),E=n(86038),y=n(95027),w=n(26067),S=n(43540),v=n(38250),b=n(31008),A=n(20455),C=n(23399);const k=e=>console.log.bind(console,e);function $(e){const t=(0,m.A)((e=>({root:{"& > *":{margin:e.spacing(1)}}}))),[n,$]=(0,o.useState)({}),[D,_]=(0,o.useState)({}),[x,T]=(0,o.useState)({}),[N,O]=(0,o.useState)({"ui:options":{label:!1},paths:{enableMarkdownInDescription:!0},title:{"ui:widget":"hidden"}}),[j,M]=(0,o.useState)(),[U,R]=(0,o.useState)(!1),[B,J]=(0,o.useState)(!0),[L,I]=(0,o.useState)(new Map),[P,W]=(0,o.useState)({progress:0,maxTimeout:100,deviceCount:0,totalDevices:0}),[z,K]=(0,o.useState)("unknown"),[F,G]=(0,o.useState)(),[H,Y]=(0,o.useState)(!1),[q,Q]=(0,o.useState)(""),V=t();function X(e,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 Z(e,t={}){let n;try{const a=Object.keys(t).length?"?"+new URLSearchParams(t).toString():"";n=await fetch(`/plugins/bt-sensors-plugin-sk/${e}${a}`,{credentials:"include",method:"GET"})}catch(e){n={status:500,statusText:e.toString()}}return n}function ee(e){return Object.keys(e.configCopy).length>0}function te(e){const t=ee(e);return i().createElement(A.A,{action:!0,onClick:()=>{e.config.mac_address=e.info.mac,T(e.schema),M(e.config)}},i().createElement("div",{class:"d-flex justify-content-between"},i().createElement("div",{class:"d-flex",style:t?{fontWeight:"normal"}:{fontStyle:"italic"}},`${e._changesMade?"*":""}${e.info.name} MAC: ${e.info.mac} RSSI: ${n=e.info.RSSI,null==n?NaN:n} ${function(e){const t=e.info?.batteryStrength;return t?`BATT: ${100*t}%`:""}(e)}`,function(e){const t=e.info.batteryStrength;return void 0===t?"":i().createElement(w.A,{size:22,orientation:"vertical",customization:{batteryBody:{fill:"silver",strokeColor:"silver",strokeWidth:2},batteryCap:{fill:"silver",strokeColor:"silver",cornerRadius:3,strokeWidth:0,capToBodyRatio:.4},readingText:{lightContrastColor:"purple",darkContrastColor:"yellow",lowBatteryColor:"red",fontFamily:"Arial",fontSize:16}},value:100*t})}(e)),i().createElement("div",{class:"d-flex "},`${e.info.state} ${e.info.error?" (ERROR)":""}`,function(e){return e.info.connected?i().createElement(d.A,null):null==e.info.lastContactDelta||e.info.lastContactDelta>e.config.discoveryTimeout?i().createElement(f.A,null):e.info.signalStrength>80?i().createElement(g.A,null):e.info.signalStrength>60?i().createElement(h.A,null):e.info.signalStrength>40?i().createElement(p.A,null):e.info.signalStrength>20?i().createElement(E.A,null):i().createElement(y.A,null)}(e))));var n}function ne(e){window.open(e,"_blank","noreferrer")}return(0,o.useEffect)((()=>{let e=null;return Z("getPluginState").then((async t=>{if(404==t.status)throw K("unknown"),new Error("unable to get plugin state");const n=await t.json();e=new EventSource("/plugins/bt-sensors-plugin-sk/sse",{withCredentials:!0}),e.addEventListener("newsensor",(e=>{!function(e){let t=JSON.parse(e.data);console.log(`New sensor: ${t.info.mac}`),I((e=>(e.set(t.info.mac,t),new Map(e))))}(e)})),e.addEventListener("sensorchanged",(e=>{!function(e){console.log("sensorchanged");const t=JSON.parse(e.data);console.log(t),I((e=>{const n=e.get(t.mac);return n&&Object.assign(n.info,t),new Map(e)}))}(e)})),e.addEventListener("progress",(e=>{const t=JSON.parse(e.data);W(t)})),e.addEventListener("pluginstate",(e=>{const t=JSON.parse(e.data);K(t.state)})),K(n.state),(async()=>{const e=await async function(){const e=await Z("getSensors");if(200!=e.status)throw new Error(`Unable get sensor data: ${e.statusText} (${e.status}) `);return await e.json()}();I(new Map(e.map((e=>[e.info.mac,e]))))})()})).catch((e=>{G(e.message)})),()=>{console.log("Closing connection to SSE"),e.close()}}),[]),(0,o.useEffect)((()=>{if(!U)return;if(!j||!L)return;const e=L.get(j.mac_address);e&&x&&j&&Object.hasOwn(j,"params")&&"UNKNOWN"==e.info.class&&j.params.sensorClass&&"UNKNOWN"!=j.params.sensorClass&&(J(!1),Q(`Please wait. Fetching schema for ${j.params.sensorClass}...`),async function(e,t){const n=await Z("getSensorInfo",{mac_address:e,class:t});if(200!=n.status)throw new Error(`Unable get sensor info: ${n.statusText} (${n.status}) `);return await n.json()}(j.mac_address,j.params.sensorClass).then((e=>{T(e.schema)})).catch((e=>{alert(e.message)})).finally((()=>{Q(""),J(!0),R(!1)})))}),[U]),(0,o.useEffect)((()=>{Y(""!=q)}),[q]),(0,o.useEffect)((()=>{"started"==z?(async function(){const e=await Z("getBaseData");if(200!=e.status)throw new Error(`Unable to get base data: ${e.statusText} (${e.status}) `);const t=await e.json();return t.schema.htmlDescription=i().createElement("div",null,(0,r.Ay)(t.schema.htmlDescription),i().createElement("p",null)),t}().then((e=>{$(e.schema),_(e.data)})).catch((e=>{G(e.message)})),async function(){const e=await Z("getProgress");if(200!=e.status)throw new Error(`Unable to get progress: ${e.statusText} (${e.status}) `);return await e.json()}().then((e=>{W(e)})).catch((e=>{G(e.message)}))):($({}),_({}))}),[z]),"stopped"==z||"unknown"==z?i().createElement("h3",null,"Enable plugin to see configuration"):i().createElement("div",null,i().createElement(c.A,{anchorOrigin:{horizontal:"center",vertical:"bottom"},onClose:()=>Y(!1),open:H,message:q,key:"snackbar"}),i().createElement("div",{className:V.root},i().createElement(l.A,{variant:"contained",onClick:()=>{ne("https://github.com/naugehyde/bt-sensors-plugin-sk/tree/1.2.0-beta#configuration")}},"Documentation"),i().createElement(l.A,{variant:"contained",onClick:()=>{ne("https://github.com/naugehyde/bt-sensors-plugin-sk/issues/new/choose")}},"Report Issue"),i().createElement(l.A,{variant:"contained",onClick:()=>{ne("https://discord.com/channels/1170433917761892493/1295425963466952725")}},"Discord Thread"),i().createElement("p",null),i().createElement("p",null)),i().createElement("hr",{style:{width:"100%",height:"1px",color:"gray","background-color":"gray","text-align":"left","margin-left":0}}),F?i().createElement("h2",{style:{color:"red"}},F):"",i().createElement(a.Ay,{schema:n,validator:s.Ay,uiSchema:{"ui:field":"LayoutGridField","ui:layoutGrid":{"ui:row":[{"ui:row":{className:"row",children:[{"ui:columns":{className:"col-xs-4",children:["adapter","transport","duplicateData","discoveryTimeout","discoveryInterval"]}}]}}]}},onChange:e=>_(e.formData),onSubmit:({formData:e},t)=>{var n;n=e,I(new Map),X("updateBaseData",n).then((e=>{200!=e.status&&G(`Unable to update base data: ${e.statusText} (${e.status})`)})),T({})},onError:k("errors"),formData:D}),i().createElement("hr",{style:{width:"100%",height:"1px",color:"gray","background-color":"gray","text-align":"left","margin-left":0}}),i().createElement("p",null),i().createElement("p",null),P.deviceCount<P.totalDevices?i().createElement(C.A,{max:P.maxTimeout,now:P.progress}):"",i().createElement("p",null),i().createElement(v.A,{defaultActiveKey:"_configured",id:"domain-tabs",className:"mb-3"},function(){const e=[...new Set([...L.entries()].map((e=>e[1].info.domain)))].sort(),t=Array.from(L.entries()).filter((e=>ee(e[1])));let n={};return n._configured=0==t.length?"Select a device from its domain tab (Electrical etc.) and configure it.":t.map((e=>te(L.get(e[0])))),e.forEach((e=>{var t;n[e]=(t=e,Array.from(L.entries()).filter((e=>e[1].info.domain===t))).map((e=>te(L.get(e[0]))))})),Object.keys(n).map((e=>function(e,t){let n=e.slice("_"===e.charAt(0)?1:0);return i().createElement(b.A,{eventKey:e,title:`${n.charAt(0).toUpperCase()}${n.slice(1)}${"string"==typeof t?"":" ("+t.length+")"}`},i().createElement(S.A,{style:{maxHeight:"300px",overflowY:"auto"}},t))}(e,n[e])))}()),i().createElement("div",{style:{paddingLeft:10,paddingTop:10,display:0==Object.keys(x).length?"none":""}},i().createElement(u.A,{container:!0,direction:"column",style:{spacing:5}},i().createElement(u.A,{item:!0},i().createElement("h2",null,x?.title),i().createElement("p",null)),i().createElement(u.A,{item:!0},(0,r.Ay)(x?.htmlDescription))),i().createElement("fieldset",{disabled:!B},i().createElement(a.Ay,{schema:x,validator:s.Ay,uiSchema:N,onChange:(e,t)=>{const n=L.get(e.formData.mac_address);n&&(n._changesMade=!0,n.config=e.formData,M(e.formData)),"root_params_sensorClass"==t&&R(!0)},onSubmit:({formData:e},t)=>{var n;X("updateSensorData",n=e).then((e=>{if(200!=e.status)throw new Error(e.statusText);I((e=>(e.delete(n.mac_address),new Map(e)))),T({})})),alert("Changes saved")},onError:k("errors"),formData:j},i().createElement("div",{className:V.root},i().createElement(l.A,{type:"submit",color:"primary",variant:"contained"},"Save"),i().createElement(l.A,{variant:"contained",onClick:()=>{var e;e=j.mac_address,L.get(e)._changesMade=!1,L.get(e).config=JSON.parse(JSON.stringify(L.get(e).configCopy)),M(L.get(e).config)}},"Undo"),i().createElement(l.A,{variant:"contained",color:"secondary",onClick:e=>function(e){const t=L.get(e);(!ee(t)||window.confirm(`Delete configuration for ${t.info.name}?`))&&function(e){try{X("removeSensorData",{mac_address:e}).then((e=>{if(200!=e.status)throw new Error(e.statusText)})),I((t=>(t.delete(e),new Map(t)))),T({})}catch{}}(e)}(j.mac_address)},"Delete"))))))}const D=$}}]);
|