@rfranzoi/scrypted-mqtt-securitysystem 1.0.38 → 1.0.40
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 +113 -175
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
package/dist/main.nodejs.js
CHANGED
|
@@ -34029,7 +34029,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
34029
34029
|
};
|
|
34030
34030
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
34031
34031
|
// --- Preload: silenzia SOLO il warning facoltativo di sdk.json ---
|
|
34032
|
-
// Copre console.error e console.warn (alcune versioni usano warn).
|
|
34033
34032
|
(() => {
|
|
34034
34033
|
const swallow = (orig) => (...args) => {
|
|
34035
34034
|
const txt = args.map(a => typeof a === 'string' ? a : (a?.message || '')).join(' ');
|
|
@@ -34040,11 +34039,11 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
34040
34039
|
console.error = swallow(console.error.bind(console));
|
|
34041
34040
|
console.warn = swallow(console.warn.bind(console));
|
|
34042
34041
|
})();
|
|
34043
|
-
// Carica lo SDK
|
|
34042
|
+
// Carica lo SDK in runtime (evita ESM per garantire l’ordine col preload)
|
|
34044
34043
|
const sdk = __webpack_require__(/*! @scrypted/sdk */ "./node_modules/@scrypted/sdk/dist/src/index.js");
|
|
34045
|
-
// Valori runtime
|
|
34046
|
-
const { ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, // enum
|
|
34047
|
-
SecuritySystemMode, // enum
|
|
34044
|
+
// Valori runtime (enum, classi, manager)
|
|
34045
|
+
const { ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, // enum: valori
|
|
34046
|
+
SecuritySystemMode, // enum: valori
|
|
34048
34047
|
systemManager, } = sdk;
|
|
34049
34048
|
const mqtt_1 = __importDefault(__webpack_require__(/*! mqtt */ "./node_modules/mqtt/build/index.js"));
|
|
34050
34049
|
/** utils */
|
|
@@ -34062,24 +34061,6 @@ function falsy(v) {
|
|
|
34062
34061
|
}
|
|
34063
34062
|
function normalize(s) { return (s || '').trim().toLowerCase(); }
|
|
34064
34063
|
function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); }
|
|
34065
|
-
function deepEqual(a, b) {
|
|
34066
|
-
try {
|
|
34067
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
34068
|
-
}
|
|
34069
|
-
catch {
|
|
34070
|
-
return a === b;
|
|
34071
|
-
}
|
|
34072
|
-
}
|
|
34073
|
-
/** Imposta una property e, se cambia, emette anche l'evento Scrypted corrispondente */
|
|
34074
|
-
function setAndEmit(dev, key, value, iface) {
|
|
34075
|
-
if (dev[key] === value)
|
|
34076
|
-
return;
|
|
34077
|
-
dev[key] = value;
|
|
34078
|
-
try {
|
|
34079
|
-
dev.onDeviceEvent?.(iface, value);
|
|
34080
|
-
}
|
|
34081
|
-
catch { }
|
|
34082
|
-
}
|
|
34083
34064
|
/** Outgoing predefiniti (PAI-like). Chiavi numeriche per compatibilità enum */
|
|
34084
34065
|
const DEFAULT_OUTGOING = {
|
|
34085
34066
|
[SecuritySystemMode.Disarmed]: 'disarm',
|
|
@@ -34112,145 +34093,46 @@ class BaseMqttSensor extends ScryptedDeviceBase {
|
|
|
34112
34093
|
handleMqtt(topic, payload) {
|
|
34113
34094
|
const p = payload?.toString() ?? '';
|
|
34114
34095
|
const np = normalize(p);
|
|
34115
|
-
// Online
|
|
34116
34096
|
if (topic === this.cfg.topics.online) {
|
|
34117
34097
|
if (truthy(np) || np === 'online')
|
|
34118
|
-
|
|
34098
|
+
this.online = true;
|
|
34119
34099
|
if (falsy(np) || np === 'offline')
|
|
34120
|
-
|
|
34100
|
+
this.online = false;
|
|
34121
34101
|
}
|
|
34122
|
-
// Tamper
|
|
34123
34102
|
if (topic === this.cfg.topics.tamper) {
|
|
34124
34103
|
if (truthy(np) || ['tamper', 'intrusion', 'cover', 'motion', 'magnetic'].includes(np)) {
|
|
34125
|
-
|
|
34126
|
-
setAndEmit(this, 'tampered', t, ScryptedInterface.TamperSensor);
|
|
34104
|
+
this.tampered = ['cover', 'intrusion', 'motion', 'magnetic'].find(x => x === np) || true;
|
|
34127
34105
|
}
|
|
34128
34106
|
else if (falsy(np))
|
|
34129
|
-
|
|
34107
|
+
this.tampered = false;
|
|
34130
34108
|
}
|
|
34131
|
-
// Battery
|
|
34132
34109
|
if (topic === this.cfg.topics.batteryLevel) {
|
|
34133
34110
|
const n = clamp(parseFloat(p), 0, 100);
|
|
34134
34111
|
if (isFinite(n))
|
|
34135
|
-
|
|
34112
|
+
this.batteryLevel = n;
|
|
34136
34113
|
}
|
|
34137
34114
|
else if (topic === this.cfg.topics.lowBattery && !this.cfg.topics.batteryLevel) {
|
|
34138
|
-
|
|
34139
|
-
setAndEmit(this, 'batteryLevel', n, ScryptedInterface.Battery);
|
|
34115
|
+
this.batteryLevel = truthy(np) ? 10 : 100;
|
|
34140
34116
|
}
|
|
34141
|
-
// Primary
|
|
34142
34117
|
this.handlePrimary(topic, np, p);
|
|
34143
34118
|
}
|
|
34144
34119
|
}
|
|
34145
|
-
/** === SENSORI CON PARSING ROBUSTO + EMISSIONE EVENTI === */
|
|
34146
34120
|
class ContactMqttSensor extends BaseMqttSensor {
|
|
34147
|
-
handlePrimary(topic, np
|
|
34148
|
-
if (topic
|
|
34149
|
-
|
|
34150
|
-
let val;
|
|
34151
|
-
// stringhe comuni
|
|
34152
|
-
if (['open', 'opened', '1', 'true', 'on', 'yes'].includes(np))
|
|
34153
|
-
val = true;
|
|
34154
|
-
else if (['closed', 'close', '0', 'false', 'off', 'no', 'shut'].includes(np))
|
|
34155
|
-
val = false;
|
|
34156
|
-
// JSON comuni
|
|
34157
|
-
if (val === undefined) {
|
|
34158
|
-
try {
|
|
34159
|
-
const j = JSON.parse(raw);
|
|
34160
|
-
if (typeof j?.open === 'boolean')
|
|
34161
|
-
val = !!j.open;
|
|
34162
|
-
else if (typeof j?.opened === 'boolean')
|
|
34163
|
-
val = !!j.opened;
|
|
34164
|
-
else if (typeof j?.contact === 'boolean')
|
|
34165
|
-
val = !j.contact; // contact:false => OPEN
|
|
34166
|
-
else if (typeof j?.state === 'string') {
|
|
34167
|
-
const s = String(j.state).toLowerCase();
|
|
34168
|
-
if (s === 'open')
|
|
34169
|
-
val = true;
|
|
34170
|
-
if (s === 'closed')
|
|
34171
|
-
val = false;
|
|
34172
|
-
}
|
|
34173
|
-
}
|
|
34174
|
-
catch { }
|
|
34175
|
-
}
|
|
34176
|
-
if (val !== undefined) {
|
|
34177
|
-
setAndEmit(this, 'entryOpen', val, ScryptedInterface.EntrySensor);
|
|
34178
|
-
}
|
|
34179
|
-
else {
|
|
34180
|
-
this.console?.debug?.(`Contact payload non gestito (${this.cfg.id}): "${raw}"`);
|
|
34181
|
-
}
|
|
34121
|
+
handlePrimary(topic, np) {
|
|
34122
|
+
if (topic === this.cfg.topics.contact)
|
|
34123
|
+
this.entryOpen = truthy(np);
|
|
34182
34124
|
}
|
|
34183
34125
|
}
|
|
34184
34126
|
class MotionMqttSensor extends BaseMqttSensor {
|
|
34185
|
-
handlePrimary(topic, np
|
|
34186
|
-
if (topic
|
|
34187
|
-
|
|
34188
|
-
let val;
|
|
34189
|
-
if (['motion', 'detected', 'active', '1', 'true', 'on', 'yes'].includes(np))
|
|
34190
|
-
val = true;
|
|
34191
|
-
else if (['clear', 'inactive', 'no_motion', 'none', '0', 'false', 'off', 'no'].includes(np))
|
|
34192
|
-
val = false;
|
|
34193
|
-
if (val === undefined) {
|
|
34194
|
-
try {
|
|
34195
|
-
const j = JSON.parse(raw);
|
|
34196
|
-
if (typeof j?.motion === 'boolean')
|
|
34197
|
-
val = !!j.motion;
|
|
34198
|
-
else if (typeof j?.occupancy === 'boolean')
|
|
34199
|
-
val = !!j.occupancy;
|
|
34200
|
-
else if (typeof j?.presence === 'boolean')
|
|
34201
|
-
val = !!j.presence;
|
|
34202
|
-
else if (typeof j?.state === 'string') {
|
|
34203
|
-
const s = String(j.state).toLowerCase();
|
|
34204
|
-
if (['on', 'motion', 'detected', 'active'].includes(s))
|
|
34205
|
-
val = true;
|
|
34206
|
-
if (['off', 'clear', 'inactive'].includes(s))
|
|
34207
|
-
val = false;
|
|
34208
|
-
}
|
|
34209
|
-
}
|
|
34210
|
-
catch { }
|
|
34211
|
-
}
|
|
34212
|
-
if (val !== undefined) {
|
|
34213
|
-
setAndEmit(this, 'motionDetected', val, ScryptedInterface.MotionSensor);
|
|
34214
|
-
}
|
|
34215
|
-
else {
|
|
34216
|
-
this.console?.debug?.(`Motion payload non gestito (${this.cfg.id}): "${raw}"`);
|
|
34217
|
-
}
|
|
34127
|
+
handlePrimary(topic, np) {
|
|
34128
|
+
if (topic === this.cfg.topics.motion)
|
|
34129
|
+
this.motionDetected = truthy(np);
|
|
34218
34130
|
}
|
|
34219
34131
|
}
|
|
34220
34132
|
class OccupancyMqttSensor extends BaseMqttSensor {
|
|
34221
|
-
handlePrimary(topic, np
|
|
34222
|
-
if (topic
|
|
34223
|
-
|
|
34224
|
-
let val;
|
|
34225
|
-
if (['occupied', 'presence', 'present', '1', 'true', 'on', 'yes'].includes(np))
|
|
34226
|
-
val = true;
|
|
34227
|
-
else if (['unoccupied', 'vacant', 'absent', '0', 'false', 'off', 'no', 'clear'].includes(np))
|
|
34228
|
-
val = false;
|
|
34229
|
-
if (val === undefined) {
|
|
34230
|
-
try {
|
|
34231
|
-
const j = JSON.parse(raw);
|
|
34232
|
-
if (typeof j?.occupied === 'boolean')
|
|
34233
|
-
val = !!j.occupied;
|
|
34234
|
-
else if (typeof j?.presence === 'boolean')
|
|
34235
|
-
val = !!j.presence;
|
|
34236
|
-
else if (typeof j?.occupancy === 'boolean')
|
|
34237
|
-
val = !!j.occupancy;
|
|
34238
|
-
else if (typeof j?.state === 'string') {
|
|
34239
|
-
const s = String(j.state).toLowerCase();
|
|
34240
|
-
if (['occupied', 'presence', 'present', 'on'].includes(s))
|
|
34241
|
-
val = true;
|
|
34242
|
-
if (['vacant', 'absent', 'clear', 'off'].includes(s))
|
|
34243
|
-
val = false;
|
|
34244
|
-
}
|
|
34245
|
-
}
|
|
34246
|
-
catch { }
|
|
34247
|
-
}
|
|
34248
|
-
if (val !== undefined) {
|
|
34249
|
-
setAndEmit(this, 'occupied', val, ScryptedInterface.OccupancySensor);
|
|
34250
|
-
}
|
|
34251
|
-
else {
|
|
34252
|
-
this.console?.debug?.(`Occupancy payload non gestito (${this.cfg.id}): "${raw}"`);
|
|
34253
|
-
}
|
|
34133
|
+
handlePrimary(topic, np) {
|
|
34134
|
+
if (topic === this.cfg.topics.occupancy)
|
|
34135
|
+
this.occupied = truthy(np);
|
|
34254
34136
|
}
|
|
34255
34137
|
}
|
|
34256
34138
|
/** ----------------- Main Plugin ----------------- */
|
|
@@ -34259,8 +34141,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34259
34141
|
super();
|
|
34260
34142
|
this.sensorsCfg = [];
|
|
34261
34143
|
this.devices = new Map();
|
|
34262
|
-
|
|
34263
|
-
this.discoveryPostponed = false;
|
|
34144
|
+
this.triedDiscoveryOnce = false;
|
|
34264
34145
|
// Tipo in UI (best-effort)
|
|
34265
34146
|
setTimeout(() => {
|
|
34266
34147
|
try {
|
|
@@ -34279,7 +34160,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34279
34160
|
],
|
|
34280
34161
|
};
|
|
34281
34162
|
this.online = this.online ?? false;
|
|
34282
|
-
// Config sensori e
|
|
34163
|
+
// Config sensori e announce
|
|
34283
34164
|
this.loadSensorsFromStorage();
|
|
34284
34165
|
this.safeDiscoverSensors(); // non spamma se deviceManager non c'è
|
|
34285
34166
|
// Connect MQTT
|
|
@@ -34325,13 +34206,17 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34325
34206
|
{ group: 'Alarm Topics', key: 'topicOnline', title: 'Get Online (subscribe)', placeholder: 'paradox/interface/availability', value: this.storage.getItem('topicOnline') || '' },
|
|
34326
34207
|
{ group: 'Publish Options', key: 'qos', title: 'QoS', type: 'integer', value: parseInt(this.storage.getItem('qos') || '0') },
|
|
34327
34208
|
{ group: 'Publish Options', key: 'retain', title: 'Retain', type: 'boolean', value: this.storage.getItem('retain') === 'true' },
|
|
34209
|
+
// ---- Danger Zone ----
|
|
34210
|
+
{ group: 'Danger Zone', key: 'danger.resetSensors', title: 'Reset all sensors (wipe)', type: 'boolean', description: 'Cancella tutti i sensori salvati e rimuove i device annunciati.' },
|
|
34211
|
+
{ group: 'Danger Zone', key: 'danger.export', title: 'Export sensors JSON (read-only)', value: JSON.stringify(this.sensorsCfg, null, 2), readonly: true },
|
|
34212
|
+
{ group: 'Danger Zone', key: 'danger.import', title: 'Import sensors JSON (paste & Save)', type: 'string', placeholder: '[]', description: 'Incolla JSON valido per sovrascrivere l’elenco sensori.' },
|
|
34328
34213
|
];
|
|
34329
|
-
// Add Sensor
|
|
34330
|
-
out.push({ group: 'Add Sensor', key: 'new.id', title: 'New Sensor ID', placeholder: 'porta-
|
|
34331
|
-
// Sensors esistenti
|
|
34214
|
+
// ---- Add Sensor
|
|
34215
|
+
out.push({ group: 'Add Sensor', key: 'new.id', title: 'New Sensor ID', placeholder: 'porta-sogg', value: this.storage.getItem('new.id') || '' }, { group: 'Add Sensor', key: 'new.name', title: 'Name', placeholder: 'Porta Soggiorno', value: this.storage.getItem('new.name') || '' }, { group: 'Add Sensor', key: 'new.kind', title: 'Type', value: this.storage.getItem('new.kind') || 'contact', choices: ['contact', 'motion', 'occupancy'] }, { group: 'Add Sensor', key: 'new.create', title: 'Create sensor', type: 'boolean', description: 'Toggle ON e Save per creare.' });
|
|
34216
|
+
// ---- Sensors esistenti
|
|
34332
34217
|
for (const cfg of this.sensorsCfg) {
|
|
34333
34218
|
const gid = `Sensor: ${cfg.name} [${cfg.id}]`;
|
|
34334
|
-
out.push({ group: gid, key: `sensor.${cfg.id}.name`, title: 'Name', value: cfg.name }, { group: gid, key: `sensor.${cfg.id}.kind`, title: 'Type', value: cfg.kind, choices: ['contact', 'motion', 'occupancy'] });
|
|
34219
|
+
out.push({ group: gid, key: `sensor.${cfg.id}.id`, title: 'ID (read-only)', value: cfg.id, readonly: true, description: 'L’ID identifica il device. Evita spazi/puntini.' }, { group: gid, key: `sensor.${cfg.id}.name`, title: 'Name', value: cfg.name }, { group: gid, key: `sensor.${cfg.id}.kind`, title: 'Type', value: cfg.kind, choices: ['contact', 'motion', 'occupancy'] }, { group: gid, key: `sensor.${cfg.id}.renameTo`, title: 'Clone/Rename → New ID', placeholder: 'es. porta-sogg', description: 'Compila e Save per clonare con nuovo ID e rimuovere il vecchio.' });
|
|
34335
34220
|
if (cfg.kind === 'contact')
|
|
34336
34221
|
out.push({ group: gid, key: `sensor.${cfg.id}.topic.contact`, title: 'Contact State Topic', value: cfg.topics.contact || '' });
|
|
34337
34222
|
else if (cfg.kind === 'motion')
|
|
@@ -34344,6 +34229,46 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34344
34229
|
}
|
|
34345
34230
|
async putSetting(key, value) {
|
|
34346
34231
|
this.storage.setItem(key, String(value));
|
|
34232
|
+
// ---- Danger Zone: reset all ----
|
|
34233
|
+
if (key === 'danger.resetSensors' && String(value) === 'true') {
|
|
34234
|
+
this.storage.removeItem('danger.resetSensors');
|
|
34235
|
+
// rimuovi device annunciati
|
|
34236
|
+
try {
|
|
34237
|
+
const dm = sdk?.deviceManager;
|
|
34238
|
+
for (const nativeId of Array.from(this.devices.keys())) {
|
|
34239
|
+
try {
|
|
34240
|
+
dm?.onDeviceRemoved?.(nativeId);
|
|
34241
|
+
}
|
|
34242
|
+
catch { }
|
|
34243
|
+
}
|
|
34244
|
+
}
|
|
34245
|
+
catch { }
|
|
34246
|
+
this.devices.clear();
|
|
34247
|
+
this.sensorsCfg = [];
|
|
34248
|
+
this.saveSensorsToStorage();
|
|
34249
|
+
this.safeDiscoverSensors(true);
|
|
34250
|
+
await this.connectMqtt(true);
|
|
34251
|
+
return;
|
|
34252
|
+
}
|
|
34253
|
+
// ---- Danger Zone: import JSON ----
|
|
34254
|
+
if (key === 'danger.import') {
|
|
34255
|
+
try {
|
|
34256
|
+
const parsed = JSON.parse(String(value) || '[]');
|
|
34257
|
+
if (!Array.isArray(parsed))
|
|
34258
|
+
throw new Error('JSON non è un array.');
|
|
34259
|
+
// sanifica
|
|
34260
|
+
this.sensorsCfg = (parsed || []).filter(x => x && x.id && x.name && x.kind && x.topics);
|
|
34261
|
+
this.saveSensorsToStorage();
|
|
34262
|
+
this.storage.removeItem('danger.import');
|
|
34263
|
+
this.safeDiscoverSensors(true);
|
|
34264
|
+
await this.connectMqtt(true);
|
|
34265
|
+
}
|
|
34266
|
+
catch (e) {
|
|
34267
|
+
this.console.error('Import JSON error:', e);
|
|
34268
|
+
}
|
|
34269
|
+
return;
|
|
34270
|
+
}
|
|
34271
|
+
// ---- Add Sensor ----
|
|
34347
34272
|
if (key === 'new.create' && String(value) === 'true') {
|
|
34348
34273
|
const id = (this.storage.getItem('new.id') || '').trim();
|
|
34349
34274
|
const name = (this.storage.getItem('new.name') || '').trim() || id;
|
|
@@ -34366,6 +34291,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34366
34291
|
await this.connectMqtt(true);
|
|
34367
34292
|
return;
|
|
34368
34293
|
}
|
|
34294
|
+
// ---- Edit/Remove/Rename sensore ----
|
|
34369
34295
|
const m = key.match(/^sensor\.([^\.]+)\.(.+)$/);
|
|
34370
34296
|
if (m) {
|
|
34371
34297
|
const sid = m[1];
|
|
@@ -34375,6 +34301,30 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34375
34301
|
this.console.warn('putSetting: sensor non trovato', sid);
|
|
34376
34302
|
return;
|
|
34377
34303
|
}
|
|
34304
|
+
// rename/clone
|
|
34305
|
+
if (prop === 'renameTo') {
|
|
34306
|
+
const newId = String(value).trim();
|
|
34307
|
+
this.storage.removeItem(key);
|
|
34308
|
+
if (!newId)
|
|
34309
|
+
return;
|
|
34310
|
+
if (this.sensorsCfg.find(s => s.id === newId)) {
|
|
34311
|
+
this.console.warn('renameTo: ID già esistente:', newId);
|
|
34312
|
+
return;
|
|
34313
|
+
}
|
|
34314
|
+
const cloned = { ...cfg, id: newId, name: cfg.name };
|
|
34315
|
+
this.sensorsCfg.push(cloned);
|
|
34316
|
+
// rimuovi vecchio
|
|
34317
|
+
this.sensorsCfg = this.sensorsCfg.filter(s => s !== cfg);
|
|
34318
|
+
try {
|
|
34319
|
+
sdk?.deviceManager?.onDeviceRemoved?.(`sensor:${sid}`);
|
|
34320
|
+
}
|
|
34321
|
+
catch { }
|
|
34322
|
+
this.saveSensorsToStorage();
|
|
34323
|
+
this.safeDiscoverSensors(true);
|
|
34324
|
+
await this.connectMqtt(true);
|
|
34325
|
+
return;
|
|
34326
|
+
}
|
|
34327
|
+
// remove
|
|
34378
34328
|
if (prop === 'remove' && String(value) === 'true') {
|
|
34379
34329
|
this.sensorsCfg = this.sensorsCfg.filter(s => s.id !== sid);
|
|
34380
34330
|
this.saveSensorsToStorage();
|
|
@@ -34387,6 +34337,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34387
34337
|
await this.connectMqtt(true);
|
|
34388
34338
|
return;
|
|
34389
34339
|
}
|
|
34340
|
+
// edit
|
|
34390
34341
|
if (prop === 'name')
|
|
34391
34342
|
cfg.name = String(value);
|
|
34392
34343
|
else if (prop === 'kind')
|
|
@@ -34400,6 +34351,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34400
34351
|
await this.connectMqtt(true);
|
|
34401
34352
|
return;
|
|
34402
34353
|
}
|
|
34354
|
+
// Altre impostazioni: riconnetti
|
|
34403
34355
|
if (key === 'sensorsJson') {
|
|
34404
34356
|
this.loadSensorsFromStorage();
|
|
34405
34357
|
this.safeDiscoverSensors(true);
|
|
@@ -34436,21 +34388,18 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34436
34388
|
this.sensorsCfg = [];
|
|
34437
34389
|
}
|
|
34438
34390
|
}
|
|
34439
|
-
/** Annuncia i sensori SOLO se deviceManager è pronto.
|
|
34391
|
+
/** Annuncia i sensori SOLO se deviceManager è pronto. */
|
|
34440
34392
|
safeDiscoverSensors(triggeredByChange = false) {
|
|
34441
34393
|
const dmAny = sdk?.deviceManager;
|
|
34442
34394
|
if (!dmAny) {
|
|
34443
|
-
|
|
34444
|
-
if (!this.discoveryPostponed) {
|
|
34395
|
+
if (!this.triedDiscoveryOnce) {
|
|
34445
34396
|
this.console.log('Device discovery postponed: deviceManager not ready yet.');
|
|
34446
|
-
this.
|
|
34397
|
+
this.triedDiscoveryOnce = true;
|
|
34447
34398
|
}
|
|
34448
34399
|
return;
|
|
34449
34400
|
}
|
|
34450
|
-
this.
|
|
34401
|
+
this.triedDiscoveryOnce = false;
|
|
34451
34402
|
this.discoverSensors(dmAny);
|
|
34452
|
-
if (triggeredByChange)
|
|
34453
|
-
this.console.log('Sensors discovered/updated.');
|
|
34454
34403
|
}
|
|
34455
34404
|
/** discoverSensors con deviceManager garantito */
|
|
34456
34405
|
discoverSensors(dmAny) {
|
|
@@ -34497,7 +34446,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34497
34446
|
}
|
|
34498
34447
|
const hasBattery = !!(cfg.topics.batteryLevel || cfg.topics.lowBattery);
|
|
34499
34448
|
if (hasBattery && dev.batteryLevel === undefined)
|
|
34500
|
-
|
|
34449
|
+
dev.batteryLevel = 100;
|
|
34501
34450
|
}
|
|
34502
34451
|
// 4) Cleanup
|
|
34503
34452
|
const announced = new Set(manifests.map(m => m.nativeId));
|
|
@@ -34562,15 +34511,15 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34562
34511
|
const tOnline = this.storage.getItem('topicOnline') || '';
|
|
34563
34512
|
client.on('connect', () => {
|
|
34564
34513
|
this.console.log('MQTT connected');
|
|
34565
|
-
|
|
34514
|
+
this.online = true;
|
|
34566
34515
|
if (subs.length)
|
|
34567
34516
|
client.subscribe(subs, { qos: 0 }, (err) => { if (err)
|
|
34568
34517
|
this.console.error('subscribe error', err); });
|
|
34569
|
-
// Al primo connect riprova
|
|
34518
|
+
// Al primo connect riprova ad annunciare i sensori
|
|
34570
34519
|
this.safeDiscoverSensors(true);
|
|
34571
34520
|
});
|
|
34572
34521
|
client.on('reconnect', () => this.console.log('MQTT reconnecting...'));
|
|
34573
|
-
client.on('close', () => { this.console.log('MQTT closed');
|
|
34522
|
+
client.on('close', () => { this.console.log('MQTT closed'); this.online = false; });
|
|
34574
34523
|
client.on('error', (e) => { this.console.error('MQTT error', e); });
|
|
34575
34524
|
client.on('message', (topic, payload) => {
|
|
34576
34525
|
try {
|
|
@@ -34578,26 +34527,23 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34578
34527
|
const np = normalize(p);
|
|
34579
34528
|
if (topic === tOnline) {
|
|
34580
34529
|
if (truthy(np) || np === 'online')
|
|
34581
|
-
|
|
34530
|
+
this.online = true;
|
|
34582
34531
|
if (falsy(np) || np === 'offline')
|
|
34583
|
-
|
|
34532
|
+
this.online = false;
|
|
34584
34533
|
return;
|
|
34585
34534
|
}
|
|
34586
34535
|
if (topic === tTamper) {
|
|
34587
|
-
if (truthy(np) || ['tamper', 'intrusion', 'cover'].includes(np))
|
|
34588
|
-
|
|
34589
|
-
|
|
34590
|
-
|
|
34591
|
-
else if (falsy(np)) {
|
|
34592
|
-
setAndEmit(this, 'tampered', false, ScryptedInterface.TamperSensor);
|
|
34593
|
-
}
|
|
34536
|
+
if (truthy(np) || ['tamper', 'intrusion', 'cover'].includes(np))
|
|
34537
|
+
this.tampered = ['cover', 'intrusion'].find(x => x === np) || true;
|
|
34538
|
+
else if (falsy(np))
|
|
34539
|
+
this.tampered = false;
|
|
34594
34540
|
return;
|
|
34595
34541
|
}
|
|
34596
34542
|
if (topic === tCurrent) {
|
|
34597
34543
|
const mode = payloadToMode(payload);
|
|
34598
34544
|
const isAlarm = ['alarm', 'triggered'].includes(np);
|
|
34599
34545
|
const current = this.securitySystemState || { mode: SecuritySystemMode.Disarmed };
|
|
34600
|
-
|
|
34546
|
+
this.securitySystemState = {
|
|
34601
34547
|
mode: mode ?? current.mode,
|
|
34602
34548
|
supportedModes: current.supportedModes ?? [
|
|
34603
34549
|
SecuritySystemMode.Disarmed,
|
|
@@ -34607,13 +34553,6 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34607
34553
|
],
|
|
34608
34554
|
triggered: isAlarm || undefined,
|
|
34609
34555
|
};
|
|
34610
|
-
if (!deepEqual(this.securitySystemState, newState)) {
|
|
34611
|
-
this.securitySystemState = newState;
|
|
34612
|
-
try {
|
|
34613
|
-
this.onDeviceEvent?.(ScryptedInterface.SecuritySystem, newState);
|
|
34614
|
-
}
|
|
34615
|
-
catch { }
|
|
34616
|
-
}
|
|
34617
34556
|
return;
|
|
34618
34557
|
}
|
|
34619
34558
|
if (topic === tTarget) {
|
|
@@ -34621,9 +34560,8 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
|
34621
34560
|
this.console.log('Target state reported:', p, '->', this.pendingTarget);
|
|
34622
34561
|
return;
|
|
34623
34562
|
}
|
|
34624
|
-
// Dispatch ai sensori
|
|
34625
|
-
|
|
34626
|
-
if (this.discoveryPostponed)
|
|
34563
|
+
// Dispatch ai sensori + eventuale discover ritardato
|
|
34564
|
+
if (this.triedDiscoveryOnce)
|
|
34627
34565
|
this.safeDiscoverSensors(true);
|
|
34628
34566
|
for (const dev of this.devices.values())
|
|
34629
34567
|
dev.handleMqtt(topic, payload);
|
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED