@rfranzoi/scrypted-mqtt-securitysystem 1.0.48 → 1.0.49

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.
@@ -34077,8 +34077,12 @@ 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) { return (s || '').trim().toLowerCase(); }
34081
- function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); }
34080
+ function normalize(s) {
34081
+ return (s || '').trim().toLowerCase();
34082
+ }
34083
+ function clamp(n, min, max) {
34084
+ return Math.max(min, Math.min(max, n));
34085
+ }
34082
34086
  /** SecuritySystem outgoing defaults (PAI-like) */
34083
34087
  const DEFAULT_OUTGOING = {
34084
34088
  [sdk_1.SecuritySystemMode.Disarmed]: 'disarm',
@@ -34149,6 +34153,7 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
34149
34153
  this.setAndEmit('batteryLevel', n, sdk_1.ScryptedInterface.Battery);
34150
34154
  }
34151
34155
  else if (topic === this.cfg.topics.lowBattery && !this.cfg.topics.batteryLevel) {
34156
+ // Se abbiamo solo lowBattery: true => 10%, false => 100% (ma solo se non c'è già un valore)
34152
34157
  if (truthy(np))
34153
34158
  this.setAndEmit('batteryLevel', 10, sdk_1.ScryptedInterface.Battery);
34154
34159
  else if (falsy(np) && this.batteryLevel === undefined)
@@ -34204,14 +34209,17 @@ class OccupancyMqttSensor extends BaseMqttSensor {
34204
34209
  class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34205
34210
  constructor() {
34206
34211
  super();
34212
+ // sensor management
34207
34213
  this.sensorsCfg = [];
34208
34214
  this.devices = new Map();
34215
+ // (facoltativo) Imposta il device type in UI
34209
34216
  setTimeout(() => {
34210
34217
  try {
34211
34218
  systemManager.getDeviceById(this.id)?.setType?.(sdk_1.ScryptedDeviceType.SecuritySystem);
34212
34219
  }
34213
34220
  catch { }
34214
34221
  });
34222
+ // Default state
34215
34223
  this.securitySystemState = this.securitySystemState || {
34216
34224
  mode: sdk_1.SecuritySystemMode.Disarmed,
34217
34225
  supportedModes: [
@@ -34222,9 +34230,12 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34222
34230
  ],
34223
34231
  };
34224
34232
  this.online = this.online ?? false;
34233
+ // Load sensors config and announce devices
34225
34234
  this.loadSensorsFromStorage();
34226
34235
  this.discoverSensors().catch(e => this.console.error('discoverSensors error', e));
34236
+ // Connect on start
34227
34237
  this.connectMqtt().catch(e => this.console.error('MQTT connect error:', e));
34238
+ // chiusura pulita del client MQTT ai reload/stop del plugin
34228
34239
  try {
34229
34240
  process.once('SIGTERM', () => { try {
34230
34241
  this.client?.end(true);
@@ -34241,7 +34252,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34241
34252
  }
34242
34253
  catch { }
34243
34254
  }
34244
- /** ---- Helpers parsing ---- */
34255
+ // ====== Strict parsing helpers ======
34245
34256
  parseJsonArray(key, fallback) {
34246
34257
  try {
34247
34258
  const raw = (this.storage.getItem(key) || '').trim();
@@ -34256,45 +34267,46 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34256
34267
  return fallback;
34257
34268
  }
34258
34269
  }
34259
- getStrictTokens() {
34260
- const target = this.parseJsonArray('targetStateValues', ['armed_home', 'armed_away', 'armed_night', 'disarmed']);
34261
- const current = this.parseJsonArray('currentStateValues', ['armed_home', 'armed_away', 'armed_night', 'disarmed', 'triggered']);
34262
- const triggered = this.parseJsonArray('triggeredValues', ['triggered', 'alarm']);
34263
- const union = new Set([...target, ...current]);
34264
- return {
34265
- union,
34266
- triggered: new Set(triggered),
34267
- };
34268
- }
34269
34270
  useStrict() {
34270
34271
  return this.storage.getItem('strictParsing') === 'true';
34271
34272
  }
34272
34273
  parseIncomingMode(payload) {
34273
- const p = payload?.toString?.() ?? String(payload ?? '');
34274
- const np = normalize(p);
34274
+ const np = normalize(payload?.toString?.() ?? String(payload ?? ''));
34275
34275
  if (!this.useStrict())
34276
34276
  return payloadToModeLoose(np);
34277
- // strict: usa SOLO i token configurati
34278
- const { union } = this.getStrictTokens();
34279
- if (union.has('disarmed') && np === 'disarmed')
34277
+ const currentVals = new Set(this.parseJsonArray('currentStateValues', ['armed_home', 'armed_away', 'armed_night', 'disarmed', 'triggered']));
34278
+ if (currentVals.has('disarmed') && np === 'disarmed')
34280
34279
  return sdk_1.SecuritySystemMode.Disarmed;
34281
- if (union.has('armed_home') && np === 'armed_home')
34280
+ if (currentVals.has('armed_home') && np === 'armed_home')
34282
34281
  return sdk_1.SecuritySystemMode.HomeArmed;
34283
- if (union.has('armed_away') && np === 'armed_away')
34282
+ if (currentVals.has('armed_away') && np === 'armed_away')
34284
34283
  return sdk_1.SecuritySystemMode.AwayArmed;
34285
- if (union.has('armed_night') && np === 'armed_night')
34284
+ if (currentVals.has('armed_night') && np === 'armed_night')
34286
34285
  return sdk_1.SecuritySystemMode.NightArmed;
34287
- // transitori/altro: ignora
34288
34286
  return undefined;
34289
34287
  }
34290
34288
  isTriggeredToken(np) {
34291
34289
  if (this.useStrict()) {
34292
- const { triggered } = this.getStrictTokens();
34290
+ const triggered = new Set(this.parseJsonArray('triggeredValues', ['triggered', 'alarm']));
34293
34291
  return triggered.has(np);
34294
34292
  }
34295
- // loose
34296
34293
  return np === 'triggered' || np === 'alarm';
34297
34294
  }
34295
+ /** Sceglie il token di publish preferito per ciascuna modalità usando targetStateValues quando strict=ON */
34296
+ preferredTokenForMode(mode) {
34297
+ const t = this.parseJsonArray('targetStateValues', ['armed_home', 'armed_away', 'armed_night', 'disarmed']);
34298
+ const pick = (...cands) => cands.find(c => t.includes(c));
34299
+ switch (mode) {
34300
+ case sdk_1.SecuritySystemMode.Disarmed:
34301
+ return pick('disarmed', 'disarm') || 'disarmed';
34302
+ case sdk_1.SecuritySystemMode.HomeArmed:
34303
+ return pick('armed_home', 'arm_home', 'home', 'stay') || 'armed_home';
34304
+ case sdk_1.SecuritySystemMode.AwayArmed:
34305
+ return pick('armed_away', 'arm_away', 'away') || 'armed_away';
34306
+ case sdk_1.SecuritySystemMode.NightArmed:
34307
+ return pick('armed_night', 'arm_night', 'night', 'sleep') || 'armed_night';
34308
+ }
34309
+ }
34298
34310
  // helpers persistenza
34299
34311
  saveSensorsToStorage() {
34300
34312
  try {
@@ -34327,6 +34339,11 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34327
34339
  { group: 'Parsing / State tokens', key: 'targetStateValues', title: 'Accepted Target State Values (JSON array)', placeholder: '["armed_home","armed_away","armed_night","disarmed"]', value: this.storage.getItem('targetStateValues') || '["armed_home","armed_away","armed_night","disarmed"]' },
34328
34340
  { group: 'Parsing / State tokens', key: 'currentStateValues', title: 'Accepted Current State Values (JSON array)', placeholder: '["armed_home","armed_away","armed_night","disarmed","triggered"]', value: this.storage.getItem('currentStateValues') || '["armed_home","armed_away","armed_night","disarmed","triggered"]' },
34329
34341
  { group: 'Parsing / State tokens', key: 'triggeredValues', title: 'Triggered tokens (JSON array)', placeholder: '["triggered","alarm"]', value: this.storage.getItem('triggeredValues') || '["triggered","alarm"]' },
34342
+ // --- Publish Payloads (override) ---
34343
+ { group: 'Publish Payloads (override)', key: 'payloadDisarm', title: 'Payload for Disarm', placeholder: 'disarmed', value: this.storage.getItem('payloadDisarm') || '', description: 'Se vuoto: usa targetStateValues (strict ON) o i default arm_*/disarm (strict OFF).' },
34344
+ { group: 'Publish Payloads (override)', key: 'payloadHome', title: 'Payload for Home Armed', placeholder: 'armed_home', value: this.storage.getItem('payloadHome') || '' },
34345
+ { group: 'Publish Payloads (override)', key: 'payloadAway', title: 'Payload for Away Armed', placeholder: 'armed_away', value: this.storage.getItem('payloadAway') || '' },
34346
+ { group: 'Publish Payloads (override)', key: 'payloadNight', title: 'Payload for Night Armed', placeholder: 'armed_night', value: this.storage.getItem('payloadNight') || '' },
34330
34347
  ];
34331
34348
  // ---- UI Add Sensor ----
34332
34349
  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: 'Fill the fields above and toggle this on to create the sensor. After creation, restart this plugin to see the accessory listed below. To show it in HomeKit, restart the HomeKit plugin as well.' });
@@ -34334,6 +34351,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34334
34351
  for (const cfg of this.sensorsCfg) {
34335
34352
  const gid = `Sensor: ${cfg.name} [${cfg.id}]`;
34336
34353
  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'] });
34354
+ // primary per tipo
34337
34355
  if (cfg.kind === 'contact') {
34338
34356
  out.push({ group: gid, key: `sensor.${cfg.id}.topic.contact`, title: 'Contact State Topic', value: cfg.topics.contact || '', placeholder: 'paradox/states/zones/XYZ/open' });
34339
34357
  }
@@ -34343,13 +34361,15 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34343
34361
  else {
34344
34362
  out.push({ group: gid, key: `sensor.${cfg.id}.topic.occupancy`, title: 'Occupancy Detected Topic', value: cfg.topics.occupancy || '', placeholder: 'paradox/states/zones/XYZ/open' });
34345
34363
  }
34364
+ // extra opzionali
34346
34365
  out.push({ group: gid, key: `sensor.${cfg.id}.topic.batteryLevel`, title: 'Battery Level Topic (0..100)', value: cfg.topics.batteryLevel || '' }, { group: gid, key: `sensor.${cfg.id}.topic.lowBattery`, title: 'Low Battery Topic (bool)', value: cfg.topics.lowBattery || '' }, { group: gid, key: `sensor.${cfg.id}.topic.tamper`, title: 'Tamper Topic', value: cfg.topics.tamper || '' }, { group: gid, key: `sensor.${cfg.id}.topic.online`, title: 'Online Topic', value: cfg.topics.online || '' }, { group: gid, key: `sensor.${cfg.id}.remove`, title: 'Remove sensor', type: 'boolean' });
34347
34366
  }
34348
34367
  return out;
34349
34368
  }
34350
34369
  async putSetting(key, value) {
34370
+ // salva sempre nella storage la value del campo (così resta in UI)
34351
34371
  this.storage.setItem(key, String(value));
34352
- // Add Sensor
34372
+ // --- Add Sensor workflow ---
34353
34373
  if (key === 'new.create' && String(value) === 'true') {
34354
34374
  const id = (this.storage.getItem('new.id') || '').trim();
34355
34375
  const name = (this.storage.getItem('new.name') || '').trim() || id;
@@ -34364,6 +34384,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34364
34384
  }
34365
34385
  this.sensorsCfg.push({ id, name, kind, topics: {} });
34366
34386
  this.saveSensorsToStorage();
34387
+ // pulisci i campi "new.*"
34367
34388
  this.storage.removeItem('new.id');
34368
34389
  this.storage.removeItem('new.name');
34369
34390
  this.storage.removeItem('new.kind');
@@ -34372,7 +34393,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34372
34393
  await this.connectMqtt(true);
34373
34394
  return;
34374
34395
  }
34375
- // Edit/Remove sensore
34396
+ // --- Edit/Remove sensore esistente ---
34376
34397
  const m = key.match(/^sensor\.([^\.]+)\.(.+)$/);
34377
34398
  if (m) {
34378
34399
  const sid = m[1];
@@ -34383,6 +34404,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34383
34404
  return;
34384
34405
  }
34385
34406
  if (prop === 'remove' && String(value) === 'true') {
34407
+ // elimina
34386
34408
  this.sensorsCfg = this.sensorsCfg.filter(s => s.id !== sid);
34387
34409
  this.saveSensorsToStorage();
34388
34410
  try {
@@ -34390,15 +34412,18 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34390
34412
  deviceManager.onDeviceRemoved?.(`sensor:${sid}`);
34391
34413
  }
34392
34414
  catch { }
34415
+ // pulisci flag
34393
34416
  this.storage.removeItem(key);
34394
34417
  await this.discoverSensors();
34395
34418
  await this.connectMqtt(true);
34396
34419
  return;
34397
34420
  }
34398
- if (prop === 'name')
34421
+ if (prop === 'name') {
34399
34422
  cfg.name = String(value);
34400
- else if (prop === 'kind')
34423
+ }
34424
+ else if (prop === 'kind') {
34401
34425
  cfg.kind = String(value);
34426
+ }
34402
34427
  else if (prop.startsWith('topic.')) {
34403
34428
  const tk = prop.substring('topic.'.length);
34404
34429
  cfg.topics[tk] = String(value).trim();
@@ -34408,8 +34433,9 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34408
34433
  await this.connectMqtt(true);
34409
34434
  return;
34410
34435
  }
34411
- // altro
34436
+ // --- Altro (MQTT / Alarm settings / parsing / payloads) ---
34412
34437
  if (key === 'sensorsJson') {
34438
+ // non più mostrato, ma se presente da vecchie versioni
34413
34439
  this.loadSensorsFromStorage();
34414
34440
  await this.discoverSensors();
34415
34441
  await this.connectMqtt(true);
@@ -34419,12 +34445,15 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34419
34445
  }
34420
34446
  }
34421
34447
  /** ---- DeviceProvider ---- */
34422
- async getDevice(nativeId) { return this.devices.get(nativeId); }
34448
+ async getDevice(nativeId) {
34449
+ return this.devices.get(nativeId);
34450
+ }
34423
34451
  async releaseDevice(_id, nativeId) {
34424
34452
  try {
34425
34453
  const dev = this.devices.get(nativeId);
34426
- if (dev)
34454
+ if (dev) {
34427
34455
  this.devices.delete(nativeId);
34456
+ }
34428
34457
  try {
34429
34458
  deviceManager.onDeviceRemoved?.(nativeId);
34430
34459
  }
@@ -34438,6 +34467,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34438
34467
  try {
34439
34468
  const raw = this.storage.getItem('sensorsJson') || '[]';
34440
34469
  const parsed = JSON.parse(raw);
34470
+ // sanitize
34441
34471
  this.sensorsCfg = (parsed || []).filter(x => x && x.id && x.name && x.kind && x.topics);
34442
34472
  }
34443
34473
  catch (e) {
@@ -34447,21 +34477,25 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34447
34477
  }
34448
34478
  /** ===== discoverSensors: annuncia PRIMA, istanzia DOPO ===== */
34449
34479
  async discoverSensors() {
34450
- // 1) Manifests
34480
+ // 1) Prepara i manifest (niente istanze qui)
34451
34481
  const manifests = this.sensorsCfg.map(cfg => {
34452
34482
  const nativeId = `sensor:${cfg.id}`;
34453
34483
  const t = cfg.topics || {};
34454
34484
  const interfaces = [sdk_1.ScryptedInterface.Online];
34485
+ // Tamper solo se c'è un topic tamper
34455
34486
  if (t.tamper)
34456
34487
  interfaces.push(sdk_1.ScryptedInterface.TamperSensor);
34488
+ // Interfaccia primaria
34457
34489
  if (cfg.kind === 'contact')
34458
34490
  interfaces.unshift(sdk_1.ScryptedInterface.EntrySensor);
34459
34491
  else if (cfg.kind === 'motion')
34460
34492
  interfaces.unshift(sdk_1.ScryptedInterface.MotionSensor);
34461
34493
  else
34462
34494
  interfaces.unshift(sdk_1.ScryptedInterface.OccupancySensor);
34463
- if ((t.batteryLevel && t.batteryLevel.trim()) || (t.lowBattery && t.lowBattery.trim()))
34495
+ // Battery solo se previsto
34496
+ if ((t.batteryLevel && t.batteryLevel.trim()) || (t.lowBattery && t.lowBattery.trim())) {
34464
34497
  interfaces.push(sdk_1.ScryptedInterface.Battery);
34498
+ }
34465
34499
  return { nativeId, name: cfg.name, type: sdk_1.ScryptedDeviceType.Sensor, interfaces };
34466
34500
  });
34467
34501
  // 2) Annuncio
@@ -34476,7 +34510,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34476
34510
  this.console.log('Annunciato:', m.nativeId);
34477
34511
  }
34478
34512
  }
34479
- // 3) Istanzia/aggiorna
34513
+ // 3) Istanzia/aggiorna DOPO l’annuncio
34480
34514
  for (const cfg of this.sensorsCfg) {
34481
34515
  const nativeId = `sensor:${cfg.id}`;
34482
34516
  let dev = this.devices.get(nativeId);
@@ -34492,9 +34526,17 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34492
34526
  else {
34493
34527
  dev.cfg = cfg;
34494
34528
  }
34495
- // niente default batteria qui
34529
+ // Default “OK” se abbiamo Battery ma nessun valore ancora ricevuto
34530
+ const hasBattery = !!(cfg.topics.batteryLevel && cfg.topics.batteryLevel.trim()) || !!(cfg.topics.lowBattery && cfg.topics.lowBattery.trim());
34531
+ if (hasBattery && dev.batteryLevel === undefined) {
34532
+ dev.batteryLevel = 100;
34533
+ try {
34534
+ dev.onDeviceEvent(sdk_1.ScryptedInterface.Battery, 100);
34535
+ }
34536
+ catch { }
34537
+ }
34496
34538
  }
34497
- // 4) cleanup
34539
+ // 4) Rimuovi quelli spariti
34498
34540
  const announced = new Set(manifests.map(m => m.nativeId));
34499
34541
  for (const [nativeId] of this.devices) {
34500
34542
  if (!announced.has(nativeId)) {
@@ -34515,7 +34557,13 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34515
34557
  const clientId = this.storage.getItem('clientId') || 'scrypted-paradox';
34516
34558
  const tls = this.storage.getItem('tls') === 'true';
34517
34559
  const rejectUnauthorized = this.storage.getItem('rejectUnauthorized') !== 'false';
34518
- const opts = { clientId, username, password, clean: true, reconnectPeriod: 3000 };
34560
+ const opts = {
34561
+ clientId,
34562
+ username,
34563
+ password,
34564
+ clean: true,
34565
+ reconnectPeriod: 3000,
34566
+ };
34519
34567
  if (tls) {
34520
34568
  opts.protocol = 'mqtts';
34521
34569
  opts.rejectUnauthorized = rejectUnauthorized;
@@ -34524,11 +34572,13 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34524
34572
  }
34525
34573
  collectAllSubscriptions() {
34526
34574
  const subs = new Set();
34575
+ // alarm
34527
34576
  for (const k of ['topicGetTarget', 'topicGetCurrent', 'topicTamper', 'topicOnline']) {
34528
34577
  const v = this.storage.getItem(k);
34529
34578
  if (v)
34530
34579
  subs.add(v);
34531
34580
  }
34581
+ // sensors
34532
34582
  for (const s of this.sensorsCfg) {
34533
34583
  const t = s.topics || {};
34534
34584
  [t.contact, t.motion, t.occupancy, t.batteryLevel, t.lowBattery, t.tamper, t.online]
@@ -34547,13 +34597,13 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34547
34597
  this.client.end(true);
34548
34598
  }
34549
34599
  catch { }
34550
- ;
34551
34600
  this.client = undefined;
34552
34601
  }
34553
34602
  const { url, opts } = this.getMqttOptions();
34554
34603
  this.console.log(`Connecting MQTT ${url} ...`);
34555
34604
  const client = mqtt_1.default.connect(url, opts);
34556
34605
  this.client = client;
34606
+ // cache alarm topics for fast compare
34557
34607
  const tTarget = this.storage.getItem('topicGetTarget') || '';
34558
34608
  const tCurrent = this.storage.getItem('topicGetCurrent') || '';
34559
34609
  const tTamper = this.storage.getItem('topicTamper') || '';
@@ -34565,9 +34615,12 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34565
34615
  this.onDeviceEvent(sdk_1.ScryptedInterface.Online, true);
34566
34616
  }
34567
34617
  catch { }
34568
- if (subs.length)
34569
- client.subscribe(subs, { qos: 0 }, (err) => { if (err)
34570
- this.console.error('subscribe error', err); });
34618
+ if (subs.length) {
34619
+ client.subscribe(subs, { qos: 0 }, (err) => {
34620
+ if (err)
34621
+ this.console.error('subscribe error', err);
34622
+ });
34623
+ }
34571
34624
  });
34572
34625
  client.on('reconnect', () => this.console.log('MQTT reconnecting...'));
34573
34626
  client.on('close', () => {
@@ -34583,6 +34636,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34583
34636
  try {
34584
34637
  const p = payload?.toString() ?? '';
34585
34638
  const np = normalize(p);
34639
+ // ---- Alarm handling ----
34586
34640
  if (topic === tOnline) {
34587
34641
  if (truthy(np) || np === 'online') {
34588
34642
  this.online = true;
@@ -34645,8 +34699,9 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34645
34699
  return;
34646
34700
  }
34647
34701
  // ---- Sensor dispatch ----
34648
- for (const dev of this.devices.values())
34702
+ for (const dev of this.devices.values()) {
34649
34703
  dev.handleMqtt(topic, payload);
34704
+ }
34650
34705
  }
34651
34706
  catch (e) {
34652
34707
  this.console.error('MQTT message handler error', e);
@@ -34668,10 +34723,25 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34668
34723
  this.console.error('publish error', err);
34669
34724
  });
34670
34725
  }
34726
+ /** Sceglie il payload di publish rispettando override → strict tokens → default arm_* */
34727
+ getOutgoing(mode) {
34728
+ const overrides = {
34729
+ [sdk_1.SecuritySystemMode.Disarmed]: this.storage.getItem('payloadDisarm') || null,
34730
+ [sdk_1.SecuritySystemMode.HomeArmed]: this.storage.getItem('payloadHome') || null,
34731
+ [sdk_1.SecuritySystemMode.AwayArmed]: this.storage.getItem('payloadAway') || null,
34732
+ [sdk_1.SecuritySystemMode.NightArmed]: this.storage.getItem('payloadNight') || null,
34733
+ };
34734
+ const override = overrides[mode];
34735
+ if (override && override.trim().length)
34736
+ return override.trim();
34737
+ if (this.useStrict())
34738
+ return this.preferredTokenForMode(mode);
34739
+ return DEFAULT_OUTGOING[mode];
34740
+ }
34671
34741
  async armSecuritySystem(mode) {
34672
34742
  const payload = this.getOutgoing(mode);
34673
34743
  this.console.log('armSecuritySystem', mode, '->', payload);
34674
- this.pendingTarget = mode;
34744
+ this.pendingTarget = mode; // memorizza target, ma NON cambiare il current
34675
34745
  this.publishSetTarget(payload);
34676
34746
  }
34677
34747
  async disarmSecuritySystem() {
@@ -34680,15 +34750,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34680
34750
  this.pendingTarget = sdk_1.SecuritySystemMode.Disarmed;
34681
34751
  this.publishSetTarget(payload);
34682
34752
  }
34683
- getOutgoing(mode) {
34684
- const map = {
34685
- [sdk_1.SecuritySystemMode.Disarmed]: this.storage.getItem('payloadDisarm') || DEFAULT_OUTGOING[sdk_1.SecuritySystemMode.Disarmed],
34686
- [sdk_1.SecuritySystemMode.HomeArmed]: this.storage.getItem('payloadHome') || DEFAULT_OUTGOING[sdk_1.SecuritySystemMode.HomeArmed],
34687
- [sdk_1.SecuritySystemMode.AwayArmed]: this.storage.getItem('payloadAway') || DEFAULT_OUTGOING[sdk_1.SecuritySystemMode.AwayArmed],
34688
- [sdk_1.SecuritySystemMode.NightArmed]: this.storage.getItem('payloadNight') || DEFAULT_OUTGOING[sdk_1.SecuritySystemMode.NightArmed],
34689
- };
34690
- return map[mode];
34691
- }
34692
34753
  }
34693
34754
  exports["default"] = ParadoxMqttSecuritySystem;
34694
34755
 
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.48",
3
+ "version": "1.0.49",
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",