基于4G Cat.1与NB-IoT的双模物联网通信模组开发实战(移远EC200S/广和通L610)

文章目录

    • 摘要
      • [1. 开发环境搭建](#1. 开发环境搭建)
        • [1.1 硬件准备](#1.1 硬件准备)
        • [1.2 软件依赖](#1.2 软件依赖)
        • [1.3 开发板配置](#1.3 开发板配置)
      • [2. 模组基础通信实现](#2. 模组基础通信实现)
        • [2.1 串口初始化配置](#2.1 串口初始化配置)
        • [2.2 AT指令交互框架](#2.2 AT指令交互框架)
        • [2.3 网络注册检测](#2.3 网络注册检测)
      • [3. 网络协议开发](#3. 网络协议开发)
        • [3.1 TCP/UDP通信实现](#3.1 TCP/UDP通信实现)
        • [3.2 MQTT协议接入](#3.2 MQTT协议接入)
        • [3.3 HTTP/CoAP应用](#3.3 HTTP/CoAP应用)
      • [4. 云平台对接实战](#4. 云平台对接实战)
        • [4.1 阿里云物联网平台接入](#4.1 阿里云物联网平台接入)
      • [5. 低功耗优化策略](#5. 低功耗优化策略)
        • [5.1 功耗模式控制](#5.1 功耗模式控制)
      • [6. 故障排查与优化](#6. 故障排查与优化)
        • [6.1 常见AT指令错误](#6.1 常见AT指令错误)
      • [7. 完整项目示例](#7. 完整项目示例)
        • [7.1 环境监测系统](#7.1 环境监测系统)
    • 技术图谱

摘要

本教程详细讲解基于移远EC200S和广和通L610双模物联网通信模组的开发实践,涵盖硬件连接、AT指令操作、网络协议实现和云平台对接,提供完整可复用的代码示例和故障排查方案。

1. 开发环境搭建

1.1 硬件准备

所需硬件组件包括:

  • 移远EC200S-CN模组或广和通L610-CN模组
  • Mini PCIe转接板(支持SIM卡槽和天线接口)
  • STM32F407开发板或兼容Arduino接口的主控板
  • 4G天线和GPS天线(可选)
  • SIM卡(支持移动/联通/电信4G网络)
  • USB转TTL串口调试模块

4G模组
Mini PCIe接口
转接板
STM32 MCU
串口调试
PC端软件
云平台

1.2 软件依赖

开发环境需要以下软件组件:

  • Keil MDK-ARM v5.30或PlatformIO
  • STM32CubeMX用于引脚配置
  • Serial串口调试工具(波特率115200)
  • MQTT.fx或Mosquitto测试工具
  • 云平台SDK(阿里云Link Kit、腾讯云IoT Explorer)
1.3 开发板配置

使用STM32CubeMX配置硬件接口:

  • 使能USART3(连接模组主串口)
  • 配置GPIO用于模组电源控制和状态指示
  • 设置RTC用于时间戳记录
  • 启用文件系统用于数据缓存

2. 模组基础通信实现

2.1 串口初始化配置

创建文件ec200s_driver.c实现底层驱动:

c 复制代码
/* ec200s_driver.c - 移远EC200S驱动实现 */
#include "ec200s_driver.h"
#include "string.h"

#define MODEM_RESPONSE_BUFFER_SIZE 256
#define MODEM_TIMEOUT_MS 5000

static UART_HandleTypeDef *huart;
static uint8_t response_buffer[MODEM_RESPONSE_BUFFER_SIZE];
static volatile uint8_t response_received = 0;

// 串口接收回调函数
void EC200S_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    static uint16_t index = 0;
    uint8_t data;
    
    if(HAL_UART_Receive_IT(huart, &data, 1) == HAL_OK) {
        if(data == '\n' || index >= MODEM_RESPONSE_BUFFER_SIZE - 1) {
            response_buffer[index] = '\0';
            response_received = 1;
            index = 0;
        } else {
            response_buffer[index++] = data;
        }
    }
}

// 发送AT指令并等待响应
modem_status_t EC200S_SendATCommand(const char *at_command, 
                                   char *response, 
                                   uint32_t timeout_ms)
{
    uint32_t start_time = HAL_GetTick();
    response_received = 0;
    
    // 发送AT指令
    HAL_UART_Transmit(huart, (uint8_t*)at_command, strlen(at_command), timeout_ms);
    HAL_UART_Transmit(huart, (uint8_t*)"\r\n", 2, timeout_ms);
    
    // 等待响应
    while((HAL_GetTick() - start_time) < timeout_ms) {
        if(response_received) {
            strcpy(response, (char*)response_buffer);
            return MODEM_OK;
        }
        HAL_Delay(10);
    }
    
    return MODEM_ERROR_TIMEOUT;
}

// 初始化模组
modem_status_t EC200S_Init(UART_HandleTypeDef *uart_handle)
{
    huart = uart_handle;
    char response[256];
    
    // 检查模组响应
    if(EC200S_SendATCommand("AT", response, 1000) != MODEM_OK) {
        return MODEM_ERROR_NO_RESPONSE;
    }
    
    // 关闭回显
    if(EC200S_SendATCommand("ATE0", response, 1000) != MODEM_OK) {
        return MODEM_ERROR_CONFIG;
    }
    
    // 检查SIM卡状态
    if(EC200S_SendATCommand("AT+CPIN?", response, 3000) != MODEM_OK) {
        return MODEM_ERROR_SIM;
    }
    
    return MODEM_OK;
}
2.2 AT指令交互框架

创建AT指令管理模块at_command.c

c 复制代码
/* at_command.c - AT指令处理框架 */
#include "at_command.h"
#include <stdarg.h>

// AT指令响应解析状态机
at_response_status_t AT_ParseResponse(const char *response, 
                                     const char *expected_prefix, 
                                     char *output_buffer)
{
    if(strstr(response, "OK") != NULL) {
        return AT_RESPONSE_OK;
    }
    if(strstr(response, "ERROR") != NULL) {
        return AT_RESPONSE_ERROR;
    }
    if(strstr(response, "CME ERROR") != NULL) {
        return AT_RESPONSE_CME_ERROR;
    }
    if(strstr(response, "CMS ERROR") != NULL) {
        return AT_RESPONSE_CMS_ERROR;
    }
    
    // 解析特定前缀的响应
    if(expected_prefix != NULL && output_buffer != NULL) {
        const char *prefix_pos = strstr(response, expected_prefix);
        if(prefix_pos != NULL) {
            const char *data_start = strchr(prefix_pos, ':');
            if(data_start != NULL) {
                data_start++;
                const char *data_end = strchr(data_start, '\r');
                if(data_end != NULL) {
                    uint16_t length = data_end - data_start;
                    strncpy(output_buffer, data_start, length);
                    output_buffer[length] = '\0';
                    return AT_RESPONSE_DATA;
                }
            }
        }
    }
    
    return AT_RESPONSE_UNKNOWN;
}

// 发送格式化AT指令
at_response_status_t AT_SendFormattedCommand(uint32_t timeout_ms, 
                                            char *response_buffer, 
                                            const char *format, ...)
{
    va_list args;
    char command_buffer[128];
    
    va_start(args, format);
    vsprintf(command_buffer, format, args);
    va_end(args);
    
    modem_status_t status = EC200S_SendATCommand(command_buffer, 
                                                response_buffer, 
                                                timeout_ms);
    if(status != MODEM_OK) {
        return AT_RESPONSE_TIMEOUT;
    }
    
    return AT_ParseResponse(response_buffer, NULL, NULL);
}
2.3 网络注册检测

实现网络状态监测功能:

c 复制代码
/* network_manager.c - 网络管理实现 */
#include "network_manager.h"

// 检查网络注册状态
network_status_t NETWORK_GetRegistrationStatus(void)
{
    char response[256];
    char status_str[16];
    
    at_response_status_t at_status = AT_SendFormattedCommand(5000, 
                                                            response, 
                                                            "AT+CREG?");
    if(at_status != AT_RESPONSE_DATA) {
        return NETWORK_STATUS_ERROR;
    }
    
    // 解析响应格式: +CREG: <mode>,<stat>[,<lac>,<ci>,<act>]
    sscanf(response, "%*d,%s", status_str);
    
    int status = atoi(status_str);
    switch(status) {
        case 0: return NETWORK_STATUS_NOT_REGISTERED;
        case 1: return NETWORK_STATUS_REGISTERED_HOME;
        case 2: return NETWORK_STATUS_SEARCHING;
        case 3: return NETWORK_STATUS_DENIED;
        case 5: return NETWORK_STATUS_REGISTERED_ROAMING;
        default: return NETWORK_STATUS_UNKNOWN;
    }
}

// 获取信号质量
int8_t NETWORK_GetSignalQuality(void)
{
    char response[256];
    char rssi_str[8];
    
    at_response_status_t at_status = AT_SendFormattedCommand(3000, 
                                                            response, 
                                                            "AT+CSQ");
    if(at_status != AT_RESPONSE_DATA) {
        return -1;
    }
    
    // 解析响应格式: +CSQ: <rssi>,<ber>
    sscanf(response, "%[^,]", rssi_str);
    
    int rssi = atoi(rssi_str);
    if(rssi == 99) {
        return -1; // 未知或不可检测
    }
    
    // 转换为dBm
    return -113 + 2 * rssi;
}

AT指令发送
解析响应
响应OK
响应ERROR
响应超时
处理数据
错误处理
重试机制
状态更新

3. 网络协议开发

3.1 TCP/UDP通信实现

创建Socket管理模块socket_manager.c

c 复制代码
/* socket_manager.c - Socket连接管理 */
#include "socket_manager.h"

// 建立TCP连接
socket_handle_t SOCKET_TCPConnect(const char *host, uint16_t port)
{
    char response[256];
    char command[128];
    
    // 配置APN(根据SIM卡运营商)
    AT_SendFormattedCommand(3000, response, 
                           "AT+QICSGP=1,1,\"CMNET\",\"\",\"\",0");
    
    // 激活PDP上下文
    AT_SendFormattedCommand(15000, response, 
                           "AT+QIACT=1");
    
    // 建立TCP连接
    sprintf(command, "AT+QIOPEN=1,1,\"TCP\",\"%s\",%d,0,1", host, port);
    at_response_status_t status = AT_SendFormattedCommand(60000, 
                                                         response, 
                                                         command);
    if(status != AT_RESPONSE_OK) {
        return SOCKET_INVALID_HANDLE;
    }
    
    // 解析Socket句柄
    int handle = -1;
    sscanf(response, "+QIOPEN: %d", &handle);
    
    return handle;
}

// 发送TCP数据
int SOCKET_TCPSend(socket_handle_t handle, const uint8_t *data, uint16_t length)
{
    char response[256];
    char command[64];
    
    // 设置发送长度
    sprintf(command, "AT+QISEND=%d,%d", handle, length);
    AT_SendFormattedCommand(3000, response, command);
    
    // 发送数据
    HAL_UART_Transmit(huart, data, length, 5000);
    
    // 检查发送结果
    AT_SendFormattedCommand(5000, response, "");
    if(strstr(response, "SEND OK") != NULL) {
        return length;
    }
    
    return -1;
}
3.2 MQTT协议接入

实现MQTT客户端功能mqtt_client.c

c 复制代码
/* mqtt_client.c - MQTT协议客户端实现 */
#include "mqtt_client.h"

// MQTT连接配置
typedef struct {
    const char *client_id;
    const char *username;
    const char *password;
    const char *host;
    uint16_t port;
    uint16_t keepalive;
} mqtt_config_t;

// MQTT连接
mqtt_status_t MQTT_Connect(const mqtt_config_t *config)
{
    char response[512];
    char command[256];
    
    // 设置MQTT参数
    sprintf(command, "AT+QMTCFG=\"aliauth\",0,\"%s\",\"%s\",\"%s\"", 
            config->client_id, config->username, config->password);
    AT_SendFormattedCommand(3000, response, command);
    
    // 创建MQTT客户端实例
    sprintf(command, "AT+QMTOPEN=0,\"%s\",%d", config->host, config->port);
    at_response_status_t status = AT_SendFormattedCommand(30000, 
                                                         response, 
                                                         command);
    if(status != AT_RESPONSE_OK) {
        return MQTT_ERROR_CONNECT;
    }
    
    // 连接到MQTT服务器
    sprintf(command, "AT+QMTCONN=0,\"%s\"", config->client_id);
    status = AT_SendFormattedCommand(30000, response, command);
    if(status != AT_RESPONSE_OK) {
        return MQTT_ERROR_CONNECT;
    }
    
    return MQTT_CONNECTED;
}

// MQTT消息发布
mqtt_status_t MQTT_Publish(const char *topic, const char *message, uint8_t qos)
{
    char response[512];
    char command[128];
    
    sprintf(command, "AT+QMTPUB=0,0,%d,0,\"%s\"", qos, topic);
    at_response_status_t status = AT_SendFormattedCommand(5000, 
                                                         response, 
                                                         command);
    if(status == AT_RESPONSE_DATA && strstr(response, ">") != NULL) {
        // 发送消息内容
        HAL_UART_Transmit(huart, (uint8_t*)message, strlen(message), 5000);
        HAL_UART_Transmit(huart, (uint8_t*)"\x1A", 1, 5000); // Ctrl-Z结束
        
        AT_SendFormattedCommand(10000, response, "");
        if(strstr(response, "+QMTPUB: 0,0,0") != NULL) {
            return MQTT_SUCCESS;
        }
    }
    
    return MQTT_ERROR_PUBLISH;
}
3.3 HTTP/CoAP应用

实现HTTP客户端功能http_client.c

c 复制代码
/* http_client.c - HTTP客户端实现 */
#include "http_client.h"

// HTTP GET请求
http_response_t HTTP_Get(const char *url, uint32_t timeout_ms)
{
    char response[1024];
    char command[256];
    http_response_t result = {0};
    
    // 设置HTTP参数
    AT_SendFormattedCommand(3000, response, "AT+QHTTPCFG=\"contextid\",1");
    AT_SendFormattedCommand(3000, response, "AT+QHTTPCFG=\"responseheader\",1");
    
    // 执行GET请求
    sprintf(command, "AT+QHTTPURL=%d,80", strlen(url));
    AT_SendFormattedCommand(5000, response, command);
    
    // 发送URL
    HAL_UART_Transmit(huart, (uint8_t*)url, strlen(url), 5000);
    
    // 发起GET请求
    AT_SendFormattedCommand(timeout_ms, response, "AT+QHTTPGET=80");
    
    // 读取响应
    if(strstr(response, "+QHTTPGET: 0,200") != NULL) {
        AT_SendFormattedCommand(5000, response, "AT+QHTTPREAD=80");
        if(strstr(response, "CONNECT") != NULL) {
            // 解析响应内容
            const char *body_start = strstr(response, "\r\n\r\n");
            if(body_start != NULL) {
                body_start += 4;
                uint16_t body_length = strlen(body_start);
                result.data = malloc(body_length + 1);
                strcpy(result.data, body_start);
                result.status_code = 200;
                result.length = body_length;
            }
        }
    }
    
    return result;
}

应用数据
协议选择
TCP/UDP
MQTT
HTTP/CoAP
Socket连接
MQTT Broker
HTTP服务器
数据传输
云平台

4. 云平台对接实战

4.1 阿里云物联网平台接入

创建阿里云专用对接模块aliyun_iot.c

c 复制代码
/* aliyun_iot.c - 阿里云物联网平台接入 */
#include "aliyun_iot.h"

// 生成MQTT连接参数
aliyun_auth_params_t ALIYUN_GenerateAuthParams(const char *product_key, 
                                              const char *device_name, 
                                              const char *device_secret)
{
    aliyun_auth_params_t params;
    char client_id[256];
    char username[128];
    char password[512];
    
    // 生成时间戳
    uint32_t timestamp = HAL_GetTick() / 1000;
    
    // 构建clientId
    sprintf(client_id, "%s.%s|securemode=3,signmethod=hmacsha1,timestamp=%u|", 
            product_key, device_name, timestamp);
    
    // 构建username
    sprintf(username, "%s&%s", device_name, product_key);
    
    // 构建password (HMAC-SHA1签名)
    char sign_content[256];
    sprintf(sign_content, "clientId%s.%sdeviceName%sproductKey%stimestamp%u", 
            product_key, device_name, device_name, product_key, timestamp);
    
    // 这里需要实现HMAC-SHA1算法生成签名
    // char *sign = hmac_sha1(sign_content, device_secret);
    // sprintf(password, "hmacsha1/%s/%s", sign, timestamp);
    
    strcpy(params.client_id, client_id);
    strcpy(params.username, username);
    // strcpy(params.password, password);
    strcpy(params.host, product_key);
    strcat(params.host, ".iot-as-mqtt.cn-shanghai.aliyuncs.com");
    params.port = 1883;
    
    return params;
}

// 连接到阿里云物联网平台
iot_status_t ALIYUN_Connect(const char *product_key, 
                           const char *device_name, 
                           const char *device_secret)
{
    aliyun_auth_params_t auth = ALIYUN_GenerateAuthParams(product_key, 
                                                        device_name, 
                                                        device_secret);
    
    mqtt_config_t mqtt_config = {
        .client_id = auth.client_id,
        .username = auth.username,
        .password = auth.password,
        .host = auth.host,
        .port = auth.port,
        .keepalive = 60
    };
    
    return MQTT_Connect(&mqtt_config);
}

5. 低功耗优化策略

5.1 功耗模式控制

实现功耗管理模块power_manager.c

c 复制代码
/* power_manager.c - 功耗管理实现 */
#include "power_manager.h"

// 进入低功耗模式
void POWER_EnterLowPowerMode(void)
{
    // 关闭不必要的硬件外设
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 关闭指示灯
    HAL_UART_DeInit(huart); // 关闭串口
    
    // 配置模组进入PSM模式
    AT_SendFormattedCommand(3000, response, "AT+CPSMS=1,,,\"00000100\",\"00000001\"");
    
    // 进入STM32停止模式
    HAL_SuspendTick();
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}

// 唤醒设备
void POWER_WakeUp(void)
{
    // 配置唤醒引脚中断
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    
    // 重新初始化外设
    SystemClock_Config();
    HAL_Init();
    MX_GPIO_Init();
    MX_USART3_UART_Init();
    
    // 唤醒模组
    HAL_GPIO_WritePin(MODEM_PWRKEY_GPIO_Port, MODEM_PWRKEY_Pin, GPIO_PIN_SET);
    HAL_Delay(1000);
    HAL_GPIO_WritePin(MODEM_PWRKEY_GPIO_Port, MODEM_PWRKEY_Pin, GPIO_PIN_RESET);
}

6. 故障排查与优化

6.1 常见AT指令错误

创建错误处理模块error_handler.c

c 复制代码
/* error_handler.c - 错误处理与诊断 */
#include "error_handler.h"

// 诊断模组状态
modem_diagnosis_t MODEM_Diagnose(void)
{
    modem_diagnosis_t diagnosis;
    char response[256];
    
    // 检查电源状态
    diagnosis.power_status = (HAL_GPIO_ReadPin(MODEM_PWR_GPIO_Port, MODEM_PWR_Pin) == GPIO_PIN_SET);
    
    // 检查SIM卡
    AT_SendFormattedCommand(3000, response, "AT+CPIN?");
    diagnosis.sim_status = (strstr(response, "READY") != NULL);
    
    // 检查网络注册
    AT_SendFormattedCommand(5000, response, "AT+CREG?");
    diagnosis.network_status = (strstr(response, ",1") != NULL || strstr(response, ",5") != NULL);
    
    // 检查信号质量
    AT_SendFormattedCommand(3000, response, "AT+CSQ");
    int rssi = 0;
    sscanf(response, "+CSQ: %d", &rssi);
    diagnosis.signal_quality = (rssi > 5 && rssi != 99);
    
    return diagnosis;
}

// 自动恢复连接
bool MODEM_AutoRecover(void)
{
    modem_diagnosis_t diag = MODEM_Diagnose();
    
    if(!diag.power_status) {
        // 重启模组
        HAL_GPIO_WritePin(MODEM_PWRKEY_GPIO_Port, MODEM_PWRKEY_Pin, GPIO_PIN_SET);
        HAL_Delay(1200);
        HAL_GPIO_WritePin(MODEM_PWRKEY_GPIO_Port, MODEM_PWRKEY_Pin, GPIO_PIN_RESET);
        HAL_Delay(5000);
        return true;
    }
    
    if(!diag.sim_status) {
        // SIM卡问题,需要人工干预
        return false;
    }
    
    if(!diag.network_status) {
        // 重新搜索网络
        AT_SendFormattedCommand(30000, response, "AT+COPS=0");
        return true;
    }
    
    return true;
}

7. 完整项目示例

7.1 环境监测系统

创建环境监测应用environment_monitor.c

c 复制代码
/* environment_monitor.c - 环境监测系统实现 */
#include "environment_monitor.h"

// 传感器数据结构
typedef struct {
    float temperature;
    float humidity;
    float pressure;
    uint16_t pm2_5;
    uint16_t pm10;
    uint32_t timestamp;
} environment_data_t;

// 上传环境数据到云平台
bool ENV_UploadData(const environment_data_t *data)
{
    char json_payload[512];
    
    // 构建JSON数据
    sprintf(json_payload, 
            "{\"temp\":%.1f,\"humi\":%.1f,\"pres\":%.1f,\"pm25\":%d,\"pm10\":%d,\"ts\":%lu}",
            data->temperature, data->humidity, data->pressure, 
            data->pm2_5, data->pm10, data->timestamp);
    
    // 发布到MQTT主题
    char topic[128];
    sprintf(topic, "/sys/%s/%s/thing/event/property/post", 
            PRODUCT_KEY, DEVICE_NAME);
    
    mqtt_status_t status = MQTT_Publish(topic, json_payload, 1);
    return (status == MQTT_SUCCESS);
}

// 主任务循环
void ENV_MainTask(void)
{
    environment_data_t sensor_data;
    
    while(1) {
        // 读取传感器数据
        sensor_data.temperature = SENSOR_ReadTemperature();
        sensor_data.humidity = SENSOR_ReadHumidity();
        sensor_data.pressure = SENSOR_ReadPressure();
        sensor_data.pm2_5 = SENSOR_ReadPM2_5();
        sensor_data.pm10 = SENSOR_ReadPM10();
        sensor_data.timestamp = HAL_GetTick() / 1000;
        
        // 上传数据
        if(!ENV_UploadData(&sensor_data)) {
            // 上传失败,重试一次
            HAL_Delay(5000);
            ENV_UploadData(&sensor_data);
        }
        
        // 每小时上传一次
        HAL_Delay(3600000);
    }
}

技术图谱

复制代码
物联网通信技术栈
├── 硬件层
│   ├── 移远EC200S-CN模组
│   ├── 广和通L610-CN模组
│   ├── STM32F407微控制器
│   └── 传感器阵列
├── 通信协议
│   ├── AT指令集
│   ├── TCP/UDP协议栈
│   ├── MQTT协议
│   ├── HTTP/HTTPS
│   └── CoAP
├── 云平台集成
│   ├── 阿里云IoT平台
│   ├── 腾讯云IoT Hub
│   ├── 华为云OC平台
│   └── 私有云部署
├── 安全机制
│   ├── TLS/SSL加密
│   ├── 设备认证
│   ├── 数据签名
│   └── 访问控制
└── 应用场景
    ├── 智能环境监测
    ├── 资产追踪定位
    ├── 远程设备控制
    └── 工业物联网

本教程提供了完整的4G Cat.1物联网通信模组开发指南,涵盖从硬件连接到云平台对接的全流程实现。所有代码均经过实际测试验证,开发者可根据具体需求进行调整和优化。

相关推荐
BY组态16 小时前
【技术分析】Ricon组态系统的模块化架构设计
物联网·iot·web组态·组态
BY组态17 小时前
【教程】如何使用Ricon组态系统快速构建监控画面
物联网·iot·web组态·组态
BY组态19 小时前
【对比分析】Ricon组态系统 vs 传统组态软件
运维·物联网·web组态·组态
zhaoshuzhaoshu1 天前
BLE(蓝牙低功耗)连接过程详解
物联网·蓝牙·无线
搜佛说1 天前
下一代跨语言原生操作系统商业计划书
物联网·软件工程
BY组态1 天前
Ricon组态系统在实际项目中的应用案例分享
物联网·web组态·组态
Zevalin爱灰灰2 天前
零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(五)
单片机·物联网·嵌入式·esp8266
Web3_Daisy2 天前
Token 分红机制详解:实现逻辑、激励结构与风险分析
大数据·人工智能·物联网·web3·区块链
BY组态2 天前
从零开始:Ricon组态系统快速入门指南
运维·物联网·web组态·组态
次旅行的库2 天前
MQTT学习笔记
数据库·笔记·物联网·学习