Linux系统下串口AT指令控制EC20连接华为云物联网平台

一、前言

在当今万物互联的时代背景下,物联网技术的快速发展极大地推动了智能化社会的构建。作为其中的关键一环,设备与云端平台之间的通信变得尤为重要。本文介绍如何在Linux操作系统环境下,利用串口通信来实现EC20模块与华为云物联网平台的有效连接。使用Linux下的/dev/ttyUSB0设备文件通过AT指令来配置EC20模块,采用C语言和Python这两种编程语言实现这一过程。

EC20 是Quectel 生产的 4G LTE 模块。是一个多功能的通信模块,广泛应用于各种 IoT(物联网)设备中,提供了可靠的无线通信能力。EC20 支持 LTE FDD、LTE TDD、WCDMA 和 GSM 网络,能够实现高速的数据传输和稳定的语音通信。

EC20 模块支持全球主要的频段,使其能够在多个国家和地区的网络环境中正常工作。它能够提供最高达 150 Mbps 的下行速率和 50 Mbps 的上行速率,这使得它非常适合需要高带宽的应用场景,如视频流、远程监控和数据传输。

该模块具有强大的数据通信能力,包括支持 TCP/IP 和 UDP 协议的网络连接。EC20 还支持各种 AT 命令,通过这些命令用户可以控制模块的操作,配置网络设置,发送和接收数据。其内置的网络协议栈使得模块可以直接进行 MQTT、HTTP、FTP 等网络协议的通信,为开发者提供了极大的便利。

除了数据通信功能,EC20 模块还支持语音通话和短信功能。这使得它不仅可以用于数据传输,还可以作为语音通信解决方案。通过 AT 命令,用户可以方便地进行拨打和接听电话,发送和接收短信,满足不同应用场景的需求。

在电源管理方面,EC20 模块具有低功耗模式,能够有效地延长设备的电池寿命。它支持多种电源管理功能,包括睡眠模式和省电模式,使得它在不使用的时候能够降低功耗,减少能量消耗。

模块的物理接口包括多个 UART 串口、USB 接口和 GPIO 引脚,这些接口允许模块与其他硬件进行连接。通过这些接口,用户可以实现串口通信、USB 数据传输以及各种数字信号的输入输出,提供了高度的灵活性和可扩展性。

在设计和生产方面,EC20 模块遵循了工业标准,确保其在各种恶劣环境下的可靠性。它的设计小巧且坚固,适合嵌入到各种嵌入式系统和终端设备中。Quectel 提供了详细的技术文档和开发工具,帮助开发者快速集成和部署模块。

二、实例代码

2.1 服务器信息

下面是我的华为云物联网服务器设备信息。

关于创建过程,可以看视频:https://www.bilibili.com/video/BV1mr421c75S

cpp 复制代码
IP地址:117.78.5.125
端口号:1883
ClientId      64000697352830580e48df07_dev1_0_0_2023030206
Username      64000697352830580e48df07_dev1
Password      a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449
订阅主题:$oc/devices/64000697352830580e48df07_dev1/sys/messages/down
发布主题:$oc/devices/64000697352830580e48df07_dev1/sys/properties/report
发布的消息:{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}

2.2 Python代码

本小节介绍 通过串口 /dev/ttyUSB0 发送 AT 指令以控制 EC20 模块连接华为云物联网平台,并完成 MQTT 通信,使用 Python 脚本实现。

AT 指令:

  • AT+RST: 重启模块
  • AT+CSIM=1: 设置工作模式为数据模式(请根据实际模块手册确认是否需要此指令)
  • AT+QMTOPEN=0,"IP地址",端口号: 连接到 MQTT 服务器
  • AT+QMTCONN=0,"ClientId","Username","Password": 使用提供的 ID、用户名和密码连接到 MQTT 服务器
  • AT+QMTSUB=0,0,"主题",1: 订阅指定主题
  • AT+QMTPUB=0,0,0,0,"主题",消息内容: 发布消息到指定主题

下面是实现代码,展示了如何用 Python 通过串口发送 AT 指令来配置 EC20 模块并连接到华为云物联网平台:

cpp 复制代码
# -*- coding: utf-8 -*-

import serial
import time

# 串口配置
SERIAL_PORT = '/dev/ttyUSB0'
BAUDRATE = 115200
TIMEOUT = 1

# MQTT 服务器信息
MQTT_SERVER_IP = '117.78.5.125'
MQTT_SERVER_PORT = '1883'
MQTT_CLIENT_ID = '64000697352830580e48df07_dev1_0_0_2023030206'
MQTT_USERNAME = '64000697352830580e48df07_dev1'
MQTT_PASSWORD = 'a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449'

# 发布的消息
PUBLISH_MESSAGE = '{"services": [{"service_id": "stm32","properties":{"DHT11_T":18,"DHT11_H":80,"MQ2":1,"water":1,"flame":1,"light":0,"LED1":0,"LED2":0,"LED3":0}}]}'

# 发送 AT 指令并获取响应
def send_at_command(serial_conn, command, response_termination='OK', delay=1):
    print(f"Sending command: {command}")
    serial_conn.write((command + '\r\n').encode())
    time.sleep(delay)
    response = serial_conn.read(serial_conn.inWaiting()).decode()
    print(f"Response: {response}")
    if response_termination and response_termination not in response:
        raise Exception(f"Unexpected response: {response}")
    return response

def main():
    # 打开串口连接
    with serial.Serial(SERIAL_PORT, BAUDRATE, timeout=TIMEOUT) as ser:
        try:
            # 重启模块
            send_at_command(ser, 'AT+RST')

            # 设置工作模式为数据模式
            send_at_command(ser, 'AT+CSIM=1')

            # 连接到 MQTT 服务器
            send_at_command(ser, f'AT+QMTOPEN=0,"{MQTT_SERVER_IP}",{MQTT_SERVER_PORT}')
            send_at_command(ser, 'AT+QMTCONN=0,"{MQTT_CLIENT_ID}","{MQTT_USERNAME}","{MQTT_PASSWORD}"')
            time.sleep(5)  # 等待连接

            # 订阅主题
            send_at_command(ser, 'AT+QMTSUB=0,0,"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down",1')

            # 发布消息
            send_at_command(ser, f'AT+QMTPUB=0,0,0,0,"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report",{PUBLISH_MESSAGE}')

        except Exception as e:
            print(f"An error occurred: {e}")

if __name__ == "__main__":
    main()

运行命令:

cpp 复制代码
root@flexusx-1a58:~# python3 mqtt_connect.py 

2.3 C语言代码

本小节介绍 用 C 语言实现通过串口发送 AT 指令来控制 EC20 模块并完成 MQTT 通信。

下面是实现代码,通过串口配置 EC20 模块并连接到 MQTT 服务器:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>

#define SERIAL_PORT "/dev/ttyUSB0"
#define BAUDRATE B115200

int setup_serial_port(const char *port) {
    int fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    struct termios options;
    tcgetattr(fd, &options);
    cfsetispeed(&options, BAUDRATE);
    cfsetospeed(&options, BAUDRATE);

    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    tcsetattr(fd, TCSANOW, &options);

    return fd;
}

void send_at_command(int fd, const char *command) {
    write(fd, command, strlen(command));
    write(fd, "\r\n", 2);
    usleep(100000);  // Wait for 100ms for the module to respond

    char response[256];
    int n = read(fd, response, sizeof(response) - 1);
    if (n > 0) {
        response[n] = '\0';
        printf("Response: %s\n", response);
    } else {
        printf("No response or read error.\n");
    }
}

int main() {
    int fd = setup_serial_port(SERIAL_PORT);

    // 1. Reset the module
    send_at_command(fd, "AT+RST");

    // 2. Connect to MQTT server
    char command[300];
    snprintf(command, sizeof(command), "AT+QMTOPEN=0,\"%s\",%d", "117.78.5.125", 1883);
    send_at_command(fd, command);

    snprintf(command, sizeof(command), "AT+QMTCONN=0,\"%s\",\"%s\",\"%s\"", 
             "64000697352830580e48df07_dev1_0_0_2023030206", 
             "64000697352830580e48df07_dev1", 
             "a695af9883c5d0e3817bc6971beeecadf8c7c595677c461b1fe75882ed2bf449");
    send_at_command(fd, command);

    usleep(5000000);  // Wait 5 seconds for connection to establish

    // 3. Subscribe to a topic
    send_at_command(fd, "AT+QMTSUB=0,0,\"$oc/devices/64000697352830580e48df07_dev1/sys/messages/down\",1");

    // 4. Publish a message
    sprintf(command,  "AT+QMTPUB=0,0,0,0,\"$oc/devices/64000697352830580e48df07_dev1/sys/properties/report\",\"{\\\"services\\\": [{\\\"service_id\\\": \\\"stm32\\\",\\\"properties\\\":{\\\"DHT11_T\\\":18,\\\"DHT11_H\\\":80,\\\"MQ2\\\":1,\\\"water\\\":1,\\\"flame\\\":1,\\\"light\\\":0,\\\"LED1\\\":0,\\\"LED2\\\":0,\\\"LED3\\\":0}}]}\"");
    send_at_command(fd, command);

    close(fd);
    return 0;
}

编译运行:

cpp 复制代码
root@flexusx-1a58:~# gcc mqtt_connect.c 
root@flexusx-1a58:~# ./a.out 

2.4 创建虚拟串口方便测试

在与硬件通信之前,可以先建立一个虚拟串口测试一下。

创建一个虚拟的串口设备 /dev/ttyUSB0 主要有两种方式:使用 socat 工具创建虚拟串口对(虚拟串口设备),或者使用 tty0tty 驱动来创建虚拟串口对。

方法 1: 使用 socat 创建虚拟串口

socat 是一个强大的网络工具,可以创建虚拟串口设备。下面是如何使用 socat 创建两个虚拟串口对:

  1. 安装 socat : 在大多数 Linux 发行版上,可以使用包管理工具安装 socat。例如,在 Debian 或 Ubuntu 上运行:

    复制代码
    sudo apt-get install socat
  2. 创建虚拟串口对 : 运行以下命令来创建两个虚拟串口设备 /dev/ttyV0/dev/ttyV1

    复制代码
    socat -d -d PTY,link=/dev/ttyV0,raw,echo=0 PTY,link=/dev/ttyV1,raw,echo=0

    这将创建两个虚拟串口设备 /dev/ttyV0/dev/ttyV1,它们会像物理串口一样工作,可以在程序中使用它们进行测试。

  3. 使用虚拟串口设备

    • 可以将一个设备用于发送数据,另一个设备用于接收数据进行测试。例如,可以将一个串口设备配置为连接到模拟的设备,另一个设备配置为模拟的串口设备的接收端。

方法 2: 使用 tty0tty 驱动

tty0tty 是一个内核模块,用于创建虚拟串口对。

以下是如何安装和使用 tty0tty

  1. 安装 tty0tty : 需要从源代码编译和安装 tty0tty。按照以下步骤进行:

    bash 复制代码
    sudo apt-get install build-essential linux-headers-$(uname -r)
    git clone https://github.com/ntop/tty0tty.git
    cd tty0tty
    make
    sudo make install
    sudo depmod -a
  2. 加载内核模块 : 运行以下命令加载 tty0tty 内核模块:

    bash 复制代码
    sudo modprobe tty0tty

    这将创建虚拟串口设备 /dev/ttyt0/dev/ttyt1

  3. 使用虚拟串口设备

    • /dev/ttyt0/dev/ttyt1 现在可以作为虚拟串口设备使用。可以在程序中将它们作为串口设备来进行测试。

示例代码

假设已经创建了 /dev/ttyV0/dev/ttyV1(使用 socat),可以在 Python 中使用这些虚拟串口设备进行测试。例如:

python 复制代码
import serial

# 打开虚拟串口
ser1 = serial.Serial('/dev/ttyV0', 115200, timeout=1)
ser2 = serial.Serial('/dev/ttyV1', 115200, timeout=1)

# 发送数据
ser1.write(b'Hello, world!\n')

# 读取数据
response = ser2.readline()
print('Received:', response.decode('utf-8'))

# 关闭串口
ser1.close()
ser2.close()
相关推荐
无己心2 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u0103055278 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u0103055279 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝10 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552710 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552711 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552713 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552713 天前
Java I/O核心操作实战
人工智能·1024程序员节
u01030552714 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节
u01030552715 天前
Java模块化编程实战指南
人工智能·笔记·1024程序员节