基于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物联网通信模组开发指南,涵盖从硬件连接到云平台对接的全流程实现。所有代码均经过实际测试验证,开发者可根据具体需求进行调整和优化。

相关推荐
武汉唯众智创2 小时前
“物联网 Python 开发教程”课程教学解决方案
开发语言·python·物联网·物联网技术·物联网 python 开发·python 开发
TDengine (老段)3 小时前
携手桂冠电力、南网储能、中能拾贝,TDengine 三项案例入选“星河奖”
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
线束线缆组件品替网4 小时前
TE Linx RF 物联网射频模块的 RF 线缆连接设计思路
数码相机·物联网·测试工具·电脑·音视频·pcb工艺
深圳市恒星物联科技有限公司4 小时前
国内排水监测公司有哪些?
大数据·网络·数据库·物联网
eonmeter5 小时前
从人工抄表到智能管控,磁卡水表如何重塑我们的用水生活?
物联网·智能水表·磁卡水表·ic卡水表
eonmeter5 小时前
物联网+水务!射频卡水表正在改变我们的用水生活
物联网·射频卡水表·智能水表·刷卡水表·用水管理
颜颜yan_19 小时前
时序数据库选型指南:工业物联网时代如何选择数据底座
数据库·物联网·时序数据库
csg110719 小时前
高效驱动,灵活控制:深度解析RZ7899大电流DC双向马达驱动芯片及其创新应用
单片机·嵌入式硬件·物联网
dixiuapp21 小时前
智能报修系统从连接到预测的价值跃迁
大数据·人工智能·物联网·sass·工单管理系统