smart-nodes 0.1.0
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/LICENSE +21 -0
- package/LICENSE.md +21 -0
- package/README.md +127 -0
- package/central/central.html +328 -0
- package/central/central.js +95 -0
- package/compare/compare.html +137 -0
- package/compare/compare.js +151 -0
- package/delay/delay.html +192 -0
- package/delay/delay.js +175 -0
- package/examples/central.json +804 -0
- package/examples/central.png +0 -0
- package/examples/compare.json +916 -0
- package/examples/compare.png +0 -0
- package/examples/delay.json +198 -0
- package/examples/delay.png +0 -0
- package/examples/forwarder.json +152 -0
- package/examples/forwarder.png +0 -0
- package/examples/hysteresis.json +358 -0
- package/examples/hysteresis.png +0 -0
- package/examples/light-control.json +499 -0
- package/examples/light-control.png +0 -0
- package/examples/logic.json +562 -0
- package/examples/logic.png +0 -0
- package/examples/long-press-control.json +113 -0
- package/examples/long-press-control.png +0 -0
- package/examples/multi-press-control.json +136 -0
- package/examples/multi-press-control.png +0 -0
- package/examples/scene-control.json +535 -0
- package/examples/scene-control.png +0 -0
- package/examples/scheduler.json +164 -0
- package/examples/scheduler.png +0 -0
- package/examples/shutter-complex-control.json +489 -0
- package/examples/shutter-complex-control.png +0 -0
- package/examples/shutter-control.json +457 -0
- package/examples/shutter-control.png +0 -0
- package/examples/statistic.json +1112 -0
- package/examples/statistic.png +0 -0
- package/forwarder/forwarder.html +100 -0
- package/forwarder/forwarder.js +95 -0
- package/hysteresis/hysteresis.html +152 -0
- package/hysteresis/hysteresis.js +146 -0
- package/light-control/light-control.html +358 -0
- package/light-control/light-control.js +231 -0
- package/logic/logic.html +168 -0
- package/logic/logic.js +171 -0
- package/long-press-control/long-press-control.html +74 -0
- package/long-press-control/long-press-control.js +75 -0
- package/multi-press-control/multi-press-control.html +135 -0
- package/multi-press-control/multi-press-control.js +68 -0
- package/package.json +59 -0
- package/persistence.js +74 -0
- package/scene-control/scene-control.html +575 -0
- package/scene-control/scene-control.js +265 -0
- package/scheduler/scheduler.html +338 -0
- package/scheduler/scheduler.js +209 -0
- package/shutter-complex-control/shutter-complex-control.html +330 -0
- package/shutter-complex-control/shutter-complex-control.js +399 -0
- package/shutter-control/shutter-control.html +283 -0
- package/shutter-control/shutter-control.js +208 -0
- package/smart_helper.js +156 -0
- package/statistic/statistic.html +107 -0
- package/statistic/statistic.js +196 -0
|
Binary file
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType("smart_forwarder", {
|
|
3
|
+
category: "Smart Nodes",
|
|
4
|
+
paletteLabel: "Forwarder",
|
|
5
|
+
color: "#E2D96E",
|
|
6
|
+
defaults: {
|
|
7
|
+
name: { value: "" },
|
|
8
|
+
enabled: { value: true },
|
|
9
|
+
always_forward_true: { value: false },
|
|
10
|
+
always_forward_false: { value: false },
|
|
11
|
+
forward_last_on_enable: { value: false },
|
|
12
|
+
save_state: { value: true },
|
|
13
|
+
resend_on_start: { value: true }
|
|
14
|
+
},
|
|
15
|
+
inputs: 1,
|
|
16
|
+
outputs: 1,
|
|
17
|
+
icon: "font-awesome/fa-forward",
|
|
18
|
+
label: function ()
|
|
19
|
+
{
|
|
20
|
+
return this.name || "Forwarder";
|
|
21
|
+
},
|
|
22
|
+
oneditprepare: function ()
|
|
23
|
+
{
|
|
24
|
+
$("#node-input-save_state").on("change", ev =>
|
|
25
|
+
{
|
|
26
|
+
if (ev.target.checked)
|
|
27
|
+
$("#resend_on_start_row").show();
|
|
28
|
+
else
|
|
29
|
+
$("#resend_on_start_row").hide();
|
|
30
|
+
});
|
|
31
|
+
$("#node-input-save_state").trigger("change");
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<script type="text/html" data-template-name="smart_forwarder">
|
|
37
|
+
<div class="form-row">
|
|
38
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
39
|
+
<input type="text" id="node-input-name" placeholder="Name" />
|
|
40
|
+
</div>
|
|
41
|
+
<div class="form-row">
|
|
42
|
+
<input type="checkbox" id="node-input-enabled" style="width: 20px;" />
|
|
43
|
+
<span for="node-input-enabled" style="width: 200px;"> Aktiviert</span>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="form-row">
|
|
46
|
+
<input type="checkbox" id="node-input-forward_last_on_enable" style="width: 20px;" />
|
|
47
|
+
<span for="node-input-forward_last_on_enable">Letzte nicht gesendete Nachricht senden, wenn die Node aktiviert wird.</span>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="form-row">
|
|
50
|
+
<input type="checkbox" id="node-input-always_forward_true" style="width: 20px;" />
|
|
51
|
+
<span for="node-input-always_forward_true"><code>msg.payload = true</code> immer weiterleiten</span>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="form-row">
|
|
54
|
+
<input type="checkbox" id="node-input-always_forward_false" style="width: 20px;" />
|
|
55
|
+
<span for="node-input-always_forward_false"><code>msg.payload = false</code> immer weiterleiten</span>
|
|
56
|
+
</div>
|
|
57
|
+
<hr/>
|
|
58
|
+
<h4 style="margin: 0.5rem 0;">Systemstart</h4>
|
|
59
|
+
<div class="form-row">
|
|
60
|
+
<input type="checkbox" id="node-input-save_state" style="width: 20px;" />
|
|
61
|
+
<label for="node-input-save_state" style="width: calc(100% - 30px);">Zustand speichern</label>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="form-row" id="resend_on_start_row">
|
|
64
|
+
<input type="checkbox" id="node-input-resend_on_start" style="width: 20px;" />
|
|
65
|
+
<label for="node-input-resend_on_start" style="width: calc(100% - 30px);">Letze Nachricht 10 Sekunden nach dem Start senden</label>
|
|
66
|
+
</div>
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<script type="text/html" data-help-name="smart_forwarder">
|
|
70
|
+
<p>Diese Node leitet eine Nachricht weiter, wenn er enabled wurde oder das dauerhafte Weiterleiten für die Nachricht aktiviert ist.</p>
|
|
71
|
+
<p>
|
|
72
|
+
<b>Hinweis:</b> Smart Nodes verwenden Topics im Format <code>name#nummer</code>, damit können verschiedene Smart Nodes mit dem gleichen Topic angesteuert werden.<br/>
|
|
73
|
+
Diese Node verwendet nur den Teil <code>name</code>. <code>#</code> und <code>nummer</code> sind dabei optional.
|
|
74
|
+
</p>
|
|
75
|
+
<p>
|
|
76
|
+
Folgende topics werden akzeptiert:
|
|
77
|
+
<table>
|
|
78
|
+
<thead>
|
|
79
|
+
<tr>
|
|
80
|
+
<th>Topic</th>
|
|
81
|
+
<th>Beschreibung</th>
|
|
82
|
+
</tr>
|
|
83
|
+
</thead>
|
|
84
|
+
<tbody>
|
|
85
|
+
<tr>
|
|
86
|
+
<td><code>enable</code></td>
|
|
87
|
+
<td>Aktiviert das Weiterleiten.</td>
|
|
88
|
+
</tr>
|
|
89
|
+
<tr>
|
|
90
|
+
<td><code>disable</code></td>
|
|
91
|
+
<td>Deaktiviert das Weiterleiten.</td>
|
|
92
|
+
</tr>
|
|
93
|
+
<tr>
|
|
94
|
+
<td><code>set_state</code></td>
|
|
95
|
+
<td>Aktiviert das Weiterleiten, wenn <code>msg.payload = true</code> oder deaktiviert das Weiterleiten, wenn <code>msg.payload = false</code>.</td>
|
|
96
|
+
</tr>
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>
|
|
99
|
+
</p>
|
|
100
|
+
</script>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module.exports = function (RED)
|
|
2
|
+
{
|
|
3
|
+
function ForwarderNode(config)
|
|
4
|
+
{
|
|
5
|
+
const node = this;
|
|
6
|
+
RED.nodes.createNode(node, config);
|
|
7
|
+
|
|
8
|
+
const smartContext = require("../persistence.js")(RED);
|
|
9
|
+
const helper = require("../smart_helper.js");
|
|
10
|
+
|
|
11
|
+
var nodeSettings = {
|
|
12
|
+
enabled: config.enabled,
|
|
13
|
+
lastMessage: null,
|
|
14
|
+
last_msg_was_sended: true
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
if (config.save_state)
|
|
18
|
+
{
|
|
19
|
+
// load old saved values
|
|
20
|
+
nodeSettings = Object.assign(nodeSettings, smartContext.get(node.id));
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
{
|
|
24
|
+
// delete old saved values
|
|
25
|
+
smartContext.del(node.id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// dynamic config
|
|
29
|
+
let forwardTrue = config.always_forward_true;
|
|
30
|
+
let forwardFalse = config.always_forward_false;
|
|
31
|
+
let forward_last_on_enable = config.forward_last_on_enable;
|
|
32
|
+
|
|
33
|
+
// runtime values
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
node.on("input", function (msg)
|
|
37
|
+
{
|
|
38
|
+
let newState = null;
|
|
39
|
+
if (msg.topic == "enable" || (msg.topic == "set_state" && msg.payload))
|
|
40
|
+
newState = true;
|
|
41
|
+
else if (msg.topic == "disable" || (msg.topic == "set_state" && !msg.payload))
|
|
42
|
+
newState = false;
|
|
43
|
+
|
|
44
|
+
// Already the correct state
|
|
45
|
+
if (newState != null && nodeSettings.enabled == newState)
|
|
46
|
+
return;
|
|
47
|
+
|
|
48
|
+
switch (newState)
|
|
49
|
+
{
|
|
50
|
+
case true:
|
|
51
|
+
case false:
|
|
52
|
+
nodeSettings.enabled = newState;
|
|
53
|
+
|
|
54
|
+
if (config.save_state)
|
|
55
|
+
smartContext.set(node.id, nodeSettings);
|
|
56
|
+
|
|
57
|
+
if (nodeSettings.enabled && forward_last_on_enable && nodeSettings.lastMessage != null && !nodeSettings.last_msg_was_sended)
|
|
58
|
+
{
|
|
59
|
+
node.send(nodeSettings.lastMessage);
|
|
60
|
+
nodeSettings.last_msg_was_sended = true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
setStatus();
|
|
64
|
+
break;
|
|
65
|
+
|
|
66
|
+
default:
|
|
67
|
+
// Forward if enabled or forced
|
|
68
|
+
if (nodeSettings.enabled || (forwardTrue && msg.payload) || (forwardFalse && !msg.payload))
|
|
69
|
+
{
|
|
70
|
+
node.send(msg);
|
|
71
|
+
nodeSettings.last_msg_was_sended = true;
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
{
|
|
75
|
+
nodeSettings.last_msg_was_sended = false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
nodeSettings.lastMessage = msg;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
let setStatus = () =>
|
|
84
|
+
{
|
|
85
|
+
if (nodeSettings.enabled)
|
|
86
|
+
node.status({ fill: "green", shape: "dot", text: "Forwarding enabled" });
|
|
87
|
+
else
|
|
88
|
+
node.status({ fill: "red", shape: "dot", text: "Forwarding disabled" });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setStatus();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
RED.nodes.registerType("smart_forwarder", ForwarderNode);
|
|
95
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
<script type="text/javascript">
|
|
2
|
+
RED.nodes.registerType("smart_hysteresis", {
|
|
3
|
+
category: "Smart Nodes",
|
|
4
|
+
paletteLabel: "Hysteresis",
|
|
5
|
+
color: "#E2D96E",
|
|
6
|
+
defaults: {
|
|
7
|
+
name: { value: "" },
|
|
8
|
+
setpoint: { value: 10 },
|
|
9
|
+
hysteresis: { value: 1 },
|
|
10
|
+
out_higher: { value: '{"topic": ""}' },
|
|
11
|
+
out_higher_type: { value: 'json' },
|
|
12
|
+
out_lower: { value: '{"topic": ""}' },
|
|
13
|
+
out_lower_type: { value: 'json' },
|
|
14
|
+
save_state: { value: true },
|
|
15
|
+
resend_on_start: { value: true }
|
|
16
|
+
},
|
|
17
|
+
inputs: 1,
|
|
18
|
+
outputs: 2,
|
|
19
|
+
outputLabels: ["Über", "Unter"],
|
|
20
|
+
icon: "font-awesome/fa-arrows-v",
|
|
21
|
+
label: function ()
|
|
22
|
+
{
|
|
23
|
+
return this.name || this.comparator || "Hysteresis";
|
|
24
|
+
},
|
|
25
|
+
oneditprepare: function ()
|
|
26
|
+
{
|
|
27
|
+
$("#node-input-setpoint").typedInput({
|
|
28
|
+
type: "num",
|
|
29
|
+
types: ["num"]
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
$("#node-input-hysteresis").typedInput({
|
|
33
|
+
type: "num",
|
|
34
|
+
types: ["num"]
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
$("#node-input-out_higher").typedInput({
|
|
38
|
+
type: "json",
|
|
39
|
+
types: ["json", {
|
|
40
|
+
value: "null",
|
|
41
|
+
label: "Originalnachricht",
|
|
42
|
+
icon: "fa fa-times",
|
|
43
|
+
hasValue: false,
|
|
44
|
+
}],
|
|
45
|
+
typeField: "#node-input-out_higher_type"
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
$("#node-input-out_lower").typedInput({
|
|
49
|
+
type: "json",
|
|
50
|
+
types: ["json", {
|
|
51
|
+
value: "null",
|
|
52
|
+
label: "Originalnachricht",
|
|
53
|
+
icon: "fa fa-times",
|
|
54
|
+
hasValue: false,
|
|
55
|
+
}],
|
|
56
|
+
typeField: "#node-input-out_lower_type"
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
$("#node-input-save_state").on("change", ev =>
|
|
60
|
+
{
|
|
61
|
+
if (ev.target.checked)
|
|
62
|
+
$("#resend_on_start_row").show();
|
|
63
|
+
else
|
|
64
|
+
$("#resend_on_start_row").hide();
|
|
65
|
+
});
|
|
66
|
+
$("#node-input-save_state").trigger("change");
|
|
67
|
+
},
|
|
68
|
+
oneditsave: function ()
|
|
69
|
+
{
|
|
70
|
+
this.setpoint = parseFloat(this.setpoint);
|
|
71
|
+
this.hysteresis = parseFloat(this.hysteresis);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<script type="text/html" data-template-name="smart_hysteresis">
|
|
77
|
+
<div class="form-row">
|
|
78
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
|
79
|
+
<input type="text" id="node-input-name" placeholder="Name" />
|
|
80
|
+
</div>
|
|
81
|
+
<div class="form-row">
|
|
82
|
+
<label for="node-input-setpoint"><i class="fa fa-sign-out"></i> Sollwert</label>
|
|
83
|
+
<input id="node-input-setpoint" />
|
|
84
|
+
</div>
|
|
85
|
+
<div class="form-row">
|
|
86
|
+
<label for="node-input-hysteresis"><i class="fa fa-sort"></i> Hysterese</label>
|
|
87
|
+
<input id="node-input-hysteresis" />
|
|
88
|
+
</div>
|
|
89
|
+
<hr/>
|
|
90
|
+
<h4 style="margin: 0.5rem 0;">Ausgangsnachrichten</h4>
|
|
91
|
+
<div class="form-row">
|
|
92
|
+
<label for="node-input-out_higher"><i class="fa fa-arrow-up"></i> Über</label>
|
|
93
|
+
<input type="text" id="node-input-out_higher"/>
|
|
94
|
+
<input type="hidden" id="node-input-out_higher_type">
|
|
95
|
+
</div>
|
|
96
|
+
<div class="form-row">
|
|
97
|
+
<label for="node-input-out_lower"><i class="fa fa-arrow-down"></i> Unter</label>
|
|
98
|
+
<input type="text" id="node-input-out_lower" />
|
|
99
|
+
<input type="hidden" id="node-input-out_lower_type">
|
|
100
|
+
</div>
|
|
101
|
+
<hr/>
|
|
102
|
+
<h4 style="margin: 0.5rem 0;">Systemstart</h4>
|
|
103
|
+
<div class="form-row">
|
|
104
|
+
<input type="checkbox" id="node-input-save_state" style="width: 20px;" />
|
|
105
|
+
<label for="node-input-save_state" style="width: calc(100% - 30px);">Zustand speichern</label>
|
|
106
|
+
</div>
|
|
107
|
+
<div class="form-row" id="resend_on_start_row">
|
|
108
|
+
<input type="checkbox" id="node-input-resend_on_start" style="width: 20px;" />
|
|
109
|
+
<label for="node-input-resend_on_start" style="width: calc(100% - 30px);">Letze Nachricht 10 Sekunden nach dem Start senden</label>
|
|
110
|
+
</div>
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<script type="text/html" data-help-name="smart_hysteresis">
|
|
114
|
+
<p>
|
|
115
|
+
Diese Node sendet die einkommende Nachricht an den Ausgang <code>Über</code>, wenn der einkommende Wert größer gleich dem Sollwert plus Hysterese ist und
|
|
116
|
+
die einkommende Nachricht an den Ausgang <code>Unter</code>, wenn der einkommende Wert kleiner gleich dem Sollwert minus Hysterese ist.<br/>
|
|
117
|
+
Die Nachricht wird dabei nur einmalig bei über- bzw. unterschreiten des Grenzwertes weitergeleitet.<br/>
|
|
118
|
+
Die Note behält den aktuellen Zustand auch nach dem Deploy bei.
|
|
119
|
+
</p>
|
|
120
|
+
<p>
|
|
121
|
+
<b>Hinweis:</b> Smart Nodes verwenden Topics im Format <code>name#nummer</code>, damit können verschiedene Smart Nodes mit dem gleichen Topic angesteuert werden.<br/>
|
|
122
|
+
Diese Node verwendet nur den Teil <code>name</code>. <code>#</code> und <code>nummer</code> sind dabei optional.
|
|
123
|
+
</p>
|
|
124
|
+
<p>
|
|
125
|
+
Folgende topics werden akzeptiert:
|
|
126
|
+
<table>
|
|
127
|
+
<thead>
|
|
128
|
+
<tr>
|
|
129
|
+
<th>Topic</th>
|
|
130
|
+
<th>Beschreibung</th>
|
|
131
|
+
</tr>
|
|
132
|
+
</thead>
|
|
133
|
+
<tbody>
|
|
134
|
+
<tr>
|
|
135
|
+
<td><code>setpoint</code></td>
|
|
136
|
+
<td>Überschreibt den Sollwert mit <code>msg.payload</code>.</td>
|
|
137
|
+
</tr>
|
|
138
|
+
<tr>
|
|
139
|
+
<td><code>hysteresis</code></td>
|
|
140
|
+
<td>Überschreibt die Hysterese mit <code>msg.payload</code>.</td>
|
|
141
|
+
</tr>
|
|
142
|
+
<tr>
|
|
143
|
+
<td><code>resend</code></td>
|
|
144
|
+
<td>Sendet den aktuellen Zustand erneut.</td>
|
|
145
|
+
</tr>
|
|
146
|
+
</tbody>
|
|
147
|
+
</table>
|
|
148
|
+
</p>
|
|
149
|
+
<p>
|
|
150
|
+
Die einkommende Nachricht wird mit den angegebenen Ausgangsnachrichten ergänzt, sofern nicht Originalnachricht ausgewählt wurde.
|
|
151
|
+
</p>
|
|
152
|
+
</script>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = function (RED)
|
|
3
|
+
{
|
|
4
|
+
function HysteresisNode(config)
|
|
5
|
+
{
|
|
6
|
+
const node = this;
|
|
7
|
+
RED.nodes.createNode(node, config);
|
|
8
|
+
|
|
9
|
+
const smartContext = require("../persistence.js")(RED);
|
|
10
|
+
const helper = require("../smart_helper.js");
|
|
11
|
+
|
|
12
|
+
var nodeSettings = {
|
|
13
|
+
active: null,
|
|
14
|
+
lastMessage: null,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
if (config.save_state)
|
|
18
|
+
{
|
|
19
|
+
// load old saved values
|
|
20
|
+
nodeSettings = Object.assign(nodeSettings, smartContext.get(node.id));
|
|
21
|
+
|
|
22
|
+
switch (nodeSettings.active)
|
|
23
|
+
{
|
|
24
|
+
case true:
|
|
25
|
+
node.status({ fill: "yellow", shape: "ring", text: "Load last state: Higher" });
|
|
26
|
+
break;
|
|
27
|
+
|
|
28
|
+
case false:
|
|
29
|
+
node.status({ fill: "yellow", shape: "ring", text: "Load last state: Lower" });
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
default:
|
|
33
|
+
node.status({ fill: "yellow", shape: "ring", text: "No last state available" });
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else
|
|
38
|
+
{
|
|
39
|
+
// delete old saved values
|
|
40
|
+
node.status({});
|
|
41
|
+
smartContext.del(node.id);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// dynamic config
|
|
45
|
+
let setpoint = parseFloat(config.setpoint);
|
|
46
|
+
let hysteresis = parseFloat(config.hysteresis);
|
|
47
|
+
let out_higher = helper.evaluateNodeProperty(RED, config.out_higher, config.out_higher_type);
|
|
48
|
+
let out_lower = helper.evaluateNodeProperty(RED, config.out_lower, config.out_lower_type);
|
|
49
|
+
|
|
50
|
+
// runtime values
|
|
51
|
+
|
|
52
|
+
node.on("input", function (msg)
|
|
53
|
+
{
|
|
54
|
+
let value = parseFloat(msg.payload);
|
|
55
|
+
let realTopic = helper.getTopicName(msg.topic);
|
|
56
|
+
|
|
57
|
+
if (isNaN(value) && realTopic !== "resend")
|
|
58
|
+
{
|
|
59
|
+
// node.error("Invalid payload: " + msg.payload);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
switch (realTopic)
|
|
64
|
+
{
|
|
65
|
+
case "setpoint":
|
|
66
|
+
setpoint = value;
|
|
67
|
+
node.status({ fill: "yellow", shape: "ring", text: "New setpoint: " + value });
|
|
68
|
+
|
|
69
|
+
if (config.save_state)
|
|
70
|
+
smartContext.set(node.id, nodeSettings);
|
|
71
|
+
break;
|
|
72
|
+
|
|
73
|
+
case "hysteresis":
|
|
74
|
+
hysteresis = value;
|
|
75
|
+
node.status({ fill: "yellow", shape: "ring", text: "New hysteresis: " + value });
|
|
76
|
+
|
|
77
|
+
if (config.save_state)
|
|
78
|
+
smartContext.set(node.id, nodeSettings);
|
|
79
|
+
break;
|
|
80
|
+
|
|
81
|
+
case "resend":
|
|
82
|
+
if (nodeSettings.active === true && nodeSettings.lastMessage != null)
|
|
83
|
+
{
|
|
84
|
+
node.status({ fill: "green", shape: "dot", text: "Resend higher value " });
|
|
85
|
+
node.send([nodeSettings.lastMessage, null]);
|
|
86
|
+
}
|
|
87
|
+
else if (nodeSettings.active === false && nodeSettings.lastMessage != null)
|
|
88
|
+
{
|
|
89
|
+
node.status({ fill: "green", shape: "dot", text: "Resend lower value " });
|
|
90
|
+
node.send([null, nodeSettings.lastMessage]);
|
|
91
|
+
}
|
|
92
|
+
else
|
|
93
|
+
{
|
|
94
|
+
node.status({ fill: "green", shape: "dot", text: "No resend, state is unknown" });
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
default:
|
|
99
|
+
if (value >= setpoint + hysteresis && nodeSettings.active !== true)
|
|
100
|
+
{
|
|
101
|
+
node.status({ fill: "green", shape: "dot", text: "Turned higher by value " + value });
|
|
102
|
+
nodeSettings.active = true;
|
|
103
|
+
nodeSettings.lastMessage = out_higher ?? msg;
|
|
104
|
+
|
|
105
|
+
if (config.save_state)
|
|
106
|
+
smartContext.set(node.id, nodeSettings);
|
|
107
|
+
|
|
108
|
+
node.send([nodeSettings.lastMessage, null]);
|
|
109
|
+
}
|
|
110
|
+
else if (value <= setpoint - hysteresis && nodeSettings.active !== false)
|
|
111
|
+
{
|
|
112
|
+
node.status({ fill: "green", shape: "dot", text: "Turned lower by value " + value });
|
|
113
|
+
nodeSettings.active = false;
|
|
114
|
+
nodeSettings.lastMessage = out_lower ?? msg;
|
|
115
|
+
|
|
116
|
+
if (config.save_state)
|
|
117
|
+
smartContext.set(node.id, nodeSettings);
|
|
118
|
+
|
|
119
|
+
node.send([null, nodeSettings.lastMessage]);
|
|
120
|
+
}
|
|
121
|
+
else
|
|
122
|
+
{
|
|
123
|
+
node.status({ fill: "yellow", shape: "ring", text: "No change by value " + value });
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
node.on("close", function ()
|
|
130
|
+
{
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (config.save_state && config.resend_on_start && nodeSettings.active && nodeSettings.lastMessage != null)
|
|
134
|
+
{
|
|
135
|
+
setTimeout(() =>
|
|
136
|
+
{
|
|
137
|
+
if (nodeSettings.active)
|
|
138
|
+
node.send([nodeSettings.lastMessage, null]);
|
|
139
|
+
else
|
|
140
|
+
node.send([null, nodeSettings.lastMessage]);
|
|
141
|
+
}, 10000);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
RED.nodes.registerType("smart_hysteresis", HysteresisNode);
|
|
146
|
+
}
|