Remote HMI Tutorial

Build a remote HMI without going on site

Traditional remote HMI work means testing against live equipment again and again. With Falcon log replay you bring the site back to your desk, let an AI agent write and test the PySide6 UI, and finish in hours what used to take days.

No line downtime

Develop and test against replayed data without touching the production schedule.

Real data, real behavior

Replay is genuine field traffic, so the UI behaves exactly as it will in production.

AI-accelerated

Clean JSON-RPC structure lets AI understand your tags and produce working PySide6 code.

Python ecosystem

PySide6 is cross-platform with friendly licensing and easy to extend with analytics and AI.

Log → Replay → PySide6 + AI

Five steps to a remote HMI

Using a stamping line as an example, here is the full flow from recording to go-live.

  1. 01

    Record traffic on site

    Insert Falcon between PLC and HMI and call log.record to capture a real shift. Every tag read and write is stored as JSON-RPC.

  2. 02

    Replay in the office

    Take the log back to the office and call log.replay. Falcon republishes the traffic to MQTT with original timing, as if the line were running.

    JSON-RPC: replay a logjson
    // Topic: falcon/line-01/rpc/req
    {
      "jsonrpc": "2.0",
      "id": "replay-01",
      "method": "log.replay",
      "params": { "log": "2026-11-03_line01_shift-a", "speed": 1.0, "loop": true }
    }
  3. 03

    Hand it to an AI agent

    Give the requirements to an AI coding agent. It subscribes to the replay, maps the tags, writes the PySide6 code and runs tests, fixing errors on its own.

    Example task for the AI agenttext
    Build a PySide6 window for "Line 01 Press".
    Data arrives as JSON-RPC notifications on MQTT topic
    falcon/line-01/event, method "traffic.observed", params.tags.
    - Show D100 (pressure, bar) as a large gauge-style number
    - Show M20 (motor running) as a green/grey status lamp
    - "Set pressure" spin box sends JSON-RPC "tag.write" for D100
      to falcon/line-01/rpc/req
    Use paho-mqtt in a QThread and Qt signals to update the UI.
  4. 04

    Validate against the replay

    Run the generated app and watch it follow the replayed data live. Refine layout, alarms and formatting until operators are happy.

    Python: PySide6 remote HMI examplepython
    import json, sys, uuid
    import paho.mqtt.client as mqtt
    from PySide6.QtCore import QObject, Signal
    from PySide6.QtWidgets import (QApplication, QLabel, QPushButton,
                                   QSpinBox, QVBoxLayout, QWidget)
    
    GW = "falcon/line-01"
    
    class Bus(QObject):
        tags = Signal(dict)
    
        def __init__(self):
            super().__init__()
            self.c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
            self.c.on_message = lambda c, u, m: self.tags.emit(
                json.loads(m.payload)["params"]["tags"])
            self.c.connect("broker.local", 1883)
            self.c.subscribe(f"{GW}/event")
            self.c.loop_start()
    
        def write(self, tag, value):
            self.c.publish(f"{GW}/rpc/req", json.dumps({
                "jsonrpc": "2.0", "id": str(uuid.uuid4()),
                "method": "tag.write", "params": {"tag": tag, "value": value}}))
    
    app = QApplication(sys.argv)
    bus, win = Bus(), QWidget()
    pressure, motor = QLabel("--"), QLabel("MOTOR")
    setpoint, apply = QSpinBox(maximum=5000), QPushButton("Set pressure")
    apply.clicked.connect(lambda: bus.write("D100", setpoint.value()))
    
    def update(tags):
        if "D100" in tags: pressure.setText(f"{tags['D100']} bar")
        if "M20" in tags:
            motor.setStyleSheet(f"background:{'#2e7d32' if tags['M20'] else '#555'}")
    
    bus.tags.connect(update)
    layout = QVBoxLayout(win)
    for w in (pressure, motor, setpoint, apply): layout.addWidget(w)
    win.setWindowTitle("Line 01 — Remote HMI"); win.show()
    sys.exit(app.exec())
  5. 05

    Go live

    Point the MQTT connection at the site broker and the remote HMI shows the real line. With authorization enabled, it can intervene through tag.write.

Topics, methods and tag names in these examples are illustrative. Adapt them to the product documentation and your actual tags.

AI Agent · Development

Let an AI agent build your remote HMI

AI coding agents such as Claude Code do more than generate code. They run it, check it and fix it on their own. Falcon’s JSON-RPC messages and log replay give an agent a place to test again and again without touching real equipment.

How AI helps OT engineers write software →

  1. Read

    The agent subscribes to the replayed MQTT topics and builds a tag list with data types from the JSON-RPC messages.

  2. Write

    It generates the PySide6 UI and MQTT connection code from your requirements.

  3. Verify

    It calls log.replay to reproduce field data and checks values, status lamps and alarms on screen.

  4. Fix

    When a check fails it edits the code and tests again, and hands over only when every check passes.

ai-agent · remote-hmi

> Build a remote HMI for the stamping press from the line-01 replay log

● Read falcon/line-01/event: found 12 tags including D100, D120, M20

● Generated remote_hmi.py (PySide6 + paho-mqtt)

● Ran log.replay: M20 lamp correct, D100 value off

↻ Fix: D100 must be divided by 10 to show bar; retesting

✓ Done. All 12 tag checks pass

Why Falcon suits AI agents

Self-describing messages

Method names like tag.read and log.replay are obvious to an agent. No proprietary protocol to guess.

Repeatable test data

The same log replays as often as needed, so the agent can confirm each change actually worked.

Standard libraries

MQTT and JSON are what agents know best, so the generated code is dependable.

No live equipment

Development and testing run on replayed data, so an agent mistake never reaches the line.

Get your line speaking MQTT today

Tell us your PLC / HMI models and site requirements. Our sales team replies with an integration assessment and quote within one business day.

Request a Quote