Data Flow & Automation Architecture Guide

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.

Table of Contents

  1. How Data Enters the Platform
  2. The Central Hub: How Every Value is Processed
  3. MQTT: Two Channels That Never Cross
  4. Live Dashboards
  5. Automation Rules
  6. Scripts
  7. Schedulers
  8. Commands That Wait for Confirmation
  9. The Processing Order
  10. Loop Prevention: How the Platform Protects Itself
  11. Common Problems & How to Solve Them
  12. Quick Reference: Source Tags

1. How Data Enters the Platform

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
MQTT client HTTP API / HTTP Requests Dashboard widget Scheduler AI Assistant JSON Splitter Script Rule Platform hub same steps for every value Database MQTT subscribers Live dashboards JSON Splitter Scripts Rules HTTP Requests

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.

2. The Central Hub: How Every Value is Processed

No matter where a value comes from, it passes through the same processing function, in this order:

  1. Size check. A historical field accepts values up to 512 characters, a standard field up to 1 MB. A larger value is rejected completely — nothing below runs — and the rejection is shown in the Debug Monitor.
  2. Confirmation check. If the value is a command to a field that waits for confirmation, it is only sent to the device; the remaining steps run when the device echoes it back. See Section 8.
  3. Forward to MQTT subscribers (MQTT values only). A value published by one client is passed on to every client subscribed to that topic — other boards, the Virtuino IoT app, Node-RED. Echoes of a command the device just received are not forwarded again (Section 10).
  4. Save to the database. A historical field keeps every value; a standard field keeps only the latest one. If the sender supplied its own timestamp (time), that time is stored.
  5. Publish via MQTT — only when the writer asked for it: the "Publish via MQTT" option of a widget, rule, scheduler or script output, or "publish": true in an HTTP API request.
  6. Update live dashboards — every open dashboard showing the field updates instantly.
  7. Run the triggers, in parallel: the JSON Splitter, scripts, rules and HTTP Requests that watch this field. Which of them may run depends on the source tag — see Section 10.
The one rule to remember: a value written by a Rule triggers nothing further — no scripts, no rules, no HTTP Requests, no JSON Splitter. It is saved, shown on dashboards and published if asked, and the chain stops there.

3. MQTT: Two Channels That Never Cross

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.

Channel 1 — client → platform

Carries everything clients publish. The platform only listens here and never sends anything on it.

Channel 2 — platform → subscribers

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.

MQTT client board, app, Node-RED MQTT Broker two channels per field, kept apart internally Platform listens on channel 1 Subscribers receive channel 2 publish channel 1 publish channel 2 The platform never receives its own outbound messages

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.

A client that both publishes and subscribes to the same topic — a relay board that listens for commands and reports its state on 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.

4. Live Dashboards

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 writes: when you press a button or move a slider, the value enters the platform with source 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).

5. Automation Rules

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.

Rule settings

SettingWhat it does
Source fieldThe field whose new values are checked
Condition>, <, == or !=. The comparison is numeric, so use it with numeric fields
ThresholdThe number to compare against
Target field and Action valueOptional. The value written to the target field while the condition is true
Publish via MQTTAlso sends the action value to the target field's MQTT subscribers
Push notification / Email alertAlerts sent when the condition becomes true
Alert messageText included in the notification
Notify everyMinimum time between two alerts of the same rule (Always, 1 minute … 24 hours)
Rule enabledTurns the rule on or off without deleting it

When a rule acts

Important: the value a rule writes does not trigger any other rule, script, HTTP Request or JSON Splitter. See Section 10.

6. Scripts

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.

Two execution modes

On event

The script runs as soon as one of its trigger inputs receives a new value. Best for fast reactions: alarms, control loops, conversions.

On timer

The script runs every set number of seconds, whether new data arrived or not. Best for periodic work: averages, counters, watchdogs.

Input and output mapping

A script sees fields only through its mapping table. Each row links a script variable to a field:

What happens to script outputs: each output enters the hub with source 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 }.

Safety limits

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.

7. Schedulers

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.

Good uses for schedulers: switching lights, pumps or heating on and off at fixed times, resetting a daily counter, enabling a mode on certain days.

8. Commands That Wait for Confirmation

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:

  1. The command is sent to the device via MQTT — nothing else happens yet.
  2. The device carries it out and publishes the same value back on the same topic.
  3. The echo arrives as a normal MQTT value and goes through the full hub: saved, shown on dashboards, published to {field}/state, and able to trigger scripts, rules and HTTP Requests.
  4. If no echo arrives within the field's timeout, the command is marked as not confirmed and the dashboard shows it.

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.

9. The Processing Order

Every value that reaches the hub goes through these steps, always in this order:

Value arrives — any source 1. Size check historical ≤ 512 characters · standard ≤ 1 MB 2. Confirmation check commands to fields that wait for confirmation 3. Forward to MQTT subscribers MQTT values only · echoes are skipped 4. Save to database with the sender's own time, if it sent one 5. Publish via MQTT only when publish is on 6. Update live dashboards WebSocket, no page refresh Too large → rejected nothing else runs Waiting for confirmation only sent to the device; the rest runs on its echo 7. JSON Splitter if set up for the field not for Rule values 7. Scripts not for Rule values chain of 5 at most 7. Rules not for Rule values 7. HTTP Requests not for Rule values or HTTP values

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.

10. Loop Prevention: How the Platform Protects Itself

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.

Level 1 — Separate MQTT channels

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.

Level 2 — Echo detection

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.

Level 3 — Source rules

The source tag limits what a value may trigger:

Level 4 — Chain length limit

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.

What is safe:

11. Common Problems & How to Solve Them

Problem 1: Values do not arrive

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.

Problem 2: A subscribed device receives nothing

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.

Problem 3: A command does not show on the dashboard

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

Problem 4: A script does not run

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.

Problem 5: Too many alerts from a rule

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.

Problem 6: A rule's target field fills with values

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.

Problem 7: A historical field grows too large

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.

What to check first when something isn't working:
  1. Debug Monitor — shows every value in and out in real time, including rejected ones and why.
  2. Data Monitor — shows what is stored for each field, with its source.
  3. Automation log — records every time a rule fires, including silenced alerts and errors.
  4. Script test console — runs a script with sample inputs before you rely on live data.

12. Quick Reference: Source Tags

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