在当今万物互联的时代背景下,物联网技术的快速发展极大地推动了智能化社会的构建。作为其中的关键一环,设备与云端平台之间的通信变得尤为重要。本文介绍如何在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 提供了详细的技术文档和开发工具,帮助开发者快速集成和部署模块。
下面是我的华为云物联网服务器设备信息。
关于创建过程,可以看视频:https://www.bilibili.com/video/BV1mr421c75S
- 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}}]}
-
本小节介绍 通过串口 /dev/ttyUSB0 发送 AT 指令以控制 EC20 模块连接华为云物联网平台,并完成 MQTT 通信,使用 Python 脚本实现。
AT 指令:
下面是实现代码,展示了如何用 Python 通过串口发送 AT 指令来配置 EC20 模块并连接到华为云物联网平台:
- # -*- 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()
-
运行命令:
- root@flexusx-1a58:~# python3 mqtt_connect.py
-
本小节介绍 用 C 语言实现通过串口发送 AT 指令来控制 EC20 模块并完成 MQTT 通信。
下面是实现代码,通过串口配置 EC20 模块并连接到 MQTT 服务器:
- #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;
- }
-
编译运行:
- root@flexusx-1a58:~# gcc mqtt_connect.c
- root@flexusx-1a58:~# ./a.out
-
在与硬件通信之前,可以先建立一个虚拟串口测试一下。
创建一个虚拟的串口设备 /dev/ttyUSB0 主要有两种方式:使用 socat 工具创建虚拟串口对(虚拟串口设备),或者使用 tty0tty 驱动来创建虚拟串口对。
socat 是一个强大的网络工具,可以创建虚拟串口设备。下面是如何使用 socat 创建两个虚拟串口对:
- sudo apt-get install socat
-
- socat -d -d PTY,link=/dev/ttyV0,raw,echo=0 PTY,link=/dev/ttyV1,raw,echo=0
-
这将创建两个虚拟串口设备 /dev/ttyV0 和 /dev/ttyV1,它们会像物理串口一样工作,可以在程序中使用它们进行测试。tty0tty 是一个内核模块,用于创建虚拟串口对。
以下是如何安装和使用 tty0tty:
- 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
-
- sudo modprobe tty0tty
-
这将创建虚拟串口设备 /dev/ttyt0 和 /dev/ttyt1。假设已经创建了 /dev/ttyV0 和 /dev/ttyV1(使用 socat),可以在 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()
-