@
SUP7R9 我用的 esp32S3 ,模块是合宙 air724UG ,串口连接。
这个方案只能接收/发送短信,拨打电话和接听电话都只能播放设定 tts 语音,没有 sip 功能,需要 sip 得用 ec20 。移动端不需要和服务端通信,只要能接收设置渠道的通知即可。
题材太敏感,没法开源,只能给你提示词。如果你的卡本身有流量的话 github 上有很多开源的转发项目,都不需要 esp32 。
我还为这个项目设计了 pcb 和外壳



# LTE-Gateway 架构分析与复刻指南
# 第一部分:架构分析
## 1. 整体结构
```
┌─────────────────────────┐ UART1 115200 JSON (v2) ┌──────────────────────────┐
│ Air724UG 4G 模块 │◄──────────────────────────►│ ESP32-S3 主控 │
│ (LuatOS / Lua 固件) │ 每行一个 JSON, 事件驱动 │ (PlatformIO + Arduino) │
│ │ │ │
│ · 短信收发 │ │ · Web 控制台 (单文件 SPA) │
│ · 外呼 + 通话中 TTS │ │ · 管理员认证 (PBKDF2) │
│ · 来电 4 种默认策略 │ │ · 联系人/短信/通话/录音管理 │
│ · 来电筛查(等主控决策) │ │ · 骚扰拦截(黑白名单+关键词)│
│ · SD 卡通话录音(WAV) │ │ · 消息通知(5 种通道) │
│ · LED 状态指示 │ │ · MQTT + Home Assistant │
│ · 看门狗/心跳 │ │ · 备份恢复(AES 加密) │
└─────────────────────────┘ │ · OTA / 配网 AP / 恢复出厂 │
└──────────────────────────┘
# 第二部分:复刻提示词
## 第 1 步:基础骨架提示词(一次性把双端跑通)
```markdown
# 角色
你是资深嵌入式固件 + IoT 全栈工程师。请帮我从零实现一个 "LTE 网关" 项目,
由两部分组成,先搭建骨架并把整条链路跑通(能收发短信),后续功能我会按迭代清单逐步添加。
# 硬件与软件环境
1. Air724UG 4G Cat.1 模块,跑 LuatOS(Lua)。业务代码 + LuatOS 标准库(lib/ 用官方 LuatOS 自带的 sys/net/sim/sms/cc/audio/pmd/ril 等模块,无需自研)。
2. ESP32-S3(8MB flash + PSRAM),PlatformIO + Arduino 框架,board=esp32-s3-devkitc-1,
flash 8MB,qio_opi,开启 PSRAM 。依赖:ArduinoJson v6 、PubSubClient 。
3. 分区表(partitions_8m_storage.csv):
nvs/otadata/phy_init/ota_0(0x1E0000)/ota_1(0x1E0000)/
storage(data fat 0x2F0000,独立 FAT 分区,持久化数据,固件 OTA 不丢失)/
spiffs(0x140000,存 Web 前端 LittleFS)。
4. 连线:Air724UG TX1→ESP32 GPIO17, RX1→ESP32 GPIO18,115200 8N1 。
Air724UG 上 GPIO5=SYS LED,GPIO4=LTE LED;SD/TF 卡接 GPIO24-28,由 LDO_VMMC 供电。
# 第 1 部分:Air724UG Lua 固件
文件结构:main.lua(入口)、protocol.lua(UART JSON 协议层)、gateway.lua(命令分发)、
sms_handler.lua(短信)、call_handler.lua(电话/TTS/来电筛查)、recording_manager.lua(录音)、
status_builder.lua(状态字段聚合)、led_controller.lua(LED)。
要求:
- protocol.lua:UART1 115200;发送走队列+独立 worker,按行字节数估算发送间隔(8N1≈10bit/byte,
下限 8ms 上限 180ms)避免挤爆缓冲;接收按 \n 切行、行上限 2048 、缓冲上限 4096;
每行一个 JSON;发送前 json.encode,失败发 error 事件。
- 命令(cmd,主机→模块)骨架阶段先实现:status(回完整状态)、sms(发送短信,校验号码≤32 位
格式 ^\+?[\d\*#]+$、文本≤1024)、reboot(200ms 后 sys.restart)。
其余命令(call/set_call_cfg/incoming_call_control/录音系列)先注册空实现或按后续迭代实现。
- 来电策略:action 0=忽略 1=挂断 2=接听+TTS 3=响 N 声(默认 3,每声 4s)后接听+TTS,
TTS 文本可配置(默认"您好,您拨打的号码已停用,请勿再次拨打。")。
call_handler 实现状态机:idle/dialing/ringing_in/connected/tts_playing/ending;
接通超时 60s 强挂、TTS 超时 30s 强挂;挂断原因归类(接听/无人接听/对方正忙/对方拒接/无拨号音/挂断)。
支持来电筛查:screening=true 时收到来电先发 incoming_call 事件并挂起等待,
超时 decision_timeout_ms(默认 3000,范围 500-15000)未收到决策则回退默认策略。
- 事件(evt,模块→主机):ready 、status 、log 、error 、rebooting 、sms_recv 、sms_sent 、
call_start 、call_connected 、tts_done 、call_end 、incoming_call 、incoming_answering 、
incoming_answered 、incoming_tts_done 、incoming_hangup 、incoming_call_control_ack 、call_cfg_set 。
- status/ready 事件字段:csq 、net_state 、sim_status 、temp 、iccid 、imei 、project 、version 、
call_action 、call_tts 、call_rings 、screening 、decision_timeout_ms 、
protocol_version=2 、features=["incoming_call_screening"]。
- 周期任务:每 5s 发一次轻量 status(不带 iccid/imei 等重字段)+ LED 心跳;
每 30s 读一次模块温度;等待网络注册(60s 超时继续);SIM 状态变化更新 LED 。
- LED:SYS(GPIO5)开机快闪→正常慢闪,主循环 12s 无心跳判 hung 熄灭;
LTE(GPIO4)无 SIM 灭、搜网快闪、已注册 4G 慢闪。
- 启动时发 AT+SETVOLTE=1;LDO_VMMC 提前拉高到 level 15(3.177V,接近 SD 卡 3.3V 需求)
并做版本兼容(旧固件用数字索引 3)。
# 第 2 部分:ESP32-S3 主控 (src/main.cpp)
骨架阶段要求:
- Serial1(GPIO17/18, 115200, 接收缓冲 8192)读模块 JSON 行,解析后按 evt 分发:
维护模块状态(ready/csq/imei/iccid/net_state/sim_status/temp/协议版本/能力位);
15s 无数据判模块离线并重置状态。
- 收到 ready/status 后,向模块同步已保存的来电配置(set_call_cfg)和录音配置。
- WiFi:AP+STA 双模,AP 名 "LTE-Gateway"(开放,无密码)带 captive portal 探测
(/generate_204 、/hotspot-detect.html 、/ncsi.txt 等返回 200/302);STA 连接可配置 WiFi,
支持静态 IP 、扫描列表;STA 连接中 AP 常开,连上后按配置决定是否保留。
- Web:端口 80,WebServer,单文件前端 data/index.html(LittleFS 提供,
非 API 路径全部回退到 index.html,即 SPA)。
- 认证:用户名固定 admin,密码首次未设置时引导 bootstrap(设置向导页:设密码→配 WiFi),
密码用 PBKDF2(500 次迭代,16 字节 salt,存 NVS);会话用 Cookie "ltegw_session"
(随机 token,TTL 12h,最多 4 个会话);所有 /api/* 写接口和部分读接口需登录。
- 前端骨架(单 HTML 文件,内联 CSS+JS,中文界面):
登录页 + 设置向导;主界面 9 个 Tab:状态/设置/联系人/短信/电话/骚扰拦截/通知/系统/日志。
骨架阶段先实现:状态 Tab(轮询 /api/status 显示信号、SIM 、IMEI 、模块在线、WiFi 、堆内存)、
日志 Tab(轮询 /api/logs)、短信 Tab(列表+发送框,调 /api/module/sms)。
- 数据持久化:短信/通话记录用 JSON Lines 存 storage FAT 分区(/sms.log 、/calls.log),
上限各 1200 条,超出时压缩(保留最新);内存中保留热缓存(PSRAM 可用时上限调大)。
记录字段:SmsRecord{ts,dir(in/out),peer,text,status(pending/sent/failed)},
CallRecord{ts,dir,peer,connected,result,reason}。
所有文件写操作走"写临时文件+rename"原子方式;掉电后启动时恢复未完成的临时文件。
- API(骨架阶段):GET /api/status 、/api/logs,POST /api/logs/clear 、
/api/module/sms 、/api/module/status 、/api/module/reboot 、
/api/sms(GET 分页+POST /api/sms/clear)、/api/calls(同上)、
/api/auth/(status/bootstrap/login/logout)、POST /api/config(wifi/mqtt 配置存取)、
POST /api/reboot 、/api/factory_reset 。
- 看门狗:esp_task_wdt 30s,主循环喂狗;记录 reset reason 到日志。
- 通用约束:全部代码 UTF-8;JSON 用 ArduinoJson;避免在 loop 里做阻塞操作;
记录/配置读写做越界与坏行容错;中文界面文案。
# 串口 JSON 协议(v2)——两端必须严格遵守的契约
- 物理:UART1 115200 8N1,每行一个 JSON,UTF-8 。
- 主机→模块:{"cmd":"...","参数..."};模块→主机:{"evt":"...","字段..."};
错误统一 {"evt":"error","msg":"...","code":"..."}。
- 命令:status / sms{to,text} / call{to,tts} /
set_call_cfg{action(0-3),tts,rings(1-20),screening(bool),decision_timeout_ms(500-15000)} /
incoming_call_control{from,action:hangup|allow_default} / reboot /
set_recording_cfg{enabled,mode:all|incoming|outgoing|voicemail|off,max_seconds,min_seconds,
voicemail_enabled,voicemail_prompt} / recording_storage / recording_delete{id} /
recording_clear / recording_play{id} / recording_stop_play / recording_fetch_chunk{id,offset,len}。
- incoming_call_control_ack:{from,action,ok,code?,msg?},失败 code:
LATE_CONTROL/STATE_MISMATCH/NUMBER_MISMATCH/INVALID_ACTION 。
- 事件:见上面 Air724UG 部分列表 + 录音系列(recording_started/recording_finished/
recording_failed/recording_storage/recording_chunk{id,offset,len,size,eof,data(base64)}/
recording_deleted/recordings_cleared/recording_play/recording_play_done/
voicemail_recording)。
- 能力协商:主机通过 status 的 protocol_version 和 features 判断模块是否支持
来电筛查(incoming_call_screening)和通话录音(call_recording_v1);
旧版模块无这些字段时,对应功能降级并在界面提示"模块不支持"。
# 验收标准
1. Air724UG 上电后 60s 内在串口发出 ready 和周期 status;ESP32 能收到并正确显示。
2. Web 控制台:未设密码走设置向导;设置后可登录;短信 Tab 能收(模块上报 sms_recv 落盘+显示)
能发(调 /api/module/sms 后模块回 sms_sent 更新状态)。
3. 断电重启后短信记录不丢;固件重刷后 storage 分区数据仍在。
4. 两端代码都要有清晰的模块划分,关键路径(串口收发、状态机、文件 IO)有日志。
```