@rfranzoi/scrypted-mqtt-securitysystem 1.0.46 → 1.0.47
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/dist/main.nodejs.js +27 -47
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
package/dist/main.nodejs.js
CHANGED
|
@@ -34077,12 +34077,8 @@ function falsy(v) {
|
|
|
34077
34077
|
const s = v.toString().trim().toLowerCase();
|
|
34078
34078
|
return s === '0' || s === 'false' || s === 'offline' || s === 'no' || s === 'off';
|
|
34079
34079
|
}
|
|
34080
|
-
function normalize(s) {
|
|
34081
|
-
|
|
34082
|
-
}
|
|
34083
|
-
function clamp(n, min, max) {
|
|
34084
|
-
return Math.max(min, Math.min(max, n));
|
|
34085
|
-
}
|
|
34080
|
+
function normalize(s) { return (s || '').trim().toLowerCase(); }
|
|
34081
|
+
function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); }
|
|
34086
34082
|
/** SecuritySystem outgoing defaults (PAI-like) */
|
|
34087
34083
|
const DEFAULT_OUTGOING = {
|
|
34088
34084
|
[sdk_1.SecuritySystemMode.Disarmed]: 'disarm',
|
|
@@ -34103,7 +34099,6 @@ function payloadToMode(payload) {
|
|
|
34103
34099
|
return sdk_1.SecuritySystemMode.AwayArmed;
|
|
34104
34100
|
if (['arm_night', 'night', 'armed_night', 'sleep', 'arm_sleep', 'armed_sleep'].includes(p))
|
|
34105
34101
|
return sdk_1.SecuritySystemMode.NightArmed;
|
|
34106
|
-
// transitori: non cambiano il mode
|
|
34107
34102
|
if (['entry_delay', 'exit_delay', 'pending', 'arming', 'disarming'].includes(p))
|
|
34108
34103
|
return undefined;
|
|
34109
34104
|
return undefined;
|
|
@@ -34128,8 +34123,8 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
|
|
|
34128
34123
|
}
|
|
34129
34124
|
/** Called by parent on each MQTT message */
|
|
34130
34125
|
handleMqtt(topic, payload) {
|
|
34131
|
-
const
|
|
34132
|
-
const np = normalize(
|
|
34126
|
+
const raw = payload?.toString() ?? '';
|
|
34127
|
+
const np = normalize(raw);
|
|
34133
34128
|
// online
|
|
34134
34129
|
if (topic === this.cfg.topics.online) {
|
|
34135
34130
|
if (truthy(np) || np === 'online')
|
|
@@ -34149,25 +34144,29 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
|
|
|
34149
34144
|
}
|
|
34150
34145
|
// battery
|
|
34151
34146
|
if (topic === this.cfg.topics.batteryLevel) {
|
|
34152
|
-
|
|
34153
|
-
|
|
34147
|
+
// aggiorna solo con numeri validi 0..100
|
|
34148
|
+
const n = clamp(parseFloat(raw), 0, 100);
|
|
34149
|
+
if (Number.isFinite(n))
|
|
34154
34150
|
this.setAndEmit('batteryLevel', n, sdk_1.ScryptedInterface.Battery);
|
|
34155
34151
|
}
|
|
34156
34152
|
else if (topic === this.cfg.topics.lowBattery && !this.cfg.topics.batteryLevel) {
|
|
34157
|
-
//
|
|
34158
|
-
|
|
34153
|
+
// LowBattery booleano: quando TRUE -> 10%; quando FALSE non forzare nulla, lascia il valore precedente
|
|
34154
|
+
if (truthy(np))
|
|
34155
|
+
this.setAndEmit('batteryLevel', 10, sdk_1.ScryptedInterface.Battery);
|
|
34156
|
+
else if (falsy(np) && this.batteryLevel === undefined) {
|
|
34157
|
+
// se è il primo messaggio ed è "ok", metti 100 (altrimenti resta undefined)
|
|
34158
|
+
this.setAndEmit('batteryLevel', 100, sdk_1.ScryptedInterface.Battery);
|
|
34159
|
+
}
|
|
34159
34160
|
}
|
|
34160
34161
|
// primary handled by subclasses
|
|
34161
|
-
this.handlePrimary(topic, np,
|
|
34162
|
+
this.handlePrimary(topic, np, raw);
|
|
34162
34163
|
}
|
|
34163
34164
|
}
|
|
34164
34165
|
class ContactMqttSensor extends BaseMqttSensor {
|
|
34165
|
-
handlePrimary(topic, np
|
|
34166
|
+
handlePrimary(topic, np) {
|
|
34166
34167
|
if (topic === this.cfg.topics.contact) {
|
|
34167
34168
|
const v = truthy(np);
|
|
34168
|
-
// usa il setter che emette l'evento di EntrySensor
|
|
34169
34169
|
this.setAndEmit?.('entryOpen', v, sdk_1.ScryptedInterface.EntrySensor);
|
|
34170
|
-
// fallback per sicurezza (in alcune minifiche setAndEmit non è visibile):
|
|
34171
34170
|
if (this.setAndEmit === undefined) {
|
|
34172
34171
|
if (this.entryOpen !== v) {
|
|
34173
34172
|
this.entryOpen = v;
|
|
@@ -34178,7 +34177,7 @@ class ContactMqttSensor extends BaseMqttSensor {
|
|
|
34178
34177
|
}
|
|
34179
34178
|
}
|
|
34180
34179
|
class MotionMqttSensor extends BaseMqttSensor {
|
|
34181
|
-
handlePrimary(topic, np
|
|
34180
|
+
handlePrimary(topic, np) {
|
|
34182
34181
|
if (topic === this.cfg.topics.motion) {
|
|
34183
34182
|
const v = truthy(np);
|
|
34184
34183
|
this.setAndEmit?.('motionDetected', v, sdk_1.ScryptedInterface.MotionSensor);
|
|
@@ -34192,7 +34191,7 @@ class MotionMqttSensor extends BaseMqttSensor {
|
|
|
34192
34191
|
}
|
|
34193
34192
|
}
|
|
34194
34193
|
class OccupancyMqttSensor extends BaseMqttSensor {
|
|
34195
|
-
handlePrimary(topic, np
|
|
34194
|
+
handlePrimary(topic, np) {
|
|
34196
34195
|
if (topic === this.cfg.topics.occupancy) {
|
|
34197
34196
|
const v = truthy(np);
|
|
34198
34197
|
this.setAndEmit?.('occupied', v, sdk_1.ScryptedInterface.OccupancySensor);
|
|
@@ -34302,7 +34301,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34302
34301
|
return out;
|
|
34303
34302
|
}
|
|
34304
34303
|
async putSetting(key, value) {
|
|
34305
|
-
// salva sempre nella storage la value del campo (così resta in UI)
|
|
34306
34304
|
this.storage.setItem(key, String(value));
|
|
34307
34305
|
// --- Add Sensor workflow ---
|
|
34308
34306
|
if (key === 'new.create' && String(value) === 'true') {
|
|
@@ -34319,7 +34317,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34319
34317
|
}
|
|
34320
34318
|
this.sensorsCfg.push({ id, name, kind, topics: {} });
|
|
34321
34319
|
this.saveSensorsToStorage();
|
|
34322
|
-
// pulisci i campi "new.*"
|
|
34323
34320
|
this.storage.removeItem('new.id');
|
|
34324
34321
|
this.storage.removeItem('new.name');
|
|
34325
34322
|
this.storage.removeItem('new.kind');
|
|
@@ -34339,7 +34336,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34339
34336
|
return;
|
|
34340
34337
|
}
|
|
34341
34338
|
if (prop === 'remove' && String(value) === 'true') {
|
|
34342
|
-
// elimina
|
|
34343
34339
|
this.sensorsCfg = this.sensorsCfg.filter(s => s.id !== sid);
|
|
34344
34340
|
this.saveSensorsToStorage();
|
|
34345
34341
|
try {
|
|
@@ -34347,18 +34343,15 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34347
34343
|
deviceManager.onDeviceRemoved?.(`sensor:${sid}`);
|
|
34348
34344
|
}
|
|
34349
34345
|
catch { }
|
|
34350
|
-
// pulisci flag
|
|
34351
34346
|
this.storage.removeItem(key);
|
|
34352
34347
|
await this.discoverSensors();
|
|
34353
34348
|
await this.connectMqtt(true);
|
|
34354
34349
|
return;
|
|
34355
34350
|
}
|
|
34356
|
-
if (prop === 'name')
|
|
34351
|
+
if (prop === 'name')
|
|
34357
34352
|
cfg.name = String(value);
|
|
34358
|
-
|
|
34359
|
-
else if (prop === 'kind') {
|
|
34353
|
+
else if (prop === 'kind')
|
|
34360
34354
|
cfg.kind = String(value);
|
|
34361
|
-
}
|
|
34362
34355
|
else if (prop.startsWith('topic.')) {
|
|
34363
34356
|
const tk = prop.substring('topic.'.length);
|
|
34364
34357
|
cfg.topics[tk] = String(value).trim();
|
|
@@ -34370,7 +34363,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34370
34363
|
}
|
|
34371
34364
|
// --- Altro (MQTT / Alarm settings) ---
|
|
34372
34365
|
if (key === 'sensorsJson') {
|
|
34373
|
-
// non più mostrato, ma se presente da vecchie versioni
|
|
34374
34366
|
this.loadSensorsFromStorage();
|
|
34375
34367
|
await this.discoverSensors();
|
|
34376
34368
|
await this.connectMqtt(true);
|
|
@@ -34386,9 +34378,8 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34386
34378
|
async releaseDevice(_id, nativeId) {
|
|
34387
34379
|
try {
|
|
34388
34380
|
const dev = this.devices.get(nativeId);
|
|
34389
|
-
if (dev)
|
|
34381
|
+
if (dev)
|
|
34390
34382
|
this.devices.delete(nativeId);
|
|
34391
|
-
}
|
|
34392
34383
|
try {
|
|
34393
34384
|
deviceManager.onDeviceRemoved?.(nativeId);
|
|
34394
34385
|
}
|
|
@@ -34402,7 +34393,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34402
34393
|
try {
|
|
34403
34394
|
const raw = this.storage.getItem('sensorsJson') || '[]';
|
|
34404
34395
|
const parsed = JSON.parse(raw);
|
|
34405
|
-
// sanitize
|
|
34406
34396
|
this.sensorsCfg = (parsed || []).filter(x => x && x.id && x.name && x.kind && x.topics);
|
|
34407
34397
|
}
|
|
34408
34398
|
catch (e) {
|
|
@@ -34412,23 +34402,21 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34412
34402
|
}
|
|
34413
34403
|
/** ===== discoverSensors: annuncia PRIMA, istanzia DOPO ===== */
|
|
34414
34404
|
async discoverSensors() {
|
|
34415
|
-
// 1)
|
|
34405
|
+
// 1) Manifests
|
|
34416
34406
|
const manifests = this.sensorsCfg.map(cfg => {
|
|
34417
34407
|
const nativeId = `sensor:${cfg.id}`;
|
|
34418
34408
|
const t = cfg.topics || {};
|
|
34419
34409
|
const interfaces = [sdk_1.ScryptedInterface.Online];
|
|
34420
|
-
// Tamper solo se c'è un topic tamper
|
|
34421
34410
|
if (t.tamper)
|
|
34422
34411
|
interfaces.push(sdk_1.ScryptedInterface.TamperSensor);
|
|
34423
|
-
// Interfaccia primaria
|
|
34424
34412
|
if (cfg.kind === 'contact')
|
|
34425
34413
|
interfaces.unshift(sdk_1.ScryptedInterface.EntrySensor);
|
|
34426
34414
|
else if (cfg.kind === 'motion')
|
|
34427
34415
|
interfaces.unshift(sdk_1.ScryptedInterface.MotionSensor);
|
|
34428
34416
|
else
|
|
34429
34417
|
interfaces.unshift(sdk_1.ScryptedInterface.OccupancySensor);
|
|
34430
|
-
// Battery
|
|
34431
|
-
if (t.batteryLevel || t.lowBattery) {
|
|
34418
|
+
// Espone Battery SOLTANTO se è configurato almeno un topic batteria (stringa non vuota)
|
|
34419
|
+
if ((t.batteryLevel && t.batteryLevel.trim()) || (t.lowBattery && t.lowBattery.trim())) {
|
|
34432
34420
|
interfaces.push(sdk_1.ScryptedInterface.Battery);
|
|
34433
34421
|
}
|
|
34434
34422
|
return { nativeId, name: cfg.name, type: sdk_1.ScryptedDeviceType.Sensor, interfaces };
|
|
@@ -34461,15 +34449,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34461
34449
|
else {
|
|
34462
34450
|
dev.cfg = cfg;
|
|
34463
34451
|
}
|
|
34464
|
-
//
|
|
34465
|
-
const hasBattery = !!(cfg.topics.batteryLevel || cfg.topics.lowBattery);
|
|
34466
|
-
if (hasBattery && dev.batteryLevel === undefined) {
|
|
34467
|
-
dev.batteryLevel = 100;
|
|
34468
|
-
try {
|
|
34469
|
-
dev.onDeviceEvent(sdk_1.ScryptedInterface.Battery, 100);
|
|
34470
|
-
}
|
|
34471
|
-
catch { }
|
|
34472
|
-
}
|
|
34452
|
+
// <<< RIMOSSO il default batteryLevel=100: niente valore finché non arriva un messaggio >>>
|
|
34473
34453
|
}
|
|
34474
34454
|
// 4) Rimuovi quelli spariti
|
|
34475
34455
|
const announced = new Set(manifests.map(m => m.nativeId));
|
|
@@ -34517,7 +34497,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34517
34497
|
for (const s of this.sensorsCfg) {
|
|
34518
34498
|
const t = s.topics || {};
|
|
34519
34499
|
[t.contact, t.motion, t.occupancy, t.batteryLevel, t.lowBattery, t.tamper, t.online]
|
|
34520
|
-
.filter(
|
|
34500
|
+
.filter((x) => !!x && String(x).trim().length > 0)
|
|
34521
34501
|
.forEach(x => subs.add(String(x)));
|
|
34522
34502
|
}
|
|
34523
34503
|
return Array.from(subs);
|
|
@@ -34661,7 +34641,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34661
34641
|
async armSecuritySystem(mode) {
|
|
34662
34642
|
const payload = this.getOutgoing(mode);
|
|
34663
34643
|
this.console.log('armSecuritySystem', mode, '->', payload);
|
|
34664
|
-
this.pendingTarget = mode;
|
|
34644
|
+
this.pendingTarget = mode;
|
|
34665
34645
|
this.publishSetTarget(payload);
|
|
34666
34646
|
}
|
|
34667
34647
|
async disarmSecuritySystem() {
|
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED