-
Notifications
You must be signed in to change notification settings - Fork 1
State Node
The state node maintains a state whose value is changed at specific times under consideration of specific conditions. Upon state change and optionally at node start, the node can send messages or set global or flow variables. Multiple state values can be configured and each can have a different trigger time. Additionally, multiple conditions can be defined which are applied to each state change.
On the configuration page, various settings of the node can be configured.
The name is optional and can be used to better distinguish different state nodes. If omitted, a default name is displayed on the node instance.
The configuration node to be used must be selected here.
Whenever the state changes, an output is produced. That output can either be a message being sent to the output port of the node or a context variable being written. The state value will be set in the specified message property, flow variable or global variable. It is also possible to specify the full output message via a JSONata expression which must return an object representing the complete message that will be sent. In context of the expression, some common expression variables as well as the node-specific variable $state
can be accessed and used to form the message. The latter is an object and has the following properties:
Property | Type | Description |
---|---|---|
id |
Number | The identifer of the state (sequential number starting with 1). |
trigger |
Object | The trigger configuration of the state (see section Trigger below for object structure). 1 |
value |
Any | The value configured for the state. |
since |
Number | Timestamp representing the date and time since when the state is active. 2 |
until |
Number | Timestamp representing the date and time until when the state will be active. |
1 If the trigger refers to an environment or context variable, $state.trigger
will contain the content loaded from that variable. If the trigger has a random offset, $state.trigger.offset
will contain the already randomized offset value and not the originally configured offset.
2 The value of $state.since
might deviate from the actual trigger time in case the trigger has a random offset and the state has been restored. State restoration takes place when the node starts, when a state is reset after a timeout due to an explicit state change, when the state is explicitly reset and when the configuration is overridden (see section Input below for more information about the latter three cases). In such case, an offset of 0 is assumed in order to prevent the state from possibly switching forth and back if the state restoration takes place during the random offset time span of the state change.
Hint: You can send multiple messages at the same time by specifying an array of message objects.
Example JSONata expression to build the output message:
{
"id": $state.id,
"payload": $state.value,
"since": $moment($state.since, $config.timezone).calendar(),
"until": $moment($state.until, $config.timezone).calendar()
}
Depending on the trigger and state configuration, configured conditions and time of execution, the resulting message (without _msgid
property) could look like the following:
{
"id": 3,
"payload": false,
"since": "Yesterday at 6:00 PM",
"until": "Sunday at 3:45 PM"
}
The states tab contains the list of defined state values that will be activated at the configured times. New entries can be added to the list using the button at the bottom. Existing entries can be reordered or deleted. The number displayed to the left of each state is the identifier which can be used in input messages to explicitly activate specific states (see section Input below). Each entry in the list can be configured as described in the following chapters.
Note: Do not specify multiple states with the same trigger time. This is not meaningful and in such case, only one of the states would be activated at the specified time.
The first row defines the trigger for the state, i.e. the time when the state will be activated (provided that the conditions match) or a manual trigger.
The time can be specified as described in section Time Input. On the right to the time input is a numeric field where an offset can be specified which will be added to or subtracted from the event time. The offset must be entered in minutes and can be in the range of -300 to +300. If the checkbox on the right side is selected, the offset will be randomized between 0 and the specified value.
If manual trigger is selected from the dropdown menu, the state will not be automatically activated based on time. Instead, the state can only be activated manually via an input message with a "set" command (see section Input below for more information about supported input messages).
If env variable, global or flow is selected from the dropdown menu, the trigger configuration is loaded from the specified environment or context variable. This allows to dynamically program the states and is useful when using the node in a sub flow or if the trigger configuration should be retrieved from a runtime source like e.g., a Node-RED dashboard UI.
The content of such an environment, global or flow variable must follow the basic, extended or structured input format as described in section Time Input. The support for basic and extended formats is limited to time-only values, however. For the structured format, the state node additionally supports the type "manual", corresponding to the manual trigger type. For this type, properties value
, offset
and random
can be omitted.
The following example is a JSON representation of environment or context variables as they can be loaded by the state node.
// state is not activated automatically based on time, only manually via input message
{
"type": "manual"
}
See also examples from section Time Input.
The second row defines the value of the state. Different types of values are supported (the types are not described in more detail as they are provided by Node-RED and should be well known):
The conditions tab specifies the conditions that can restrict state changes to specific days and months.
Specifies the evaluation method for changing states based on the results of the conditions. The following table describes the possible evaluation methods:
Selection | Description |
---|---|
logical AND | Upon triggered, the state is changed only if all conditions evaluate to true . |
logical OR | Upon triggered, the state is changed if at least one of the conditions evaluates to true . |
expression | Upon triggered, the state is changed if the specified JSONata expression evaluates to true . |
If expression is selected, a JSONata expression can be specified in order to perform enhanced evaluation of the condition results. The JSONata expression must result in a boolean value, otherwise an error is emitted. If the expression evaluates to true
, the state is changed, in case of false
, it remains the same.
In the JSONata expression, the results of the conditions can be accessed through the variable $condition
which is an array of boolean values.
($condition[0] or $condition[1]) and $condition[2]
($condition[0] and $not($condition[1])) or $condition[2]
The conditions are evaluated against the trigger times of the states. New entries can be added to the list using the button at the bottom. Existing entries can be reordered or deleted. Each entry in the list can be configured as follows:
The operator defines the type of operands which are used to evaluate the condition. The provided possibilities are described in more detail in the following table.
Selection | Description |
---|---|
days | This operator checks if the trigger time matches special days of a month. |
week days | This operator checks if the trigger time matches one of the selected week days. |
months | This operator checks if the trigger time matches one of the selected months. |
For operator days the type of days can be selected from the dropdown box. The provided possibilities are described in more detail in the following table.
Selection | Description |
---|---|
first | Matches the first week day, day, workday or weekend day of the month. |
second | Matches the second week day of the month. |
third | Matches the third week day of the month. |
fourth | Matches the fourth week day of the month. |
fifth | Matches the fifth week day of the month. |
last | Matches the last week day, day, workday or weekend day of the month. |
even days | Matches all even days of the month. |
specific day | Matches a specific day of a specific month or of every month. |
The conditions can be negated by selecting the Exclude (⊘) checkbox.
For days types first, second, third, fourth, fifth and last the related day has to be selected:
Selection | Applicable to | Description |
---|---|---|
Monday .. Sunday | all | Matches the selected day of the week. |
day | first, last | Matches any day. |
workday | first, last | Matches a day of the workweek (Monday to Friday). |
weekend day | first, last | Matches a day of the weekend (Saturday and Sunday). |
For days type specific the day of the month has to be entered and the month has to be selected:
Selection | Description |
---|---|
January .. December | Matches the selected month. |
each month | Matches any month. |
For operator week days each day of a week can be selected or cleared.
For operator months each month of a year can be selected or cleared.
If option Output current state on start after X second(s) is selected, the current state will be output when the node starts in the same way as if a state change happened. Optionally you can choose a delay after which the output is produced (defaults to 0.1 seconds).
If option Passive trigger mode is selected, the state node will not actively change states upon reaching their trigger times. Instead, state changes must be triggered by an external trigger source via input message (see "trigger" command in section Input below). This allows for instance to operate a state node and a scheduler node in tandem processing having the scheduler node acting as external timer for the state node.
The state node can be programmatically controlled via specifically formed input messages.
The state node can be dynamically controlled in various ways using an input message. msg.topic
must be set to a string containing the command to be executed. Depending on the command, msg.payload
might be required as well.
Property | Type | Mandatory | Description |
---|---|---|---|
msg.topic |
String | yes | The control command to be executed, which can be one of "trigger", "get", "getid", "set", "reset", "reload", "pause" or "resume". |
msg.payload |
Number | yes for "set", no otherwise | Identifier of the state to trigger or activate. |
msg.timeout |
Number, Object | no | Timeout after which the original state is restored. |
The following commands are currently supported:
Command | Description |
---|---|
trigger |
Triggers a state change, see below for details. Only supported in passive trigger mode. |
get |
Explicitly sends or stores the output of the current state. |
getid |
Sends a message with the identifier of the currently active state in msg.payload to the output port. |
set |
Sets the current state to a specific one from configuration, see below for details. |
reset |
Sets the state back to its original value according to the configured trigger time and conditions. |
reload |
Reloads programmed data from environment and context variables. |
pause |
Suppresses automatic state changes when trigger times have been reached. Does nothing if passive trigger mode is enabled. |
reload |
Resumes automatic state changes. Does nothing if passive trigger mode is enabled. |
The command "trigger" can be used in two ways:
- Set
msg.payload
to a valid identifier of a configured state. If the configured conditions are fulfilled, the state is immediately changed to the target state upon receiving the input message. Use this way if the external trigger source sends the messages at the exact trigger times of the states. - Leave
msg.payload
undefined. Upon receiving the input message, the node checks if one of the configured states has reached its trigger time and if the conditions are fulfilled. If both is the case, the state is changed accordingly. Use this way if the external trigger source sends messages in a regular interval (e.g., every minute).
Hint: If using the second way (without msg.payload
being set), it is recommended to have the external trigger source sending the messages as near as possible to time boundaries so that the messages arrive at the state node shortly after those time boundaries (e.g., you can use a scheduler node with a cron table). This way you have the highest precision for the state changes.
The command "set" unconditionally activates a configured state identified by the number passed in msg.payload
. Optionally, a timeout can be specified in msg.timeout
. After the timeout has elapsed, the state is restored in the same way as the "reset" command does.
If msg.timeout
is a number, the value is interpreted as minutes. Alternatively, the timeout can be specified as an object containing the following properties:
Property | Type | Mandatory | Description |
---|---|---|---|
hours |
Number | no 1 | Part of the timeout in hours. |
minutes |
Number | no 1 | Part of the timeout in minutes. |
seconds |
Number | no 1 | Part of the timeout in seconds. |
1 At least one of hours
, minutes
or seconds
must be supplied.
If no timeout is specified, the state remains active until the chronologically next state according to the configured trigger time and conditions is activated (either actively by the state node itself or by an external trigger source in passive trigger mode). If the state actually changed by the "trigger", "set" or "reset" command, the output of the activated state is sent or stored.
Hint: State identifiers to be used with commands "trigger" and "set" are displayed in the state list next to each entry.
Note: Resuming automatic state changes with the command "resume" does not reset the current state to the last state that would have normally been activated during paused period. If you also want to have the state reset, additionally send a message with the "reset" command.
The following examples are JSON representations of the complete input message.
Triggers a change to state #3 if conditions are fulfilled:
{
"topic": "trigger",
"payload": 3
}
Triggers a change to the state whose trigger time is now if conditions are fulfilled:
{
"topic": "trigger" // triggers a change to the state whose trigger time is now if conditions are fulfilled
}
Causes the output for the current state to be sent or stored:
{
"topic": "get"
}
Activates the state #2 for one and a half hours:
{
"topic": "set"
"payload": 2,
"timeout":
{
"hours": 1,
"minutes": 30
}
}
The state configuration as well as the conditions can be dynamically overridden via the input message. The overridden configuration will be applied until one of the following situations occurs:
- The flow is redeployed or restarted.
- The Node-RED runtime is stopped or restarted.
For overriding via input message, msg.topic
must be set to the string "configure" and msg.payload
must be an object containing the following properties (all properties are optional, but at least one should be provided to have an effect by the command):
Property | Type | Description |
---|---|---|
states |
Array | List of states to be overriden. |
conditions |
Array | List of conditions to be overriden. |
Each element of the states
array corresponds to an entry in the state configuration and must be an object containing the following properties (again, all properties are optional, but at least one should be provided for a meaningful setup). To keep a configured state unchanged, set the corresponding array element to null
.
Property | Type | Description |
---|---|---|
trigger |
Object | Trigger of the state. |
state |
Object | Value of the state. |
The structure of the object trigger
is the same as described above in section Trigger. The state
property has the following structure:
Property | Type | Description |
---|---|---|
value |
Any | The actual value of the state. |
The following property can optionally be added and must be set to "date". In this case, the property value
is not required.
Property | Type | Description |
---|---|---|
type |
String | Output property/variable will contain a timestamp of the time when the output is produced (same behavior as if selecting timestamp type in UI). |
Each element of the conditions
array corresponds to an entry in the condition configuration and must be an object containing the following properties. To keep a configured condition unchanged, set the corresponding array element to null
.
Property | Type | Description |
---|---|---|
operator |
String | The operator for comparison, which can be one of "days", "weekdays" or "months". |
operands |
Object, Array | The operand(s) for comparison, see below for content. |
If operator
is "days", operands
must be an object containing the following properties:
Property | Type | Description |
---|---|---|
type |
String | The operand type, which can be one of "first", "second", "third", "fourth", "fifth", "last", "even" or "specific". |
day |
String, Number | Depending on the operand type the name of a day ("monday", "tuesday", ..., "sunday", "day", "workday" or "weekend") or the day of the month as number. This property is not applicable for type "even". |
month |
String | The name of the month ("january", "february", ...). This property is only applicable for type "specific" and optional. When omitted, condition matches for any month. |
exclude |
Boolean | When set to true , the result of the condition will be negated. |
If operator
is "weekdays", operands
must be an object. It may contain boolean properties with names of days of the week. If true
, the condition is fullfilled for trigger times on that day or not fulfilled if the property is false
or not present.
If operator
is "months", operands
must be an object. It may contain boolean properties with names of months of the year. If true
, the condition is fullfilled for trigger times in that month or not fulfilled if the property is false
or not present.
The following example is a JSON representation of the complete input message. In this example, two states and two conditions are overridden by a single message.
{
"topic": "configure",
"payload":
{
"states":
[
{
"trigger": // overrides the trigger of the first state
{
"type": "sun",
"value": "sunset",
"offset": 30,
"random": true
},
"state": // overrides the value of the first state
{
"value": true
}
},
{
"trigger": // overrides the trigger of the second state
{
"type": "time",
"value": "22:30",
"offset": 0,
"random": true
},
"state": // overrides the value of the second state
{
"value": false
}
}
],
"conditions":
[
{ // overrides the first condition
"operator": "weekdays",
"operands":
{
"monday": true,
"tuesday": true,
"wednesday": true,
"thursday": true,
"friday": true
}
},
{ // overrides the second condition
"operator": "months",
"operands":
{
"january": true,
"february": true,
"march": true,
"october": true,
"november": true,
"december": true
}
}
]
}
}
Whenever the state changes and the output is configured to be a message property or a full message, a message containing the state value is sent to the output port of this node. Additionally, a response to the "getid" command may be sent to the output port. In order to distinguish these two kind of messages, the response message to the "getid" command contains the original msg.topic
property with "getid".
node-red-contrib-chronos - Copyright (c) 2024 Jens-Uwe Rossbach. Licensed under the MIT License.
Home | Configuration | Scheduler | State | Repeat | Delay | Time Switch | Time Filter | Time Change