@rfranzoi/scrypted-mqtt-securitysystem 1.0.32 → 1.0.34
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/README.md +2 -2
- package/dist/main.nodejs.js +59 -88
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MQTT SecuritySystem (Scrypted)
|
|
2
2
|
|
|
3
|
-
Control and sync
|
|
3
|
+
Control and sync alarm panels over MQTT (e.g. Paradox with PAI/PAI-MQTT), exposed in Scrypted as a **SecuritySystem**. Optional child sensors (contact, motion, occupancy) can also be integrated.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
package/dist/main.nodejs.js
CHANGED
|
@@ -34024,46 +34024,28 @@ function socketOnError() {
|
|
|
34024
34024
|
|
|
34025
34025
|
"use strict";
|
|
34026
34026
|
|
|
34027
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
34028
|
-
if (k2 === undefined) k2 = k;
|
|
34029
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
34030
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
34031
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
34032
|
-
}
|
|
34033
|
-
Object.defineProperty(o, k2, desc);
|
|
34034
|
-
}) : (function(o, m, k, k2) {
|
|
34035
|
-
if (k2 === undefined) k2 = k;
|
|
34036
|
-
o[k2] = m[k];
|
|
34037
|
-
}));
|
|
34038
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
34039
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
34040
|
-
}) : function(o, v) {
|
|
34041
|
-
o["default"] = v;
|
|
34042
|
-
});
|
|
34043
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
34044
|
-
var ownKeys = function(o) {
|
|
34045
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
34046
|
-
var ar = [];
|
|
34047
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34048
|
-
return ar;
|
|
34049
|
-
};
|
|
34050
|
-
return ownKeys(o);
|
|
34051
|
-
};
|
|
34052
|
-
return function (mod) {
|
|
34053
|
-
if (mod && mod.__esModule) return mod;
|
|
34054
|
-
var result = {};
|
|
34055
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34056
|
-
__setModuleDefault(result, mod);
|
|
34057
|
-
return result;
|
|
34058
|
-
};
|
|
34059
|
-
})();
|
|
34060
34027
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
34061
34028
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34062
34029
|
};
|
|
34063
34030
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
34064
|
-
|
|
34031
|
+
// --- Silence ONLY the optional sdk.json warning from @scrypted/sdk ---
|
|
34032
|
+
const __origConsoleError = console.error.bind(console);
|
|
34033
|
+
console.error = (...args) => {
|
|
34034
|
+
const first = args?.[0];
|
|
34035
|
+
const msg = typeof first === 'string' ? first : (first?.message || '');
|
|
34036
|
+
if (typeof msg === 'string' && msg.includes('failed to load custom interface descriptors')) {
|
|
34037
|
+
// swallow just this warning
|
|
34038
|
+
return;
|
|
34039
|
+
}
|
|
34040
|
+
__origConsoleError(...args);
|
|
34041
|
+
};
|
|
34042
|
+
// Carica lo SDK (non tipizziamo qui per non perdere le proprietà runtime)
|
|
34043
|
+
const sdk = __webpack_require__(/*! @scrypted/sdk */ "./node_modules/@scrypted/sdk/dist/src/index.js");
|
|
34044
|
+
// Valori runtime (enum/classi/manager) dal modulo SDK
|
|
34045
|
+
const { ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, // valore (enum)
|
|
34046
|
+
SecuritySystemMode, // valore (enum)
|
|
34047
|
+
systemManager, deviceManager, } = sdk;
|
|
34065
34048
|
const mqtt_1 = __importDefault(__webpack_require__(/*! mqtt */ "./node_modules/mqtt/build/index.js"));
|
|
34066
|
-
const { systemManager, deviceManager } = sdk_1.default;
|
|
34067
34049
|
/** utils */
|
|
34068
34050
|
function truthy(v) {
|
|
34069
34051
|
if (!v)
|
|
@@ -34083,12 +34065,13 @@ function normalize(s) {
|
|
|
34083
34065
|
function clamp(n, min, max) {
|
|
34084
34066
|
return Math.max(min, Math.min(max, n));
|
|
34085
34067
|
}
|
|
34086
|
-
/** SecuritySystem outgoing defaults (PAI-like)
|
|
34068
|
+
/** SecuritySystem outgoing defaults (PAI-like)
|
|
34069
|
+
* Nota: usare number come chiave evita stranezze con gli enum in TS. */
|
|
34087
34070
|
const DEFAULT_OUTGOING = {
|
|
34088
|
-
[
|
|
34089
|
-
[
|
|
34090
|
-
[
|
|
34091
|
-
[
|
|
34071
|
+
[SecuritySystemMode.Disarmed]: 'disarm',
|
|
34072
|
+
[SecuritySystemMode.HomeArmed]: 'arm_home',
|
|
34073
|
+
[SecuritySystemMode.AwayArmed]: 'arm_away',
|
|
34074
|
+
[SecuritySystemMode.NightArmed]: 'arm_night',
|
|
34092
34075
|
};
|
|
34093
34076
|
/** Parse incoming payload -> final mode (ignore transition states) */
|
|
34094
34077
|
function payloadToMode(payload) {
|
|
@@ -34096,23 +34079,22 @@ function payloadToMode(payload) {
|
|
|
34096
34079
|
return;
|
|
34097
34080
|
const p = normalize(payload.toString());
|
|
34098
34081
|
if (['disarm', 'disarmed', 'off', '0', 'idle', 'ready'].includes(p))
|
|
34099
|
-
return
|
|
34082
|
+
return SecuritySystemMode.Disarmed;
|
|
34100
34083
|
if (['arm_home', 'home', 'stay', 'armed_home'].includes(p))
|
|
34101
|
-
return
|
|
34084
|
+
return SecuritySystemMode.HomeArmed;
|
|
34102
34085
|
if (['arm_away', 'away', 'armed_away', 'away_armed'].includes(p))
|
|
34103
|
-
return
|
|
34086
|
+
return SecuritySystemMode.AwayArmed;
|
|
34104
34087
|
if (['arm_night', 'night', 'armed_night', 'sleep', 'arm_sleep', 'armed_sleep'].includes(p))
|
|
34105
|
-
return
|
|
34088
|
+
return SecuritySystemMode.NightArmed;
|
|
34106
34089
|
// transitori: non cambiano il mode
|
|
34107
34090
|
if (['entry_delay', 'exit_delay', 'pending', 'arming', 'disarming'].includes(p))
|
|
34108
34091
|
return undefined;
|
|
34109
34092
|
return undefined;
|
|
34110
34093
|
}
|
|
34111
|
-
class BaseMqttSensor extends
|
|
34094
|
+
class BaseMqttSensor extends ScryptedDeviceBase {
|
|
34112
34095
|
constructor(nativeId, cfg) {
|
|
34113
34096
|
super(nativeId);
|
|
34114
34097
|
this.cfg = cfg;
|
|
34115
|
-
// non impostare stati qui: l'annuncio device deve avvenire prima
|
|
34116
34098
|
}
|
|
34117
34099
|
/** Called by parent on each MQTT message */
|
|
34118
34100
|
handleMqtt(topic, payload) {
|
|
@@ -34141,9 +34123,7 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
|
|
|
34141
34123
|
this.batteryLevel = n;
|
|
34142
34124
|
}
|
|
34143
34125
|
else if (topic === this.cfg.topics.lowBattery && !this.cfg.topics.batteryLevel) {
|
|
34144
|
-
//
|
|
34145
|
-
// True -> 10% (warning)
|
|
34146
|
-
// False -> 100% (ok)
|
|
34126
|
+
// se abbiamo SOLO lowBattery (bool):
|
|
34147
34127
|
this.batteryLevel = truthy(np) ? 10 : 100;
|
|
34148
34128
|
}
|
|
34149
34129
|
// primary handled by subclasses
|
|
@@ -34151,37 +34131,28 @@ class BaseMqttSensor extends sdk_1.ScryptedDeviceBase {
|
|
|
34151
34131
|
}
|
|
34152
34132
|
}
|
|
34153
34133
|
class ContactMqttSensor extends BaseMqttSensor {
|
|
34154
|
-
|
|
34155
|
-
super(nativeId, cfg);
|
|
34156
|
-
}
|
|
34157
|
-
handlePrimary(topic, np, _raw) {
|
|
34134
|
+
handlePrimary(topic, np) {
|
|
34158
34135
|
if (topic === this.cfg.topics.contact) {
|
|
34159
34136
|
this.entryOpen = truthy(np);
|
|
34160
34137
|
}
|
|
34161
34138
|
}
|
|
34162
34139
|
}
|
|
34163
34140
|
class MotionMqttSensor extends BaseMqttSensor {
|
|
34164
|
-
|
|
34165
|
-
super(nativeId, cfg);
|
|
34166
|
-
}
|
|
34167
|
-
handlePrimary(topic, np, _raw) {
|
|
34141
|
+
handlePrimary(topic, np) {
|
|
34168
34142
|
if (topic === this.cfg.topics.motion) {
|
|
34169
34143
|
this.motionDetected = truthy(np);
|
|
34170
34144
|
}
|
|
34171
34145
|
}
|
|
34172
34146
|
}
|
|
34173
34147
|
class OccupancyMqttSensor extends BaseMqttSensor {
|
|
34174
|
-
|
|
34175
|
-
super(nativeId, cfg);
|
|
34176
|
-
}
|
|
34177
|
-
handlePrimary(topic, np, _raw) {
|
|
34148
|
+
handlePrimary(topic, np) {
|
|
34178
34149
|
if (topic === this.cfg.topics.occupancy) {
|
|
34179
34150
|
this.occupied = truthy(np);
|
|
34180
34151
|
}
|
|
34181
34152
|
}
|
|
34182
34153
|
}
|
|
34183
34154
|
/** ----------------- Main Plugin ----------------- */
|
|
34184
|
-
class ParadoxMqttSecuritySystem extends
|
|
34155
|
+
class ParadoxMqttSecuritySystem extends ScryptedDeviceBase {
|
|
34185
34156
|
constructor() {
|
|
34186
34157
|
super();
|
|
34187
34158
|
// sensor management
|
|
@@ -34190,26 +34161,26 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34190
34161
|
// (facoltativo) Imposta il device type in UI
|
|
34191
34162
|
setTimeout(() => {
|
|
34192
34163
|
try {
|
|
34193
|
-
systemManager.getDeviceById(this.id)?.setType?.(
|
|
34164
|
+
systemManager.getDeviceById(this.id)?.setType?.(ScryptedDeviceType.SecuritySystem);
|
|
34194
34165
|
}
|
|
34195
34166
|
catch { }
|
|
34196
34167
|
});
|
|
34197
34168
|
// Default state
|
|
34198
34169
|
this.securitySystemState = this.securitySystemState || {
|
|
34199
|
-
mode:
|
|
34170
|
+
mode: SecuritySystemMode.Disarmed,
|
|
34200
34171
|
supportedModes: [
|
|
34201
|
-
|
|
34202
|
-
|
|
34203
|
-
|
|
34204
|
-
|
|
34172
|
+
SecuritySystemMode.Disarmed,
|
|
34173
|
+
SecuritySystemMode.HomeArmed,
|
|
34174
|
+
SecuritySystemMode.AwayArmed,
|
|
34175
|
+
SecuritySystemMode.NightArmed,
|
|
34205
34176
|
],
|
|
34206
34177
|
};
|
|
34207
34178
|
this.online = this.online ?? false;
|
|
34208
34179
|
// Load sensors config and announce devices
|
|
34209
34180
|
this.loadSensorsFromStorage();
|
|
34210
|
-
this.discoverSensors().catch(e => this.console.error('discoverSensors error', e));
|
|
34181
|
+
this.discoverSensors().catch((e) => this.console.error('discoverSensors error', e));
|
|
34211
34182
|
// Connect on start
|
|
34212
|
-
this.connectMqtt().catch(e => this.console.error('MQTT connect error:', e));
|
|
34183
|
+
this.connectMqtt().catch((e) => this.console.error('MQTT connect error:', e));
|
|
34213
34184
|
// chiusura pulita del client MQTT ai reload/stop del plugin
|
|
34214
34185
|
try {
|
|
34215
34186
|
process.once('SIGTERM', () => { try {
|
|
@@ -34391,22 +34362,22 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34391
34362
|
const manifests = this.sensorsCfg.map(cfg => {
|
|
34392
34363
|
const nativeId = `sensor:${cfg.id}`;
|
|
34393
34364
|
const t = cfg.topics || {};
|
|
34394
|
-
const interfaces = [
|
|
34365
|
+
const interfaces = [ScryptedInterface.Online];
|
|
34395
34366
|
// Tamper solo se c'è un topic tamper
|
|
34396
34367
|
if (t.tamper)
|
|
34397
|
-
interfaces.push(
|
|
34368
|
+
interfaces.push(ScryptedInterface.TamperSensor);
|
|
34398
34369
|
// Interfaccia primaria
|
|
34399
34370
|
if (cfg.kind === 'contact')
|
|
34400
|
-
interfaces.unshift(
|
|
34371
|
+
interfaces.unshift(ScryptedInterface.EntrySensor);
|
|
34401
34372
|
else if (cfg.kind === 'motion')
|
|
34402
|
-
interfaces.unshift(
|
|
34373
|
+
interfaces.unshift(ScryptedInterface.MotionSensor);
|
|
34403
34374
|
else
|
|
34404
|
-
interfaces.unshift(
|
|
34375
|
+
interfaces.unshift(ScryptedInterface.OccupancySensor);
|
|
34405
34376
|
// Battery solo se previsto
|
|
34406
34377
|
if (t.batteryLevel || t.lowBattery) {
|
|
34407
|
-
interfaces.push(
|
|
34378
|
+
interfaces.push(ScryptedInterface.Battery);
|
|
34408
34379
|
}
|
|
34409
|
-
return { nativeId, name: cfg.name, type:
|
|
34380
|
+
return { nativeId, name: cfg.name, type: ScryptedDeviceType.Sensor, interfaces };
|
|
34410
34381
|
});
|
|
34411
34382
|
// 2) Annuncio
|
|
34412
34383
|
const dmAny = deviceManager;
|
|
@@ -34551,14 +34522,14 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34551
34522
|
if (topic === tCurrent) {
|
|
34552
34523
|
const mode = payloadToMode(payload);
|
|
34553
34524
|
const isAlarm = ['alarm', 'triggered'].includes(np);
|
|
34554
|
-
const current = this.securitySystemState || { mode:
|
|
34525
|
+
const current = this.securitySystemState || { mode: SecuritySystemMode.Disarmed };
|
|
34555
34526
|
const newState = {
|
|
34556
34527
|
mode: mode ?? current.mode,
|
|
34557
34528
|
supportedModes: current.supportedModes ?? [
|
|
34558
|
-
|
|
34559
|
-
|
|
34560
|
-
|
|
34561
|
-
|
|
34529
|
+
SecuritySystemMode.Disarmed,
|
|
34530
|
+
SecuritySystemMode.HomeArmed,
|
|
34531
|
+
SecuritySystemMode.AwayArmed,
|
|
34532
|
+
SecuritySystemMode.NightArmed,
|
|
34562
34533
|
],
|
|
34563
34534
|
triggered: isAlarm || undefined,
|
|
34564
34535
|
};
|
|
@@ -34602,17 +34573,17 @@ class ParadoxMqttSecuritySystem extends sdk_1.ScryptedDeviceBase {
|
|
|
34602
34573
|
this.publishSetTarget(payload);
|
|
34603
34574
|
}
|
|
34604
34575
|
async disarmSecuritySystem() {
|
|
34605
|
-
const payload = this.getOutgoing(
|
|
34576
|
+
const payload = this.getOutgoing(SecuritySystemMode.Disarmed);
|
|
34606
34577
|
this.console.log('disarmSecuritySystem ->', payload);
|
|
34607
|
-
this.pendingTarget =
|
|
34578
|
+
this.pendingTarget = SecuritySystemMode.Disarmed;
|
|
34608
34579
|
this.publishSetTarget(payload);
|
|
34609
34580
|
}
|
|
34610
34581
|
getOutgoing(mode) {
|
|
34611
34582
|
const map = {
|
|
34612
|
-
[
|
|
34613
|
-
[
|
|
34614
|
-
[
|
|
34615
|
-
[
|
|
34583
|
+
[SecuritySystemMode.Disarmed]: this.storage.getItem('payloadDisarm') || DEFAULT_OUTGOING[SecuritySystemMode.Disarmed],
|
|
34584
|
+
[SecuritySystemMode.HomeArmed]: this.storage.getItem('payloadHome') || DEFAULT_OUTGOING[SecuritySystemMode.HomeArmed],
|
|
34585
|
+
[SecuritySystemMode.AwayArmed]: this.storage.getItem('payloadAway') || DEFAULT_OUTGOING[SecuritySystemMode.AwayArmed],
|
|
34586
|
+
[SecuritySystemMode.NightArmed]: this.storage.getItem('payloadNight') || DEFAULT_OUTGOING[SecuritySystemMode.NightArmed],
|
|
34616
34587
|
};
|
|
34617
34588
|
return map[mode];
|
|
34618
34589
|
}
|
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED