- 实现AT指令通信和4G模组管理 - 支持PDU模式短信接收和发送 - 长短信自动合并功能 - 多通道推送支持(钉钉/飞书/Telegram等) - 管理员短信远程控制 - RESTful API接口 - 完整的日志系统
311 lines
6.3 KiB
Markdown
311 lines
6.3 KiB
Markdown
# 4G模块AT指令交互文档
|
||
|
||
## 串口配置
|
||
|
||
- **波特率**: 115200
|
||
- **数据位**: 8
|
||
- **停止位**: 1
|
||
- **校验**: None
|
||
- **流控**: None
|
||
|
||
## 初始化流程
|
||
|
||
### 1. 基础握手
|
||
```
|
||
AT
|
||
响应: OK
|
||
作用: 测试模组是否响应
|
||
```
|
||
|
||
### 2. 查询模组信息
|
||
```
|
||
ATI
|
||
响应:
|
||
厂商名称
|
||
型号
|
||
固件版本
|
||
OK
|
||
作用: 获取模组厂商、型号、固件版本
|
||
```
|
||
|
||
### 3. 禁用数据连接(防止流量消耗)
|
||
```
|
||
AT+CGACT=0,1
|
||
响应: OK
|
||
作用: 关闭4G数据连接,防止自动联网消耗流量
|
||
注意: ML307Y型号此命令有bug,需跳过
|
||
```
|
||
|
||
### 4. 配置短信URC上报
|
||
```
|
||
AT+CNMI=2,2,0,0,0
|
||
响应: OK
|
||
作用: 配置短信到达时主动上报(URC模式)
|
||
参数说明:
|
||
- 第1参数=2: 缓冲URC到TE
|
||
- 第2参数=2: 短信直接上报+CMT URC(PDU模式)
|
||
- 其余参数=0: 禁用状态报告、广播消息等
|
||
```
|
||
|
||
### 5. 设置PDU模式
|
||
```
|
||
AT+CMGF=0
|
||
响应: OK
|
||
作用: 设置短信为PDU模式(支持中文、长短信)
|
||
```
|
||
|
||
### 6. 等待网络注册
|
||
```
|
||
AT+CEREG?
|
||
响应: +CEREG: <n>,<stat>
|
||
OK
|
||
作用: 查询LTE网络注册状态
|
||
<stat>值:
|
||
- 0: 未注册,未搜索
|
||
- 1: 已注册,本地网络
|
||
- 2: 未注册,正在搜索
|
||
- 3: 注册被拒绝
|
||
- 4: 未知状态
|
||
- 5: 已注册,漫游网络
|
||
成功条件: <stat>=1 或 5
|
||
```
|
||
|
||
## 短信接收(URC自动上报)
|
||
|
||
当收到短信时,模组会主动发送:
|
||
|
||
```
|
||
+CMT: ,<length>
|
||
<PDU_HEX_STRING>
|
||
```
|
||
|
||
**示例**:
|
||
```
|
||
+CMT: ,26
|
||
0891683108200005F0040D91683158148764F30000222151114270802C4F60597D
|
||
```
|
||
|
||
### PDU解析
|
||
|
||
PDU是十六进制字符串,需要使用PDU解析库(如 `node-pdu`)解析:
|
||
- **发送者号码**
|
||
- **时间戳**(YYMMDDHHMMSS格式,带时区)
|
||
- **短信内容**(支持中文UCS2编码)
|
||
- **长短信信息**(参考号、当前段号、总段数)
|
||
|
||
### 长短信处理
|
||
|
||
长短信PDU包含额外头部(UDH):
|
||
- **参考号** (Reference Number): 用于标识同一条长短信的不同分段
|
||
- **总段数** (Total Parts): 该长短信分为几段
|
||
- **当前段号** (Part Number): 当前是第几段(从1开始)
|
||
|
||
**合并逻辑**:
|
||
1. 检测到长短信(总段数 > 1)时,创建缓存槽位
|
||
2. 使用 `(参考号 + 发送者号码)` 作为唯一标识
|
||
3. 收到每一段后,存入对应位置
|
||
4. 收齐所有分段后,按段号顺序拼接内容
|
||
5. 30秒超时保护:未收齐也强制转发已收到的部分
|
||
|
||
## 短信发送(PDU模式)
|
||
|
||
### 1. 编码PDU
|
||
使用PDU编码库将目标号码和短信内容编码为PDU十六进制字符串。
|
||
|
||
### 2. 发送AT+CMGS命令
|
||
```
|
||
AT+CMGS=<length>
|
||
响应: > (提示符)
|
||
作用: 准备发送短信,<length>为PDU数据长度(字节数,不含SMSC)
|
||
```
|
||
|
||
### 3. 发送PDU数据
|
||
```
|
||
<PDU_HEX_STRING><Ctrl+Z>
|
||
响应: +CMGS: <mr>
|
||
OK
|
||
作用: 发送PDU数据,以Ctrl+Z(0x1A)结束
|
||
<mr>: 消息参考号
|
||
```
|
||
|
||
**完整流程示例**:
|
||
```
|
||
-> AT+CMGS=23
|
||
<- >
|
||
-> 0011000D91683158148764F30000AA05E4BDA0E5A5BD1A
|
||
<- +CMGS: 123
|
||
OK
|
||
```
|
||
|
||
## 其他常用命令
|
||
|
||
### 查询信号强度
|
||
```
|
||
AT+CSQ
|
||
响应: +CSQ: <rssi>,<ber>
|
||
OK
|
||
<rssi>: 信号强度 (0-31, 99=未知)
|
||
- 0-9: 弱
|
||
- 10-14: 一般
|
||
- 15-19: 好
|
||
- 20-31: 很好
|
||
- 99: 未知或不可检测
|
||
```
|
||
|
||
### 查询SIM卡状态
|
||
```
|
||
AT+CPIN?
|
||
响应: +CPIN: READY (或其他状态)
|
||
OK
|
||
状态:
|
||
- READY: SIM卡已就绪
|
||
- SIM PIN: 需要PIN码
|
||
- SIM PUK: 需要PUK码
|
||
```
|
||
|
||
### 查询ICCID
|
||
```
|
||
AT+CCID
|
||
响应: +CCID: <iccid>
|
||
OK
|
||
作用: 获取SIM卡ICCID(集成电路卡识别码)
|
||
```
|
||
|
||
### 查询IMEI
|
||
```
|
||
AT+GSN
|
||
响应: <imei>
|
||
OK
|
||
作用: 获取模组IMEI号
|
||
```
|
||
|
||
### 查询运营商
|
||
```
|
||
AT+COPS?
|
||
响应: +COPS: <mode>,<format>,<oper>
|
||
OK
|
||
示例: +COPS: 0,0,"CHINA MOBILE"
|
||
```
|
||
|
||
### 临时激活数据连接(用于Ping)
|
||
```
|
||
AT+CGACT=1,1
|
||
响应: OK
|
||
作用: 激活数据连接(用于网络测试后需关闭)
|
||
```
|
||
|
||
### Ping测试
|
||
```
|
||
AT+CPING="www.baidu.com",1,4,64,1000,10000,0
|
||
响应: +CPING: 1,<ip>,<time>,<ttl>
|
||
+CPING: 2,0,0,0,0
|
||
OK
|
||
参数: 域名,回显次数,数据包大小,超时,间隔,最大等待,保留
|
||
注意: 需要先激活数据连接(AT+CGACT=1,1)
|
||
```
|
||
|
||
### 删除所有短信(清理存储空间)
|
||
```
|
||
AT+CMGD=1,4
|
||
响应: OK
|
||
作用: 删除所有短信(参数4=删除所有)
|
||
```
|
||
|
||
## URC(主动上报)消息
|
||
|
||
### 短信到达
|
||
```
|
||
+CMT: ,<length>
|
||
<PDU_HEX_STRING>
|
||
```
|
||
|
||
### 网络注册状态变化
|
||
```
|
||
+CEREG: <stat>
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### 常见ERROR原因
|
||
- **命令格式错误**: 检查AT命令语法
|
||
- **参数错误**: 检查参数范围和类型
|
||
- **模组未就绪**: 确保模组已完成初始化
|
||
- **网络未注册**: 等待CEREG状态变为1或5
|
||
- **SIM卡未就绪**: 检查SIM卡是否插好
|
||
|
||
### 超时处理
|
||
- **AT命令超时**: 一般1-2秒,网络相关命令5-10秒
|
||
- **发送短信超时**: 30秒
|
||
- **网络注册超时**: 30次重试(约30-60秒)
|
||
|
||
### 重试策略
|
||
- 初始化命令失败:立即重试
|
||
- 网络注册失败:等待后重试
|
||
- 发送短信失败:记录日志,不重试
|
||
|
||
## Node.js实现要点
|
||
|
||
### 串口读取
|
||
- 使用 `serialport` 库
|
||
- 设置行解析器 (`@serialport/parser-readline`)
|
||
- 监听数据事件,逐行处理
|
||
|
||
### AT命令发送
|
||
```javascript
|
||
async function sendATCommand(cmd, timeout = 2000) {
|
||
return new Promise((resolve, reject) => {
|
||
let buffer = '';
|
||
port.write(cmd + '\r\n');
|
||
|
||
const timer = setTimeout(() => {
|
||
reject(new Error('Timeout'));
|
||
}, timeout);
|
||
|
||
const handler = (data) => {
|
||
buffer += data;
|
||
if (buffer.includes('OK') || buffer.includes('ERROR')) {
|
||
clearTimeout(timer);
|
||
port.removeListener('data', handler);
|
||
resolve(buffer);
|
||
}
|
||
};
|
||
|
||
port.on('data', handler);
|
||
});
|
||
}
|
||
```
|
||
|
||
### PDU解析
|
||
使用 `node-pdu` 库:
|
||
```javascript
|
||
const PDU = require('node-pdu');
|
||
|
||
const parsed = PDU.parse(pduHexString);
|
||
// parsed.sender: 发送者号码
|
||
// parsed.text: 短信内容
|
||
// parsed.time: 时间戳
|
||
```
|
||
|
||
### URC监听
|
||
```javascript
|
||
parser.on('data', (line) => {
|
||
if (line.startsWith('+CMT:')) {
|
||
// 下一行是PDU数据
|
||
isWaitingPDU = true;
|
||
} else if (isWaitingPDU && /^[0-9A-Fa-f]+$/.test(line)) {
|
||
// 收到PDU数据
|
||
handleSMS(line);
|
||
isWaitingPDU = false;
|
||
}
|
||
});
|
||
```
|
||
|
||
## 状态机设计
|
||
|
||
```
|
||
IDLE状态
|
||
└─ 收到 +CMT: → WAIT_PDU状态
|
||
└─ 收到十六进制行 → 解析PDU → 处理短信 → IDLE状态
|
||
└─ 收到非十六进制行 → IDLE状态
|
||
```
|