Data Flow & Automation Architecture Guide

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.

Table of Contents

  1. How Data Enters the Platform
  2. The Central Hub: How Every Value is Processed
  3. MQTT Topics — Inbound vs. Outbound
  4. Real-Time Dashboards via WebSocket
  5. Automation Rules
  6. Scripts
  7. Schedulers
  8. The Automation Execution Order
  9. Loop Prevention: How the Platform Protects Itself
  10. Common Problems & How to Avoid Them
  11. Quick Reference: Source Tags

1. How Data Enters the Platform

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
MQTT device HTTP device Dashboard (manual) Scheduler Automation Rule Script Platform Hub handleIncomingData() Database save MQTT publish (out) Dashboard update Rules check Scripts trigger

Figure 1 — Every entry point funnels through the platform hub, which then distributes the value to all downstream systems.

2. The Central Hub: How Every Value is Processed

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:

  1. Forward via MQTT (only for MQTT-sourced values). If the value arrived via MQTT from a device, the platform immediately re-publishes it on the outbound topic (/out/) so that other MQTT subscribers (apps, displays, other devices) can receive it in real time.
  2. Save to the database. The value is written to persistent storage. If the field is configured as historical, every value is appended. If it is configured as live-only, only the latest value is kept.
  3. Publish outbound via MQTT (for rules, scripts, schedulers). If an automation component has the "MQTT Publish" option enabled, the value is sent out via MQTT so devices can receive it.
  4. Push to real-time dashboards. The value is broadcast instantly to all open dashboards that are displaying that field.
  5. Trigger Automation Rules (if applicable — see Section 9 for conditions).
  6. Trigger Scripts (if applicable — see Section 9 for conditions).
Important: Steps 5 and 6 — triggering rules and scripts — only happen for values that come from "external" sources (devices, HTTP, Dashboard, Scheduler). Values that are produced by rules or scripts are treated differently to prevent endless loops. This is explained in detail in Section 9.

3. MQTT Topics — Inbound vs. Outbound

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.

Inbound Topics — Device → Platform

{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

Outbound Topics — Platform → Device

{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
Device (sensor / MCU) MQTT Broker +/in/# | +/out/# separate namespaces Platform subscribes: +/in/# Apps / Devices subscribe: +/out/# publish /in/ +/in/# only publish /out/ +/out/# only Platform never sees its own outbound messages — loop is architecturally impossible

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.

Topic Structure Reference

SegmentMeaningExample
{shortId}Your unique account/customer identifierabc123
in or outDirection: inbound (device → platform) or outbound (platform → device)in
deviceKeyword indicating a named device followsdevice
{deviceName}The name of your device as registered in the platformgreenhouse
{fieldName}The specific data field / variable nametemperature
Device Configuration: Make sure your physical devices are configured to publish to the /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.

Publishing without a named device

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

4. Real-Time Dashboards via WebSocket

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 writes: When a user manually sets a value through a dashboard widget (a slider, a button, an input field), that value enters the platform with source 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.

5. Automation Rules

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.

How a Rule Works

  1. A new value arrives for a monitored field.
  2. The platform evaluates all active rules that watch that field.
  3. If a rule's condition is met, it performs its configured action: writing a value to a target field, sending an email, sending a push notification, or any combination.
  4. The written value enters the hub with source AUTOMATION_RULE.

Rule Configuration Options

SettingDescription
Source fieldThe field whose incoming value will trigger the condition check
Source deviceOptionally restrict the rule to a specific device
OperatorThe comparison: >, <, ==, !=, >=, <=
ThresholdThe value to compare against
Target fieldThe field that will receive the action value
Target valueThe value to write to the target field when the condition is met
MQTT PublishIf enabled, the written value is also sent out via MQTT to devices
Email / Push notificationAlert notifications, controlled by a cooldown interval to avoid spam
Notify interval (seconds)Minimum time between repeat notifications for the same rule

Rule Triggering Behaviour

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.

Important: A Rule that writes to a target field will not trigger other rules or scripts for that written value. This is by design — see Section 9 for the full explanation.

6. Scripts

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.

Two execution modes

On Event (Trigger mode)

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.

On Timer (Polling mode)

The script runs on a fixed schedule (e.g., every 30 seconds, every hour). Best for periodic calculations: averages, aggregations, scheduled reports.

IO Mapping

Scripts interact with platform data through a mapping table, not by directly naming database tables. Each row in the mapping table declares:

Script outputs — what happens next: When a script writes to an output field, that value enters the hub with source 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.

Script safety limits

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.

7. Schedulers

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.

Good use cases for Schedulers: Resetting a daily counter, enabling or disabling a device at a specific time, writing a reference value that scripts or rules react to, sending a periodic heartbeat value.

8. The Automation Execution Order

When any value arrives at the platform hub, the following sequence always takes place in this order:

Value arrives (any source) 1. Forward via MQTT (only if source = MQTT) 2. Save to database (historical or live-only) 3. Publish via MQTT (outbound) (only if publish = true) 4. Push to dashboards (WebSocket) (always) 5. Rules check (if not from a Rule) 6. Scripts trigger (if not from Rule/Script)

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.

9. Loop Prevention: How the Platform Protects Itself

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:

Level 1 — Architectural: MQTT Namespace Isolation

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.

Level 2 — Source-Based: Smart Trigger Filtering

The platform tracks the source of every value and applies strict rules about what can trigger what:

Value Source Can trigger Scripts? Can trigger Rules? MQTT / HTTP / Dashboard / Scheduler ✓ Yes ✓ Yes SCRIPT ✗ No — prevents script→script ✓ Yes AUTOMATION_RULE ✗ No — prevents rule→script→rule ✗ No — prevents rule→rule Key insight: A value produced by a Rule triggers nothing further. A value produced by a Script can still trigger Rules, but not other Scripts.

Figure 4 — Source-based trigger filtering. The source tag determines what the value is allowed to trigger.

Level 3 — Script depth limit

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.

Summary of what is safe and what is not:

10. Common Problems & How to Avoid Them

Problem 1: Rule fires repeatedly for the same condition

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.

Problem 2: Script output does not trigger another script

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.

Problem 3: Rule action value does not appear on the dashboard immediately

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.

Problem 4: Device values not arriving at the platform

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.

Problem 5: MQTT-subscribed device not receiving platform values

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.

Problem 6: Script runs but output field is not updated

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.

Problem 7: Historical field grows too large

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

What to check first when something isn't working:
  1. Open the Data Monitor — it shows all incoming values in real time. If the value appears there, the platform received it.
  2. Check the Automation Logs — they record every time a rule fires, including errors.
  3. Use the Script Test Console — run your script manually with sample inputs to verify the logic before relying on live data.
  4. Verify the MQTT topic format — it is the most common cause of device connectivity issues.

11. Quick Reference: Source Tags

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 TagOriginTriggers 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
External sources MQTT / HTTP / Dashboard / Schedule Platform Hub source tag travels with data Automation Rules → write AUTOMATION_RULE Scripts → write SCRIPT AUTOMATION_RULE → no further triggers SCRIPT → rules only, no scripts

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