从零到一:用Air724UG 4G模块和Python,手把手教你搭建一个物联网数据上报系统(含完整代码)
从零构建物联网数据上报系统:Air724UG与Python实战指南
在万物互联的时代,物联网技术正悄然改变着我们的生活和工作方式。想象一下,您只需轻点手机,就能实时查看千里之外温湿度数据;或是远程监控设备运行状态,提前预警潜在故障。这种看似科幻的场景,如今借助4G模块和简单编程就能实现。本文将带您从零开始,使用Air724UG 4G模块和Python语言,构建一套完整的物联网数据上报系统。
这个项目特别适合那些已经掌握基础编程知识,但渴望将零散技能整合为实际应用的开发者。不同于单纯的理论讲解,我们将聚焦于端到端的实现过程——从硬件连接到云端展示,每个环节都配有可落地的代码和配置说明。无论您是希望快速验证创意的极客,还是需要实际部署监测系统的工程师,都能从中获得实用价值。
1. 硬件准备与环境搭建
1.1 所需材料清单
构建这套系统需要以下硬件组件:
- Air724UG 4G模块:支持LTE Cat1,具备TCP/IP协议栈
- STM32/51单片机开发板:作为数据采集终端
- SIM卡:支持移动/联通/电信的物联网卡或普通流量卡
- 温湿度传感器:如DHT11或更精确的SHT30
- USB转TTL模块:用于调试4G模块
- 杜邦线若干:用于各组件间连接
提示:购买Air724UG时注意选择带有IPEX天线接口的版本,确保信号稳定性
1.2 硬件连接示意图
将各组件按以下方式连接:
[单片机] --(UART)--> [Air724UG] |--(I2C/GPIO)--> [温湿度传感器]具体接线参考下表:
| 组件接口 | 连接目标 | 引脚说明 |
|---|---|---|
| 单片机TX | Air724UG RX | 数据发送端 |
| 单片机RX | Air724UG TX | 数据接收端 |
| 单片机GND | Air724UG GND | 共地连接 |
| 单片机3.3V | Air724UG VCC | 电源输入 |
| 单片机SCL | 传感器SCL | I2C时钟线 |
| 单片机SDA | 传感器SDA | I2C数据线 |
1.3 开发环境配置
在开始编程前,需要准备好以下软件环境:
- Python 3.8+:用于服务器端开发
# 检查Python版本 python --version - PyCharm/VSCode:推荐使用的IDE
- Keil MDK/STM32CubeIDE:单片机开发环境
- 串口调试工具:如SecureCRT或Putty
安装必要的Python库:
pip install pyserial flask sqlalchemy2. 4G模块配置与网络连接
2.1 Air724UG基础AT指令测试
通过USB转TTL模块连接电脑和Air724UG,使用串口工具发送以下指令测试模块状态:
AT AT+CPIN? # 查询SIM卡状态 AT+CSQ # 检查信号强度 AT+COPS? # 查询当前运营商正常响应应类似:
AT OK +CPIN: READY +CSQ: 24,0 +COPS: 0,0,"CHINA MOBILE"2.2 配置TCP/IP参数
建立网络连接需要配置APN(接入点名称),不同运营商APN不同:
| 运营商 | APN设置指令 |
|---|---|
| 中国移动 | AT+CGDCONT=1,"IP","CMNET" |
| 中国联通 | AT+CGDCONT=1,"IP","UNINET" |
| 中国电信 | AT+CGDCONT=1,"IP","CTNET" |
激活网络连接:
AT+CGATT=1 # 附着网络 AT+NETOPEN # 打开网络 AT+IPSTATUS # 查看网络状态2.3 建立TCP连接
假设服务器IP为192.168.1.100,端口为8080:
AT+CIPOPEN=0,"TCP","192.168.1.100",8080 AT+CIPSEND=0,15 # 准备发送15字节数据 > Hello,Server! # 输入要发送的数据成功连接后,模块会返回:
+CIPOPEN:0,0 +CIPSEND:0,15,153. Python服务器开发
3.1 TCP服务器实现
创建一个简单的TCP服务器接收4G模块数据:
import socket def start_tcp_server(host='0.0.0.0', port=8080): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((host, port)) s.listen() print(f"Server listening on {host}:{port}") while True: conn, addr = s.accept() with conn: print(f"Connected by {addr}") while True: data = conn.recv(1024) if not data: break print(f"Received: {data.decode()}") # 简单响应 conn.sendall(b"ACK: " + data) if __name__ == "__main__": start_tcp_server()3.2 数据解析与存储
定义数据格式并存储到SQLite数据库:
from sqlalchemy import create_engine, Column, Integer, Float, DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from datetime import datetime Base = declarative_base() class SensorData(Base): __tablename__ = 'sensor_data' id = Column(Integer, primary_key=True) temperature = Column(Float) humidity = Column(Float) timestamp = Column(DateTime, default=datetime.now) engine = create_engine('sqlite:///iot_data.db') Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) def parse_and_store(raw_data): try: # 示例数据格式: "T25.6H50.2" temp = float(raw_data.split('T')[1].split('H')[0]) humi = float(raw_data.split('H')[1]) session = Session() new_data = SensorData(temperature=temp, humidity=humi) session.add(new_data) session.commit() return True except Exception as e: print(f"Error parsing data: {e}") return False3.3 Web数据展示界面
使用Flask创建简单的数据可视化页面:
from flask import Flask, render_template import pandas as pd from sqlalchemy import create_engine app = Flask(__name__) @app.route('/') def show_data(): engine = create_engine('sqlite:///iot_data.db') df = pd.read_sql('SELECT * FROM sensor_data ORDER BY timestamp DESC LIMIT 100', engine) return render_template('dashboard.html', tables=[df.to_html(classes='data')], titles=df.columns.values) if __name__ == '__main__': app.run(debug=True)对应的HTML模板(templates/dashboard.html):
<!DOCTYPE html> <html> <head> <title>物联网数据监控</title> <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> </head> <body> <h1>环境数据实时监控</h1> <div id="tempChart" style="width:600px;height:250px;"></div> <div id="humiChart" style="width:600px;height:250px;"></div> <script> var tempData = { x: {{ timestamps|safe }}, y: {{ temperatures|safe }}, type: 'scatter' }; var humiData = { x: {{ timestamps|safe }}, y: {{ humidities|safe }}, type: 'scatter' }; Plotly.newPlot('tempChart', [tempData], {title: '温度变化曲线'}); Plotly.newPlot('humiChart', [humiData], {title: '湿度变化曲线'}); </script> </body> </html>4. 单片机端程序开发
4.1 传感器数据采集
以STM32 HAL库为例,读取SHT30温湿度传感器数据:
#include "sht30.h" #include <stdio.h> #define SHT30_ADDR 0x44<<1 void SHT30_Read(float *temp, float *humi) { uint8_t cmd[2] = {0x2C, 0x06}; uint8_t data[6]; HAL_I2C_Master_Transmit(&hi2c1, SHT30_ADDR, cmd, 2, 100); HAL_Delay(10); HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR, data, 6, 100); uint16_t temp_raw = (data[0] << 8) | data[1]; uint16_t humi_raw = (data[3] << 8) | data[4]; *temp = -45 + 175 * (temp_raw / 65535.0); *humi = 100 * (humi_raw / 65535.0); }4.2 数据格式化与发送
将采集到的数据格式化为字符串并通过串口发送:
void Send_Sensor_Data(float temp, float humi) { char buffer[32]; sprintf(buffer, "T%.1fH%.1f", temp, humi); HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 100); }4.3 与4G模块通信
单片机通过串口向Air724UG发送AT指令:
void Send_AT_Command(const char *cmd) { HAL_UART_Transmit(&huart2, (uint8_t*)cmd, strlen(cmd), 100); HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", 2, 100); } void Connect_To_Server() { Send_AT_Command("AT+CGATT=1"); HAL_Delay(1000); Send_AT_Command("AT+NETOPEN"); HAL_Delay(2000); Send_AT_Command("AT+CIPOPEN=0,\"TCP\",\"192.168.1.100\",8080"); HAL_Delay(3000); }5. 系统集成与调试
5.1 数据流验证
完整的系统数据流向如下:
- 传感器采集环境数据
- 单片机格式化数据
- 通过串口发送到4G模块
- 4G模块通过TCP传输到服务器
- 服务器解析并存储数据
- Web界面展示历史数据
5.2 常见问题排查
遇到连接问题时,可以按照以下步骤检查:
- SIM卡状态:确认SIM卡已正确插入且未欠费
- 信号强度:使用
AT+CSQ检查,数值应大于10 - APN配置:确保与所用运营商匹配
- 服务器连接:
- 检查服务器IP和端口是否正确
- 确认服务器防火墙允许该端口通信
- 在服务器使用
netstat -tulnp查看端口监听状态
5.3 性能优化建议
- 数据压缩:在单片机端将浮点数转换为整型减少传输量
- 心跳机制:定期发送心跳包保持TCP连接
- 本地缓存:在网络不可用时暂存数据,恢复后补传
- 睡眠模式:在不采集时让模块进入低功耗状态
在实际部署中,我发现最影响稳定性的因素是网络信号质量。当模块处于信号边缘区域时,可以尝试以下改进:
- 更换更高增益的天线
- 调整模块位置寻找最佳信号点
- 增加网络连接重试机制
- 降低数据上报频率减轻网络负担
