This guide explains how data moves through Virtuino Cloud — from the moment a value is sent, all the way to storage, live dashboards, MQTT subscribers, rules, scripts and HTTP requests. Knowing this path helps you design reliable automations and quickly find out why something did not happen.
Every value is written to a field. The field's name is also its MQTT topic — for example kitchen/temperature. Whoever sends the value, it carries a source tag that travels with it through the whole platform and decides what it is allowed to trigger.
| Entry point | Source tag | Typical use |
|---|---|---|
MQTT A client publishes to the field's topic, e.g. kitchen/temperature |
MQTT |
ESP32, ESP8266, Arduino, Node-RED, the Virtuino IoT app — any MQTT client |
| HTTP A request to the HTTP API, or the response of an HTTP Request stored in a field | HTTP |
Boards and services that make web requests; data pulled from external web APIs |
| WS A user changes a value from a dashboard widget | DASHBOARD |
Buttons, switches, sliders, input fields |
| SCHEDULER A scheduled ON/OFF event fires | SCHEDULER |
Switching things on and off at set times |
| RULE An automation rule writes its action value | RULE |
"When the temperature is above 30, set the fan to 1" |
| SCRIPT A script writes an output | SCRIPT |
Calculations, conversions, control logic |
| JSON The JSON Splitter extracts a value from a JSON payload | JSON |
One message carries many readings; each goes to its own field |
| AI You ask the AI Assistant to send a value | AI |
Quick manual commands from the chat |
Figure 1 — Every entry point goes through the same hub. The JSON Splitter, scripts, rules and HTTP Requests write new values, which enter the hub again from the left.
No matter where a value comes from, it passes through the same processing function, in this order:
time), that time is stored."publish": true in an HTTP API request.In your device code, a field is one topic: publish to kitchen/temperature to send a value, subscribe to kitchen/relay to receive commands. There is nothing to register besides the field itself — the topic is the field name, slashes included. For connection details and examples see the MQTT guide.
Under the hood the broker keeps two separate channels for every field, and picks the right one automatically: what a client publishes goes to the platform's inbound channel, and what a client subscribes to is read from the outbound channel. Nothing about this needs configuring.
Carries everything clients publish. The platform only listens here and never sends anything on it.
Carries everything subscribers receive: values forwarded from other clients and commands from dashboards, rules, scripts and schedulers. The platform only sends here and never listens.
Figure 2 — The platform only listens on channel 1, so what it sends on channel 2 can never come back to it as a new value.
kitchen/relay — works as expected: it receives commands on channel 2, and what it publishes arrives on channel 1. If it echoes a command straight back, the echo is recognised and not bounced back to it (Section 10).
Fields that wait for confirmation also get a third, read-only topic, {field}/state — for example kitchen/relay/state. It carries the value only once the device has confirmed it, so apps that subscribe to it always show the real state. See Section 8.
Every value the hub saves is also pushed to all open dashboards that show that field, through a live WebSocket connection — no page refresh needed:
DASHBOARD and is processed like any other value — saved, shown on other dashboards, published via MQTT if the widget's "Publish via MQTT" option is on, and able to trigger scripts, rules and HTTP Requests.
One exception: for a field that waits for confirmation, a new command is saved and pushed to dashboards only after the device has confirmed it (Section 8).
A rule watches one field and compares each new value with a threshold — for example "when kitchen/temperature is greater than 30". When the condition is true it can write a value to another field, send a push notification, send an email, or any combination. Rules are created with the Rule widget on a dashboard.
| Setting | What it does |
|---|---|
| Source field | The field whose new values are checked |
| Condition | >, <, == or !=. The comparison is numeric, so use it with numeric fields |
| Threshold | The number to compare against |
| Target field and Action value | Optional. The value written to the target field while the condition is true |
| Publish via MQTT | Also sends the action value to the target field's MQTT subscribers |
| Push notification / Email alert | Alerts sent when the condition becomes true |
| Alert message | Text included in the notification |
| Notify every | Minimum time between two alerts of the same rule (Always, 1 minute … 24 hours) |
| Rule enabled | Turns the rule on or off without deleting it |
Scripts run your own JavaScript on the server. They read one or more input fields, calculate, and write results to output fields. Open them from a dashboard: Tools → Scripts. Full reference: Scripts guide.
The script runs as soon as one of its trigger inputs receives a new value. Best for fast reactions: alarms, control loops, conversions.
The script runs every set number of seconds, whether new data arrived or not. Best for periodic work: averages, counters, watchdogs.
A script sees fields only through its mapping table. Each row links a script variable to a field:
SCRIPT. It is saved, shown on dashboards, and can trigger rules, HTTP Requests and other scripts. An output set to null is skipped, and an output can carry its own time as { value, time }.
Each run takes place in an isolated sandbox and is stopped after 50 ms. When one script's output starts another script, the chain can be at most five scripts long; beyond that, scripts are not started. A script only runs when it is both active and ready.
A scheduler writes a fixed ON or OFF value to one field at set times — no conditions, no code. It is added with the Scheduler widget on a dashboard, and each event can repeat:
Times follow the dashboard's time zone. With "Publish via MQTT" on, the value is also sent to the field's subscribers, so a relay can switch at the scheduled time.
Scheduler values enter the hub with source SCHEDULER and can trigger scripts, rules and HTTP Requests, exactly like values from a device.
Normally a command from a dashboard, rule, script or scheduler is saved and shown as soon as it is sent. On a field with command confirmation turned on, the platform waits for proof that the device actually carried it out:
{field}/state, and able to trigger scripts, rules and HTTP Requests.This way the database and your automations always reflect what the device really did, not what it was asked to do. Setup and firmware examples: Confirmed commands.
Every value that reaches the hub goes through these steps, always in this order:
Figure 3 — The fixed processing order. The four triggers of step 7 run in parallel, and the source tag decides which of them may run.
The danger in any automation platform is an endless loop: a value triggers a script, which writes a value that triggers the script again, forever — filling the database and wasting server resources. Virtuino Cloud stops loops at four levels.
The platform only listens on the channel clients publish to and only sends on the channel subscribers read (Section 3). Its own MQTT messages can never come back to it as new values.
Many devices answer a command by publishing the same value back. Without protection, that echo would be forwarded to subscribers as a new command, the device would echo it again, and so on. So when a device sends back exactly the value it was just sent — within 3 seconds, or within the confirmation timeout for fields that wait for confirmation — the value is saved as usual but not forwarded again.
The source tag limits what a value may trigger:
Scripts may start other scripts, and the JSON Splitter's values may start scripts, but every link adds one step to the chain. After five steps, no more scripts or splitters are started — whatever the conditions.
Symptom: a device publishes or posts, but nothing appears.
Cause: the topic (or HTTP field name) does not match an existing field exactly — the value is rejected as an unknown field. Or the value is too large: a historical field accepts at most 512 characters.
Solution: open the Debug Monitor; every rejected value is shown there with its reason. Compare the topic with the field name in Console → Fields, character for character — see the MQTT topic guide.
Symptom: a board subscribes to receive commands, but values from the dashboard, a rule, a script or a scheduler never reach it.
Cause: the writer's "Publish via MQTT" option is off (for scripts: the OUT row's Publish box; for the HTTP API: "publish": true missing), or the board subscribes to a different topic.
Solution: turn on publishing where the value is written, and subscribe to the field name itself, e.g. kitchen/relay. For debugging, subscribe to # to see everything the platform sends you.
Symptom: a rule, script or widget writes a value, but the widget does not change.
Cause: either the widget shows a different field than the one written, or the field waits for confirmation and the device has not echoed the command back yet.
Solution: make sure the target field and the widget's field are the same. For confirmed fields, check that the firmware publishes the value back after carrying it out (Confirmed commands).
Symptom: the script works in the test console but never runs on live data, or its output field is not updated.
Cause: the script is not both active and ready; the input is not marked as a trigger; only on change is on and the value did not change; trigger from excludes the value's source; the value came from a rule; or the chain of scripts reached its limit of five. Outputs set to null are skipped.
Solution: check the script's status and trigger options, and confirm the OUT row points to the right field. The script's last error is shown in the Scripts list.
Symptom: a rule keeps sending notifications.
Cause: alerts are sent each time the condition becomes true. A value hovering around the threshold — 29.9, 30.1, 29.9, 30.1 — makes it true again and again.
Solution: set Notify every to a cooldown such as 5 or 30 minutes.
Symptom: a historical target field gets a new entry on every reading.
Cause: a rule writes its action value on every value that meets the condition, not only the first one.
Solution: make the target field standard (non-historical), or use a script that writes only when the state changes.
Symptom: a historical field stores a huge number of values.
Cause: a device or script writes to it very often, e.g. every second.
Solution: send less often from the device, switch the field to standard if you do not need its history, or use a script that writes only when the value changes enough.
Every stored value keeps its source tag — you can see it in the Data Monitor. It decides what the value may trigger and when it goes out via MQTT.
| Source tag | Origin | Triggers scripts? | Triggers rules? | Triggers HTTP Requests? | Sent via MQTT |
|---|---|---|---|---|---|
MQTT |
MQTT client | Yes | Yes | Yes | Always forwarded to subscribers (echoes excepted) |
HTTP |
HTTP API, or an HTTP Request's stored response | Yes | Yes | No | API: only with "publish": true. HTTP Request responses: never |
DASHBOARD |
Dashboard widget | Yes | Yes | Yes | If the widget's "Publish via MQTT" is on |
SCHEDULER |
Scheduler event | Yes | Yes | Yes | If the scheduler's "Publish via MQTT" is on |
SCRIPT |
Script output | Yes, up to 5 in a chain | Yes | Yes | If Publish is ticked on that OUT row |
JSON |
JSON Splitter | Yes, within the chain limit | Yes | Yes | Never |
AI |
AI Assistant | Yes | Yes | Yes | Always |
RULE |
Rule action | No | No | No | If the rule's "Publish via MQTT" is on |
With trigger from narrowed on a script input, only the ticked sources start that script: Device means MQTT and HTTP, plus DASHBOARD and SCHEDULER as ticked.
Virtuino Cloud Platform — Data Flow & Automation Architecture Guide