This document explains everything you need to install, how to run the system, and how to test that the full pipeline works end-to-end.
- Express.js backend (HTTP API)
- C gateway (HTTP ⇄ MQTT bridge)
- Mosquitto MQTT broker (message bus for the robot)
IMPORTANT: This project assumes you’re running on a Linux machine (Ubuntu/Debian) and running all components locally on the same machine.
High level architecture (all on one machine):
[Express Backend] <----HTTP----> [C Gateway] <----MQTT----> [Mosquitto Broker]
^ ^
| |
curl / frontend Robot / test clients
Message directions:
-
Commands: Backend → Gateway → MQTT → Robot
- Backend sends
start/stop→ Gateway publishes torobot/commandtopic.
- Backend sends
-
Telemetry: Robot → MQTT → Gateway → Backend
- Robot publishes status → Gateway forwards JSON to backend
/api/telemetry.
- Robot publishes status → Gateway forwards JSON to backend
Install build tools:
sudo apt update
sudo apt install -y build-essentialsudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquittoThis installs:
- MQTT broker (
mosquitto) on port1883 - MQTT test tools:
mosquitto_pub,mosquitto_sub
sudo apt install -y \
libcurl4-openssl-dev \
libmicrohttpd-dev \
libmosquitto-devThese provide:
curl/curl.h+ libcurl (HTTP client)microhttpd.h+ libmicrohttpd (HTTP server)- libmosquitto (MQTT client library)
If you don’t already have Node.js:
sudo apt install -y nodejs npmThis is our C gateway project:
project-root/
├── Makefile
├── include/
│ ├── config.h
│ ├── gateway.h
│ ├── signals.h
│ ├── http_client.h
│ ├── mqtt_client.h
│ ├── http_server.h
│
└── src/
├── main.c
│
├── gateway/
│ └── gateway.c
│
├── mqtt/
│ └── mqtt_client.c
│
├── http/
│ ├── http_client.c
│ └── http_server.c
│
└── platform/
└── signals.c
This is our test express.js http backend:
express-backend/
├── package.json
├── server.js
└── .env
Make sure this file has these values (for fully local setup):
// config.h
#ifndef CONFIG_H
#define CONFIG_H
// MQTT broker on same machine
#define MQTT_HOST "localhost"
#define MQTT_PORT 1883
#define MQTT_TOPIC_COMMAND "robot/command"
#define MQTT_TOPIC_TELEMETRY "robot/telemetry"
// HTTP server (this gateway)
#define GATEWAY_HTTP_PORT 8000
// Backend (Express.js) URL that receives telemetry
#define BACKEND_URL "http://localhost:8080/api/telemetry"
// Max size for HTTP request bodies (JSON)
#define MAX_BODY_SIZE 1024
#endif // CONFIG_HIn express-backend/.env:
PORT=8080
GATEWAY_URL=http://localhost:8000/command- Backend listens on
http://localhost:8080 - Backend forwards commands to the C gateway at
http://localhost:8000/command
From the C project root (where the Makefile is):
makeThis compiles all src/*.c files into an executable named:
c_gateway
If you need to clean and rebuild:
make clean
makeYou’ll typically use three terminals:
If you already enabled it earlier, it should be running. To be safe:
sudo systemctl start mosquitto
sudo systemctl status mosquittoYou don’t need to leave this terminal open if the service is managed by systemd.
Go to your backend folder:
cd express-backend
npm install # first time only
npm startYou should see something like:
[BACKEND] Starting server...
[BACKEND] Gateway URL: http://localhost:8000/command
[BACKEND] Listening on http://localhost:8080
Optional health check (in another terminal):
curl http://localhost:8080/healthExpected response (or similar):
{"status":"ok","gateway":"http://localhost:8000/command"}From your C project root:
./c_gatewayExpected output:
[GATEWAY] Starting...
[MQTT] Connecting to localhost:1883
[MQTT] Subscribed to robot/telemetry
[HTTP SERVER] Listening on port 8000
[GATEWAY] Running. Press Ctrl+C to exit.
Now the whole system is running:
- Mosquitto broker
- Express backend
- C gateway
We’ll simulate a “robot” by subscribing to the robot/command topic.
mosquitto_sub -h localhost -t robot/command -q 1Keep this running. It will print any command the gateway publishes.
In another terminal, run:
curl -X POST http://localhost:8080/api/start-
Robot subscriber (mosquitto_sub) terminal:
{"action":"start"} -
Gateway terminal:
[HTTP SERVER] /command body: {"action":"start"} [MQTT] Published to robot/command: {"action":"start"} -
Backend terminal:
[BACKEND] Forwarding 'start' to gateway...
You can also test stop:
curl -X POST http://localhost:8080/api/stopExpect to see:
{"action":"stop"}in the mosquitto_sub terminal.
If this works, the command path is good ✅
Now we simulate the robot sending telemetry.
In a new terminal:
mosquitto_pub -h localhost -t robot/telemetry \
-m '{"status":"cleaning","battery":82}'-
Gateway terminal:
[MQTT] Message on topic 'robot/telemetry' [MQTT] Telemetry received: {"status":"cleaning","battery":82} [HTTP CLIENT] POST http://localhost:8080/api/telemetry [HTTP CLIENT] Body: {"status":"cleaning","battery":82} [HTTP CLIENT] Response status: 200 -
Backend terminal:
[BACKEND] Telemetry: { status: 'cleaning', battery: 82 }
If this shows up, your telemetry path is working
-
curl/curl.h: No such file or directory→ Install dev package:sudo apt install -y libcurl4-openssl-dev
-
microhttpd.h: No such file or directory→ Install:sudo apt install -y libmicrohttpd-dev
-
undefined reference to mosquitto_*→ Install:sudo apt install -y libmosquitto-dev
-
Gateway can’t connect to MQTT (
Connection refused) → Check Mosquitto status:sudo systemctl status mosquitto
-
Backend says “connection refused” when hitting gateway → Make sure
./c_gatewayis running andGATEWAY_HTTP_PORTinconfig.hmatchesGATEWAY_URLin.env(port 8000).
Once both tests pass, it demonstrates:
-
Backend → Gateway → MQTT
- HTTP
POST /api/start→ gateway → publishes MQTT command torobot/command.
- HTTP
-
MQTT → Gateway → Backend
mosquitto_pubonrobot/telemetry→ gateway → HTTPPOST /api/telemetry→ backend.