Cloud box frp client (aarch64 frpc bundled)
Project description
meiyoufrpclient(云盒 frp 客户端)
在蜂窝模块(如 Quectel RM500U)拨号联网后,从控制面 HTTP 拉取 frp 参数,生成本地 frpc 配置并启动客户端;同时提供本机状态 HTTP 接口,便于观测联网与配置阶段。
日志:运行目录下按天落盘 djcloudbox-YYYY-MM-DD.log(见 src/meiyoufrpclient/main.py)。
配置文件默认路径 ~/deploy/meiyoufrpclient.env(见 PyPI 安装);也可用 MEIYOUFRP_ENV 指定路径。包内提供 meiyoufrpclient.env.example 作模板。
启动流程简图(中文)
flowchart TD
A[启动入口 main] --> B[初始化日志 setup_logging]
B --> C[进入主编排 run_forever]
C --> D[执行 bootstrap]
D --> E[读取 client_sn]
E --> F[初始化云盒状态 cloud_state]
F --> G[启动本机状态接口 status_api]
G --> H[DNS 预检查 ensure_dns_configured]
H --> I[等待网络就绪 wait_network_ready]
I --> J{ICMP 探测是否可用}
J -->|可用| K[尝试预取远程配置 _try_fetch_config_as_connectivity]
J -->|不可用| L[后台拨号 sim_dial]
L --> M[拨号后 DNS 再检查]
M --> I
K --> N{是否已拿到配置}
N -->|是| O[写入 frpc.toml]
N -->|否| P[循环拉远程配置 wait_remote_config]
P --> O
O --> Q[启动 frpc 子进程]
Q --> R[进入看门狗循环]
R --> S[周期性网络检测 check_network_connection]
S --> T[更新 cloud_state 网络状态]
T --> T1[触发本机 D-BUS NetworkStatusChanged]
T1 --> SUB[订阅端如 MeiyouDrone 可转 MQTT]
T1 --> U[sleep 间隔]
U --> R
编排与状态相关环境变量(FRPCLIENT_*)
与 frpc.toml 中 frp 官方字段区分开,本进程编排与状态服务使用 FRPCLIENT_*:
| 变量 | 默认 | 作用 |
|---|---|---|
FRPCLIENT_POST_DIAL_WAIT_SEC |
3 |
拨号发出后等待几秒再做 DNS 复检 |
FRPCLIENT_DIAL_TIMEOUT_SEC |
30 |
单轮拨号后持续不通网超过该秒数则重拨 |
FRPCLIENT_CONFIG_RETRY_SEC |
30 |
拉控制面配置失败后的重试间隔 |
FRPCLIENT_WATCHDOG_INTERVAL_SEC |
5 |
主循环网络看门狗(ICMP)间隔 |
FRPCLIENT_STATUS_HOST |
127.0.0.1 |
状态 HTTP 绑定地址 |
FRPCLIENT_STATUS_PORT |
18080 |
状态 HTTP 端口 |
FRPCLIENT_NET_FAIL_THRESHOLD |
2 |
连续 ICMP 探测失败多少次后判定“离线”(用于 D-BUS/状态快照) |
FRPCLIENT_FRPC_BIN |
(自动探测) | frpc 可执行文件路径;未设置时依次尝试:本变量 → pip 包内 frpc_bin/frpc → PATH 中的 frpc |
FRPCLIENT_NO_DIAL |
(无) | 设为 1 时跳过 sim_dial(由 systemd 等单独管拨号时使用) |
FRPCLIENT_QUECTEL_CM |
quectel-CM |
拨号可执行文件路径 |
FRPCLIENT_QUECTEL_CM_SUDO |
1 |
设为 0 时不通过 sudo 调用拨号程序 |
FRPCLIENT_DIAL_VERBOSE |
0 |
设为 1 时在控制台打印 quectel-CM 详细输出;默认静默写日志 |
FRPCLIENT_DIAL_LOG_PATH |
quectel-cm-YYYY-MM-DD.log |
FRPCLIENT_DIAL_VERBOSE=0 时 quectel-CM 输出文件路径 |
配置文件查找顺序(启动时自动加载文件中全部键,不覆盖已存在的环境变量):
MEIYOUFRP_ENV指向的路径~/deploy/meiyoufrpclient.env- 源码/安装目录旁
deploy/meiyoufrpclient.env
控制面相关(写在上述 env 文件中):
| 变量 | 说明 |
|---|---|
CLOUD_BOX_SN |
云盒序列号;常用 eth0 MAC 大写、无冒号(例 XXXXXXXXXXXXXX) |
CLOUD_CONFIG_URL |
控制面 API,支持 {CLOUD_BOX_SN} |
CLOUD_API_SECRET |
控制面 api_secret(请求头 X-Api-Secret) |
MEIYOUFRP_ENV |
可选,显式指定 env 文件绝对路径 |
状态接口路由:
GET /health→{"ok": true}GET /api/v1/net/status→cloud_state快照,并含frp_running(是否检测到frpc进程)
本机 D-BUS 联网状态信号(可观测联动)
程序会在主循环的网络探测结果变化时,向系统 D-BUS 发出一个联网状态信号,供本机其它脚本订阅联动显示。
- Bus:默认
system - 对象路径:
/org/meiyoufrpclient/Network - 信号接口/成员:
org.meiyoufrpclient.Network.NetworkStatusChanged - 信号入参顺序:
string client_snboolean connectedint32 delay_msint32 online_duration_secondsstring last_seenstring status(在线/离线)
调试订阅:
dbus-monitor --system "type='signal',interface='org.meiyoufrpclient.Network',member='NetworkStatusChanged'"
订阅端建议放在其它包中(本机同机部署 MeiyouDrone 时,由其 dbus_subscriber 订阅 D-BUS 并用业务 MQTT 发布 cloudbox/{云盒SN}/network/status),或使用 dbus-monitor 调试。
可选开关:
FRPCLIENT_DBUS_ENABLE=0:禁用 D-BUS 广播FRPCLIENT_DBUS_BUS=session|system:选择session或system总线(默认 system)FRPCLIENT_DBUS_OFFLINE_REPEAT_SEC=5:离线状态下重复广播的最小间隔(秒);设为0关闭离线重复广播
网卡与探测(CLOUDBOX_*)
由 NetUtil.py 使用(ICMP 绑网卡顺序:先蜂窝相关接口,再有线):
CLOUDBOX_QUECTEL_IFACE:蜂窝接口列表,逗号分隔;默认含wwan0,并与自动发现的enx* USB 网卡组合。CLOUDBOX_ETH_IFACE:有线/无线接口列表,逗号分隔(例wlan0,eth0);默认eth0。DNS_RESOLVECTL_INTERFACE:若填写了本机不存在的网卡名,启动时会 WARNING 提示(不会静默失败)。CLOUDBOX_PING_HOST:ICMP 目标主机;默认223.5.5.5(IP 直连,避免 DNS 波动影响联网判定)。
若本机 ping 不支持 -I(常见于 BusyBox),会回退为默认路由 ping;需要按网卡探测时可安装 iputils-ping。
联网判定策略:先 ICMP(按网卡绑定 + 默认路由兜底)。在拨号阶段会直接尝试访问控制面配置接口,只要能返回合法 JSON 配置,即视为已联网并继续启动 frpc。
控制面 API 字段(v1.0.4+,仅认下列键名)
GET CLOUD_CONFIG_URL 返回 {"code":0,"data":{...}} 时,data 内须包含:
| 字段 | 示例 | 说明 |
|---|---|---|
frp_server_addr |
XXXXXX.com:7000 |
frps 地址,必须为 host:port |
frp_client_port |
5007 |
本机 SSH(22) 映射到云端的端口 |
frpclient_novnc_remote_port |
4007 |
本机 noVNC(6080) 映射到云端的端口 |
frp_token |
XXXXXX |
写入 frpc.toml 的 auth.token(必填) |
不再解析旧字段(如 serverAddr、FRPCLIENT_NOVNC_REMOTE_PORT、单独 frp_server_port 等)。缺任一项则拉配置失败并重试。
启动后 frpc.toml 含两条 TCP 代理:SSH → frp_client_port;noVNC → frpclient_novnc_remote_port(本地固定 6080,需板子运行 websockify + VNC 5900)。
外网 noVNC 示例(端口以 API 为准):
http://<frp_server_host>:<frpclient_novnc_remote_port>/vnc_auto.html?autoconnect=1&password=XXXXXX
仓库结构
说明:src/ 是源码根目录(src layout),实际 Python 包名是 meiyoufrpclient。
meiyou-frpclient/
├── README.md
├── pyproject.toml
├── requirements.txt
├── deploy/
│ ├── meiyoufrpclient.env
│ ├── meiyoufrpclient.service # 系统级 unit 示例(需 root)
│ └── djifrpclient.user.service # 用户级 unit 示例
└── src/
├── frpc_bin/
│ └── frpc # aarch64 静态链接 frpc(随 pip 包安装)
└── meiyoufrpclient/
├── main.py
├── orchestrator.py
├── cloud_state.py
├── status_api.py
├── remote_config.py
├── dns_connectivity.py
├── NetUtil.py
├── device_utils.py
├── frp.py
└── frpc.toml
模块职责一览
| 模块 | 作用 |
|---|---|
src/meiyoufrpclient/main.py |
包入口:meiyoufrpclient 脚本调用入口 |
src/meiyoufrpclient/orchestrator.py |
编排核心:状态服务 → DNS → 拨号 → 拉配置 → 启动 frp |
src/meiyoufrpclient/cloud_state.py |
线程安全快照:phase、net、remote_debug、last_config_error |
src/meiyoufrpclient/status_api.py |
只读 JSON,供现场或其它进程轮询 |
src/meiyoufrpclient/remote_config.py |
GET 控制面 JSON;解析 frp_server_addr 等四个 API 字段 |
src/meiyoufrpclient/dns_connectivity.py |
DNS 核心逻辑(resolvectl / resolv 兜底 + 自定义 DNS HTTP) |
src/meiyoufrpclient/NetUtil.py |
ICMP 与多网卡探测 |
src/meiyoufrpclient/device_utils.py |
sim_dial 等硬件相关调用 |
src/meiyoufrpclient/frp.py |
根据 API 生成 frpc.toml(SSH + noVNC)并 Popen 启动 frpc |
PyPI 安装
PyPI:https://pypi.org/project/meiyoufrpclient/
| 项 | 说明 |
|---|---|
| Python | 3.8+(嵌入式 Ubuntu 18.04 可用;建议 pip>=21) |
| pip 升级 | python3 -m pip install -U pip(3.8 可用 get-pip 3.8) |
| 架构 | wheel 捆绑 aarch64 frpc;x86 请自备并设 FRPCLIENT_FRPC_BIN |
国内用户推荐:
python3 -m pip install -U pip
python3 -m pip install meiyoufrpclient -i https://pypi.tuna.tsinghua.edu.cn/simple
官方源:
pip install meiyoufrpclient
安装后自检(无需先 source env,会自动读 ~/deploy/meiyoufrpclient.env):
meiyoufrpclient --check-config
wheel 内 frpc 位于 site-packages/frpc_bin/frpc;frpc.toml 由运行时写入包目录。env 不会自动创建,请复制模板:
mkdir -p ~/deploy
cp "$(python3 -c "import meiyoufrpclient, os; print(os.path.join(os.path.dirname(meiyoufrpclient.__file__), 'meiyoufrpclient.env.example'))")" ~/deploy/meiyoufrpclient.env
# 源码仓库也可: cp deploy/meiyoufrpclient.env ~/deploy/meiyoufrpclient.env
vi ~/deploy/meiyoufrpclient.env
1. 编辑 env 文件(标准路径 ~/deploy/meiyoufrpclient.env):
写入完整示例(按现场修改 SN、secret、网卡名;FRPCLIENT_FRPC_BIN 可省略):
# ---- 必填 ----
CLOUD_BOX_SN=XXXXXXXXXXXXXX
CLOUD_CONFIG_URL=https://XXXXXX/uav/other/cloudbox/api/box/{CLOUD_BOX_SN}
CLOUD_API_SECRET=XXXXXX
# ---- 主流程 ----
FRPCLIENT_POST_DIAL_WAIT_SEC=31
FRPCLIENT_DIAL_TIMEOUT_SEC=30
FRPCLIENT_CONFIG_RETRY_SEC=30
FRPCLIENT_WATCHDOG_INTERVAL_SEC=5
# ---- 拨号 ----
FRPCLIENT_NO_DIAL=0
FRPCLIENT_QUECTEL_CM=quectel-CM
FRPCLIENT_QUECTEL_CM_SUDO=1
FRPCLIENT_DIAL_VERBOSE=0
FRPCLIENT_DIAL_LOG_PATH=quectel-cm.log
# ---- frpc(可选;默认使用 pip 包内 site-packages/frpc_bin/frpc)----
# FRPCLIENT_FRPC_BIN=/path/to/custom/frpc
# frp / noVNC 云端端口仅由 API 下发,勿设 FRPCLIENT_NOVNC_REMOTE_PORT
# ---- 状态接口 ----
FRPCLIENT_STATUS_HOST=127.0.0.1
FRPCLIENT_STATUS_PORT=18080
# ---- DNS ----
DNS_PROBE_HOST=www.baidu.com
DNS_FALLBACK_NAMESERVERS=223.5.5.5,114.114.114.114
DNS_MANAGE_RESOLV_CONF=1
DNS_RESOLVECTL_INTERFACE=wlan0
# ---- 联网探测 ----
CLOUDBOX_QUECTEL_IFACE=wwan0,enxb657fb68191c
CLOUDBOX_ETH_IFACE=wlan0,eth0
CLOUDBOX_PING_HOST=223.5.5.5
保存:按 Esc,输入 :wq 回车。
2. 前台试运行(程序会自动加载 ~/deploy/meiyoufrpclient.env,一般无需 source):
meiyoufrpclient --check-config # 建议先自检
meiyoufrpclient
3. 用户级 systemd 自启(推荐)
pip 部署时由 systemd 的 EnvironmentFile 注入全部变量,无需 source。妙算等设备无 sudo 时使用用户级 unit。
启用前先停掉前台或 nohup 实例,避免端口 18080 冲突:
pkill -f '\.local/bin/meiyoufrpclient' 2>/dev/null || true
pkill -x frpc 2>/dev/null || true
新建 unit 文件(示例可直接拷贝,按现场改 Python 版本路径):
mkdir -p ~/.config/systemd/user
vi ~/.config/systemd/user/djifrpclient.service
写入:
[Unit]
Description=meiyoufrpclient (pip install, user service)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
EnvironmentFile=-%h/deploy/meiyoufrpclient.env
ExecStart=%h/.local/bin/meiyoufrpclient
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.target
保存后启用:
systemctl --user daemon-reload
systemctl --user enable --now djifrpclient
loginctl enable-linger "$USER" # 未登录时也保持用户服务运行
说明:%h 为当前用户 home;env 默认 %h/deploy/meiyoufrpclient.env。pip 安装的 unit 示例亦在 share/meiyoufrpclient/systemd/。
常用运维:
systemctl --user status djifrpclient
journalctl --user -u djifrpclient -f
systemctl --user restart djifrpclient # 改 env 后重启
systemctl --user disable --now djifrpclient
4. 系统级 systemd 自启(需 root,可选)
有 sudo 的服务器可用系统级 unit,以指定用户(如 meiyou)运行 pip 安装的 meiyoufrpclient。env 路径为 ~/deploy/meiyoufrpclient.env(须由运行用户创建)。
sudo vi /etc/systemd/system/meiyoufrpclient.service
写入(将 meiyou 与 /home/meiyou 改为实际运行用户):
[Unit]
Description=meiyoufrpclient (pip install)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=meiyou
Group=meiyou
EnvironmentFile=-/home/meiyou/deploy/meiyoufrpclient.env
ExecStart=/home/meiyou/.local/bin/meiyoufrpclient
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
保存后启用:
sudo systemctl daemon-reload
sudo systemctl enable --now meiyoufrpclient
journalctl -u meiyoufrpclient -f
说明:须以目标用户执行 pip install meiyoufrpclient;env 放在该用户 ~/deploy/ 下。妙算等无 sudo 设备用上文 §3 用户级 unit 即可。
Ubuntu 18.04 + aarch64(妙算 / Wheeltec 等)
- Python 3.8 + pip:
python3 -m pip install -U pip(必要时用 get-pip 3.8 脚本) pip install meiyoufrpclient -i https://pypi.tuna.tsinghua.edu.cn/simplemkdir -p ~/deploy,从meiyoufrpclient.env.example复制并填写 SN(eth0 MAC 大写无冒号)meiyoufrpclient --check-config→meiyoufrpclient或配置用户级 systemd- 状态:
curl -sS http://127.0.0.1:18080/api/v1/net/status
启动方式
开发环境运行(不安装,frpc 自动使用 src/frpc_bin/frpc):
PYTHONPATH=src python3 -m meiyoufrpclient.main
源码 editable 安装(同样包含 frpc_bin):
python3.9 -m pip install -e .
meiyoufrpclient
源码部署 + 环境文件:
set -a && source deploy/meiyoufrpclient.env && set +a
python3 -m meiyoufrpclient.main
源码目录用户级 systemd:示例见 deploy/djifrpclient.user.service;生产 pip 部署见上文 PyPI 安装 §3。
系统级 systemd(需 root):见上文 PyPI 安装 §4;仓库参考 deploy/meiyoufrpclient.service。
查看状态:
curl -sS http://127.0.0.1:18080/health
curl -sS http://127.0.0.1:18080/api/v1/net/status
本机快速自检(与客户端相同的 DNS/ICMP 逻辑):
PYTHONPATH=src python3 -m meiyoufrpclient.check_network
PYTHONPATH=src python3 -m meiyoufrpclient.check_network --status
依赖
见 pyproject.toml:Python ≥ 3.8,psutil>=5.6.4;wheel 捆绑 aarch64 frpc(约 14MB)。变更见 CHANGELOG.md。
联网状态通过 D-BUS 发出,由 D-BUS 等订阅端转发 。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file meiyoufrpclient-1.0.4.tar.gz.
File metadata
- Download URL: meiyoufrpclient-1.0.4.tar.gz
- Upload date:
- Size: 5.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5ca341c647226677b7e73c748c24a14b116871a1e0c2f5ba018cd43891a9a22
|
|
| MD5 |
4cb9a9309a9d580143642cc27118cef9
|
|
| BLAKE2b-256 |
7cf504a060f2be4db8bbf73cf56a551435b3e659f032780fddd56da1bb227a2a
|
File details
Details for the file meiyoufrpclient-1.0.4-py3-none-any.whl.
File metadata
- Download URL: meiyoufrpclient-1.0.4-py3-none-any.whl
- Upload date:
- Size: 5.5 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d793b3b29158b32545f1a9836dd81ed827ca092c97ef48fca1224e68e383dfd1
|
|
| MD5 |
014f9688a90dde28fb9976948d7885d4
|
|
| BLAKE2b-256 |
46e104c7c4cf0b23f1d31810f72aa2801ccf7a7fb39ba2b2cbc4be64e04c7174
|