bt-sensors-plugin-sk 1.3.4-beta → 1.3.5-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BTSensor.js +60 -7
- package/README.md +10 -3
- package/development/TestData/Jikong.json +14 -0
- package/diff.txt +1 -1
- package/index.js +28 -15
- package/package.json +2 -2
- package/plugin_defaults.json +13 -0
- 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 +41 -2
- 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/SwitchBotMeterPlus.js +1 -0
- package/sensor_classes/SwitchBotTH.js +1 -1
- package/sensor_classes/XiaomiMiBeacon.js +1 -0
- package/src/components/PluginConfigurationPanel.js +44 -3
- 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
|
|
@@ -955,6 +959,19 @@ class BTSensor extends EventEmitter {
|
|
|
955
959
|
throw new Error("Subclass must implement ::emitGATT function")
|
|
956
960
|
}
|
|
957
961
|
|
|
962
|
+
getCurrentValue(tag){
|
|
963
|
+
return this._currentValues[tag]
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
setCurrentValue(tag,value){
|
|
967
|
+
this._currentValues[tag]=value
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
emit(tag, value){
|
|
971
|
+
super.emit(tag, value)
|
|
972
|
+
this.setCurrentValue(tag,value)
|
|
973
|
+
}
|
|
974
|
+
|
|
958
975
|
emitData(tag, buffer, ...args){
|
|
959
976
|
const md = this.getPath(tag)
|
|
960
977
|
if (md && md.read)
|
|
@@ -1048,7 +1065,7 @@ class BTSensor extends EventEmitter {
|
|
|
1048
1065
|
this._app.handleMessage(id,
|
|
1049
1066
|
{
|
|
1050
1067
|
updates:
|
|
1051
|
-
[{ meta: [{path: this.preparePath(path), value: { units: pathMeta?.unit }}]}]
|
|
1068
|
+
[{ meta: [{path: this.preparePath(path), value: { units: pathMeta?.unit, zones:pathMeta?.zones} }]}]
|
|
1052
1069
|
})
|
|
1053
1070
|
}
|
|
1054
1071
|
})
|
|
@@ -1062,11 +1079,7 @@ class BTSensor extends EventEmitter {
|
|
|
1062
1079
|
if (!(path === undefined)) {
|
|
1063
1080
|
let preparedPath = this.preparePath(path)
|
|
1064
1081
|
this.on(tag, (val)=>{
|
|
1065
|
-
|
|
1066
|
-
this._app.notify(tag, val, id )
|
|
1067
|
-
} else {*/
|
|
1068
|
-
this.updatePath(preparedPath,val, id, source)
|
|
1069
|
-
//}
|
|
1082
|
+
this.updatePath(preparedPath,val, id, source)
|
|
1070
1083
|
})
|
|
1071
1084
|
}
|
|
1072
1085
|
})
|
|
@@ -1075,7 +1088,10 @@ class BTSensor extends EventEmitter {
|
|
|
1075
1088
|
this._app.handleMessage(id, {updates: [ { $source: source, values: [ { path: path, value: val }] } ] })
|
|
1076
1089
|
}
|
|
1077
1090
|
elapsedTimeSinceLastContact(){
|
|
1078
|
-
|
|
1091
|
+
if (this.device instanceof OutOfRangeDevice)
|
|
1092
|
+
return Infinity
|
|
1093
|
+
else
|
|
1094
|
+
return (Date.now()-this?._lastContact??Date.now())/1000
|
|
1079
1095
|
}
|
|
1080
1096
|
|
|
1081
1097
|
prepareConfig(config){
|
|
@@ -1116,7 +1132,44 @@ class BTSensor extends EventEmitter {
|
|
|
1116
1132
|
return resultString || str; // Return original string if no replacements were made
|
|
1117
1133
|
}
|
|
1118
1134
|
|
|
1135
|
+
notifyUnableToCommunicate(){
|
|
1136
|
+
this._app.handleMessage('bt-sensors-plugin-sk',
|
|
1137
|
+
{
|
|
1138
|
+
updates: [{
|
|
1139
|
+
$source: this.getName(),
|
|
1140
|
+
timestamp: (new Date()).toISOString(),
|
|
1141
|
+
values: [{
|
|
1142
|
+
path: `notifications.sensors.${this.macAndName()}`,
|
|
1143
|
+
value: {
|
|
1144
|
+
state: "warn",
|
|
1145
|
+
message: "Unable to communicate with sensor",
|
|
1146
|
+
method: ["visual", "sound"]
|
|
1147
|
+
}
|
|
1148
|
+
}]
|
|
1149
|
+
}]
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1119
1154
|
|
|
1155
|
+
clearUnableToCommunicate(){
|
|
1156
|
+
this._app.handleMessage('bt-sensors-plugin-sk',
|
|
1157
|
+
{
|
|
1158
|
+
updates: [{
|
|
1159
|
+
$source: this.getName(),
|
|
1160
|
+
timestamp: (new Date()).toISOString(),
|
|
1161
|
+
values: [{
|
|
1162
|
+
path: `notifications.sensors.${this.macAndName()}`,
|
|
1163
|
+
value: null
|
|
1164
|
+
}]
|
|
1165
|
+
}]
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
getBatteryStrength(){
|
|
1171
|
+
return this.getCurrentValue(this.constructor.batteryStrengthTag)
|
|
1172
|
+
}
|
|
1120
1173
|
}
|
|
1121
1174
|
|
|
1122
1175
|
module.exports = BTSensor
|
package/README.md
CHANGED
|
@@ -2,16 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## WHAT'S NEW
|
|
4
4
|
|
|
5
|
+
# Verstion 1.3.5
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
- Battery strength notification for supported sensors
|
|
8
|
+
- Battery strength value/icon displayed on config page
|
|
9
|
+
- MicrotikTag TG-BT5 environment sensor support
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
# Version 1.3.4
|
|
9
12
|
|
|
13
|
+
- Inactivity timeout configuration option. If > 0 and there's been no contact with any Bluetooth device, the plugin will power cycle the bluetooth adapter.
|
|
14
|
+
- Exclude non-active devices that are Out of Range from Last Error and Status on SignalK Dashboard
|
|
15
|
+
|
|
10
16
|
# Version 1.3.3
|
|
11
17
|
|
|
12
18
|
- Support for additional Xiaomi environmental sensors
|
|
13
19
|
- Out Of Range device automatic retry
|
|
14
|
-
-
|
|
20
|
+
- [Device pairing guide](./pairing.md)
|
|
15
21
|
|
|
16
22
|
# Version 1.3.2-1
|
|
17
23
|
|
|
@@ -156,6 +162,7 @@ It's pretty easy to write and deploy your own sensor class for any currently uns
|
|
|
156
162
|
|[BTHome](https://bthome.io/)| NOTE: Framework for IOT sensor devices. |
|
|
157
163
|
|[Inkbird](https://inkbird.com/)| TH-2 Temp and Humidity Sensor |
|
|
158
164
|
|[SensorPush](https://www.sensorpush.com/)| Temperature, Humidity and Atmospheric Pressure sensor|
|
|
165
|
+
|[MicrotikTag](https://mikrotik.com/products/group/iot-products)| TG-BT5 Temperature and Humidity and sensor|
|
|
159
166
|
|
|
160
167
|
|
|
161
168
|
### 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
|
}
|
|
@@ -178,8 +181,8 @@ module.exports = function (app) {
|
|
|
178
181
|
minimum: 10,
|
|
179
182
|
maximum: 3600
|
|
180
183
|
},
|
|
181
|
-
inactivityTimeout: {title: "Inactivity timeout
|
|
182
|
-
type: "integer", default:
|
|
184
|
+
inactivityTimeout: {title: "Inactivity timeout in seconds -- set to 0 to disable. (If no contact with any sensors for this period, the plugin will attempt to power cycle the Bluetooth adapter.)",
|
|
185
|
+
type: "integer", default: 0,
|
|
183
186
|
minimum: 0,
|
|
184
187
|
maximum: 3600
|
|
185
188
|
},
|
|
@@ -208,8 +211,6 @@ module.exports = function (app) {
|
|
|
208
211
|
plugin.started=true
|
|
209
212
|
var adapterID=options.adapter
|
|
210
213
|
var foundConfiguredDevices=0
|
|
211
|
-
var lastContactDelta=Infinity
|
|
212
|
-
|
|
213
214
|
|
|
214
215
|
if (Object.keys(options).length==0){ //empty config means initial startup. save defaults and enabled=true.
|
|
215
216
|
let json = {configuration:{adapter:"hci0", transport:"le", discoveryTimeout:30, discoveryInterval:10}, enabled:true, enableDebug:false}
|
|
@@ -330,7 +331,8 @@ module.exports = function (app) {
|
|
|
330
331
|
transport: options.transport,
|
|
331
332
|
duplicateData: options.duplicateData,
|
|
332
333
|
discoveryTimeout: options.discoveryTimeout,
|
|
333
|
-
discoveryInterval: options.discoveryInterval
|
|
334
|
+
discoveryInterval: options.discoveryInterval,
|
|
335
|
+
inactivityTimeout: options.inactivityTimeout
|
|
334
336
|
}
|
|
335
337
|
}
|
|
336
338
|
);
|
|
@@ -387,6 +389,7 @@ module.exports = function (app) {
|
|
|
387
389
|
debugLog: sensor.getDebugLog(),
|
|
388
390
|
RSSI: sensor.getRSSI(),
|
|
389
391
|
signalStrength: sensor.getSignalStrength(),
|
|
392
|
+
batteryStrength: sensor.getBatteryStrength(),
|
|
390
393
|
connected: sensor.isConnected(),
|
|
391
394
|
lastContactDelta: sensor.elapsedTimeSinceLastContact()
|
|
392
395
|
}
|
|
@@ -503,8 +506,10 @@ module.exports = function (app) {
|
|
|
503
506
|
device.once("deviceFound",async (device)=>{
|
|
504
507
|
s.device=device
|
|
505
508
|
s.listen()
|
|
506
|
-
if (config.active)
|
|
509
|
+
if (config.active) {
|
|
510
|
+
s.clearUnableToCommunicate()
|
|
507
511
|
await s.activate(config, plugin)
|
|
512
|
+
}
|
|
508
513
|
else {
|
|
509
514
|
s.unsetError()
|
|
510
515
|
s.setState("DORMANT")
|
|
@@ -517,14 +522,18 @@ module.exports = function (app) {
|
|
|
517
522
|
}
|
|
518
523
|
if (startNumber == starts ) {
|
|
519
524
|
const errorTxt = `Unable to communicate with device ${deviceNameAndAddress(config)} Reason: ${e?.message??e}`
|
|
520
|
-
|
|
521
|
-
{
|
|
522
|
-
s
|
|
523
|
-
|
|
524
|
-
|
|
525
|
+
|
|
526
|
+
if (config.active) {
|
|
527
|
+
if(s) {
|
|
528
|
+
s.setError(errorTxt)
|
|
529
|
+
s.notifyUnableToCommunicate()
|
|
530
|
+
}
|
|
531
|
+
else
|
|
532
|
+
plugin.setError(errorTxt)
|
|
525
533
|
}
|
|
534
|
+
plugin.debug(errorTxt)
|
|
526
535
|
plugin.debug(e)
|
|
527
|
-
|
|
536
|
+
|
|
528
537
|
reject( e?.message??e )
|
|
529
538
|
}
|
|
530
539
|
})})
|
|
@@ -764,10 +773,9 @@ module.exports = function (app) {
|
|
|
764
773
|
}
|
|
765
774
|
const minTimeout=Math.min(...deviceConfigs.map((dc)=>dc?.discoveryTimeout??options.discoveryTimeout))
|
|
766
775
|
const intervalTimeout = ((minTimeout==Infinity)?(options?.discoveryTimeout??plugin.schema.properties.discoveryTimeout.default):minTimeout)*1000
|
|
767
|
-
|
|
768
|
-
|
|
769
776
|
|
|
770
777
|
deviceHealthID = setInterval( async ()=> {
|
|
778
|
+
let lastContactDelta=Infinity
|
|
771
779
|
sensorMap.forEach((sensor)=>{
|
|
772
780
|
const config = getDeviceConfig(sensor.getMacAddress())
|
|
773
781
|
const dt = config?.discoveryTimeout??options.discoveryTimeout
|
|
@@ -778,7 +786,7 @@ module.exports = function (app) {
|
|
|
778
786
|
updateSensor(sensor)
|
|
779
787
|
}
|
|
780
788
|
})
|
|
781
|
-
if (sensorMap.size && lastContactDelta > options.inactivityTimeout)
|
|
789
|
+
if (sensorMap.size && options.inactivityTimeout && lastContactDelta > options.inactivityTimeout)
|
|
782
790
|
{
|
|
783
791
|
|
|
784
792
|
plugin.debug(`No contact with any sensors for ${lastContactDelta} seconds. Recycling Bluetooth adapter.`)
|
|
@@ -813,6 +821,11 @@ module.exports = function (app) {
|
|
|
813
821
|
progressTimeoutID=null
|
|
814
822
|
}
|
|
815
823
|
|
|
824
|
+
if (deviceHealthID) {
|
|
825
|
+
clearTimeout(deviceHealthID)
|
|
826
|
+
deviceHealthID=null
|
|
827
|
+
}
|
|
828
|
+
|
|
816
829
|
if ((sensorMap)){
|
|
817
830
|
for await (const sensorEntry of sensorMap.entries()) {
|
|
818
831
|
try{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bt-sensors-plugin-sk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5-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": {
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
|
27
27
|
"@material-ui/core": "^4.12.4",
|
|
28
28
|
"@material-ui/icons": "^4.11.3",
|
|
29
|
+
"react-battery-gauge": "^1.0.7",
|
|
29
30
|
"babel-loader": "^8.1.0",
|
|
30
31
|
"chai": "^4.2.0",
|
|
31
32
|
"css-loader": "^5.0.0",
|
|
32
|
-
"d3": "^6.2.0",
|
|
33
33
|
"file-loader": "^6.1.1",
|
|
34
34
|
"font-awesome": "^4.7.0",
|
|
35
35
|
"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
|
|
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),b=n(38250),v=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 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} ${function(e){const t=e.info?.batteryStrength;return t?`BATT: ${100*t}%`:""}(e)}`,i().createElement("div",{class:"d-flex justify-content-between "},`${e.info.state} ${e.info.error?" (ERROR)":""}`,i().createElement("div",{class:"d-flex justify-content-between "},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),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)))));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(b.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(v.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=$}}]);
|