首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >服务器机房环境记录仪开发:以太网变送器数据本地存储与远端上云方案

服务器机房环境记录仪开发:以太网变送器数据本地存储与远端上云方案

原创
作者头像
HONSOR盛世宏博
发布于 2026-09-24 13:20:30
发布于 2026-09-24 13:20:30
810
举报

服务器机房环境记录仪开发:以太网变送器数据本地存储与远端上云方案

关键词:以太网变送器、环境记录仪开发、本地存储架构、远端上云、断网续传、多协议上报、边缘计算、腾讯云物联网平台、数据同步、混合云存储 标签:#物联网 #Modbus #TCP/IP #UDP #POE供电 #腾讯云 #Python #InfluxDB #以太网温湿度传感器 #网口温湿度变送器 #机房监控 #边缘计算

一、产品定义:从"传感器"到"记录仪"的跨越

前几篇讲的是如何把现成的 RJ45 温湿度变送器接入系统。本篇换个视角——如果你要自己开发一款以太网环境记录仪,核心需求是:

  • 机房现场持续采集温湿度(及其他环境量)
  • 本地可靠存储(断网不丢数据,至少 30 天)
  • 远端上云(腾讯云 IoT / 自建时序库 / 双通道)
  • 上电即工作,Web 配置,零运维

这不是简单的"传感器 + MCU + 网口"拼装,而是一台边缘数据记录设备。本文从硬件选型、固件架构、存储设计、上云通道四个维度展开。


二、硬件平台选型

2.1 核心板方案对比

方案

SoC

内存

存储

网络

功耗

开发难度

适合场景

ESP32 + LAN8720​

双核 240MHz

520KB SRAM + PSRAM

SPI Flash 4~16MB

10/100M RMII

<2W

低(ESP-IDF/Arduino)

低成本单点记录仪

树莓派 CM4​

BCM2711 4核 1.5GHz

1~8GB

eMMC/SD

千兆

5~8W

低(Linux 全栈)

多通道、高算力

i.MX6ULL + Linux​

Cortex-A7 800MHz

256~512MB DDR

NAND/eMMC

10/100M

3~5W

中(Yocto/Buildroot)

工业级、长生命周期

全志 F1C200s​

ARM9 900MHz

64MB DDR

SPI NAND

10/100M

2~3W

中

超低成本、精简功能

STM32H7 + LAN8742​

Cortex-M7 480MHz

1MB SRAM

外部 QSPI Flash

10/100M

<1W

高(裸机/RT-Thread)

超低功耗、实时性要求

推荐选择:

  • 快速原型/小批量:树莓派 CM4 + 底板(PoE 模块、传感器接口),Linux 上直接跑 Python/C 服务,开发效率最高。
  • 量产/工业级:i.MX6ULL + Yocto 定制系统,长生命周期、宽温、稳定供货。
  • 超低成本:ESP32 + LAN8720,FreeRTOS + lwIP,适合单点采集、不上跑复杂逻辑。

2.2 传感器接口

记录仪不只是温湿度,典型需要接入:

传感器

接口

说明

温湿度

I²C(SHT30/SHT35)或 1-Wire(DS18B20)

精度 ±0.3℃/±2%RH

露点

算法计算

T + RH → 露点公式

气压

I²C(BMP280/BME280)

可选

水浸

干接点/模拟量

开关量输入

烟雾

I²C(SGP30)或 4~20mA

可选

门磁

GPIO 中断

状态变化触发记录

2.3 存储方案

层级

介质

容量

用途

L1:掉电保护缓冲

FRAM / 超级电容 + SRAM

几 KB

最近一条记录,断电不丢

L2:高速缓存

SPI Flash / eMMC 分区

几十 MB

环形缓冲,最近数万条

L3:长期存储

SD 卡(工业级) / eMMC

8~64GB

历史数据、补传队列

L4:远端

腾讯云 IoT / InfluxDB

无限

云端持久化、分析


三、固件架构

3.1 软件分层

代码语言:javascript
复制
┌─────────────────────────────────────────────────────────────┐
│                     应用层(业务逻辑)                       │
├─────────────────────────────────────────────────────────────┤
│  采集调度 │ 本地存储 │ 网络管理 │ 云端通道 │ Web 配置      │
│  (采样周  │ (环形缓  │ (WiFi/   │ (MQTT/   │ (REST/      │
│   期控制) │  冲管理) │  以太网)  │  HTTPS)  │  mDNS)      │
├─────────────────────────────────────────────────────────────┤
│                     中间件层                                │
├─────────────────────────────────────────────────────────────┤
│  lwIP │ Flash FS │ SQLite │ TLS │ JSON │ Modbus Slave    │
├─────────────────────────────────────────────────────────────┤
│                     系统层                                  │
├─────────────────────────────────────────────────────────────┤
│  Linux (CM4/i.MX6ULL) 或 FreeRTOS (ESP32/STM32)           │
├─────────────────────────────────────────────────────────────┤
│                     硬件抽象层(HAL)                        │
├─────────────────────────────────────────────────────────────┤
│  GPIO │ I²C │ SPI │ Ethernet MAC/PHY │ RTC │ Watchdog     │
└─────────────────────────────────────────────────────────────┘

3.2 核心线程/任务划分

代码语言:javascript
复制
/* 以 FreeRTOS + ESP32 为例,展示任务划分 */

void app_main() {
    /* 硬件初始化 */
    i2c_init();
    spi_flash_init();
    ethernet_init();
    rtc_init();
    watchdog_init();
    
    /* 创建队列 */
    QueueHandle_t sensor_queue = xQueueCreate(10, sizeof(sensor_record_t));
    QueueHandle_t storage_queue = xQueueCreate(100, sizeof(storage_record_t));
    QueueHandle_t cloud_queue = xQueueCreate(50, sizeof(cloud_record_t));
    
    /* 启动任务 */
    xTaskCreate(sensor_task,     "sensor",     4096, sensor_queue,  4, NULL);
    xTaskCreate(storage_task,    "storage",    8192, storage_queue,  3, NULL);
    xTaskCreate(network_task,    "network",    4096, NULL,           3, NULL);
    xTaskCreate(cloud_task,      "cloud",      8192, cloud_queue,    2, NULL);
    xTaskCreate(web_server_task, "web",        6144, NULL,           2, NULL);
    xTaskCreate(watchdog_task,   "watchdog",   2048, NULL,           5, NULL);
}

四、本地存储设计

4.1 存储格式选择

方案

优点

缺点

适用场景

二进制环形缓冲​

写入快、空间紧凑、掉电安全(顺序写)

查询不便、需自定义工具

高频采样(1~5s)

SQLite​

SQL 查询、事务、成熟

写入开销大、Flash 磨损

低频采样(≥30s)、需本地查询

LittleFS/SPIFFS​

文件接口、磨损均衡

随机写性能差

配置存储、日志

混合:二进制 + SQLite 索引

兼顾写入速度和查询

实现复杂

专业记录仪

推荐:高频采样用二进制环形缓冲(顺序写 Flash),配合 SQLite 做索引和元数据。

4.2 二进制环形缓冲布局

代码语言:javascript
复制
Flash 分区(以 16MB SPI Flash 为例):

0x000000 ~ 0x00FFFF  引导区 + 配置(64KB)
0x010000 ~ 0x01FFFF  元数据区:环形头/尾指针、序列号、校准参数(64KB)
0x020000 ~ 0x7FFFFF  主数据区:约 8MB,每条 32 字节(约 26 万条)
0x800000 ~ 0xFFFFFF  备用/扩展区

每条记录 32 字节:
┌────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ 时标   │ 温度   │ 湿度   │ 露点   │ 气压   │ 状态   │ CRC16  │
│ 4B     │ 2B×10  │ 2B×10  │ 2B×10  │ 2B     │ 1B     │ 2B     │
└────────┴────────┴────────┴────────┴────────┴────────┴────────┘
代码语言:javascript
复制
/* storage.c - 存储核心逻辑 */

#include "esp_flash.h"
#include "crc16.h"

#define DATA_START  0x020000
#define DATA_END    0x800000
#define RECORD_SIZE 32
#define MAX_RECORDS ((DATA_END - DATA_START) / RECORD_SIZE)

typedef struct {
    uint32_t timestamp;
    int16_t  temperature;   /* ×10 */
    int16_t  humidity;      /* ×10 */
    int16_t  dewpoint;      /* ×10 */
    int16_t  pressure;      /* ×0.1 hPa */
    uint8_t  status;        /* bit0=sensor_ok, bit1=sd_card, bit2=cloud_connected */
    uint16_t crc;
} record_t;

typedef struct {
    uint32_t head;      /* 最旧记录位置 */
    uint32_t tail;      /* 下次写入位置 */
    uint32_t count;     /* 当前记录数 */
    uint32_t total_written;
    uint32_t write_errors;
} storage_meta_t;

static storage_meta_t meta;
static SemaphoreHandle_t storage_mutex;

esp_err_t storage_write_record(const record_t *rec) {
    xSemaphoreTake(storage_mutex, portMAX_DELAY);
    
    record_t to_write = *rec;
    to_write.crc = crc16((uint8_t*)&to_write, RECORD_SIZE - 2);
    
    esp_err_t ret = esp_flash_write(NULL, &to_write, 
                                     DATA_START + meta.tail * RECORD_SIZE, 
                                     RECORD_SIZE);
    if (ret != ESP_OK) {
        meta.write_errors++;
        xSemaphoreGive(storage_mutex);
        return ret;
    }
    
    meta.tail = (meta.tail + 1) % MAX_RECORDS;
    meta.count = (meta.count < MAX_RECORDS) ? meta.count + 1 : MAX_RECORDS;
    
    if (meta.tail == meta.head && meta.count == MAX_RECORDS) {
        meta.head = (meta.head + 1) % MAX_RECORDS;  /* 覆盖最旧 */
    }
    
    meta.total_written++;
    storage_save_meta();  /* 持久化元数据 */
    
    xSemaphoreGive(storage_mutex);
    return ESP_OK;
}

esp_err_t storage_read_range(uint32_t start_seq, uint32_t end_seq, 
                              record_t *out, uint32_t *count) {
    /* 按序列号范围读取 */
    uint32_t idx = meta.head;
    uint32_t found = 0;
    
    for (uint32_t i = 0; i < meta.count && found < *count; i++) {
        record_t rec;
        esp_flash_read(NULL, &rec, DATA_START + idx * RECORD_SIZE, RECORD_SIZE);
        
        if (rec.crc != crc16((uint8_t*)&rec, RECORD_SIZE - 2)) {
            idx = (idx + 1) % MAX_RECORDS;
            continue;  /* 坏块跳过 */
        }
        
        uint32_t seq = rec.timestamp;  /* 简化:用时间戳作序列 */
        if (seq >= start_seq && seq <= end_seq) {
            out[found++] = rec;
        }
        idx = (idx + 1) % MAX_RECORDS;
    }
    
    *count = found;
    return ESP_OK;
}

4.3 掉电保护

关键设计:

  • 超级电容(0.1F/5.5V):维持 MCU 和 Flash 供电 3~5s,确保最后一条记录写完。
  • FRAM 缓冲:最近 10 条记录同时写 FRAM(无限擦写寿命),上电后检查 FRAM 与 Flash 一致性。
  • 写前校验:每次写入后回读 CRC 校验,失败标记坏块并重试。

五、远端上云方案

5.1 上云通道选择

通道

协议

优势

劣势

适用场景

腾讯云 IoT Explorer​

MQTT over TLS

托管、规则引擎、小程序、告警

需联网注册设备、有费用

快速上云、多租户

腾讯云 IoT Hub​

MQTT/CoAP

更底层、自定义强

开发量大

工业级、私有协议

自建 InfluxDB + HTTPS​

Line Protocol / JSON

完全自主、无厂商锁定

需自建高可用

企业私有云

MQTT 公有 Broker​

MQTT

简单、开源生态

不可靠、无 SLA

测试/非关键

双通道:云 + 本地服务器

MQTT + HTTP

冗余、断网本地存

复杂度高

关键机房

推荐:腾讯云 IoT Explorer(设备接入 + 规则引擎转发到时序数据库)+ 本地 HTTP 推送(可选),双通道冗余。

5.2 腾讯云 IoT Explorer 接入

代码语言:javascript
复制
"""
cloud_uploader.py - 腾讯云 IoT Explorer MQTT 上云
运行在记录仪本地(Linux/Python)或作为边缘网关服务
"""

import paho.mqtt.client as mqtt
import ssl
import json
import time
import hmac
import hashlib
import random
from datetime import datetime

class TencentCloudIoT:
    def __init__(self, product_id, device_name, device_secret, region="ap-guangzhou"):
        self.product_id = product_id
        self.device_name = device_name
        self.device_secret = device_secret
        self.region = region
        self.broker = f"{product_id}.iotcloud.tencentdevices.com"
        self.port = 8883
        self.client = mqtt.Client(client_id=self._gen_client_id())
        self._setup_tls()
        self._setup_auth()
        self.connected = False
        self.pending_queue = []  # 未确认消息
    
    def _gen_client_id(self):
        # 格式: {product_id}{device_name}
        return f"{self.product_id}{self.device_name}"
    
    def _setup_tls(self):
        self.client.tls_set(ca_certs="root_cert.pem",
                           cert_reqs=ssl.CERT_REQUIRED,
                           tls_version=ssl.PROTOCOL_TLSv1_2)
    
    def _setup_auth(self):
        # 用户名: {product_id}{device_name};{sdkappid};{connid};{expiry}
        # 密码: 签名
        username = f"{self.product_id}{self.device_name};12010126;12345;{int(time.time())+3600 * 24}"
        password = self._sign(username)
        self.client.username_pw_set(username, password)
    
    def _sign(self, username):
        # HMAC-SHA256(username, device_secret)
        return hmac.new(
            self.device_secret.encode(),
            username.encode(),
            hashlib.sha256
        ).hexdigest()
    
    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            self.connected = True
            # 订阅属性下发
            client.subscribe(f"$thing/down/property/{self.product_id}/{self.device_name}")
            # 重发未确认消息
            self._resend_pending()
        else:
            self.connected = False
    
    def on_message(self, client, userdata, msg):
        # 处理云端下发的属性设置/服务调用
        payload = json.loads(msg.payload)
        self._handle_downlink(payload)
    
    def publish_telemetry(self, temp, hum, dewpoint, status):
        if not self.connected:
            self.pending_queue.append({
                "temp": temp, "hum": hum, "dewpoint": dewpoint,
                "status": status, "ts": time.time()
            })
            return False
        
        payload = {
            "method": "report",
            "clientToken": f"{self.device_name}_{int(time.time()*1000)}",
            "params": {
                "temperature": temp,
                "humidity": hum,
                "dewpoint": dewpoint,
                "status": status,
                "timestamp": int(time.time())
            }
        }
        
        topic = f"$thing/up/property/{self.product_id}/{self.device_name}"
        result = self.client.publish(topic, json.dumps(payload), qos=1)
        return result.rc == mqtt.MQTT_ERR_SUCCESS
    
    def _resend_pending(self):
        while self.pending_queue and self.connected:
            item = self.pending_queue.pop(0)
            self.publish_telemetry(item["temp"], item["hum"], 
                                    item["dewpoint"], item["status"])
    
    def _handle_downlink(self, payload):
        # 处理云端下发的设定值、重启指令等
        if "params" in payload:
            params = payload["params"]
            if "set_temperature" in params:
                # 写本地寄存器/触发动作
                pass
            if "reset" in params:
                # 软重启
                pass
    
    def start(self):
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message
        self.client.connect(self.broker, self.port, keepalive=60)
        self.client.loop_start()

5.3 数据同步策略

代码语言:javascript
复制
┌─────────────────────────────────────────────────────────────┐
│                    数据同步状态机                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  采样 → 写本地存储 → 尝试上云                               │
│       │              │                                      │
│       │              ├── 成功 → 标记已同步                   │
│       │              └── 失败 → 加入待同步队列               │
│       │                                                     │
│  网络恢复检测(每 30s)                                      │
│       │                                                     │
│       ├── 有网 → 从待同步队列取数据上云                      │
│       │       ├── 成功 → 标记已同步,继续取                  │
│       │       └── 失败 → 保持队列,等待重试                  │
│       │                                                     │
│       └── 无网 → 仅本地存储,等待网络恢复                    │
│                                                             │
│  补传策略:                                                  │
│  - 按时间顺序补传,避免时序错乱                              │
│  - 批量补传(每批 50 条),限速(每批间隔 1s)              │
│  - 补传完成条件:队列空 或 追上实时                          │
│  - 云端去重:消息携带 seq/timestamp,云端幂等                │
└─────────────────────────────────────────────────────────────┘
代码语言:javascript
复制
"""
sync_manager.py - 本地存储与云端同步管理
"""

import asyncio
import time
from dataclasses import dataclass

@dataclass
class SyncState:
    last_synced_seq: int = 0
    last_sync_attempt: float = 0.0
    sync_in_progress: bool = False
    pending_count: int = 0
    consecutive_failures: int = 0

class SyncManager:
    def __init__(self, storage, cloud, batch_size=50, batch_interval=1.0):
        self.storage = storage
        self.cloud = cloud
        self.batch_size = batch_size
        self.batch_interval = batch_interval
        self.state = SyncState()
    
    async def sync_loop(self):
        """主同步循环"""
        while True:
            try:
                if not self.cloud.connected:
                    await asyncio.sleep(5)
                    continue
                
                if self.state.sync_in_progress:
                    await asyncio.sleep(1)
                    continue
                
                # 查询未同步记录数
                unsynced = self.storage.get_unsynced_count()
                if unsynced == 0:
                    await asyncio.sleep(10)
                    continue
                
                self.state.sync_in_progress = True
                self.state.pending_count = unsynced
                
                # 批量读取未同步记录
                records = self.storage.read_unsynced(self.batch_size)
                
                for rec in records:
                    success = self.cloud.publish_telemetry(
                        rec.temperature / 10.0,
                        rec.humidity / 10.0,
                        rec.dewpoint / 10.0,
                        rec.status
                    )
                    if success:
                        self.storage.mark_synced(rec.seq)
                        self.state.last_synced_seq = rec.seq
                        self.state.consecutive_failures = 0
                    else:
                        self.state.consecutive_failures += 1
                        break
                
                self.state.sync_in_progress = False
                self.state.last_sync_attempt = time.time()
                
                # 限速
                await asyncio.sleep(self.batch_interval)
                
            except Exception as e:
                print(f"sync error: {e}")
                self.state.sync_in_progress = False
                await asyncio.sleep(5)

六、Web 配置与运维

6.1 嵌入式 Web 服务

记录仪内置 Web 服务器,通过浏览器直接配置:

  • 网络配置:静态 IP / DHCP、DNS、网关
  • 采集配置:采样周期、传感器校准参数
  • 云端配置:腾讯云 IoT 产品/设备信息、MQTT 参数
  • 存储管理:查看存储状态、手动触发补传、格式化
  • 系统信息:固件版本、运行时间、存储用量、网络状态
代码语言:javascript
复制
"""
web_server.py - 轻量 Web 配置界面(aiohttp)
"""

from aiohttp import web
import json

routes = web.RouteTableDef()

@routes.get('/api/status')
async def api_status(request):
    """系统状态"""
    return web.json_response({
        "uptime_s": get_uptime(),
        "firmware": FIRMWARE_VERSION,
        "storage": {
            "total_records": storage.get_total_count(),
            "unsynced": storage.get_unsynced_count(),
            "health": storage.get_health()
        },
        "network": {
            "ip": get_ip_address(),
            "rssi": get_wifi_rssi(),  # 如果有 WiFi
            "cloud_connected": cloud.connected
        },
        "sensors": {
            "temperature": current_reading.temp,
            "humidity": current_reading.hum,
            "last_sample_ts": current_reading.ts
        }
    })

@routes.post('/api/config/network')
async def api_config_network(request):
    """网络配置"""
    data = await request.json()
    # 验证参数
    # 写入配置(持久化到 Flash)
    # 触发网络重连
    return web.json_response({"status": "ok"})

@routes.post('/api/config/cloud')
async def api_config_cloud(request):
    """云端配置"""
    data = await request.json()
    # 保存腾讯云 IoT 凭证
    # 重启 MQTT 连接
    return web.json_response({"status": "ok"})

@routes.post('/api/storage/backfill')
async def api_storage_backfill(request):
    """手动触发补传"""
    asyncio.create_task(sync_manager.force_sync())
    return web.json_response({"status": "started"})

@routes.get('/api/storage/export')
async def api_storage_export(request):
    """导出历史数据为 CSV"""
    start = request.query.get('start')
    end = request.query.get('end')
    records = storage.read_time_range(start, end)
    # 生成 CSV
    csv_data = generate_csv(records)
    return web.Response(text=csv_data, content_type='text/csv')

app = web.Application()
app.add_routes(routes)
# 静态文件(前端页面)
app.router.add_static('/', path='web_root', name='static')

web.run_app(app, host='0.0.0.0', port=80)

前端用 Vue/React 或纯 HTML + fetch,轻量即可。


七、工程落地检查项

7.1 硬件

  • [ ] 网口变压器选型(PoE 需支持 802.3af)
  • [ ] Flash 寿命评估:按采样周期计算擦写次数
  • [ ] 超级电容容量计算:维持写操作完成
  • [ ] 看门狗电路:硬件看门狗 + 喂狗逻辑
  • [ ] RTC:断电后时间保持(纽扣电池或超级电容)
  • [ ] EMC/ESD:网口防雷、传感器接口保护

7.2 固件

  • [ ] 启动流程:Bootloader → 自检 → 配置加载 → 服务启动
  • [ ] OTA 升级:HTTPS 下载 + 签名验证 + 回滚
  • [ ] 日志系统:环形日志缓冲,可导出
  • [ ] 故障自恢复:异常重启计数、自动恢复出厂(长按按钮)
  • [ ] 多协议:Modbus TCP Slave(可选,用于本地采集)

7.3 云端

  • [ ] 设备注册:腾讯云 IoT 产品/设备创建
  • [ ] 数据模板:属性定义(温度、湿度、露点、状态)
  • [ ] 规则引擎:转发到时序数据库 / 云函数
  • [ ] 告警策略:阈值告警、离线告警
  • [ ] 数据保留策略:热数据 / 冷数据分层

7.4 测试

  • [ ] 老化测试:连续运行 30 天,验证存储不溢出
  • [ ] 断网测试:断网 7 天,恢复后补传完整
  • [ ] 压力测试:高频采样(1s)下存储和云端同步
  • [ ] 异常注入:断电、网线拔插、云端不可达
  • [ ] 校准测试:传感器偏差校准后数据一致性

八、典型坑

  1. Flash 磨损:高频采样 + 无磨损均衡 = 几周报废 Flash。必须用环形缓冲或文件系统磨损均衡。
  2. 时间戳漂移:无 NTP 时设备时钟每天漂移数秒,长期断网后时间偏差大。RTC + NTP 定期同步。
  3. MQTT QoS 1 消息堆积:网络抖动时未确认消息堆积内存,需限制队列深度。
  4. 云端去重缺失:补传时重复数据导致曲线异常,云端需按 seq/timestamp 幂等。
  5. OTA 变砖:升级中断导致设备无法启动,需 A/B 分区 + 回滚。
  6. 配置丢失:配置存在 Flash 但未做版本管理,固件升级后配置格式不兼容。
  7. PoE 供电不足:多传感器接入时总功耗超 PoE Class 预算,设备反复重启。
  8. Web 端口冲突:80 端口被其他服务占用,需配置端口或反向代理。
  9. 时区处理:设备用 UTC,云端用本地时区,面板显示错乱。
  10. 证书过期:TLS 根证书过期导致 MQTT 连接失败,需 OTA 更新证书或支持跳过验证(不安全)。

九、小结

开发一款以太网环境记录仪,核心在三个设计决策:存储架构决定数据可靠性、上云通道决定可用性、Web 配置决定可运维性。本地存储用环形缓冲保证高频写入和掉电安全,上云用腾讯云 IoT Explorer 托管设备生命周期和规则引擎,Web 配置让现场零运维。三者配合,记录仪从"能采"变成"能用、好用、可靠用"。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 服务器机房环境记录仪开发:以太网变送器数据本地存储与远端上云方案
    • 一、产品定义:从"传感器"到"记录仪"的跨越
    • 二、硬件平台选型
      • 2.1 核心板方案对比
      • 2.2 传感器接口
      • 2.3 存储方案
    • 三、固件架构
      • 3.1 软件分层
      • 3.2 核心线程/任务划分
    • 四、本地存储设计
      • 4.1 存储格式选择
      • 4.2 二进制环形缓冲布局
      • 4.3 掉电保护
    • 五、远端上云方案
      • 5.1 上云通道选择
      • 5.2 腾讯云 IoT Explorer 接入
      • 5.3 数据同步策略
    • 六、Web 配置与运维
      • 6.1 嵌入式 Web 服务
    • 七、工程落地检查项
      • 7.1 硬件
      • 7.2 固件
      • 7.3 云端
      • 7.4 测试
    • 八、典型坑
    • 九、小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档