@rfranzoi/scrypted-mqtt-securitysystem 1.0.95 → 1.0.96
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 +75 -116
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
package/dist/main.nodejs.js
CHANGED
|
@@ -34457,7 +34457,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34457
34457
|
super();
|
|
34458
34458
|
// device management
|
|
34459
34459
|
this.sensorsCfg = [];
|
|
34460
|
-
this.bypassCfg = [];
|
|
34461
34460
|
this.devices = new Map();
|
|
34462
34461
|
// load runtime flags
|
|
34463
34462
|
updateRuntimeFromStorage((k) => this.storage.getItem(k) || '');
|
|
@@ -34481,7 +34480,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34481
34480
|
this.online = this.online ?? false;
|
|
34482
34481
|
// Load configs and announce devices
|
|
34483
34482
|
this.loadSensorsFromStorage();
|
|
34484
|
-
this.loadBypassFromStorage();
|
|
34485
34483
|
this.discoverDevices().catch(e => this.console.error('discoverDevices error', e));
|
|
34486
34484
|
// Connect on start
|
|
34487
34485
|
this.connectMqtt().catch(e => this.console.error('MQTT connect error:', e));
|
|
@@ -34562,14 +34560,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34562
34560
|
this.console.error('saveSensorsToStorage error', e);
|
|
34563
34561
|
}
|
|
34564
34562
|
}
|
|
34565
|
-
saveBypassToStorage() {
|
|
34566
|
-
try {
|
|
34567
|
-
this.storage.setItem('bypassJson', JSON.stringify(this.bypassCfg));
|
|
34568
|
-
}
|
|
34569
|
-
catch (e) {
|
|
34570
|
-
this.console.error('saveBypassToStorage error', e);
|
|
34571
|
-
}
|
|
34572
|
-
}
|
|
34573
34563
|
/** ---- Settings UI ---- */
|
|
34574
34564
|
async getSettings() {
|
|
34575
34565
|
const out = [
|
|
@@ -34604,8 +34594,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34604
34594
|
];
|
|
34605
34595
|
// ---- UI Add Sensor ----
|
|
34606
34596
|
out.push({ group: 'Add Sensor', key: 'new.id', title: 'New Sensor ID', placeholder: 'front-door', value: this.storage.getItem('new.id') || '' }, { group: 'Add Sensor', key: 'new.name', title: 'Name', placeholder: 'Front Door', 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.' });
|
|
34607
|
-
// ---- UI Add Bypass Switch ----
|
|
34608
|
-
out.push({ group: 'Add Bypass Switch', key: 'bypass.new.id', title: 'New Bypass ID', placeholder: 'living-room-window', value: this.storage.getItem('bypass.new.id') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.zoneName', title: 'Zone Name', placeholder: 'Living Room Window', value: this.storage.getItem('bypass.new.zoneName') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.topic.control', title: 'Control Topic', placeholder: 'paradox/control/zones/Living_Room_Window', value: this.storage.getItem('bypass.new.topic.control') || '' }, { group: 'Add Bypass Switch', key: 'bypass.new.topic.state', title: 'State Topic', placeholder: 'paradox/states/zones/Living_Room_Window/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.' });
|
|
34609
34597
|
// ---- UI for existing sensors ----
|
|
34610
34598
|
for (const cfg of this.sensorsCfg) {
|
|
34611
34599
|
const gid = `Sensor: ${cfg.name} [${cfg.id}]`;
|
|
@@ -34616,12 +34604,7 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34616
34604
|
out.push({ group: gid, key: `sensor.${cfg.id}.topic.motion`, title: 'Motion Detected Topic', value: cfg.topics.motion || '', placeholder: 'paradox/states/zones/XYZ/open' });
|
|
34617
34605
|
else
|
|
34618
34606
|
out.push({ group: gid, key: `sensor.${cfg.id}.topic.occupancy`, title: 'Occupancy Detected Topic', value: cfg.topics.occupancy || '', placeholder: 'paradox/states/zones/XYZ/open' });
|
|
34619
|
-
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' });
|
|
34620
|
-
}
|
|
34621
|
-
// ---- UI for existing bypass switches ----
|
|
34622
|
-
for (const cfg of this.bypassCfg) {
|
|
34623
|
-
const gid = `Bypass: ${cfg.zoneName} [${cfg.id}]`;
|
|
34624
|
-
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/Living_Room_Window' }, { group: gid, key: `bypass.${cfg.id}.topic.state`, title: 'State Topic', value: cfg.topics.state || '', placeholder: 'paradox/states/zones/Living_Room_Window/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' });
|
|
34607
|
+
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/Living_Room_Window', description: 'Configuring bypass topics creates a separate bypass switch accessory for this sensor.' }, { group: gid, key: `sensor.${cfg.id}.bypass.state`, title: 'Bypass State Topic', value: cfg.bypass?.state || '', placeholder: 'paradox/states/zones/Living_Room_Window/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' });
|
|
34625
34608
|
}
|
|
34626
34609
|
return out;
|
|
34627
34610
|
}
|
|
@@ -34654,44 +34637,6 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34654
34637
|
await this.connectMqtt(true);
|
|
34655
34638
|
return;
|
|
34656
34639
|
}
|
|
34657
|
-
// --- Add Bypass Switch workflow ---
|
|
34658
|
-
if (key === 'bypass.new.create' && String(value) === 'true') {
|
|
34659
|
-
const id = (this.storage.getItem('bypass.new.id') || '').trim();
|
|
34660
|
-
const zoneName = (this.storage.getItem('bypass.new.zoneName') || '').trim() || id;
|
|
34661
|
-
const control = (this.storage.getItem('bypass.new.topic.control') || '').trim();
|
|
34662
|
-
const state = (this.storage.getItem('bypass.new.topic.state') || '').trim();
|
|
34663
|
-
const payloadOn = (this.storage.getItem('bypass.new.payloadOn') || 'bypass').trim() || 'bypass';
|
|
34664
|
-
const payloadOff = (this.storage.getItem('bypass.new.payloadOff') || 'clear_bypass').trim() || 'clear_bypass';
|
|
34665
|
-
if (!id) {
|
|
34666
|
-
this.console.warn('Create bypass: missing id');
|
|
34667
|
-
return;
|
|
34668
|
-
}
|
|
34669
|
-
if (this.bypassCfg.find(b => b.id === id)) {
|
|
34670
|
-
this.console.warn('Create bypass: id already exists');
|
|
34671
|
-
return;
|
|
34672
|
-
}
|
|
34673
|
-
this.bypassCfg.push({
|
|
34674
|
-
id,
|
|
34675
|
-
zoneName,
|
|
34676
|
-
topics: { control, state },
|
|
34677
|
-
payloadOn,
|
|
34678
|
-
payloadOff,
|
|
34679
|
-
});
|
|
34680
|
-
this.saveBypassToStorage();
|
|
34681
|
-
// clear "bypass.new.*" fields
|
|
34682
|
-
this.storage.removeItem('bypass.new.id');
|
|
34683
|
-
this.storage.removeItem('bypass.new.zoneName');
|
|
34684
|
-
this.storage.removeItem('bypass.new.topic.control');
|
|
34685
|
-
this.storage.removeItem('bypass.new.topic.state');
|
|
34686
|
-
this.storage.removeItem('bypass.new.payloadOn');
|
|
34687
|
-
this.storage.removeItem('bypass.new.payloadOff');
|
|
34688
|
-
this.storage.removeItem('bypass.new.create');
|
|
34689
|
-
await this.discoverDevices();
|
|
34690
|
-
await this.connectMqtt(true);
|
|
34691
|
-
return;
|
|
34692
|
-
}
|
|
34693
|
-
if (key.startsWith('bypass.new.'))
|
|
34694
|
-
return;
|
|
34695
34640
|
// --- Edit/Remove existing sensor ---
|
|
34696
34641
|
const m = key.match(/^sensor\.([^\.]+)\.(.+)$/);
|
|
34697
34642
|
if (m) {
|
|
@@ -34725,53 +34670,19 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34725
34670
|
const tk = prop.substring('topic.'.length);
|
|
34726
34671
|
cfg.topics[tk] = String(value).trim();
|
|
34727
34672
|
}
|
|
34728
|
-
|
|
34729
|
-
|
|
34730
|
-
|
|
34731
|
-
|
|
34732
|
-
}
|
|
34733
|
-
// --- Edit/Remove existing bypass ---
|
|
34734
|
-
const mb = key.match(/^bypass\.([^\.]+)\.(.+)$/);
|
|
34735
|
-
if (mb) {
|
|
34736
|
-
const bid = mb[1];
|
|
34737
|
-
const prop = mb[2];
|
|
34738
|
-
const cfg = this.bypassCfg.find(b => b.id === bid);
|
|
34739
|
-
if (!cfg) {
|
|
34740
|
-
this.console.warn('putSetting: bypass not found', bid);
|
|
34741
|
-
return;
|
|
34673
|
+
else if (prop.startsWith('bypass.')) {
|
|
34674
|
+
const bk = prop.substring('bypass.'.length);
|
|
34675
|
+
cfg.bypass = cfg.bypass || {};
|
|
34676
|
+
cfg.bypass[bk] = String(value).trim();
|
|
34742
34677
|
}
|
|
34743
|
-
|
|
34744
|
-
this.bypassCfg = this.bypassCfg.filter(b => b.id !== bid);
|
|
34745
|
-
this.saveBypassToStorage();
|
|
34746
|
-
try {
|
|
34747
|
-
this.devices.delete(`bypass:${bid}`);
|
|
34748
|
-
deviceManager.onDeviceRemoved?.(`bypass:${bid}`);
|
|
34749
|
-
}
|
|
34750
|
-
catch { }
|
|
34751
|
-
this.storage.removeItem(key);
|
|
34752
|
-
await this.discoverDevices();
|
|
34753
|
-
await this.connectMqtt(true);
|
|
34754
|
-
return;
|
|
34755
|
-
}
|
|
34756
|
-
if (prop === 'zoneName')
|
|
34757
|
-
cfg.zoneName = String(value);
|
|
34758
|
-
else if (prop === 'payloadOn')
|
|
34759
|
-
cfg.payloadOn = String(value).trim();
|
|
34760
|
-
else if (prop === 'payloadOff')
|
|
34761
|
-
cfg.payloadOff = String(value).trim();
|
|
34762
|
-
else if (prop.startsWith('topic.')) {
|
|
34763
|
-
const tk = prop.substring('topic.'.length);
|
|
34764
|
-
cfg.topics[tk] = String(value).trim();
|
|
34765
|
-
}
|
|
34766
|
-
this.saveBypassToStorage();
|
|
34678
|
+
this.saveSensorsToStorage();
|
|
34767
34679
|
await this.discoverDevices();
|
|
34768
34680
|
await this.connectMqtt(true);
|
|
34769
34681
|
return;
|
|
34770
34682
|
}
|
|
34771
34683
|
// --- Other (MQTT / Alarm settings / parsing / payloads / logging) ---
|
|
34772
|
-
if (key === 'sensorsJson'
|
|
34684
|
+
if (key === 'sensorsJson') {
|
|
34773
34685
|
this.loadSensorsFromStorage();
|
|
34774
|
-
this.loadBypassFromStorage();
|
|
34775
34686
|
await this.discoverDevices();
|
|
34776
34687
|
await this.connectMqtt(true);
|
|
34777
34688
|
}
|
|
@@ -34812,7 +34723,8 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34812
34723
|
}
|
|
34813
34724
|
if (nativeId.startsWith('bypass:')) {
|
|
34814
34725
|
const bid = nativeId.substring('bypass:'.length);
|
|
34815
|
-
const
|
|
34726
|
+
const sensor = this.sensorsCfg.find(s => s.id === bid);
|
|
34727
|
+
const cfg = sensor ? this.buildBypassConfig(sensor) : undefined;
|
|
34816
34728
|
if (!cfg)
|
|
34817
34729
|
return undefined;
|
|
34818
34730
|
const dev = new BypassMqttSwitch(nativeId, cfg, this);
|
|
@@ -34847,33 +34759,75 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34847
34759
|
name: String(x.name),
|
|
34848
34760
|
kind: x.kind,
|
|
34849
34761
|
topics: x.topics || {},
|
|
34762
|
+
bypass: {
|
|
34763
|
+
control: x.bypass?.control || '',
|
|
34764
|
+
state: x.bypass?.state || '',
|
|
34765
|
+
payloadOn: x.bypass?.payloadOn || 'bypass',
|
|
34766
|
+
payloadOff: x.bypass?.payloadOff || 'clear_bypass',
|
|
34767
|
+
},
|
|
34850
34768
|
}));
|
|
34851
34769
|
}
|
|
34852
34770
|
catch (e) {
|
|
34853
34771
|
this.console.error('Invalid sensorsJson:', e);
|
|
34854
34772
|
this.sensorsCfg = [];
|
|
34855
34773
|
}
|
|
34774
|
+
this.migrateBypassFromStorage();
|
|
34856
34775
|
}
|
|
34857
|
-
|
|
34776
|
+
migrateBypassFromStorage() {
|
|
34858
34777
|
try {
|
|
34859
34778
|
const raw = this.storage.getItem('bypassJson') || '[]';
|
|
34860
34779
|
const parsed = JSON.parse(raw);
|
|
34861
|
-
|
|
34862
|
-
|
|
34863
|
-
|
|
34864
|
-
|
|
34865
|
-
|
|
34866
|
-
|
|
34867
|
-
|
|
34868
|
-
|
|
34869
|
-
|
|
34870
|
-
|
|
34780
|
+
if (!Array.isArray(parsed))
|
|
34781
|
+
return;
|
|
34782
|
+
let changed = false;
|
|
34783
|
+
for (const b of (parsed || [])) {
|
|
34784
|
+
if (!b || !b.id)
|
|
34785
|
+
continue;
|
|
34786
|
+
const sensor = this.sensorsCfg.find(s => s.id === String(b.id));
|
|
34787
|
+
if (!sensor)
|
|
34788
|
+
continue;
|
|
34789
|
+
const bypass = sensor.bypass || {};
|
|
34790
|
+
if (!bypass.control && b.topics?.control) {
|
|
34791
|
+
bypass.control = String(b.topics.control);
|
|
34792
|
+
changed = true;
|
|
34793
|
+
}
|
|
34794
|
+
if (!bypass.state && b.topics?.state) {
|
|
34795
|
+
bypass.state = String(b.topics.state);
|
|
34796
|
+
changed = true;
|
|
34797
|
+
}
|
|
34798
|
+
if ((!bypass.payloadOn || bypass.payloadOn === 'bypass') && b.payloadOn) {
|
|
34799
|
+
bypass.payloadOn = String(b.payloadOn);
|
|
34800
|
+
changed = true;
|
|
34801
|
+
}
|
|
34802
|
+
if ((!bypass.payloadOff || bypass.payloadOff === 'clear_bypass') && b.payloadOff) {
|
|
34803
|
+
bypass.payloadOff = String(b.payloadOff);
|
|
34804
|
+
changed = true;
|
|
34805
|
+
}
|
|
34806
|
+
sensor.bypass = bypass;
|
|
34807
|
+
}
|
|
34808
|
+
if (changed)
|
|
34809
|
+
this.saveSensorsToStorage();
|
|
34871
34810
|
}
|
|
34872
34811
|
catch (e) {
|
|
34873
34812
|
this.console.error('Invalid bypassJson:', e);
|
|
34874
|
-
this.bypassCfg = [];
|
|
34875
34813
|
}
|
|
34876
34814
|
}
|
|
34815
|
+
buildBypassConfig(sensor) {
|
|
34816
|
+
const bypass = sensor.bypass;
|
|
34817
|
+
if (!bypass)
|
|
34818
|
+
return;
|
|
34819
|
+
const control = (bypass.control || '').trim();
|
|
34820
|
+
const state = (bypass.state || '').trim();
|
|
34821
|
+
if (!control && !state)
|
|
34822
|
+
return;
|
|
34823
|
+
return {
|
|
34824
|
+
id: sensor.id,
|
|
34825
|
+
zoneName: (sensor.name || '').trim() || sensor.id,
|
|
34826
|
+
topics: { control, state },
|
|
34827
|
+
payloadOn: (bypass.payloadOn || 'bypass').trim() || 'bypass',
|
|
34828
|
+
payloadOff: (bypass.payloadOff || 'clear_bypass').trim() || 'clear_bypass',
|
|
34829
|
+
};
|
|
34830
|
+
}
|
|
34877
34831
|
/** ===== discoverDevices: announce first, instantiate after ===== */
|
|
34878
34832
|
async discoverDevices() {
|
|
34879
34833
|
// 1) manifest
|
|
@@ -34895,7 +34849,10 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34895
34849
|
interfaces.push(sdk_1.ScryptedInterface.Battery);
|
|
34896
34850
|
manifests.push({ nativeId, name: cfg.name, type: sdk_1.ScryptedDeviceType.Sensor, interfaces });
|
|
34897
34851
|
}
|
|
34898
|
-
for (const
|
|
34852
|
+
for (const sensor of this.sensorsCfg) {
|
|
34853
|
+
const cfg = this.buildBypassConfig(sensor);
|
|
34854
|
+
if (!cfg)
|
|
34855
|
+
continue;
|
|
34899
34856
|
const nativeId = `bypass:${cfg.id}`;
|
|
34900
34857
|
const zoneName = (cfg.zoneName || '').trim() || cfg.id;
|
|
34901
34858
|
const name = `${zoneName} Bypass`;
|
|
@@ -34944,7 +34901,10 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34944
34901
|
catch { }
|
|
34945
34902
|
}
|
|
34946
34903
|
}
|
|
34947
|
-
for (const
|
|
34904
|
+
for (const sensor of this.sensorsCfg) {
|
|
34905
|
+
const cfg = this.buildBypassConfig(sensor);
|
|
34906
|
+
if (!cfg)
|
|
34907
|
+
continue;
|
|
34948
34908
|
const nativeId = `bypass:${cfg.id}`;
|
|
34949
34909
|
let dev = this.devices.get(nativeId);
|
|
34950
34910
|
if (!dev) {
|
|
@@ -35005,11 +34965,10 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
35005
34965
|
.forEach(x => subs.add(String(x)));
|
|
35006
34966
|
}
|
|
35007
34967
|
// bypass switches
|
|
35008
|
-
for (const
|
|
35009
|
-
const
|
|
35010
|
-
|
|
35011
|
-
.
|
|
35012
|
-
.forEach(x => subs.add(String(x)));
|
|
34968
|
+
for (const s of this.sensorsCfg) {
|
|
34969
|
+
const state = s.bypass?.state;
|
|
34970
|
+
if (state && state.trim().length > 0)
|
|
34971
|
+
subs.add(state);
|
|
35013
34972
|
}
|
|
35014
34973
|
return Array.from(subs);
|
|
35015
34974
|
}
|
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED