node-red-contrib-boolean-logic-ultimate 1.2.8 → 1.2.11
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/CHANGELOG.md +20 -0
- package/README.md +62 -64
- package/boolean-logic-ultimate/DebouncerUltimate.html +76 -0
- package/boolean-logic-ultimate/DebouncerUltimate.js +190 -0
- package/boolean-logic-ultimate/HysteresisUltimate.html +137 -0
- package/boolean-logic-ultimate/HysteresisUltimate.js +197 -0
- package/boolean-logic-ultimate/RateLimiterUltimate.html +7 -7
- package/examples/DebouncerUltimate.json +168 -0
- package/examples/HysteresisUltimate.json +109 -0
- package/examples/README.md +2 -2
- package/img/debouncer.png +0 -0
- package/package.json +5 -3
- package/test/debouncer.spec.js +146 -0
- package/test/helpers.js +6 -0
- package/test/hysteresis.spec.js +87 -0
- package/examples/AlarmSystemUltimate.json +0 -286
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { expect } = require('chai');
|
|
4
|
+
const { helper, loadDebouncer } = require('./helpers');
|
|
5
|
+
|
|
6
|
+
describe('DebouncerUltimate node', function () {
|
|
7
|
+
this.timeout(5000);
|
|
8
|
+
|
|
9
|
+
before(function (done) {
|
|
10
|
+
helper.startServer(done);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
after(function (done) {
|
|
14
|
+
helper.stopServer(done);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
afterEach(function () {
|
|
18
|
+
return helper.unload();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('trailing debounce emits only the last message after quiet time', function (done) {
|
|
22
|
+
const flowId = 'flow1';
|
|
23
|
+
const flow = [
|
|
24
|
+
{ id: flowId, type: 'tab', label: 'flow1' },
|
|
25
|
+
{
|
|
26
|
+
id: 'debouncer',
|
|
27
|
+
type: 'DebouncerUltimate',
|
|
28
|
+
z: flowId,
|
|
29
|
+
wait: 40,
|
|
30
|
+
emitOn: 'trailing',
|
|
31
|
+
controlTopic: 'debouncer',
|
|
32
|
+
wires: [['out']],
|
|
33
|
+
},
|
|
34
|
+
{ id: 'in', type: 'helper', z: flowId, wires: [['debouncer']] },
|
|
35
|
+
{ id: 'out', type: 'helper', z: flowId },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
loadDebouncer(flow).then(() => {
|
|
39
|
+
const debouncer = helper.getNode('debouncer');
|
|
40
|
+
const out = helper.getNode('out');
|
|
41
|
+
const seen = [];
|
|
42
|
+
|
|
43
|
+
out.on('input', (msg) => {
|
|
44
|
+
seen.push(msg.payload);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
debouncer.receive({ topic: 'sensor', payload: 'first' });
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
debouncer.receive({ topic: 'sensor', payload: 'second' });
|
|
50
|
+
}, 15);
|
|
51
|
+
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
try {
|
|
54
|
+
expect(seen).to.deep.equal(['second']);
|
|
55
|
+
done();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
done(error);
|
|
58
|
+
}
|
|
59
|
+
}, 120);
|
|
60
|
+
}).catch(done);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('both mode emits first immediately and last after quiet time', function (done) {
|
|
64
|
+
const flowId = 'flow2';
|
|
65
|
+
const flow = [
|
|
66
|
+
{ id: flowId, type: 'tab', label: 'flow2' },
|
|
67
|
+
{
|
|
68
|
+
id: 'debouncer',
|
|
69
|
+
type: 'DebouncerUltimate',
|
|
70
|
+
z: flowId,
|
|
71
|
+
wait: 50,
|
|
72
|
+
emitOn: 'both',
|
|
73
|
+
controlTopic: 'debouncer',
|
|
74
|
+
wires: [['out']],
|
|
75
|
+
},
|
|
76
|
+
{ id: 'in', type: 'helper', z: flowId, wires: [['debouncer']] },
|
|
77
|
+
{ id: 'out', type: 'helper', z: flowId },
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
loadDebouncer(flow).then(() => {
|
|
81
|
+
const debouncer = helper.getNode('debouncer');
|
|
82
|
+
const out = helper.getNode('out');
|
|
83
|
+
const seen = [];
|
|
84
|
+
|
|
85
|
+
out.on('input', (msg) => {
|
|
86
|
+
seen.push(msg.payload);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
debouncer.receive({ topic: 'sensor', payload: 'first' });
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
debouncer.receive({ topic: 'sensor', payload: 'second' });
|
|
92
|
+
}, 15);
|
|
93
|
+
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
try {
|
|
96
|
+
expect(seen).to.deep.equal(['first', 'second']);
|
|
97
|
+
done();
|
|
98
|
+
} catch (error) {
|
|
99
|
+
done(error);
|
|
100
|
+
}
|
|
101
|
+
}, 140);
|
|
102
|
+
}).catch(done);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('leading mode emits only the first message during the debounce window', function (done) {
|
|
106
|
+
const flowId = 'flow3';
|
|
107
|
+
const flow = [
|
|
108
|
+
{ id: flowId, type: 'tab', label: 'flow3' },
|
|
109
|
+
{
|
|
110
|
+
id: 'debouncer',
|
|
111
|
+
type: 'DebouncerUltimate',
|
|
112
|
+
z: flowId,
|
|
113
|
+
wait: 60,
|
|
114
|
+
emitOn: 'leading',
|
|
115
|
+
controlTopic: 'debouncer',
|
|
116
|
+
wires: [['out']],
|
|
117
|
+
},
|
|
118
|
+
{ id: 'in', type: 'helper', z: flowId, wires: [['debouncer']] },
|
|
119
|
+
{ id: 'out', type: 'helper', z: flowId },
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
loadDebouncer(flow).then(() => {
|
|
123
|
+
const debouncer = helper.getNode('debouncer');
|
|
124
|
+
const out = helper.getNode('out');
|
|
125
|
+
const seen = [];
|
|
126
|
+
|
|
127
|
+
out.on('input', (msg) => {
|
|
128
|
+
seen.push(msg.payload);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
debouncer.receive({ topic: 'sensor', payload: 'first' });
|
|
132
|
+
setTimeout(() => {
|
|
133
|
+
debouncer.receive({ topic: 'sensor', payload: 'second' });
|
|
134
|
+
}, 15);
|
|
135
|
+
|
|
136
|
+
setTimeout(() => {
|
|
137
|
+
try {
|
|
138
|
+
expect(seen).to.deep.equal(['first']);
|
|
139
|
+
done();
|
|
140
|
+
} catch (error) {
|
|
141
|
+
done(error);
|
|
142
|
+
}
|
|
143
|
+
}, 140);
|
|
144
|
+
}).catch(done);
|
|
145
|
+
});
|
|
146
|
+
});
|
package/test/helpers.js
CHANGED
|
@@ -6,6 +6,7 @@ const helper = require('node-red-node-test-helper');
|
|
|
6
6
|
helper.init(require.resolve('node-red')); // initialise with Node-RED runtime
|
|
7
7
|
|
|
8
8
|
const nodes = {
|
|
9
|
+
DebouncerUltimate: require(path.join('..', 'boolean-logic-ultimate', 'DebouncerUltimate.js')),
|
|
9
10
|
RateLimiterUltimate: require(path.join('..', 'boolean-logic-ultimate', 'RateLimiterUltimate.js')),
|
|
10
11
|
PresenceSimulatorUltimate: require(path.join('..', 'boolean-logic-ultimate', 'PresenceSimulatorUltimate.js')),
|
|
11
12
|
RailwaySwitchUltimate: require(path.join('..', 'boolean-logic-ultimate', 'RailwaySwitchUltimate.js')),
|
|
@@ -33,6 +34,10 @@ function loadRateLimiter(flow, credentials = {}) {
|
|
|
33
34
|
return loadNode(nodes.RateLimiterUltimate, flow, credentials);
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
function loadDebouncer(flow, credentials = {}) {
|
|
38
|
+
return loadNode(nodes.DebouncerUltimate, flow, credentials);
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
function loadPresence(flow, credentials = {}) {
|
|
37
42
|
return loadNode(nodes.PresenceSimulatorUltimate, flow, credentials);
|
|
38
43
|
}
|
|
@@ -43,6 +48,7 @@ function loadRailwaySwitch(flow, credentials = {}) {
|
|
|
43
48
|
|
|
44
49
|
module.exports = {
|
|
45
50
|
helper,
|
|
51
|
+
loadDebouncer,
|
|
46
52
|
loadRateLimiter,
|
|
47
53
|
loadPresence,
|
|
48
54
|
loadRailwaySwitch,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { expect } = require('chai');
|
|
4
|
+
const { helper } = require('./helpers');
|
|
5
|
+
|
|
6
|
+
const hysteresisNode = require('../boolean-logic-ultimate/HysteresisUltimate.js');
|
|
7
|
+
|
|
8
|
+
function loadHysteresis(flow, credentials) {
|
|
9
|
+
const normalizedFlow = flow.map((node, index) => {
|
|
10
|
+
if (
|
|
11
|
+
node &&
|
|
12
|
+
node.type &&
|
|
13
|
+
node.type !== 'tab' &&
|
|
14
|
+
node.type !== 'subflow' &&
|
|
15
|
+
node.type !== 'group' &&
|
|
16
|
+
node.z &&
|
|
17
|
+
!(Object.prototype.hasOwnProperty.call(node, 'x') && Object.prototype.hasOwnProperty.call(node, 'y'))
|
|
18
|
+
) {
|
|
19
|
+
return { ...node, x: 100 + index * 10, y: 100 + index * 10 };
|
|
20
|
+
}
|
|
21
|
+
return node;
|
|
22
|
+
});
|
|
23
|
+
return helper.load(hysteresisNode, normalizedFlow, credentials || {});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
describe('HysteresisUltimate node', function () {
|
|
27
|
+
this.timeout(5000);
|
|
28
|
+
|
|
29
|
+
before(function (done) {
|
|
30
|
+
helper.startServer(done);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
after(function (done) {
|
|
34
|
+
helper.stopServer(done);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(function () {
|
|
38
|
+
return helper.unload();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('emits on state transitions only', function (done) {
|
|
42
|
+
const flowId = 'hys1';
|
|
43
|
+
const flow = [
|
|
44
|
+
{ id: flowId, type: 'tab', label: 'hys1' },
|
|
45
|
+
{
|
|
46
|
+
id: 'hys',
|
|
47
|
+
type: 'HysteresisUltimate',
|
|
48
|
+
z: flowId,
|
|
49
|
+
mode: 'high',
|
|
50
|
+
onThreshold: 70,
|
|
51
|
+
offThreshold: 60,
|
|
52
|
+
emitOnlyOnChange: true,
|
|
53
|
+
onPayload: true,
|
|
54
|
+
onPayloadType: 'bool',
|
|
55
|
+
offPayload: false,
|
|
56
|
+
offPayloadType: 'bool',
|
|
57
|
+
wires: [['out'], ['diag']],
|
|
58
|
+
},
|
|
59
|
+
{ id: 'in', type: 'helper', z: flowId, wires: [['hys']] },
|
|
60
|
+
{ id: 'out', type: 'helper', z: flowId },
|
|
61
|
+
{ id: 'diag', type: 'helper', z: flowId },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
loadHysteresis(flow).then(() => {
|
|
65
|
+
const hys = helper.getNode('hys');
|
|
66
|
+
const out = helper.getNode('out');
|
|
67
|
+
const results = [];
|
|
68
|
+
|
|
69
|
+
out.on('input', (msg) => {
|
|
70
|
+
results.push(msg.payload);
|
|
71
|
+
if (results.length === 2) {
|
|
72
|
+
try {
|
|
73
|
+
expect(results).to.deep.equal([true, false]);
|
|
74
|
+
done();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
done(error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
hys.receive({ topic: 'sensor', payload: 65 });
|
|
82
|
+
hys.receive({ topic: 'sensor', payload: 72 });
|
|
83
|
+
hys.receive({ topic: 'sensor', payload: 68 });
|
|
84
|
+
hys.receive({ topic: 'sensor', payload: 58 });
|
|
85
|
+
}).catch(done);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": "al_tab_1",
|
|
4
|
-
"type": "tab",
|
|
5
|
-
"label": "AlarmSystemUltimate - demo base",
|
|
6
|
-
"disabled": false,
|
|
7
|
-
"info": "Esempio per il nodo ALARM (Alarm System Ultimate - BETA): armo/disarmo, bypass zone, trigger sensori, eventi e sirena."
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
"id": "al_cmt_1",
|
|
11
|
-
"type": "comment",
|
|
12
|
-
"z": "al_tab_1",
|
|
13
|
-
"name": "Topic di controllo = alarm | Topic sirena = siren",
|
|
14
|
-
"info": "Comandi principali (topic=alarm): arm_away/arm_home/arm_night, disarm, status, bypass/unbypass (con msg.zone). I sensori entrano con msg.topic uguale a quello configurato nelle zone e payload booleano true/false.",
|
|
15
|
-
"x": 260,
|
|
16
|
-
"y": 60,
|
|
17
|
-
"wires": []
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"id": "al_inj_arm_away",
|
|
21
|
-
"type": "inject",
|
|
22
|
-
"z": "al_tab_1",
|
|
23
|
-
"name": "ARM AWAY (code=1234)",
|
|
24
|
-
"props": [
|
|
25
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
26
|
-
{ "p": "command", "v": "arm_away", "vt": "str" },
|
|
27
|
-
{ "p": "code", "v": "1234", "vt": "str" }
|
|
28
|
-
],
|
|
29
|
-
"repeat": "",
|
|
30
|
-
"crontab": "",
|
|
31
|
-
"once": false,
|
|
32
|
-
"onceDelay": 0.1,
|
|
33
|
-
"x": 160,
|
|
34
|
-
"y": 140,
|
|
35
|
-
"wires": [["al_alarm_1"]]
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"id": "al_inj_arm_home",
|
|
39
|
-
"type": "inject",
|
|
40
|
-
"z": "al_tab_1",
|
|
41
|
-
"name": "ARM HOME (code=1234)",
|
|
42
|
-
"props": [
|
|
43
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
44
|
-
{ "p": "command", "v": "arm_home", "vt": "str" },
|
|
45
|
-
{ "p": "code", "v": "1234", "vt": "str" }
|
|
46
|
-
],
|
|
47
|
-
"repeat": "",
|
|
48
|
-
"crontab": "",
|
|
49
|
-
"once": false,
|
|
50
|
-
"onceDelay": 0.1,
|
|
51
|
-
"x": 160,
|
|
52
|
-
"y": 180,
|
|
53
|
-
"wires": [["al_alarm_1"]]
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"id": "al_inj_disarm",
|
|
57
|
-
"type": "inject",
|
|
58
|
-
"z": "al_tab_1",
|
|
59
|
-
"name": "DISARM (code=1234)",
|
|
60
|
-
"props": [
|
|
61
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
62
|
-
{ "p": "command", "v": "disarm", "vt": "str" },
|
|
63
|
-
{ "p": "code", "v": "1234", "vt": "str" }
|
|
64
|
-
],
|
|
65
|
-
"repeat": "",
|
|
66
|
-
"crontab": "",
|
|
67
|
-
"once": false,
|
|
68
|
-
"onceDelay": 0.1,
|
|
69
|
-
"x": 160,
|
|
70
|
-
"y": 220,
|
|
71
|
-
"wires": [["al_alarm_1"]]
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"id": "al_inj_status",
|
|
75
|
-
"type": "inject",
|
|
76
|
-
"z": "al_tab_1",
|
|
77
|
-
"name": "STATUS",
|
|
78
|
-
"props": [
|
|
79
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
80
|
-
{ "p": "command", "v": "status", "vt": "str" }
|
|
81
|
-
],
|
|
82
|
-
"repeat": "",
|
|
83
|
-
"crontab": "",
|
|
84
|
-
"once": false,
|
|
85
|
-
"onceDelay": 0.1,
|
|
86
|
-
"x": 110,
|
|
87
|
-
"y": 260,
|
|
88
|
-
"wires": [["al_alarm_1"]]
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
"id": "al_inj_bypass_front",
|
|
92
|
-
"type": "inject",
|
|
93
|
-
"z": "al_tab_1",
|
|
94
|
-
"name": "BYPASS front_door",
|
|
95
|
-
"props": [
|
|
96
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
97
|
-
{ "p": "command", "v": "bypass", "vt": "str" },
|
|
98
|
-
{ "p": "zone", "v": "front_door", "vt": "str" }
|
|
99
|
-
],
|
|
100
|
-
"repeat": "",
|
|
101
|
-
"crontab": "",
|
|
102
|
-
"once": false,
|
|
103
|
-
"onceDelay": 0.1,
|
|
104
|
-
"x": 140,
|
|
105
|
-
"y": 320,
|
|
106
|
-
"wires": [["al_alarm_1"]]
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
"id": "al_inj_unbypass_front",
|
|
110
|
-
"type": "inject",
|
|
111
|
-
"z": "al_tab_1",
|
|
112
|
-
"name": "UNBYPASS front_door",
|
|
113
|
-
"props": [
|
|
114
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
115
|
-
{ "p": "command", "v": "unbypass", "vt": "str" },
|
|
116
|
-
{ "p": "zone", "v": "front_door", "vt": "str" }
|
|
117
|
-
],
|
|
118
|
-
"repeat": "",
|
|
119
|
-
"crontab": "",
|
|
120
|
-
"once": false,
|
|
121
|
-
"onceDelay": 0.1,
|
|
122
|
-
"x": 150,
|
|
123
|
-
"y": 360,
|
|
124
|
-
"wires": [["al_alarm_1"]]
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"id": "al_cmt_2",
|
|
128
|
-
"type": "comment",
|
|
129
|
-
"z": "al_tab_1",
|
|
130
|
-
"name": "Sensori (topic = zona) | payload true = trigger | payload false = restore",
|
|
131
|
-
"info": "La zona front_door è con entry delay e chime quando disarmata. pir_living è attiva solo in away. smoke è fire 24/7 (sempre attiva).",
|
|
132
|
-
"x": 320,
|
|
133
|
-
"y": 420,
|
|
134
|
-
"wires": []
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
"id": "al_inj_front_open",
|
|
138
|
-
"type": "inject",
|
|
139
|
-
"z": "al_tab_1",
|
|
140
|
-
"name": "Front door OPEN (true)",
|
|
141
|
-
"props": [
|
|
142
|
-
{ "p": "topic", "v": "sensor/frontdoor", "vt": "str" },
|
|
143
|
-
{ "p": "payload", "v": "true", "vt": "bool" }
|
|
144
|
-
],
|
|
145
|
-
"repeat": "",
|
|
146
|
-
"crontab": "",
|
|
147
|
-
"once": false,
|
|
148
|
-
"onceDelay": 0.1,
|
|
149
|
-
"x": 170,
|
|
150
|
-
"y": 500,
|
|
151
|
-
"wires": [["al_alarm_1"]]
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
"id": "al_inj_front_close",
|
|
155
|
-
"type": "inject",
|
|
156
|
-
"z": "al_tab_1",
|
|
157
|
-
"name": "Front door CLOSE (false)",
|
|
158
|
-
"props": [
|
|
159
|
-
{ "p": "topic", "v": "sensor/frontdoor", "vt": "str" },
|
|
160
|
-
{ "p": "payload", "v": "false", "vt": "bool" }
|
|
161
|
-
],
|
|
162
|
-
"repeat": "",
|
|
163
|
-
"crontab": "",
|
|
164
|
-
"once": false,
|
|
165
|
-
"onceDelay": 0.1,
|
|
166
|
-
"x": 180,
|
|
167
|
-
"y": 540,
|
|
168
|
-
"wires": [["al_alarm_1"]]
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"id": "al_inj_pir",
|
|
172
|
-
"type": "inject",
|
|
173
|
-
"z": "al_tab_1",
|
|
174
|
-
"name": "PIR living (true)",
|
|
175
|
-
"props": [
|
|
176
|
-
{ "p": "topic", "v": "sensor/living_pir", "vt": "str" },
|
|
177
|
-
{ "p": "payload", "v": "true", "vt": "bool" }
|
|
178
|
-
],
|
|
179
|
-
"repeat": "",
|
|
180
|
-
"crontab": "",
|
|
181
|
-
"once": false,
|
|
182
|
-
"onceDelay": 0.1,
|
|
183
|
-
"x": 150,
|
|
184
|
-
"y": 600,
|
|
185
|
-
"wires": [["al_alarm_1"]]
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
"id": "al_inj_smoke",
|
|
189
|
-
"type": "inject",
|
|
190
|
-
"z": "al_tab_1",
|
|
191
|
-
"name": "SMOKE (true)",
|
|
192
|
-
"props": [
|
|
193
|
-
{ "p": "topic", "v": "sensor/smoke", "vt": "str" },
|
|
194
|
-
{ "p": "payload", "v": "true", "vt": "bool" }
|
|
195
|
-
],
|
|
196
|
-
"repeat": "",
|
|
197
|
-
"crontab": "",
|
|
198
|
-
"once": false,
|
|
199
|
-
"onceDelay": 0.1,
|
|
200
|
-
"x": 130,
|
|
201
|
-
"y": 640,
|
|
202
|
-
"wires": [["al_alarm_1"]]
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
"id": "al_alarm_1",
|
|
206
|
-
"type": "AlarmSystemUltimate",
|
|
207
|
-
"z": "al_tab_1",
|
|
208
|
-
"name": "ALARM",
|
|
209
|
-
"controlTopic": "alarm",
|
|
210
|
-
"payloadPropName": "payload",
|
|
211
|
-
"translatorConfig": "",
|
|
212
|
-
"persistState": true,
|
|
213
|
-
"requireCodeForArm": true,
|
|
214
|
-
"requireCodeForDisarm": true,
|
|
215
|
-
"armCode": "1234",
|
|
216
|
-
"duressCode": "9999",
|
|
217
|
-
"blockArmOnViolations": true,
|
|
218
|
-
"exitDelaySeconds": 10,
|
|
219
|
-
"entryDelaySeconds": 5,
|
|
220
|
-
"sirenDurationSeconds": 15,
|
|
221
|
-
"sirenLatchUntilDisarm": false,
|
|
222
|
-
"sirenTopic": "siren",
|
|
223
|
-
"sirenOnPayload": true,
|
|
224
|
-
"sirenOnPayloadType": "bool",
|
|
225
|
-
"sirenOffPayload": false,
|
|
226
|
-
"sirenOffPayloadType": "bool",
|
|
227
|
-
"emitRestoreEvents": true,
|
|
228
|
-
"maxLogEntries": 50,
|
|
229
|
-
"zones": "{\"id\":\"front_door\",\"name\":\"Porta ingresso\",\"topic\":\"sensor/frontdoor\",\"type\":\"perimeter\",\"entry\":true,\"modes\":[\"away\",\"home\",\"night\"],\"bypassable\":true,\"chime\":true}\n{\"id\":\"pir_living\",\"name\":\"PIR soggiorno\",\"topic\":\"sensor/living_pir\",\"type\":\"motion\",\"modes\":[\"away\"],\"entry\":false,\"bypassable\":true,\"cooldownSeconds\":5}\n{\"id\":\"smoke\",\"name\":\"Fumo\",\"topic\":\"sensor/smoke\",\"type\":\"fire\",\"modes\":[],\"entry\":false,\"bypassable\":false}",
|
|
230
|
-
"x": 450,
|
|
231
|
-
"y": 280,
|
|
232
|
-
"wires": [["al_dbg_evt"], ["al_dbg_siren"]]
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
"id": "al_dbg_evt",
|
|
236
|
-
"type": "debug",
|
|
237
|
-
"z": "al_tab_1",
|
|
238
|
-
"name": "Events (output 1)",
|
|
239
|
-
"active": true,
|
|
240
|
-
"tosidebar": true,
|
|
241
|
-
"console": false,
|
|
242
|
-
"tostatus": false,
|
|
243
|
-
"complete": "true",
|
|
244
|
-
"targetType": "full",
|
|
245
|
-
"statusVal": "",
|
|
246
|
-
"statusType": "auto",
|
|
247
|
-
"x": 680,
|
|
248
|
-
"y": 260,
|
|
249
|
-
"wires": []
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
"id": "al_dbg_siren",
|
|
253
|
-
"type": "debug",
|
|
254
|
-
"z": "al_tab_1",
|
|
255
|
-
"name": "Siren (output 2)",
|
|
256
|
-
"active": true,
|
|
257
|
-
"tosidebar": true,
|
|
258
|
-
"console": false,
|
|
259
|
-
"tostatus": false,
|
|
260
|
-
"complete": "true",
|
|
261
|
-
"targetType": "full",
|
|
262
|
-
"statusVal": "",
|
|
263
|
-
"statusType": "auto",
|
|
264
|
-
"x": 680,
|
|
265
|
-
"y": 300,
|
|
266
|
-
"wires": []
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
"id": "al_inj_disarm_duress",
|
|
270
|
-
"type": "inject",
|
|
271
|
-
"z": "al_tab_1",
|
|
272
|
-
"name": "DISARM (DURESS 9999)",
|
|
273
|
-
"props": [
|
|
274
|
-
{ "p": "topic", "v": "alarm", "vt": "str" },
|
|
275
|
-
{ "p": "command", "v": "disarm", "vt": "str" },
|
|
276
|
-
{ "p": "code", "v": "9999", "vt": "str" }
|
|
277
|
-
],
|
|
278
|
-
"repeat": "",
|
|
279
|
-
"crontab": "",
|
|
280
|
-
"once": false,
|
|
281
|
-
"onceDelay": 0.1,
|
|
282
|
-
"x": 160,
|
|
283
|
-
"y": 400,
|
|
284
|
-
"wires": [["al_alarm_1"]]
|
|
285
|
-
}
|
|
286
|
-
]
|