This guide explains how data moves through Virtuino Cloud — from the moment a device sends a value, all the way to storage, real-time dashboards, automation rules, and scripts. Understanding this flow helps you design reliable automations, avoid common pitfalls, and get the most out of the platform's capabilities.
Every value that reaches Virtuino Cloud arrives through one of the following entry points. Each one identifies itself with a source tag that travels with the data throughout its entire journey inside the platform.
| Entry Point | Source Tag | Typical Use |
|---|---|---|
MQTT Device publishes to {shortId}/in/device/{name}/{field} |
MQTT |
Microcontrollers, sensors, ESP32, Arduino, any MQTT-capable device |
| HTTP Device sends an HTTP POST/GET request | HTTP |
Any device or service that can make web requests |
| WS User writes a value from a Dashboard widget | DASHBOARD |
Manual control, sliders, buttons in the UI |
| RULE An Automation Rule fires an action | AUTOMATION_RULE |
Conditional logic that writes to a field when a threshold is met |
| SCRIPT A Script writes an output value | SCRIPT |
JavaScript logic that computes and writes results |
| SCHEDULE A Scheduler writes a value on a timer | SCHEDULE |
Periodic writes, e.g. every hour or every day |
Figure 1 — Every entry point funnels through the platform hub, which then distributes the value to all downstream systems.
No matter where a value originates, it always passes through the platform's central processing function. This hub performs the same sequence of actions for every incoming value:
/out/) so that other MQTT subscribers (apps, displays, other devices) can receive it in real time.MQTT is a publish/subscribe messaging protocol. Devices publish values to "topics" — think of these as named channels. The platform subscribes to topics to receive device data, and also publishes to topics to send data back to devices.
Virtuino Cloud uses a strict namespace separation between incoming and outgoing MQTT traffic. This is one of the most important architectural decisions in the platform, as it eliminates an entire class of potential infinite loops.
{shortId}/in/device/{deviceName}/{fieldName}
{shortId}/in/{fieldName}
Used by your physical devices to send data to the platform. The platform subscribes only to +/in/# — it only "listens" on these topics.
Example:
abc123/in/device/greenhouse/temperature
{shortId}/out/device/{deviceName}/{fieldName}
{shortId}/out/{fieldName}
Used by the platform to send data back to devices, or for other apps to subscribe to real-time updates. The platform never subscribes to these topics.
Example:
abc123/out/device/greenhouse/temperature
Figure 2 — Inbound and outbound topics are completely separate. The platform subscribes only to /in/, so values it publishes to /out/ never come back to it.
| Segment | Meaning | Example |
|---|---|---|
{shortId} | Your unique account/customer identifier | abc123 |
in or out | Direction: inbound (device → platform) or outbound (platform → device) | in |
device | Keyword indicating a named device follows | device |
{deviceName} | The name of your device as registered in the platform | greenhouse |
{fieldName} | The specific data field / variable name | temperature |
/in/ namespace. If a device publishes to the old format (without /in/ or /out/), the platform will not receive the message. Update your device firmware or MQTT client configuration accordingly.
If your device does not have a specific device name, you can publish directly to a field without the device/{name} part. The platform will assign the value to a generic device called unspecified:
// Simplified topic without a device name:
{shortId}/in/{fieldName}
// Example:
abc123/in/temperature
Every time any value is processed by the platform hub — regardless of source — it is instantly broadcast to all open dashboards that are displaying that field. This happens through an internal real-time channel (WebSocket), so there is no need to refresh the page.
This means:
DASHBOARD and is processed exactly like any other incoming value — saved to the database, broadcast to all other dashboards, and eligible to trigger rules and scripts.
Automation Rules are condition-based triggers. You define a condition (e.g., "when field temperature is greater than 80") and an action (e.g., "write value 1 to field alarm"). When the condition is met, the action fires automatically.
AUTOMATION_RULE.| Setting | Description |
|---|---|
| Source field | The field whose incoming value will trigger the condition check |
| Source device | Optionally restrict the rule to a specific device |
| Operator | The comparison: >, <, ==, !=, >=, <= |
| Threshold | The value to compare against |
| Target field | The field that will receive the action value |
| Target value | The value to write to the target field when the condition is met |
| MQTT Publish | If enabled, the written value is also sent out via MQTT to devices |
| Email / Push notification | Alert notifications, controlled by a cooldown interval to avoid spam |
| Notify interval (seconds) | Minimum time between repeat notifications for the same rule |
Rules use an internal triggered flag. When a condition is first met, the rule fires and sets the flag to true. If the condition remains true on subsequent data arrivals, the action does not fire again (it already fired). The flag resets to false only when the condition is no longer met — this prevents the rule from repeatedly firing while the condition is continuously true.
Scripts allow you to write JavaScript logic that runs automatically when data arrives or on a timer. They can read multiple input fields, perform calculations, and write results to output fields.
The script runs immediately when one of its configured input fields receives a new value. Best for low-latency responses: alarms, control loops, value transformations.
The script runs on a fixed schedule (e.g., every 30 seconds, every hour). Best for periodic calculations: averages, aggregations, scheduled reports.
Scripts interact with platform data through a mapping table, not by directly naming database tables. Each row in the mapping table declares:
SCRIPT. It will be saved to the database, shown on dashboards, and is eligible to trigger rules — but will not trigger other scripts. See Section 9.
Each script runs in an isolated sandbox with a strict 50ms execution timeout. If the script takes longer than 50ms, it is terminated. This protects the platform from poorly written scripts consuming server resources. Additionally, script-to-script cascade chains are limited to a maximum depth of 5 levels.
Schedulers allow you to write a specific value to a specific field at a fixed time or on a repeating interval — without any condition or script logic. They are the simplest form of automation: "every day at 08:00, write value 1 to field morning_flag".
Values written by schedulers enter the hub with source SCHEDULE and are eligible to trigger both rules and scripts, exactly like values from external devices.
When any value arrives at the platform hub, the following sequence always takes place in this order:
Figure 3 — The fixed processing order for every incoming value. Steps 5 and 6 run in parallel and have conditions based on the value's source.
The most dangerous scenario in any automation platform is an infinite loop: a value triggers a rule, which writes a new value, which triggers a script, which writes another value, which triggers the rule again — endlessly. This would fill the database, consume all server resources, and crash the platform.
Virtuino Cloud prevents loops at three levels:
The platform subscribes only to +/in/# topics. All values it publishes go to +/out/# topics. Since the platform never subscribes to +/out/#, its own outbound MQTT messages can never come back to it. This makes MQTT-based loops architecturally impossible — not just prevented by code logic, but structurally impossible by design.
The platform tracks the source of every value and applies strict rules about what can trigger what:
Figure 4 — Source-based trigger filtering. The source tag determines what the value is allowed to trigger.
Scripts that are triggered by other scripts (through a chain of field writes) are limited to a maximum cascade depth of 5 levels. If a script's output triggers another script, and that script's output triggers another, and so on, the chain is cut at level 5 regardless of conditions.
Symptom: A rule seems to fire over and over, filling the automation log with repeated entries.
Cause: The triggered flag mechanism prevents repeat fires within the same condition state. However, if the source field is receiving many new values (e.g., every second), and the condition remains true, the rule evaluates every time but fires only on the first occurrence — this is normal. If you are seeing log entries on every value, check that the rule's notify interval is set appropriately.
Solution: Set the notify interval to a minimum cooldown period (e.g., 300 seconds) to silence repeat notifications while the condition remains true.
Symptom: Script A writes to a field. Script B is configured to trigger on that same field. Script B never runs.
Cause: This is intentional. Values produced by scripts are tagged with source SCRIPT, and the platform will not trigger other scripts from script-produced values. This prevents infinite script chains.
Solution: Combine the logic into a single script that reads all the input fields and writes all the outputs directly, instead of chaining scripts.
Symptom: A rule writes a value to a target field, but the dashboard widget for that field does not update.
Cause: The dashboard widget may be configured to show a different device's field, or the field mapping is incorrect.
Solution: Verify that the rule's target field matches exactly the field displayed by the dashboard widget, including the device name. Check the Data Monitor to confirm the value is actually being written.
Symptom: A device is publishing via MQTT but no data appears in the platform.
Cause: The device is publishing to the wrong topic format — likely the old format without /in/, or to /out/ instead of /in/.
Solution: Update your device to publish to {shortId}/in/device/{deviceName}/{fieldName}. Verify the shortId matches your account's short identifier exactly. Use the Data Monitor to observe incoming data in real time.
Symptom: A device subscribes to MQTT to receive commands or values from rules/scripts, but receives nothing.
Cause: The device is subscribed to the wrong topic — likely /in/ instead of /out/. Platform outbound values go to /out/ topics.
Solution: Update the device to subscribe to {shortId}/out/device/{deviceName}/{fieldName} or {shortId}/out/# to receive all outbound values for your account.
Symptom: A script executes without errors in the test console, but the target field shows no new value.
Cause: Either the output mapping row has an incorrect field reference, or the script is writing to the output variable but the Is Ready / Is Active flags are not both enabled.
Solution: Confirm both Is Active and Is Ready are checked. Verify the OUT mapping row points to the correct device and field. Use the built-in test console to run the script and check the output values shown.
Symptom: A field configured as historical is storing every value, consuming large amounts of storage.
Cause: A device or script is writing to a historical field very frequently (e.g., every second).
Solution: Either reduce the write frequency on the device side, switch the field to live-only mode if history is not needed, or use a script to filter and write only when the value changes significantly (deadband filtering).
The source tag is attached to every value in the platform. It determines what that value is allowed to trigger and is visible in the Data Monitor and automation logs.
| Source Tag | Origin | Triggers Rules? | Triggers Scripts? | MQTT outbound? |
|---|---|---|---|---|
MQTT |
Device via MQTT /in/ |
Yes | Yes | Forwarded to /out/ automatically |
HTTP |
Device via HTTP | Yes | Yes | Only if publish is enabled |
DASHBOARD |
Manual write from UI widget | Yes | Yes | Only if publish is enabled |
SCHEDULE |
Scheduler write | Yes | Yes | Only if publish is enabled |
SCRIPT |
Script output write | Yes | No | Only if publish is enabled for that output mapping |
AUTOMATION_RULE |
Rule action write | No | No | Only if MQTT publish is enabled on the rule |
Figure 5 — The complete automation execution graph. External sources can trigger both rules and scripts. Rule outputs and script outputs have restricted downstream triggering to prevent loops.
Virtuino Cloud Platform — Data Flow & Automation Architecture Guide