Skip to content

State Node

Jens Rossbach edited this page Jun 16, 2024 · 4 revisions

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.

State Node

Configuration

On the configuration page, various settings of the node can be configured.

General

General Configuration

Name

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.

Configuration

The configuration node to be used must be selected here.

States and Conditions

Output

Output

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

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"
}

States

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.

Trigger

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.

Event 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.

Dynamic Trigger

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.

Examples

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.

State Value

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):

State Value Type Selection

Conditions

The conditions tab specifies the conditions that can restrict state changes to specific days and months.

Evaluation

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.

JSONata Expression

In the JSONata expression, the results of the conditions can be accessed through the variable $condition which is an array of boolean values.

Examples
($condition[0] or $condition[1]) and $condition[2]

($condition[0] and $not($condition[1])) or $condition[2]

Conditions

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:

Operator

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.
Operands

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:

Special Days

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:

Specific Days

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.

Week Days

For operator months each month of a year can be selected or cleared.

Months

Options

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.

Passive Trigger Mode

Input

The state node can be programmatically controlled via specifically formed input messages.

Control State Node

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:

  1. 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.
  2. 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.

Examples

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
    }
}

Override States and Conditions

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.

Examples

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
                }
            }
        ]
    }
}

Outputs

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".