LabWired The easy way to build hardware

Simulating a cellular modem and MQTT without a full network

Category: Engineering

Telematics firmware does not need a tower, a SIM, or a public broker to prove the interesting part: the MCU talks AT, gets a GNSS fix, publishes JSON, and someone can collect that payload. We built that surface in LabWired — deliberately not a full cellular network.

A CLM-style device looks simple on a slide: modem, GPS, cloud. On the bench it is SIMs, antennas, broker accounts, and “works once” demos. The firmware path that matters for bring-up is narrower:

  1. Drive the modem with Quectel-style AT (AT+QGPS*, AT+QMT*).
  2. Parse a GNSS fix.
  3. Publish a small JSON payload (lat/lon, source).
  4. Collect that message for a human, a test, or an agent.

That is the product surface. Not EPC, not TLS termination, not a real MQTT 3.1.1 wire broker.

What we simulate (and what we don’t) {#what-we-simulate}

In scopeOut of scope
BG770A AT surface over UART (QGPS, QMT open/conn/pub/sub)Full LTE-M/NB-IoT air interface / RAN / EPC
GNSS reply shapes (+QGPSLOC) with lab coordinatesReal constellation dynamics
SimMqttFabric — land publishes, inspect/collectReal MQTT broker, auth, retained sessions
Path-loss CSQ from a shared RF mediumAccurate link-budget engineering
Headless io-smoke in CI (UART + fabric payload)Carrier certification

Honesty is the feature: demos stay honest about stand-ins, and CI still gates the firmware path that will run on silicon.

The stack: MCU, modem AT, AirBus {#the-stack}

The demo board is an STM32H735 virtual MCU:

The network peer is not “the internet.” It is SimMqttFabric, on the lab AirBus next to nRF/BLE virtual air and the shared path-loss RfMedium:

MCU ──USART──► BG770A AT model

                  ├── RfMedium (range → CSQ)
                  └── SimMqttFabric (QMTPUB → collect)

One bind path: attach_lab_air. CLI mints a private lab air when a modem is present; the playground rebinds the same API to a shared AirBus. Multi-node World can put every UE on one fabric so publishes share a collection surface — publisher on one node, subscriber on another.

Send and collect {#send-and-collect}

Firmware does what production firmware does:

AT+QGPS=1
AT+QGPSLOC=0          → parse lat/lon
AT+QMTOPEN=0,"broker…",1883
AT+QMTCONN=0,"client"
AT+QMTPUB=0,0,0,0,"telematics/location",N
  > {"lat":…,"lon":…,"src":"qgpsloc"}
  Ctrl-Z
→ +QMTPUB: 0,0,0

On submit, the payload is retained on the fabric. That is collect:

Optional: QMTSUB on the same fabric gets +QMTRECV (loopback or a second UE). Still not a carrier — enough for multi-node “message arrived” stories.

Radio quality without a radio {#radio-quality}

When an RfMedium is attached, UE↔cell distance (SimInput Range) drives path loss → dBm → CSQ. Drag range far enough and you get no-service.

MQTT respects that: with RF below the floor, open fails (+QMTOPEN: id,1) and publish does not pretend success. Healthy CSQ: open, connect, and publish follow the AT happy path. Weak radio → no cloud messages.

Try it {#try-it}

Playground board id h735-telematics-lab — Run, open Serial for the AT log, watch the fabric strip collect the MQTT payload.

Live telematics lab. Open full-screen ↗

CLI (from labwired-core):

cargo build -p h735-telematics-lab --release --target thumbv7em-none-eabi
cargo run -q -p labwired-cli -- test \
  --script examples/h735-telematics-lab/io-smoke.yaml \
  --output-dir /tmp/h735-out --no-uart-stdout

Two UEs (publisher + subscriber) on one fabric: examples/h735-telematics-lab/env-two-ue-smoke.yaml.

Receipts {#receipts}

The same model powers unit tests for fabric publish, loopback +QMTRECV, and RF-gated open; example io-smoke asserting GPS + publish and fabric payload; dual-UE fan-out; and source under examples/h735-telematics-lab/ plus SimMqttFabric in core.

Send messages. Collect data. Don’t fake a network you don’t have. That is the bar for modem + MQTT in LabWired — enough to develop and CI telematics firmware before anyone finds a SIM tray.

Andrii Shylenko
Andrii Shylenko

Founder, LabWired.