项目:物联网网关
完整 IoT 网关:采集 Modbus / I2C / GPIO 数据,通过 MQTT 上传云端,支持反向控制。
一、目标
- 多种数据源采集
- MQTT 上传(阿里云 / 华为云 / AWS IoT)
- 反向控制(下发指令)
- 本地存储(SQLite)
- Web 配置界面
二、架构
┌─────────────────────────────────────┐
│ 应用进程 │
├─────────────────────────────────────┤
│ MQTT │ Config │ Storage │ Logger │
├───────┴──────────┴───────┴────────┤
│ 数据聚合 & 业务逻辑 │
├─────────────────────────────────────┤
│ Modbus │ I2C │ GPIO │ RS232/485 │
│ 主/从 │ 传感器│ 开关 │ GPS/UART │
└─────────────────────────────────────┘
三、核心代码结构
gateway/
├── main.c
├── config.c
├── config.h
├── mqtt_client.c
├── modbus_master.c
├── sensor_i2c.c
├── storage.c
├── logger.c
├── web_server.c
├── cmd.h
└── Makefile
四、JSON 配置
{
"device": {
"id": "gw001",
"name": "Lab Gateway"
},
"mqtt": {
"host": "broker.example.com",
"port": 1883,
"user": "device",
"pass": "xxx",
"tls": false
},
"modbus": [
{"port": "/dev/ttymxc0", "baud": 9600, "devices": [
{"addr": 1, "func": "input_register", "reg": 100, "qty": 2, "name": "temperature"}
]}
],
"sensors": [
{"type": "htu21d", "bus": 1, "addr": 0x40, "name": "temp_hum"}
],
"upload_interval": 30,
"web_port": 8080
}
五、MQTT 上报
// 上报数据
void publish_sensor(const char *name, double value)
{
char topic[128];
snprintf(topic, sizeof(topic), "devices/%s/data/%s", device_id, name);
char payload[256];
snprintf(payload, sizeof(payload),
"{\"name\":\"%s\",\"value\":%.2f,\"ts\":%lld}",
name, value, (long long)time(NULL));
MQTTClient_message msg = {
.payload = payload,
.payloadlen = strlen(payload),
.qos = 1,
.retained = 0,
};
MQTTClient_publishMessage(client, topic, &msg, NULL);
}
六、MQTT 反向控制
void on_msg(char *topic, MQTTClient_message *msg)
{
char cmd[256];
snprintf(cmd, sizeof(cmd), "%.*s", msg->payloadlen, (char*)msg->payload);
// 解析 JSON
cJSON *root = cJSON_Parse(cmd);
cJSON *act = cJSON_GetObjectItem(root, "action");
if (strcmp(act->valuestring, "set") == 0) {
cJSON *relay = cJSON_GetObjectItem(root, "relay");
cJSON *val = cJSON_GetObjectItem(root, "value");
set_relay(relay->valueint, val->valueint);
}
cJSON_Delete(root);
MQTTClient_freeMessage(&msg);
MQTTClient_free(topic);
}
七、Modbus Master
// 用 libmodbus
modbus_t *ctx = modbus_new_rtu("/dev/ttymxc0", 9600, 'N', 8, 1);
modbus_set_slave(ctx, 1);
modbus_connect(ctx);
uint16_t tab_reg[32];
int rc = modbus_read_input_registers(ctx, 100, 2, tab_reg);
if (rc == 2) {
float temp = tab_reg[0] / 10.0;
publish_sensor("temperature", temp);
}
modbus_close(ctx);
modbus_free(ctx);
八、数据采集调度
static void *collector_thread(void *arg)
{
while (running) {
// Modbus
for (int i = 0; i < config.modbus_count; i++) {
poll_modbus(&config.modbus[i]);
}
// I2C 传感器
for (int i = 0; i < config.sensor_count; i++) {
poll_i2c_sensor(&config.sensors[i]);
}
sleep(config.upload_interval);
}
return NULL;
}
九、本地存储(SQLite)
#include <sqlite3.h>
sqlite3 *db;
sqlite3_open("/var/lib/gateway.db", &db);
sqlite3_exec(db,
"CREATE TABLE IF NOT EXISTS data ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"ts INTEGER, name TEXT, value REAL)",
NULL, NULL, NULL);
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db,
"INSERT INTO data (ts, name, value) VALUES (?,?,?)", -1, &stmt, NULL);
sqlite3_bind_int64(stmt, 1, time(NULL));
sqlite3_bind_text(stmt, 2, "temp", -1, SQLITE_STATIC);
sqlite3_bind_double(stmt, 3, 25.6);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
sqlite3_close(db);
十、Web 配置界面
用 mongoose + 静态文件:
if (mg_match(hm->uri, mg_str("/api/config"), NULL)) {
if (hm->method.len == 4 && !memcmp(hm->method.buf, "GET", 3)) {
char *json = config_to_json();
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s", json);
free(json);
} else if (hm->method.len == 4 && !memcmp(hm->method.buf, "POST", 4)) {
// 解析 body
char body[1024] = { 0 };
memcpy(body, hm->body.buf, hm->body.len);
config_from_json(body);
save_config();
mg_http_reply(c, 200, "", "OK");
}
}
十一、设备接入云端
| 云平台 | 协议 |
|---|---|
| AWS IoT Core | MQTT over TLS |
| 阿里云 LinkKit | MQTT |
| 华为云 IoTDA | MQTT/HTTPS/LwM2M |
| 腾讯云 IoT Explorer | MQTT |
| Azure IoT Hub | MQTT/AMQP |
| EMQ X | 自建 MQTT broker |
| Mosquitto | 自建 |
十二、远程升级
# OTA:监听 MQTT 升级指令
if (msg topic == "device/upgrade") {
if (confirm) {
wget http://server/firmware.swu
swupdate -i firmware.swu -e stable
}
}
十三、调试
# MQTT 调试
mosquitto_sub -h broker -t '#' -v
mosquitto_pub -h broker -t 'cmd' -m '...'
# Modbus 调试
mbpoll -m rtu -b 9600 -a 1 /dev/ttymxc0 -r 100
# 网络
tcpdump -i eth0 -w cap.pcap
wireshark cap.pcap