smart-nodes 0.3.22 → 0.3.26

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.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # The MIT License (MIT)
2
2
 
3
- Copyright (c) 2023 Samuel Bergen
3
+ Copyright (c) 2024 BergenSoft
4
4
 
5
5
  > Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  > of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # General information
2
2
 
3
3
  The smart nodes was created to control smart home devices like lights, power outlets shutter and some more.
4
- This controls are designed to work with the [node-red-contrib-knx-ultimate](https://github.com/Supergiovane/node-red-contrib-knx-ultimate) but it could also work with other smart technologies.
4
+ This nodes are designed to work with the [node-red-contrib-knx-ultimate](https://github.com/Supergiovane/node-red-contrib-knx-ultimate) but it could also work with other smart technologies.
5
5
 
6
6
  The knx binary input and output/switching modules should be configured very stupid. Closing a binary input should output 1 and releasing 0.
7
7
  Same for the output/switching modules, 1 should turn on and 0 turn out. That makes it easy to count the presses or check for short and long presses.
@@ -62,8 +62,8 @@ This node can control multiple light/scene controls or shutter controls at the s
62
62
 
63
63
  ## 5. Long press control
64
64
 
65
- This control is used to detect a short or a long press.
66
- The time can be configured in this control.
65
+ This node is used to detect a short or a long press.
66
+ The time can be configured in this node.
67
67
 
68
68
  ### **Features:**
69
69
 
@@ -71,8 +71,8 @@ The time can be configured in this control.
71
71
 
72
72
  ## 6. Multi press control
73
73
 
74
- This control is used to detect multiple presses on a button.
75
- The max wait time between presses can be configured in this control.
74
+ This node is used to detect multiple presses on a button.
75
+ The max wait time between presses can be configured in this node.
76
76
  You can also choose 2-4 press detection.
77
77
 
78
78
  ### **Features:**
@@ -81,7 +81,7 @@ You can also choose 2-4 press detection.
81
81
 
82
82
  ## 7. Hysteresis
83
83
 
84
- This control is checking if the input value reachs a defined value until the upper message is send. When the lower level is reached, the lower masssage will be send
84
+ This node is checking if the input value reachs a defined value until the upper message is send. When the lower level is reached, the lower masssage will be send
85
85
 
86
86
  ### **Features:**
87
87
 
@@ -90,7 +90,7 @@ This control is checking if the input value reachs a defined value until the upp
90
90
 
91
91
  ## 8. Logic
92
92
 
93
- This control can be used for AND, OR and XOR logics.
93
+ This node can be used for AND, OR and XOR logics.
94
94
 
95
95
  ### **Features:**
96
96
 
@@ -102,7 +102,7 @@ This control can be used for AND, OR and XOR logics.
102
102
 
103
103
  ## 9. Statistic
104
104
 
105
- This control can be used for getting the following types of values: Minimum, Maximum, Sum, Difference, Absolute Value, Absolute Difference, Average and Running average.
105
+ This node can be used for getting the following types of values: Minimum, Maximum, Sum, Difference, Absolute Value, Absolute Difference, Average and Running average.
106
106
 
107
107
  ### **Features:**
108
108
 
@@ -113,7 +113,7 @@ This control can be used for getting the following types of values: Minimum, Max
113
113
 
114
114
  ## 10. Compare
115
115
 
116
- This control can compare 2 values with the following operators: < <= == >= > !=
116
+ This node can compare 2 values with the following operators: < <= == >= > !=
117
117
 
118
118
  ### **Features:**
119
119
 
@@ -123,7 +123,7 @@ This control can compare 2 values with the following operators: < <= == >= > !=
123
123
 
124
124
  ## 11. Delay
125
125
 
126
- This control can delay incomming messages.
126
+ This node can delay incomming messages.
127
127
 
128
128
  ### **Features:**
129
129
 
@@ -134,7 +134,7 @@ This control can delay incomming messages.
134
134
 
135
135
  ## 12. Forwarder
136
136
 
137
- This control can control if an incomming message should be forwarded or not.
137
+ This node can control if an incomming message should be forwarded or not.
138
138
 
139
139
  ### **Features:**
140
140
 
@@ -144,7 +144,7 @@ This control can control if an incomming message should be forwarded or not.
144
144
 
145
145
  ## 13. Scheduler
146
146
 
147
- This control can send a defined message on defined times.
147
+ This node can send a defined message on defined times.
148
148
 
149
149
  ### **Features:**
150
150
 
@@ -156,20 +156,50 @@ This control can send a defined message on defined times.
156
156
 
157
157
  ## 14. Text execution
158
158
 
159
- This control parses a text and performs actions to the selected and matching smart nodes
159
+ This node parses a text and performs actions to the selected and matching smart nodes
160
160
 
161
161
  ### **Features:**
162
162
 
163
- - Control light and scenes (only on or off) in german and english
164
- - Control shutter in german and english
163
+ - Control light and scenes (only on or off) in german and english.
164
+ - Control shutter in german and english.
165
165
 
166
166
  ### Examples
167
167
 
168
168
  [ text ] is optional
169
169
 
170
- - Turn on [the light in] the living room and the kitchen off
171
- - Open [the shutter in] the kitchen and turn studio off
172
- - Close [the shutter in the] sleeping room
173
- - Living room to 10 %
174
- - Turn on living room except the couch light
175
- - Sends debug message to output
170
+ - Turn on [the light in] the living room and the kitchen off.
171
+ - Open [the shutter in] the kitchen and turn studio off.
172
+ - Close [the shutter in the] sleeping room.
173
+ - Living room to 10 %.
174
+ - Turn on living room except the couch light.
175
+ - Sends debug message to output.
176
+
177
+ ## 15. Mixing valve
178
+
179
+ This node can control a mixing valve to get the required tput temperature. It is working for heating and cooling.
180
+
181
+ ### **Features:**
182
+
183
+ - Define target temperature.
184
+ - Support heating and cooling.
185
+ - Define off mode to do nothing, open or close the valve.
186
+
187
+ ## 16. Heating curve
188
+
189
+ This node calculates the needed flow temperature regarding to the target room temperature and the current outside temperature.
190
+
191
+ ### **Features:**
192
+
193
+ - Define slope and offset values.
194
+ - Limit flow temperature with min and max values.
195
+ - Preview of different curves in the node editor.
196
+
197
+ ## 17. Counter
198
+
199
+ This node countes up and down within a specified range.
200
+
201
+ ### **Features:**
202
+
203
+ - Define min, max and step values.
204
+ - Set to a specific value
205
+ - Increment and decrement by default or by a given value.
@@ -1,5 +1,7 @@
1
1
  module.exports = function (RED)
2
2
  {
3
+ "use strict";
4
+
3
5
  function CentralControlNode(config)
4
6
  {
5
7
  const node = this;
@@ -33,7 +35,7 @@ module.exports = function (RED)
33
35
  node.on("input", function (msg)
34
36
  {
35
37
  // copy message, so original message stays unchanged
36
- let newMsg = Object.assign({}, msg);
38
+ let new_msg = Object.assign({}, msg);
37
39
 
38
40
  // make connected nodes behavior homogenous
39
41
  switch (config.mode)
@@ -42,16 +44,16 @@ module.exports = function (RED)
42
44
  if (msg.topic == "up_stop")
43
45
  {
44
46
  if (isAllOff())
45
- newMsg.topic = "up";
47
+ new_msg.topic = "up";
46
48
  else
47
- newMsg.topic = "stop";
49
+ new_msg.topic = "stop";
48
50
  }
49
51
  else if (msg.topic == "down_stop")
50
52
  {
51
53
  if (isAllOff())
52
- newMsg.topic = "down";
54
+ new_msg.topic = "down";
53
55
  else
54
- newMsg.topic = "stop";
56
+ new_msg.topic = "stop";
55
57
  }
56
58
  break;
57
59
 
@@ -59,9 +61,9 @@ module.exports = function (RED)
59
61
  if (msg.topic == "toggle")
60
62
  {
61
63
  if (isAllOff())
62
- newMsg.topic = "on";
64
+ new_msg.topic = "on";
63
65
  else
64
- newMsg.topic = "off";
66
+ new_msg.topic = "off";
65
67
  }
66
68
  break;
67
69
  }
@@ -71,7 +73,7 @@ module.exports = function (RED)
71
73
  {
72
74
  // console.log(node.id + " -> " + link);
73
75
  // console.log(newMsg);
74
- RED.events.emit("node:" + link, newMsg);
76
+ RED.events.emit("node:" + link, new_msg);
75
77
  });
76
78
  });
77
79
 
@@ -3,6 +3,7 @@
3
3
  category: "Smart Nodes",
4
4
  paletteLabel: "Compare",
5
5
  color: "#E2D96E",
6
+ color: "#E2D96E",
6
7
  defaults: {
7
8
  name: { value: "" },
8
9
  comparator: { value: "EQUAL" }, // EQUAL, GREATER, GREATER_EQUAL, SMALLER, SMALLER_EQUAL, UNEQUAL
@@ -10,6 +11,10 @@
10
11
  value1_type: { value: "null" },
11
12
  value2: { value: "" },
12
13
  value2_type: { value: "null" },
14
+ out_false: { value: '{"topic": ""}' },
15
+ out_false_type: { value: 'json' },
16
+ out_true: { value: '{"topic": ""}' },
17
+ out_true_type: { value: 'json' },
13
18
  save_state: { value: true },
14
19
  resend_on_start: { value: true }
15
20
  },
@@ -60,6 +65,28 @@
60
65
  typeField: "#node-input-value2_type"
61
66
  });
62
67
 
68
+ $("#node-input-out_true").typedInput({
69
+ type: "json",
70
+ types: ["json", {
71
+ value: "null",
72
+ label: "Nichts senden",
73
+ icon: "fa fa-times",
74
+ hasValue: false,
75
+ }],
76
+ typeField: "#node-input-out_true_type"
77
+ });
78
+
79
+ $("#node-input-out_false").typedInput({
80
+ type: "json",
81
+ types: ["json", {
82
+ value: "null",
83
+ label: "Nichts senden",
84
+ icon: "fa fa-times",
85
+ hasValue: false,
86
+ }],
87
+ typeField: "#node-input-out_false_type"
88
+ });
89
+
63
90
  $("#node-input-save_state").on("change", ev =>
64
91
  {
65
92
  if (ev.target.checked)
@@ -95,6 +122,27 @@
95
122
  <input type="hidden" id="node-input-value2_type">
96
123
  </div>
97
124
  <hr/>
125
+ <h4 style="margin: 0.5rem 0;">Ausgangsnachrichten</h4>
126
+ <div class="form-row">
127
+ <label for="node-input-out_true"><i class="fa fa-check-circle"></i> Wahr</label>
128
+ <input type="text" id="node-input-out_true"/>
129
+ <input type="hidden" id="node-input-out_true_type">
130
+ </div>
131
+ <div class="form-row">
132
+ <label for="node-input-out_false"><i class="fa fa-times-circle"></i> Falsch</label>
133
+ <input type="text" id="node-input-out_false" />
134
+ <input type="hidden" id="node-input-out_false_type">
135
+ </div>
136
+ <div class="form-row">
137
+ <span><strong>Hinweis:</strong></span>
138
+ </div>
139
+ <div class="form-row">
140
+ <span>
141
+ <code>msg.payload</code> wird automatisch auf das Logik-Ergebnis gesetzt.<br/>
142
+ <code>msg.comperator</code> wird automatisch auf den Logik-Operator gesetzt.
143
+ </span>
144
+ </div>
145
+ <hr/>
98
146
  <h4 style="margin: 0.5rem 0;">Systemstart</h4>
99
147
  <div class="form-row">
100
148
  <input type="checkbox" id="node-input-save_state" style="width: 20px;" />
@@ -1,34 +1,38 @@
1
1
  module.exports = function (RED)
2
2
  {
3
+ "use strict";
4
+
3
5
  function CompareNode(config)
4
6
  {
5
7
  const node = this;
6
8
  RED.nodes.createNode(node, config);
7
9
 
8
- const smartContext = require("../persistence.js")(RED);
10
+ const smart_context = require("../persistence.js")(RED);
9
11
  const helper = require("../smart_helper.js");
10
12
 
11
- var nodeSettings = {
13
+ var node_settings = {
12
14
  values: [
13
15
  helper.evaluateNodeProperty(RED, config.value1, config.value1_type),
14
16
  helper.evaluateNodeProperty(RED, config.value2, config.value2_type)
15
17
  ],
16
- lastResult: null,
18
+ last_message: null,
17
19
  };
18
20
 
19
21
  if (config.save_state)
20
22
  {
21
23
  // load old saved values
22
- nodeSettings = Object.assign(nodeSettings, smartContext.get(node.id));
24
+ node_settings = Object.assign(node_settings, smart_context.get(node.id));
23
25
  }
24
26
  else
25
27
  {
26
28
  // delete old saved values
27
- smartContext.del(node.id);
29
+ smart_context.del(node.id);
28
30
  }
29
31
 
30
32
  // dynamic config
31
33
  let comparator = config.comparator;
34
+ let out_true = helper.evaluateNodeProperty(RED, config.out_true, config.out_true_type);
35
+ let out_false = helper.evaluateNodeProperty(RED, config.out_false, config.out_false_type);
32
36
 
33
37
  // runtime values
34
38
 
@@ -51,47 +55,59 @@ module.exports = function (RED)
51
55
  }
52
56
 
53
57
  // Save new value
54
- nodeSettings.values[input - 1] = num;
58
+ node_settings.values[input - 1] = num;
55
59
 
56
60
  let result = getResult();
57
61
  setStatus(result);
58
62
 
59
63
  if (result != null)
60
64
  {
61
- nodeSettings.lastResult = result;
65
+ let msg = result ? out_true : out_false;
66
+
67
+ if (msg != null)
68
+ {
69
+ msg = Object.assign(
70
+ {},
71
+ msg,
72
+ { payload: result, comparator: comparator }
73
+ );
74
+ }
75
+
76
+ node_settings.last_message = msg;
62
77
 
63
78
  if (config.save_state)
64
- smartContext.set(node.id, nodeSettings);
79
+ smart_context.set(node.id, node_settings);
65
80
 
66
- node.send({ payload: result, comparator: comparator });
81
+ if (msg != null)
82
+ node.send(msg);
67
83
  }
68
84
  });
69
85
 
70
86
  let getResult = () =>
71
87
  {
72
88
  // Wait until both values are set
73
- if (nodeSettings.values[0] == null || nodeSettings.values[1] == null)
89
+ if (node_settings.values[0] == null || node_settings.values[1] == null)
74
90
  return null;
75
91
 
76
92
  switch (comparator)
77
93
  {
78
94
  case "SMALLER":
79
- return nodeSettings.values[0] < nodeSettings.values[1];
95
+ return node_settings.values[0] < node_settings.values[1];
80
96
 
81
97
  case "SMALLER_EQUAL":
82
- return nodeSettings.values[0] <= nodeSettings.values[1];
98
+ return node_settings.values[0] <= node_settings.values[1];
83
99
 
84
100
  case "EQUAL":
85
- return nodeSettings.values[0] === nodeSettings.values[1];
101
+ return node_settings.values[0] === node_settings.values[1];
86
102
 
87
103
  case "UNEQUAL":
88
- return nodeSettings.values[0] !== nodeSettings.values[1];
104
+ return node_settings.values[0] !== node_settings.values[1];
89
105
 
90
106
  case "GREATER_EQUAL":
91
- return nodeSettings.values[0] >= nodeSettings.values[1];
107
+ return node_settings.values[0] >= node_settings.values[1];
92
108
 
93
109
  case "GREATER":
94
- return nodeSettings.values[0] > nodeSettings.values[1];
110
+ return node_settings.values[0] > node_settings.values[1];
95
111
  }
96
112
 
97
113
  return null;
@@ -129,22 +145,22 @@ module.exports = function (RED)
129
145
  if (result == null)
130
146
  node.status({});
131
147
  else
132
- node.status({ fill: "yellow", shape: "ring", text: (new Date()).toLocaleString() + ": " + nodeSettings.values.join(" " + getComparatorSign() + " ") + " => " + result });
148
+ node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + node_settings.values.join(" " + getComparatorSign() + " ") + " => " + result });
133
149
  }
134
150
 
135
151
  node.on("close", function ()
136
152
  {
137
153
  });
138
154
 
139
- if (config.save_state && config.resend_on_start && nodeSettings.lastResult != null)
155
+ if (config.save_state && config.resend_on_start && node_settings.last_message != null)
140
156
  {
141
157
  setTimeout(() =>
142
158
  {
143
- node.send({ payload: nodeSettings.lastResult, comparator: comparator });
159
+ node.send(node_settings.last_message);
144
160
  }, 10000);
145
161
  }
146
162
 
147
- setStatus(nodeSettings.lastResult);
163
+ setStatus(node_settings.last_message?.payload);
148
164
  }
149
165
 
150
166
  RED.nodes.registerType("smart_compare", CompareNode);
@@ -0,0 +1,104 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType("smart_counter", {
3
+ category: "Smart Nodes",
4
+ paletteLabel: "Counter",
5
+ color: "#6EE2D9",
6
+ defaults: {
7
+ name: { value: "" },
8
+ start: { value: 0 },
9
+ step: { value: 1 },
10
+ min: { value: 0 },
11
+ max: { value: 10 },
12
+ save_state: { value: true },
13
+ resend_on_start: { value: true }
14
+ },
15
+ inputs: 1,
16
+ outputs: 1,
17
+ icon: "smart_counter.png",
18
+ label: function ()
19
+ {
20
+ return this.name || "Counter";
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_counter">
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
+ <label for="node-input-start"><i class="fa fa-cog"></i> Start</label>
43
+ <input type="number" id="node-input-start" placeholder="Startwert">
44
+ </div>
45
+ <div class="form-row">
46
+ <label for="node-input-step"><i class="fa fa-forward"></i> Schritt</label>
47
+ <input type="number" id="node-input-step" placeholder="Schrittweite">
48
+ </div>
49
+ <div class="form-row">
50
+ <label for="node-input-min"><i class="fa fa-arrow-down"></i> Min</label>
51
+ <input type="number" id="node-input-min" placeholder="Min">
52
+ </div>
53
+ <div class="form-row">
54
+ <label for="node-input-max"><i class="fa fa-arrow-up"></i> Max</label>
55
+ <input type="number" id="node-input-max" placeholder="Max">
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_counter">
70
+ <p>Diese Node kann verwendet werden um nach oben oder unten zu zählen.</p>
71
+ <p>
72
+ Die Standardschrittweite kann vorgegeben oder durch einkommende Nachrichten temporär überschrieben werden.
73
+ Es sind auch Kommazahlen möglich.
74
+ </p>
75
+ <p>
76
+ <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/>
77
+ Diese Node verwendet nur den Teil <code>name</code>. <code>#</code> und <code>nummer</code> sind dabei optional.
78
+ </p>
79
+ <p>
80
+ Folgende topics werden akzeptiert:
81
+ <table>
82
+ <thead>
83
+ <tr>
84
+ <th>Topic</th>
85
+ <th>Beschreibung</th>
86
+ </tr>
87
+ </thead>
88
+ <tbody>
89
+ <tr>
90
+ <td><code>up</code></td>
91
+ <td>Erhöht den Wert um <code>msg.payload</code> oder falls nicht gesetzt (oder <code>null</code>) um die konfigurierte Schrittweite. Der neue Wert ist dabei immer innerhalb der Min- und Max-Werte.</td>
92
+ </tr>
93
+ <tr>
94
+ <td><code>down</code></td>
95
+ <td>Verringert den Wert um <code>msg.payload</code> oder falls nicht gesetzt (oder <code>null</code>) um die konfigurierte Schrittweite. Der neue Wert ist dabei immer innerhalb der Min- und Max-Werte.</td>
96
+ </tr>
97
+ <tr>
98
+ <td><code>reset</code></td>
99
+ <td>Setzt den Wert auf <code>msg.payload</code> oder falls nicht gesetzt (oder <code>null</code>) auf den Startwert zurück. Der neue Wert ist dabei immer innerhalb der Min- und Max-Werte.</td>
100
+ </tr>
101
+ </tbody>
102
+ </table>
103
+ </p>
104
+ </script>
@@ -0,0 +1,120 @@
1
+ module.exports = function (RED)
2
+ {
3
+ "use strict";
4
+
5
+ function CounterNode(config)
6
+ {
7
+ const node = this;
8
+ RED.nodes.createNode(node, config);
9
+
10
+ const smart_context = require("../persistence.js")(RED);
11
+ const helper = require("../smart_helper.js");
12
+
13
+ var node_settings = {
14
+ value: null,
15
+ last_message: null,
16
+ };
17
+
18
+ if (config.save_state)
19
+ {
20
+ // load old saved values
21
+ node_settings = Object.assign(node_settings, smart_context.get(node.id));
22
+ }
23
+ else
24
+ {
25
+ // delete old saved values
26
+ smart_context.del(node.id);
27
+ }
28
+
29
+ // dynamic config
30
+ let start = config.start;
31
+ let step = config.step;
32
+ let min = config.min;
33
+ let max = config.max;
34
+
35
+ // runtime values
36
+
37
+ node.on("input", function (msg)
38
+ {
39
+ handleTopic(msg);
40
+ sendResult();
41
+ setStatus();
42
+ });
43
+
44
+ let handleTopic = msg =>
45
+ {
46
+ let real_topic = helper.getTopicName(msg.topic);
47
+ let temp_value;
48
+ switch (real_topic)
49
+ {
50
+ case "up":
51
+ temp_value = parseFloat(msg.payload);
52
+ if (isNaN(temp_value) && !isFinite(temp_value))
53
+ temp_value = step;
54
+
55
+ node_settings.value += temp_value;
56
+ break;
57
+
58
+ case "down":
59
+ temp_value = parseFloat(msg.payload);
60
+ if (isNaN(temp_value) && !isFinite(temp_value))
61
+ temp_value = step;
62
+
63
+ node_settings.value -= temp_value;
64
+ break;
65
+
66
+ case "reset":
67
+ temp_value = parseFloat(msg.payload);
68
+ if (isNaN(temp_value) && !isFinite(temp_value))
69
+ temp_value = start;
70
+
71
+ node_settings.value = temp_value;
72
+ break;
73
+
74
+ default:
75
+ node.error("Invalid topic: " + real_topic);
76
+ return;
77
+ }
78
+
79
+ // Check value is in range
80
+ node_settings.value = Math.min(max, Math.max(min, node_settings.value));
81
+ }
82
+
83
+ let sendResult = () =>
84
+ {
85
+ // Nothing changed, nothing to do
86
+ if (node_settings.value == node_settings.last_message?.payload)
87
+ return;
88
+
89
+ node_settings.last_message = { payload: node_settings.value };
90
+ smart_context.set(node.id, node_settings);
91
+
92
+ node.send(node_settings.last_message);
93
+ }
94
+
95
+ node.on("close", function ()
96
+ {
97
+ });
98
+
99
+ // updates the status
100
+ let setStatus = () =>
101
+ {
102
+ if (node_settings.value == null)
103
+ node.status({});
104
+ else
105
+ node.status({ fill: "yellow", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Value = " + node_settings.value });
106
+ }
107
+
108
+ if (config.save_state && config.resend_on_start && node_settings.last_message != null)
109
+ {
110
+ setTimeout(() =>
111
+ {
112
+ node.send(node_settings.last_message);
113
+ }, 10000);
114
+ }
115
+
116
+ setStatus();
117
+ }
118
+
119
+ RED.nodes.registerType("smart_counter", CounterNode);
120
+ }