@rfranzoi/scrypted-mqtt-securitysystem 1.0.90 → 1.0.93

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.
@@ -34241,9 +34241,10 @@ function payloadToModeLoose(payload) {
34241
34241
  return undefined;
34242
34242
  }
34243
34243
  class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
34244
- constructor(nativeId, cfg) {
34244
+ constructor(nativeId, cfg, publishBypass) {
34245
34245
  super(nativeId);
34246
34246
  this.cfg = cfg;
34247
+ this.publishBypass = publishBypass;
34247
34248
  }
34248
34249
  /** setter centralizzato + evento + (log opzionale) */
34249
34250
  setAndEmit(prop, val, iface, logContext) {
@@ -34299,7 +34300,17 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
34299
34300
  });
34300
34301
  return;
34301
34302
  }
34302
- // 4) LOW BATTERY (bool)
34303
+ // 4) BYPASS STATE
34304
+ if (topic === this.cfg.bypass?.state) {
34305
+ if (truthy(np)) {
34306
+ this.setAndEmit('on', true, sdk_1.ScryptedInterface.OnOff, { topic, raw, propLabel: 'bypass' });
34307
+ }
34308
+ else if (falsy(np)) {
34309
+ this.setAndEmit('on', false, sdk_1.ScryptedInterface.OnOff, { topic, raw, propLabel: 'bypass' });
34310
+ }
34311
+ return;
34312
+ }
34313
+ // 5) LOW BATTERY (bool)
34303
34314
  if (topic === topics.lowBattery) {
34304
34315
  const isLow = np === 'true' ||
34305
34316
  np === '1' ||
@@ -34322,7 +34333,7 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
34322
34333
  }
34323
34334
  return;
34324
34335
  }
34325
- // 5) BATTERY LEVEL (0..100)
34336
+ // 6) BATTERY LEVEL (0..100)
34326
34337
  if (topic === topics.batteryLevel) {
34327
34338
  const n = Number(raw);
34328
34339
  if (isFinite(n)) {
@@ -34342,6 +34353,34 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
34342
34353
  return;
34343
34354
  }
34344
34355
  }
34356
+ async turnOn() {
34357
+ const bypass = this.cfg.bypass;
34358
+ if (!bypass?.control) {
34359
+ this.console?.warn?.('Bypass control topic non configurato.');
34360
+ return;
34361
+ }
34362
+ const payload = (bypass.payloadOn || 'bypass').trim() || 'bypass';
34363
+ if (this.publishBypass(this.cfg, payload))
34364
+ this.setAndEmit('on', true, sdk_1.ScryptedInterface.OnOff, { propLabel: 'bypass' });
34365
+ }
34366
+ async turnOff() {
34367
+ const bypass = this.cfg.bypass;
34368
+ if (!bypass?.control) {
34369
+ this.console?.warn?.('Bypass control topic non configurato.');
34370
+ return;
34371
+ }
34372
+ const payload = (bypass.payloadOff || 'clear_bypass').trim() || 'clear_bypass';
34373
+ if (this.publishBypass(this.cfg, payload))
34374
+ this.setAndEmit('on', false, sdk_1.ScryptedInterface.OnOff, { propLabel: 'bypass' });
34375
+ }
34376
+ async setPowerState(on) {
34377
+ if (on)
34378
+ return this.turnOn();
34379
+ return this.turnOff();
34380
+ }
34381
+ async setOn(on) {
34382
+ return this.setPowerState(on);
34383
+ }
34345
34384
  }
34346
34385
  class ContactMqttSensor extends BaseMqttSensor {
34347
34386
  handlePrimary(topic, np, raw) {
@@ -34367,72 +34406,12 @@ class OccupancyMqttSensor extends BaseMqttSensor {
34367
34406
  }
34368
34407
  }
34369
34408
  }
34370
- class BypassMqttSwitch extends sdk_1.ScryptedDeviceBase {
34371
- constructor(nativeId, cfg, parent) {
34372
- super(nativeId);
34373
- this.cfg = cfg;
34374
- this.parent = parent;
34375
- }
34376
- updateConfig(cfg) {
34377
- this.cfg = cfg;
34378
- }
34379
- setOn(val, logContext) {
34380
- if (this.on === val)
34381
- return;
34382
- this.on = val;
34383
- try {
34384
- this.onDeviceEvent(sdk_1.ScryptedInterface.OnOff, val);
34385
- }
34386
- catch (e) {
34387
- this.console?.warn?.('onDeviceEvent error', e);
34388
- }
34389
- if (RUNTIME.logSensors) {
34390
- const source = logContext?.source ? ` ${logContext.source}` : '';
34391
- const extra = logContext?.topic ? ` (${logContext.topic}="${logContext.raw ?? ''}")` : '';
34392
- this.console?.log?.(`[Bypass] ${this.cfg.zoneName} [${this.cfg.id}] on -> ${val}${source}${extra}`);
34393
- }
34394
- }
34395
- handleMqtt(topic, payload) {
34396
- if (topic !== this.cfg.topics.state)
34397
- return;
34398
- const raw = payload?.toString() ?? '';
34399
- const np = normalize(raw);
34400
- if (truthy(np))
34401
- this.setOn(true, { topic, raw, source: 'state' });
34402
- else if (falsy(np))
34403
- this.setOn(false, { topic, raw, source: 'state' });
34404
- }
34405
- async turnOn() {
34406
- if (RUNTIME.logSensors) {
34407
- const topic = this.cfg.topics?.control || '';
34408
- this.console?.log?.(`[Bypass] cmd ON ${this.cfg.zoneName} [${this.cfg.id}] -> ${topic}`);
34409
- }
34410
- const payload = (this.cfg.payloadOn || 'bypass').trim() || 'bypass';
34411
- if (this.parent.publishBypass(this.cfg, payload))
34412
- this.setOn(true, { source: 'local' });
34413
- }
34414
- async turnOff() {
34415
- if (RUNTIME.logSensors) {
34416
- const topic = this.cfg.topics?.control || '';
34417
- this.console?.log?.(`[Bypass] cmd OFF ${this.cfg.zoneName} [${this.cfg.id}] -> ${topic}`);
34418
- }
34419
- const payload = (this.cfg.payloadOff || 'clear_bypass').trim() || 'clear_bypass';
34420
- if (this.parent.publishBypass(this.cfg, payload))
34421
- this.setOn(false, { source: 'local' });
34422
- }
34423
- async setPowerState(on) {
34424
- if (on)
34425
- return this.turnOn();
34426
- return this.turnOff();
34427
- }
34428
- }
34429
34409
  /** ----------------- Main Plugin ----------------- */
34430
34410
  class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34431
34411
  constructor() {
34432
34412
  super();
34433
34413
  // sensor management
34434
34414
  this.sensorsCfg = [];
34435
- this.bypassCfg = [];
34436
34415
  this.devices = new Map();
34437
34416
  // carica flag runtime
34438
34417
  updateRuntimeFromStorage((k) => this.storage.getItem(k) || '');
@@ -34456,7 +34435,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34456
34435
  this.online = this.online ?? false;
34457
34436
  // Load configs and announce devices
34458
34437
  this.loadSensorsFromStorage();
34459
- this.loadBypassFromStorage();
34460
34438
  this.discoverDevices().catch(e => this.console.error('discoverDevices error', e));
34461
34439
  // Connect on start
34462
34440
  this.connectMqtt().catch(e => this.console.error('MQTT connect error:', e));
@@ -34537,14 +34515,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34537
34515
  this.console.error('saveSensorsToStorage error', e);
34538
34516
  }
34539
34517
  }
34540
- saveBypassToStorage() {
34541
- try {
34542
- this.storage.setItem('bypassJson', JSON.stringify(this.bypassCfg));
34543
- }
34544
- catch (e) {
34545
- this.console.error('saveBypassToStorage error', e);
34546
- }
34547
- }
34548
34518
  /** ---- Settings UI ---- */
34549
34519
  async getSettings() {
34550
34520
  const out = [
@@ -34579,8 +34549,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34579
34549
  ];
34580
34550
  // ---- UI Add Sensor ----
34581
34551
  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.' });
34582
- // ---- UI Add Bypass Switch ----
34583
- out.push({ group: 'Add Bypass Switch', key: 'bypass.new.id', title: 'New Bypass ID', placeholder: 'zona-1', value: this.storage.getItem('bypass.new.id') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.zoneName', title: 'Zone Name', placeholder: 'Zona 1', value: this.storage.getItem('bypass.new.zoneName') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.topic.control', title: 'Control Topic', placeholder: 'paradox/control/zones/Zona_1', value: this.storage.getItem('bypass.new.topic.control') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.topic.state', title: 'State Topic', placeholder: 'paradox/states/zones/Zona_1/bypassed', value: this.storage.getItem('bypass.new.topic.state') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.payloadOn', title: 'Payload for ON', placeholder: 'bypass', value: this.storage.getItem('bypass.new.payloadOn') || 'bypass' }, { group: 'Add Bypass Switch', key: 'bypass.new.payloadOff', title: 'Payload for OFF', placeholder: 'clear_bypass', value: this.storage.getItem('bypass.new.payloadOff') || 'clear_bypass' }, { group: 'Add Bypass Switch', key: 'bypass.new.create', title: 'Create bypass switch', type: 'boolean', description: 'Fill the fields above and toggle this on to create the bypass switch. After creation, restart this plugin to see the accessory listed below.' });
34584
34552
  // ---- UI per sensori esistenti ----
34585
34553
  for (const cfg of this.sensorsCfg) {
34586
34554
  const gid = `Sensor: ${cfg.name} [${cfg.id}]`;
@@ -34591,12 +34559,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34591
34559
  out.push({ group: gid, key: `sensor.${cfg.id}.topic.motion`, title: 'Motion Detected Topic', value: cfg.topics.motion || '', placeholder: 'paradox/states/zones/XYZ/open' });
34592
34560
  else
34593
34561
  out.push({ group: gid, key: `sensor.${cfg.id}.topic.occupancy`, title: 'Occupancy Detected Topic', value: cfg.topics.occupancy || '', placeholder: 'paradox/states/zones/XYZ/open' });
34594
- 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' });
34595
- }
34596
- // ---- UI per bypass esistenti ----
34597
- for (const cfg of this.bypassCfg) {
34598
- const gid = `Bypass: ${cfg.zoneName} [${cfg.id}]`;
34599
- out.push({ group: gid, key: `bypass.${cfg.id}.zoneName`, title: 'Zone Name', value: cfg.zoneName }, { group: gid, key: `bypass.${cfg.id}.topic.control`, title: 'Control Topic', value: cfg.topics.control || '', placeholder: 'paradox/control/zones/Zona_1' }, { group: gid, key: `bypass.${cfg.id}.topic.state`, title: 'State Topic', value: cfg.topics.state || '', placeholder: 'paradox/states/zones/Zona_1/bypassed' }, { group: gid, key: `bypass.${cfg.id}.payloadOn`, title: 'Payload for ON', value: cfg.payloadOn || 'bypass' }, { group: gid, key: `bypass.${cfg.id}.payloadOff`, title: 'Payload for OFF', value: cfg.payloadOff || 'clear_bypass' }, { group: gid, key: `bypass.${cfg.id}.remove`, title: 'Remove bypass switch', type: 'boolean' });
34562
+ 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}.bypass.control`, title: 'Bypass Control Topic', value: cfg.bypass?.control || '', placeholder: 'paradox/control/zones/Zona_1' }, { group: gid, key: `sensor.${cfg.id}.bypass.state`, title: 'Bypass State Topic', value: cfg.bypass?.state || '', placeholder: 'paradox/states/zones/Zona_1/bypassed' }, { group: gid, key: `sensor.${cfg.id}.bypass.payloadOn`, title: 'Bypass Payload ON', value: cfg.bypass?.payloadOn || 'bypass' }, { group: gid, key: `sensor.${cfg.id}.bypass.payloadOff`, title: 'Bypass Payload OFF', value: cfg.bypass?.payloadOff || 'clear_bypass' }, { group: gid, key: `sensor.${cfg.id}.remove`, title: 'Remove sensor', type: 'boolean' });
34600
34563
  }
34601
34564
  return out;
34602
34565
  }
@@ -34629,44 +34592,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34629
34592
  await this.connectMqtt(true);
34630
34593
  return;
34631
34594
  }
34632
- // --- Add Bypass Switch workflow ---
34633
- if (key === 'bypass.new.create' && String(value) === 'true') {
34634
- const id = (this.storage.getItem('bypass.new.id') || '').trim();
34635
- const zoneName = (this.storage.getItem('bypass.new.zoneName') || '').trim() || id;
34636
- const control = (this.storage.getItem('bypass.new.topic.control') || '').trim();
34637
- const state = (this.storage.getItem('bypass.new.topic.state') || '').trim();
34638
- const payloadOn = (this.storage.getItem('bypass.new.payloadOn') || 'bypass').trim() || 'bypass';
34639
- const payloadOff = (this.storage.getItem('bypass.new.payloadOff') || 'clear_bypass').trim() || 'clear_bypass';
34640
- if (!id) {
34641
- this.console.warn('Create bypass: id mancante');
34642
- return;
34643
- }
34644
- if (this.bypassCfg.find(b => b.id === id)) {
34645
- this.console.warn('Create bypass: id già esistente');
34646
- return;
34647
- }
34648
- this.bypassCfg.push({
34649
- id,
34650
- zoneName,
34651
- topics: { control, state },
34652
- payloadOn,
34653
- payloadOff,
34654
- });
34655
- this.saveBypassToStorage();
34656
- // pulizia campi "bypass.new.*"
34657
- this.storage.removeItem('bypass.new.id');
34658
- this.storage.removeItem('bypass.new.zoneName');
34659
- this.storage.removeItem('bypass.new.topic.control');
34660
- this.storage.removeItem('bypass.new.topic.state');
34661
- this.storage.removeItem('bypass.new.payloadOn');
34662
- this.storage.removeItem('bypass.new.payloadOff');
34663
- this.storage.removeItem('bypass.new.create');
34664
- await this.discoverDevices();
34665
- await this.connectMqtt(true);
34666
- return;
34667
- }
34668
- if (key.startsWith('bypass.new.'))
34669
- return;
34670
34595
  // --- Edit/Remove sensore esistente ---
34671
34596
  const m = key.match(/^sensor\.([^\.]+)\.(.+)$/);
34672
34597
  if (m) {
@@ -34700,53 +34625,19 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34700
34625
  const tk = prop.substring('topic.'.length);
34701
34626
  cfg.topics[tk] = String(value).trim();
34702
34627
  }
34703
- this.saveSensorsToStorage();
34704
- await this.discoverDevices();
34705
- await this.connectMqtt(true);
34706
- return;
34707
- }
34708
- // --- Edit/Remove bypass esistente ---
34709
- const mb = key.match(/^bypass\.([^\.]+)\.(.+)$/);
34710
- if (mb) {
34711
- const bid = mb[1];
34712
- const prop = mb[2];
34713
- const cfg = this.bypassCfg.find(b => b.id === bid);
34714
- if (!cfg) {
34715
- this.console.warn('putSetting: bypass non trovato', bid);
34716
- return;
34717
- }
34718
- if (prop === 'remove' && String(value) === 'true') {
34719
- this.bypassCfg = this.bypassCfg.filter(b => b.id !== bid);
34720
- this.saveBypassToStorage();
34721
- try {
34722
- this.devices.delete(`bypass:${bid}`);
34723
- deviceManager.onDeviceRemoved?.(`bypass:${bid}`);
34724
- }
34725
- catch { }
34726
- this.storage.removeItem(key);
34727
- await this.discoverDevices();
34728
- await this.connectMqtt(true);
34729
- return;
34730
- }
34731
- if (prop === 'zoneName')
34732
- cfg.zoneName = String(value);
34733
- else if (prop === 'payloadOn')
34734
- cfg.payloadOn = String(value).trim();
34735
- else if (prop === 'payloadOff')
34736
- cfg.payloadOff = String(value).trim();
34737
- else if (prop.startsWith('topic.')) {
34738
- const tk = prop.substring('topic.'.length);
34739
- cfg.topics[tk] = String(value).trim();
34628
+ else if (prop.startsWith('bypass.')) {
34629
+ const bk = prop.substring('bypass.'.length);
34630
+ cfg.bypass = cfg.bypass || {};
34631
+ cfg.bypass[bk] = String(value).trim();
34740
34632
  }
34741
- this.saveBypassToStorage();
34633
+ this.saveSensorsToStorage();
34742
34634
  await this.discoverDevices();
34743
34635
  await this.connectMqtt(true);
34744
34636
  return;
34745
34637
  }
34746
34638
  // --- Altro (MQTT / Alarm settings / parsing / payloads / logging) ---
34747
- if (key === 'sensorsJson' || key === 'bypassJson') {
34639
+ if (key === 'sensorsJson') {
34748
34640
  this.loadSensorsFromStorage();
34749
- this.loadBypassFromStorage();
34750
34641
  await this.discoverDevices();
34751
34642
  await this.connectMqtt(true);
34752
34643
  }
@@ -34756,6 +34647,8 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34756
34647
  }
34757
34648
  /** ---- DeviceProvider ---- */
34758
34649
  async getDevice(nativeId) {
34650
+ if (RUNTIME.logSensors)
34651
+ this.console.log(`[DeviceProvider] getDevice ${nativeId}`);
34759
34652
  const existing = this.devices.get(nativeId);
34760
34653
  if (existing)
34761
34654
  return existing;
@@ -34766,11 +34659,11 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34766
34659
  return undefined;
34767
34660
  let dev;
34768
34661
  if (cfg.kind === 'contact')
34769
- dev = new ContactMqttSensor(nativeId, cfg);
34662
+ dev = new ContactMqttSensor(nativeId, cfg, this.publishSensorBypass.bind(this));
34770
34663
  else if (cfg.kind === 'motion')
34771
- dev = new MotionMqttSensor(nativeId, cfg);
34664
+ dev = new MotionMqttSensor(nativeId, cfg, this.publishSensorBypass.bind(this));
34772
34665
  else
34773
- dev = new OccupancyMqttSensor(nativeId, cfg);
34666
+ dev = new OccupancyMqttSensor(nativeId, cfg, this.publishSensorBypass.bind(this));
34774
34667
  this.devices.set(nativeId, dev);
34775
34668
  const hasBattery = !!(cfg.topics.batteryLevel && cfg.topics.batteryLevel.trim())
34776
34669
  || !!(cfg.topics.lowBattery && cfg.topics.lowBattery.trim());
@@ -34783,17 +34676,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34783
34676
  }
34784
34677
  return dev;
34785
34678
  }
34786
- if (nativeId.startsWith('bypass:')) {
34787
- const bid = nativeId.substring('bypass:'.length);
34788
- const cfg = this.bypassCfg.find(b => b.id === bid);
34789
- if (!cfg)
34790
- return undefined;
34791
- const dev = new BypassMqttSwitch(nativeId, cfg, this);
34792
- if (dev.on === undefined)
34793
- dev.on = false;
34794
- this.devices.set(nativeId, dev);
34795
- return dev;
34796
- }
34797
34679
  return undefined;
34798
34680
  }
34799
34681
  async releaseDevice(_id, nativeId) {
@@ -34815,31 +34697,22 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34815
34697
  const raw = this.storage.getItem('sensorsJson') || '[]';
34816
34698
  const parsed = JSON.parse(raw);
34817
34699
  // sanitize
34818
- this.sensorsCfg = (parsed || []).filter(x => x && x.id && x.name && x.kind && x.topics);
34819
- }
34820
- catch (e) {
34821
- this.console.error('Invalid sensorsJson:', e);
34822
- this.sensorsCfg = [];
34823
- }
34824
- }
34825
- loadBypassFromStorage() {
34826
- try {
34827
- const raw = this.storage.getItem('bypassJson') || '[]';
34828
- const parsed = JSON.parse(raw);
34829
- this.bypassCfg = (parsed || []).filter(x => x && x.id && x.zoneName && x.topics).map(x => ({
34700
+ this.sensorsCfg = (parsed || []).filter(x => x && x.id && x.name && x.kind && x.topics).map(x => ({
34830
34701
  id: String(x.id),
34831
- zoneName: String(x.zoneName),
34832
- topics: {
34833
- control: x.topics?.control || '',
34834
- state: x.topics?.state || '',
34702
+ name: String(x.name),
34703
+ kind: x.kind,
34704
+ topics: x.topics || {},
34705
+ bypass: {
34706
+ control: x.bypass?.control || '',
34707
+ state: x.bypass?.state || '',
34708
+ payloadOn: x.bypass?.payloadOn || 'bypass',
34709
+ payloadOff: x.bypass?.payloadOff || 'clear_bypass',
34835
34710
  },
34836
- payloadOn: String(x.payloadOn || 'bypass'),
34837
- payloadOff: String(x.payloadOff || 'clear_bypass'),
34838
34711
  }));
34839
34712
  }
34840
34713
  catch (e) {
34841
- this.console.error('Invalid bypassJson:', e);
34842
- this.bypassCfg = [];
34714
+ this.console.error('Invalid sensorsJson:', e);
34715
+ this.sensorsCfg = [];
34843
34716
  }
34844
34717
  }
34845
34718
  /** ===== discoverDevices: annuncia PRIMA, istanzia DOPO ===== */
@@ -34861,19 +34734,18 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34861
34734
  // Battery solo se definita davvero
34862
34735
  if ((t.batteryLevel && t.batteryLevel.trim()) || (t.lowBattery && t.lowBattery.trim()))
34863
34736
  interfaces.push(sdk_1.ScryptedInterface.Battery);
34737
+ const hasBypass = !!(cfg.bypass?.control?.trim() || cfg.bypass?.state?.trim());
34738
+ if (hasBypass)
34739
+ interfaces.push(sdk_1.ScryptedInterface.OnOff);
34864
34740
  manifests.push({ nativeId, name: cfg.name, type: sdk_1.ScryptedDeviceType.Sensor, interfaces });
34865
34741
  }
34866
- for (const cfg of this.bypassCfg) {
34867
- const nativeId = `bypass:${cfg.id}`;
34868
- const zoneName = (cfg.zoneName || '').trim() || cfg.id;
34869
- const name = `${zoneName} Bypass`;
34870
- const interfaces = [sdk_1.ScryptedInterface.OnOff];
34871
- manifests.push({ nativeId, name, type: sdk_1.ScryptedDeviceType.Switch, interfaces });
34872
- }
34873
34742
  // 2) annuncio
34874
34743
  const dmAny = deviceManager;
34875
34744
  if (typeof dmAny.onDevicesChanged === 'function') {
34876
- dmAny.onDevicesChanged({ devices: manifests });
34745
+ const payload = { devices: manifests };
34746
+ if (this.nativeId)
34747
+ payload.providerNativeId = this.nativeId;
34748
+ dmAny.onDevicesChanged(payload);
34877
34749
  this.console.log('Annunciati (batch):', manifests.map(m => m.nativeId).join(', '));
34878
34750
  }
34879
34751
  else {
@@ -34888,11 +34760,11 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34888
34760
  let dev = this.devices.get(nativeId);
34889
34761
  if (!dev) {
34890
34762
  if (cfg.kind === 'contact')
34891
- dev = new ContactMqttSensor(nativeId, cfg);
34763
+ dev = new ContactMqttSensor(nativeId, cfg, this.publishSensorBypass.bind(this));
34892
34764
  else if (cfg.kind === 'motion')
34893
- dev = new MotionMqttSensor(nativeId, cfg);
34765
+ dev = new MotionMqttSensor(nativeId, cfg, this.publishSensorBypass.bind(this));
34894
34766
  else
34895
- dev = new OccupancyMqttSensor(nativeId, cfg);
34767
+ dev = new OccupancyMqttSensor(nativeId, cfg, this.publishSensorBypass.bind(this));
34896
34768
  this.devices.set(nativeId, dev);
34897
34769
  }
34898
34770
  else {
@@ -34909,17 +34781,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34909
34781
  catch { }
34910
34782
  }
34911
34783
  }
34912
- for (const cfg of this.bypassCfg) {
34913
- const nativeId = `bypass:${cfg.id}`;
34914
- let dev = this.devices.get(nativeId);
34915
- if (!dev) {
34916
- dev = new BypassMqttSwitch(nativeId, cfg, this);
34917
- this.devices.set(nativeId, dev);
34918
- }
34919
- else {
34920
- dev.updateConfig(cfg);
34921
- }
34922
- }
34923
34784
  // 4) cleanup
34924
34785
  const announced = new Set(manifests.map(m => m.nativeId));
34925
34786
  for (const [nativeId] of this.devices) {
@@ -34965,14 +34826,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
34965
34826
  // sensors
34966
34827
  for (const s of this.sensorsCfg) {
34967
34828
  const t = s.topics || {};
34968
- [t.contact, t.motion, t.occupancy, t.batteryLevel, t.lowBattery, t.tamper, t.online]
34969
- .filter((x) => !!x && String(x).trim().length > 0)
34970
- .forEach(x => subs.add(String(x)));
34971
- }
34972
- // bypass switches
34973
- for (const b of this.bypassCfg) {
34974
- const t = b.topics || {};
34975
- [t.state]
34829
+ [t.contact, t.motion, t.occupancy, t.batteryLevel, t.lowBattery, t.tamper, t.online, s.bypass?.state]
34976
34830
  .filter((x) => !!x && String(x).trim().length > 0)
34977
34831
  .forEach(x => subs.add(String(x)));
34978
34832
  }
@@ -35121,8 +34975,8 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
35121
34975
  this.console.log(`[Alarm] published target "${payload}" to ${topic}`);
35122
34976
  });
35123
34977
  }
35124
- publishBypass(cfg, payload) {
35125
- const topic = cfg.topics?.control?.trim();
34978
+ publishSensorBypass(cfg, payload) {
34979
+ const topic = cfg.bypass?.control?.trim();
35126
34980
  if (!topic || !this.client) {
35127
34981
  this.console.warn('Bypass topic control o MQTT non configurati.');
35128
34982
  return false;
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.90",
3
+ "version": "1.0.93",
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",
@@ -42,7 +42,8 @@
42
42
  "SecuritySystem",
43
43
  "Settings",
44
44
  "TamperSensor",
45
- "Online"
45
+ "Online",
46
+ "DeviceProvider"
46
47
  ]
47
48
  }
48
49
  }