@rfranzoi/scrypted-mqtt-securitysystem 1.0.38 → 1.0.39

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.
@@ -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,38 +34039,53 @@ 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 (runtime only: niente import ESM per evitare che il bundler lo esegua prima del preload)
34042
+ // Runtime SDK via require (evita esecuzione anticipata del bundler)
34044
34043
  const sdk = __webpack_require__(/*! @scrypted/sdk */ "./node_modules/@scrypted/sdk/dist/src/index.js");
34045
- // Valori runtime dal modulo SDK
34046
- const { ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, // enum (valori)
34047
- SecuritySystemMode, // enum (valori)
34048
- systemManager, } = sdk;
34044
+ const { ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, SecuritySystemMode, systemManager, } = sdk;
34049
34045
  const mqtt_1 = __importDefault(__webpack_require__(/*! mqtt */ "./node_modules/mqtt/build/index.js"));
34050
34046
  /** utils */
34047
+ function normalize(s) { return (s || '').trim().toLowerCase(); }
34051
34048
  function truthy(v) {
34052
34049
  if (!v)
34053
34050
  return false;
34054
- const s = v.toString().trim().toLowerCase();
34055
- return s === '1' || s === 'true' || s === 'online' || s === 'yes' || s === 'on' || s === 'ok';
34051
+ const s = normalize(v);
34052
+ return s === '1' || s === 'true' || s === 'online' || s === 'yes' || s === 'on' || s === 'ok' || s === 'open';
34056
34053
  }
34057
34054
  function falsy(v) {
34058
34055
  if (!v)
34059
34056
  return false;
34060
- const s = v.toString().trim().toLowerCase();
34061
- return s === '0' || s === 'false' || s === 'offline' || s === 'no' || s === 'off';
34057
+ const s = normalize(v);
34058
+ return s === '0' || s === 'false' || s === 'offline' || s === 'no' || s === 'off' || s === 'closed' || s === 'close';
34062
34059
  }
34063
- function normalize(s) { return (s || '').trim().toLowerCase(); }
34064
34060
  function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); }
34065
- function deepEqual(a, b) {
34061
+ function deepEqual(a, b) { try {
34062
+ return JSON.stringify(a) === JSON.stringify(b);
34063
+ }
34064
+ catch {
34065
+ return a === b;
34066
+ } }
34067
+ /** Match topic con wildcard MQTT (+, #) oppure confronto esatto */
34068
+ function topicMatches(topic, pattern) {
34069
+ if (!pattern)
34070
+ return false;
34071
+ if (pattern === topic)
34072
+ return true;
34073
+ if (!pattern.includes('+') && !pattern.includes('#'))
34074
+ return false;
34075
+ // Escapa tutto tranne '/'
34076
+ const esc = pattern.replace(/[-/\\^$*?.()|[\]{}]/g, '\\$&');
34077
+ const rx = '^' + esc
34078
+ .replace(/\\\+/g, '[^/]+') // '+' => un segmento
34079
+ .replace(/\\\#/g, '.+'); // '#" => qualsiasi suffisso
34066
34080
  try {
34067
- return JSON.stringify(a) === JSON.stringify(b);
34081
+ return new RegExp(rx + '$').test(topic);
34068
34082
  }
34069
34083
  catch {
34070
- return a === b;
34084
+ return false;
34071
34085
  }
34072
34086
  }
34073
- /** Imposta una property e, se cambia, emette anche l'evento Scrypted corrispondente */
34074
- function setAndEmit(dev, key, value, iface) {
34087
+ /** set + emit evento scrypted */
34088
+ function setAndEmit(dev, key, value, iface, log) {
34075
34089
  if (dev[key] === value)
34076
34090
  return;
34077
34091
  dev[key] = value;
@@ -34079,15 +34093,19 @@ function setAndEmit(dev, key, value, iface) {
34079
34093
  dev.onDeviceEvent?.(iface, value);
34080
34094
  }
34081
34095
  catch { }
34096
+ try {
34097
+ if (log)
34098
+ dev.console?.log?.(log);
34099
+ }
34100
+ catch { }
34082
34101
  }
34083
- /** Outgoing predefiniti (PAI-like). Chiavi numeriche per compatibilità enum */
34102
+ /** Outgoing predefiniti (PAI-like). Chiavi numeriche per compat enum */
34084
34103
  const DEFAULT_OUTGOING = {
34085
34104
  [SecuritySystemMode.Disarmed]: 'disarm',
34086
34105
  [SecuritySystemMode.HomeArmed]: 'arm_home',
34087
34106
  [SecuritySystemMode.AwayArmed]: 'arm_away',
34088
34107
  [SecuritySystemMode.NightArmed]: 'arm_night',
34089
34108
  };
34090
- /** Parse incoming payload -> final mode (ignora transitori) */
34091
34109
  function payloadToMode(payload) {
34092
34110
  if (payload == null)
34093
34111
  return;
@@ -34110,45 +34128,46 @@ class BaseMqttSensor extends ScryptedDeviceBase {
34110
34128
  this.cfg = cfg;
34111
34129
  }
34112
34130
  handleMqtt(topic, payload) {
34113
- const p = payload?.toString() ?? '';
34114
- const np = normalize(p);
34131
+ const raw = payload?.toString() ?? '';
34132
+ const np = normalize(raw);
34115
34133
  // Online
34116
- if (topic === this.cfg.topics.online) {
34134
+ if (topicMatches(topic, this.cfg.topics.online)) {
34117
34135
  if (truthy(np) || np === 'online')
34118
- setAndEmit(this, 'online', true, ScryptedInterface.Online);
34119
- if (falsy(np) || np === 'offline')
34120
- setAndEmit(this, 'online', false, ScryptedInterface.Online);
34136
+ setAndEmit(this, 'online', true, ScryptedInterface.Online, `[${this.name}] online=true`);
34137
+ else if (falsy(np) || np === 'offline')
34138
+ setAndEmit(this, 'online', false, ScryptedInterface.Online, `[${this.name}] online=false`);
34121
34139
  }
34122
34140
  // Tamper
34123
- if (topic === this.cfg.topics.tamper) {
34141
+ if (topicMatches(topic, this.cfg.topics.tamper)) {
34124
34142
  if (truthy(np) || ['tamper', 'intrusion', 'cover', 'motion', 'magnetic'].includes(np)) {
34125
34143
  const t = ['cover', 'intrusion', 'motion', 'magnetic'].find(x => x === np) || true;
34126
- setAndEmit(this, 'tampered', t, ScryptedInterface.TamperSensor);
34144
+ setAndEmit(this, 'tampered', t, ScryptedInterface.TamperSensor, `[${this.name}] tampered=${t}`);
34145
+ }
34146
+ else if (falsy(np)) {
34147
+ setAndEmit(this, 'tampered', false, ScryptedInterface.TamperSensor, `[${this.name}] tampered=false`);
34127
34148
  }
34128
- else if (falsy(np))
34129
- setAndEmit(this, 'tampered', false, ScryptedInterface.TamperSensor);
34130
34149
  }
34131
34150
  // Battery
34132
- if (topic === this.cfg.topics.batteryLevel) {
34133
- const n = clamp(parseFloat(p), 0, 100);
34151
+ if (topicMatches(topic, this.cfg.topics.batteryLevel)) {
34152
+ const n = clamp(parseFloat(raw), 0, 100);
34134
34153
  if (isFinite(n))
34135
- setAndEmit(this, 'batteryLevel', n, ScryptedInterface.Battery);
34154
+ setAndEmit(this, 'batteryLevel', n, ScryptedInterface.Battery, `[${this.name}] batteryLevel=${n}`);
34136
34155
  }
34137
- else if (topic === this.cfg.topics.lowBattery && !this.cfg.topics.batteryLevel) {
34156
+ else if (topicMatches(topic, this.cfg.topics.lowBattery) && !this.cfg.topics.batteryLevel) {
34138
34157
  const n = truthy(np) ? 10 : 100;
34139
- setAndEmit(this, 'batteryLevel', n, ScryptedInterface.Battery);
34158
+ setAndEmit(this, 'batteryLevel', n, ScryptedInterface.Battery, `[${this.name}] batteryLevel=${n} (lowBattery)`);
34140
34159
  }
34141
- // Primary
34142
- this.handlePrimary(topic, np, p);
34160
+ // Primario
34161
+ this.handlePrimary(topic, np, raw);
34143
34162
  }
34144
34163
  }
34145
- /** === SENSORI CON PARSING ROBUSTO + EMISSIONE EVENTI === */
34164
+ /** === SENSORI: parsing robusto + eventi === */
34146
34165
  class ContactMqttSensor extends BaseMqttSensor {
34147
34166
  handlePrimary(topic, np, raw) {
34148
- if (topic !== this.cfg.topics.contact)
34167
+ if (!topicMatches(topic, this.cfg.topics.contact))
34149
34168
  return;
34150
34169
  let val;
34151
- // stringhe comuni
34170
+ // stringhe comuni (True/False compresi via normalize)
34152
34171
  if (['open', 'opened', '1', 'true', 'on', 'yes'].includes(np))
34153
34172
  val = true;
34154
34173
  else if (['closed', 'close', '0', 'false', 'off', 'no', 'shut'].includes(np))
@@ -34162,9 +34181,9 @@ class ContactMqttSensor extends BaseMqttSensor {
34162
34181
  else if (typeof j?.opened === 'boolean')
34163
34182
  val = !!j.opened;
34164
34183
  else if (typeof j?.contact === 'boolean')
34165
- val = !j.contact; // contact:false => OPEN
34184
+ val = !j.contact; // contact:false => aperto
34166
34185
  else if (typeof j?.state === 'string') {
34167
- const s = String(j.state).toLowerCase();
34186
+ const s = normalize(j.state);
34168
34187
  if (s === 'open')
34169
34188
  val = true;
34170
34189
  if (s === 'closed')
@@ -34174,16 +34193,16 @@ class ContactMqttSensor extends BaseMqttSensor {
34174
34193
  catch { }
34175
34194
  }
34176
34195
  if (val !== undefined) {
34177
- setAndEmit(this, 'entryOpen', val, ScryptedInterface.EntrySensor);
34196
+ setAndEmit(this, 'entryOpen', val, ScryptedInterface.EntrySensor, `[${this.name}] entryOpen=${val} (${topic})`);
34178
34197
  }
34179
34198
  else {
34180
- this.console?.debug?.(`Contact payload non gestito (${this.cfg.id}): "${raw}"`);
34199
+ this.console?.debug?.(`Contact payload non gestito (${this.cfg.id}) topic=${topic} raw="${raw}"`);
34181
34200
  }
34182
34201
  }
34183
34202
  }
34184
34203
  class MotionMqttSensor extends BaseMqttSensor {
34185
34204
  handlePrimary(topic, np, raw) {
34186
- if (topic !== this.cfg.topics.motion)
34205
+ if (!topicMatches(topic, this.cfg.topics.motion))
34187
34206
  return;
34188
34207
  let val;
34189
34208
  if (['motion', 'detected', 'active', '1', 'true', 'on', 'yes'].includes(np))
@@ -34200,7 +34219,7 @@ class MotionMqttSensor extends BaseMqttSensor {
34200
34219
  else if (typeof j?.presence === 'boolean')
34201
34220
  val = !!j.presence;
34202
34221
  else if (typeof j?.state === 'string') {
34203
- const s = String(j.state).toLowerCase();
34222
+ const s = normalize(j.state);
34204
34223
  if (['on', 'motion', 'detected', 'active'].includes(s))
34205
34224
  val = true;
34206
34225
  if (['off', 'clear', 'inactive'].includes(s))
@@ -34210,16 +34229,16 @@ class MotionMqttSensor extends BaseMqttSensor {
34210
34229
  catch { }
34211
34230
  }
34212
34231
  if (val !== undefined) {
34213
- setAndEmit(this, 'motionDetected', val, ScryptedInterface.MotionSensor);
34232
+ setAndEmit(this, 'motionDetected', val, ScryptedInterface.MotionSensor, `[${this.name}] motionDetected=${val} (${topic})`);
34214
34233
  }
34215
34234
  else {
34216
- this.console?.debug?.(`Motion payload non gestito (${this.cfg.id}): "${raw}"`);
34235
+ this.console?.debug?.(`Motion payload non gestito (${this.cfg.id}) topic=${topic} raw="${raw}"`);
34217
34236
  }
34218
34237
  }
34219
34238
  }
34220
34239
  class OccupancyMqttSensor extends BaseMqttSensor {
34221
34240
  handlePrimary(topic, np, raw) {
34222
- if (topic !== this.cfg.topics.occupancy)
34241
+ if (!topicMatches(topic, this.cfg.topics.occupancy))
34223
34242
  return;
34224
34243
  let val;
34225
34244
  if (['occupied', 'presence', 'present', '1', 'true', 'on', 'yes'].includes(np))
@@ -34236,7 +34255,7 @@ class OccupancyMqttSensor extends BaseMqttSensor {
34236
34255
  else if (typeof j?.occupancy === 'boolean')
34237
34256
  val = !!j.occupancy;
34238
34257
  else if (typeof j?.state === 'string') {
34239
- const s = String(j.state).toLowerCase();
34258
+ const s = normalize(j.state);
34240
34259
  if (['occupied', 'presence', 'present', 'on'].includes(s))
34241
34260
  val = true;
34242
34261
  if (['vacant', 'absent', 'clear', 'off'].includes(s))
@@ -34246,10 +34265,10 @@ class OccupancyMqttSensor extends BaseMqttSensor {
34246
34265
  catch { }
34247
34266
  }
34248
34267
  if (val !== undefined) {
34249
- setAndEmit(this, 'occupied', val, ScryptedInterface.OccupancySensor);
34268
+ setAndEmit(this, 'occupied', val, ScryptedInterface.OccupancySensor, `[${this.name}] occupied=${val} (${topic})`);
34250
34269
  }
34251
34270
  else {
34252
- this.console?.debug?.(`Occupancy payload non gestito (${this.cfg.id}): "${raw}"`);
34271
+ this.console?.debug?.(`Occupancy payload non gestito (${this.cfg.id}) topic=${topic} raw="${raw}"`);
34253
34272
  }
34254
34273
  }
34255
34274
  }
@@ -34259,7 +34278,6 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34259
34278
  super();
34260
34279
  this.sensorsCfg = [];
34261
34280
  this.devices = new Map();
34262
- // Evita loop di log: tenta una volta finché deviceManager non c’è, poi riprova su eventi utili.
34263
34281
  this.discoveryPostponed = false;
34264
34282
  // Tipo in UI (best-effort)
34265
34283
  setTimeout(() => {
@@ -34279,12 +34297,9 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34279
34297
  ],
34280
34298
  };
34281
34299
  this.online = this.online ?? false;
34282
- // Config sensori e (tentativo) announce
34283
34300
  this.loadSensorsFromStorage();
34284
- this.safeDiscoverSensors(); // non spamma se deviceManager non c'è
34285
- // Connect MQTT
34301
+ this.safeDiscoverSensors();
34286
34302
  this.connectMqtt().catch((e) => this.console.error('MQTT connect error:', e));
34287
- // Shutdown pulito
34288
34303
  try {
34289
34304
  process.once('SIGTERM', () => { try {
34290
34305
  this.client?.end(true);
@@ -34328,12 +34343,11 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34328
34343
  ];
34329
34344
  // Add Sensor
34330
34345
  out.push({ group: 'Add Sensor', key: 'new.id', title: 'New Sensor ID', placeholder: 'porta-ingresso', value: this.storage.getItem('new.id') || '' }, { group: 'Add Sensor', key: 'new.name', title: 'Name', placeholder: 'Porta Ingresso', 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 to create the sensor.' });
34331
- // Sensors esistenti
34332
34346
  for (const cfg of this.sensorsCfg) {
34333
34347
  const gid = `Sensor: ${cfg.name} [${cfg.id}]`;
34334
34348
  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'] });
34335
34349
  if (cfg.kind === 'contact')
34336
- out.push({ group: gid, key: `sensor.${cfg.id}.topic.contact`, title: 'Contact State Topic', value: cfg.topics.contact || '' });
34350
+ out.push({ group: gid, key: `sensor.${cfg.id}.topic.contact`, title: 'Contact State Topic', value: cfg.topics.contact || '', placeholder: 'paradox/states/zones/XYZ/open (supporta +/#)' });
34337
34351
  else if (cfg.kind === 'motion')
34338
34352
  out.push({ group: gid, key: `sensor.${cfg.id}.topic.motion`, title: 'Motion Detected Topic', value: cfg.topics.motion || '' });
34339
34353
  else
@@ -34436,11 +34450,9 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34436
34450
  this.sensorsCfg = [];
34437
34451
  }
34438
34452
  }
34439
- /** Annuncia i sensori SOLO se deviceManager è pronto. Niente loop infinito. */
34440
34453
  safeDiscoverSensors(triggeredByChange = false) {
34441
34454
  const dmAny = sdk?.deviceManager;
34442
34455
  if (!dmAny) {
34443
- // Posticipa una sola volta; poi riproviamo su connect MQTT e al primo messaggio
34444
34456
  if (!this.discoveryPostponed) {
34445
34457
  this.console.log('Device discovery postponed: deviceManager not ready yet.');
34446
34458
  this.discoveryPostponed = true;
@@ -34452,9 +34464,7 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34452
34464
  if (triggeredByChange)
34453
34465
  this.console.log('Sensors discovered/updated.');
34454
34466
  }
34455
- /** discoverSensors con deviceManager garantito */
34456
34467
  discoverSensors(dmAny) {
34457
- // 1) Manifests
34458
34468
  const manifests = this.sensorsCfg.map(cfg => {
34459
34469
  const nativeId = `sensor:${cfg.id}`;
34460
34470
  const t = cfg.topics || {};
@@ -34471,15 +34481,11 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34471
34481
  interfaces.push(ScryptedInterface.Battery);
34472
34482
  return { nativeId, name: cfg.name, type: ScryptedDeviceType.Sensor, interfaces };
34473
34483
  });
34474
- // 2) Annuncio
34475
- if (typeof dmAny.onDevicesChanged === 'function') {
34484
+ if (typeof dmAny.onDevicesChanged === 'function')
34476
34485
  dmAny.onDevicesChanged({ devices: manifests });
34477
- }
34478
- else if (typeof dmAny.onDeviceDiscovered === 'function') {
34486
+ else if (typeof dmAny.onDeviceDiscovered === 'function')
34479
34487
  for (const m of manifests)
34480
34488
  dmAny.onDeviceDiscovered(m);
34481
- }
34482
- // 3) Istanzia/aggiorna
34483
34489
  for (const cfg of this.sensorsCfg) {
34484
34490
  const nativeId = `sensor:${cfg.id}`;
34485
34491
  let dev = this.devices.get(nativeId);
@@ -34497,9 +34503,8 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34497
34503
  }
34498
34504
  const hasBattery = !!(cfg.topics.batteryLevel || cfg.topics.lowBattery);
34499
34505
  if (hasBattery && dev.batteryLevel === undefined)
34500
- setAndEmit(dev, 'batteryLevel', 100, ScryptedInterface.Battery);
34506
+ setAndEmit(dev, 'batteryLevel', 100, ScryptedInterface.Battery, `[${cfg.name}] batteryLevel=100 (default)`);
34501
34507
  }
34502
- // 4) Cleanup
34503
34508
  const announced = new Set(manifests.map(m => m.nativeId));
34504
34509
  for (const [nativeId] of this.devices) {
34505
34510
  if (!announced.has(nativeId)) {
@@ -34562,38 +34567,37 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34562
34567
  const tOnline = this.storage.getItem('topicOnline') || '';
34563
34568
  client.on('connect', () => {
34564
34569
  this.console.log('MQTT connected');
34565
- setAndEmit(this, 'online', true, ScryptedInterface.Online);
34570
+ setAndEmit(this, 'online', true, ScryptedInterface.Online, `[Alarm] online=true`);
34566
34571
  if (subs.length)
34567
34572
  client.subscribe(subs, { qos: 0 }, (err) => { if (err)
34568
34573
  this.console.error('subscribe error', err); });
34569
- // Al primo connect riprova (silenziosamente) ad annunciare i sensori
34570
34574
  this.safeDiscoverSensors(true);
34571
34575
  });
34572
34576
  client.on('reconnect', () => this.console.log('MQTT reconnecting...'));
34573
- client.on('close', () => { this.console.log('MQTT closed'); setAndEmit(this, 'online', false, ScryptedInterface.Online); });
34577
+ client.on('close', () => { this.console.log('MQTT closed'); setAndEmit(this, 'online', false, ScryptedInterface.Online, `[Alarm] online=false`); });
34574
34578
  client.on('error', (e) => { this.console.error('MQTT error', e); });
34575
34579
  client.on('message', (topic, payload) => {
34576
34580
  try {
34577
- const p = payload?.toString() ?? '';
34578
- const np = normalize(p);
34579
- if (topic === tOnline) {
34581
+ const raw = payload?.toString() ?? '';
34582
+ const np = normalize(raw);
34583
+ if (topicMatches(topic, tOnline)) {
34580
34584
  if (truthy(np) || np === 'online')
34581
- setAndEmit(this, 'online', true, ScryptedInterface.Online);
34582
- if (falsy(np) || np === 'offline')
34583
- setAndEmit(this, 'online', false, ScryptedInterface.Online);
34585
+ setAndEmit(this, 'online', true, ScryptedInterface.Online, `[Alarm] online=true (${topic})`);
34586
+ else if (falsy(np) || np === 'offline')
34587
+ setAndEmit(this, 'online', false, ScryptedInterface.Online, `[Alarm] online=false (${topic})`);
34584
34588
  return;
34585
34589
  }
34586
- if (topic === tTamper) {
34590
+ if (topicMatches(topic, tTamper)) {
34587
34591
  if (truthy(np) || ['tamper', 'intrusion', 'cover'].includes(np)) {
34588
34592
  const t = ['cover', 'intrusion'].find(x => x === np) || true;
34589
- setAndEmit(this, 'tampered', t, ScryptedInterface.TamperSensor);
34593
+ setAndEmit(this, 'tampered', t, ScryptedInterface.TamperSensor, `[Alarm] tampered=${t} (${topic})`);
34590
34594
  }
34591
34595
  else if (falsy(np)) {
34592
- setAndEmit(this, 'tampered', false, ScryptedInterface.TamperSensor);
34596
+ setAndEmit(this, 'tampered', false, ScryptedInterface.TamperSensor, `[Alarm] tampered=false (${topic})`);
34593
34597
  }
34594
34598
  return;
34595
34599
  }
34596
- if (topic === tCurrent) {
34600
+ if (topicMatches(topic, tCurrent)) {
34597
34601
  const mode = payloadToMode(payload);
34598
34602
  const isAlarm = ['alarm', 'triggered'].includes(np);
34599
34603
  const current = this.securitySystemState || { mode: SecuritySystemMode.Disarmed };
@@ -34613,16 +34617,16 @@ class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
34613
34617
  this.onDeviceEvent?.(ScryptedInterface.SecuritySystem, newState);
34614
34618
  }
34615
34619
  catch { }
34620
+ this.console.log(`[Alarm] currentState=${JSON.stringify(newState)} (${topic})`);
34616
34621
  }
34617
34622
  return;
34618
34623
  }
34619
- if (topic === tTarget) {
34624
+ if (topicMatches(topic, tTarget)) {
34620
34625
  this.pendingTarget = payloadToMode(payload);
34621
- this.console.log('Target state reported:', p, '->', this.pendingTarget);
34626
+ this.console.log(`[Alarm] target reported: "${raw}" -> ${this.pendingTarget} (${topic})`);
34622
34627
  return;
34623
34628
  }
34624
- // Dispatch ai sensori
34625
- // (E prova ad annunciare se era stato posticipato e ora il manager è pronto)
34629
+ // Sensors: se discovery rimandata, riprova
34626
34630
  if (this.discoveryPostponed)
34627
34631
  this.safeDiscoverSensors(true);
34628
34632
  for (const dev of this.devices.values())
package/dist/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rfranzoi/scrypted-mqtt-securitysystem",
3
- "version": "1.0.38",
3
+ "version": "1.0.39",
4
4
  "description": "Scrypted plugin: Paradox Security System via MQTT (PAI/PAI-MQTT style).",
5
5
  "license": "MIT",
6
6
  "main": "dist/main.nodejs.js",