ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Meshtastic 固件 Fake NodeDB Fixtures:确定性节点数据库测试数据生成与加载指南

Meshtastic 固件 Fake NodeDB Fixtures:确定性节点数据库测试数据生成与加载指南 物联网嵌入式通信智能硬件【免费下载链接】firmwareThe official firmware for Meshtastic, an open-source, off-grid mesh communication system.项目地址https://gitcode.com/GitHub_Trending/fi/firmware点击查看免费下载本指南围绕 Meshtastic 开源固件仓库中的 test/fixtures/nodedb/README.md 展开系统讲解其 Fake NodeDB Fixtures 测试数据流水线如何用确定性 JSONL 种子文件生成 v25meshtastic_NodeDatabase二进制原型文件并加载到 Portduino 模拟器或 USB 硬件设备上用于测试固件启动时NodeDB::loadFromDisk的节点数据库读取、裁剪与迁移逻辑。读完本文你将掌握种子生成、时间戳语义、设备白名单与角色白名单约束、proto 编译、手工场景编辑以及 XModem 推送硬件等一整套可复现的测试数据操作流程。一、什么是 Fake NodeDB Fixturestest/fixtures/nodedb/目录下存放的是确定性的 JSONL 种子文件每一行代表一个看起来真实的 Meshtastic 对端节点NodeInfoLite 头部 可选的 PositionLite / DeviceMetrics / EnvironmentMetrics / StatusMessage 卫星数据配套工具链负责把它们编译为二进制.proto文件并推到设备上测试。这套 fixture 面向固件 v25 的meshtastic_NodeDatabase磁盘格式对应设备端文件/prefs/nodes.proto常量定义见 src/mesh/NodeDB.h用途是让测试环境拥有一份最近刚听到过邻居的节点数据库快照从而验证冷启动时loadFromDisk()见 src/mesh/NodeDB.cpp对 v25 文件的解析与版本检查超过平台节点上限时nodeDBSelfCare()见 src/mesh/NodeDB.cpp的截断 / 降级 / 重写逻辑旧版本nodes.proto文件的迁移路径DEVICESTATE_MIN_VER 24、DEVICESTATE_CUR_VER 25见 src/mesh/NodeDB.h。默认地理位置以美国新墨西哥州 Truth or Consequences, NM33.1284°N, 107.2528°W为中心节点按 60 km 的高斯分布铺开如需要不同的地理分布可在生成种子时用--centroid与--spread-km调整。目录内容文件大小用途seed_v25_0250.jsonl~200 KB匹配 ESP32-S3 高闪存档的MAX_NUM_NODES上限seed_v25_0500.jsonl~400 KB介于各平台上限之间的压力场景seed_v25_1000.jsonl~800 KB大型网状网络压力场景seed_v25_2000.jsonl~1.6 MB截断/驱逐压力超出所有平台上限其中 250 节点档位正好对应固件侧的迁移解码上限NODEDB_MIGRATION_LOAD_CEILING 250src/mesh/NodeDB.h——即其它固件写出的 nodes.proto 在解码流中的最大节点数它不是本构建的节点上限本构建上限是MAX_NUM_NODES在 Portduino 上是运行时值portduino_config.MaxNodes默认 200见 variants/native/portduino/variant.h在真实硬件上是编译期常量。二、流水线总览从种子到设备数据经过如下三级流水线bin/gen-fake-nodedb-seed.py ↓ (single Random(seed); no wall-clock dependence) test/fixtures/nodedb/seed_v25_N.jsonl ← committed, hand-editable ↓ bin/seed-json-to-proto.py ↓ (resolves *_offset_sec → now-relative epochs at compile time) build/fixtures/nodedb/nodes_v25_N.proto ← .gitignored, fresh timestamps ↓ - Portduino: cp to ~/.portduino/config/prefs/nodes.proto - Hardware: XModem upload via the meshtastic-mcp push_fake_nodedb tool三个环节各自职责清晰种子生成bin/gen-fake-nodedb-seed.py用固定随机种子生成结构字段产出可提交、可手工编辑的 JSONLproto 编译bin/seed-json-to-proto.py把 JSONL 解析为NodeDatabaseprotobuf 并序列化为二进制输出被.gitignore忽略的构建产物加载Portduino 直接拷贝到 prefs 目录真实硬件则通过 XModem 协议推送到/prefs/nodes.proto。编译侧的核心入口是loadFromDisk()中通过loadProto(nodeDatabaseFileName, ...)对/prefs/nodes.proto的pb_decode解码src/mesh/NodeDB.cpp随后按版本号决定丢弃重装默认值 / 迁移 / 直接使用。三、确定性契约结构确定、时间戳新鲜这套 fixture 最核心的设计约束是结构字段确定 时间戳非确定两者分别服务于可复现测试与看起来像刚听到过的真实感。3.1 结构字段固定 seed 即逐字节一致给定固定--seed以下字段完全确定NodeInfoLite头部num、long_name、short_name、hw_model、role、public_key、snr、channel、hops_away、next_hop、全部bitfield标志位PositionLite纬度/经度/海拔与位置来源DeviceMetrics电池电量、电压、信道占用、发送占用、运行时长EnvironmentMetrics温度、湿度、气压、IAQStatusMessage状态文本通常为健康状态。种子生成器只使用单个random.Random(args.seed)实例不依赖墙钟时间输出 JSONL 时启用sort_keysTrue与ensure_asciiFalse保证同一 seed 在任何 Python 版本下都产出逐字节一致的 JSONL详见 bin/gen-fake-nodedb-seed.py。文件首行的_meta中generated_at_iso由 seed 推导而来而非墙钟因此也不影响确定性。3.2 时间戳offset 相对时间编译时解析JSONL 中所有时间都以*_offset_sec距 now 多少秒存储例如last_heard_offset_sec、position.time_offset_sec。编译步骤把它们从当前墙钟减去得到绝对 Unix epochdef _resolve_time(node, field_absolute, field_offset, now_epoch): if field_absolute in node and node[field_absolute] is not None: return int(node[field_absolute]) # 绝对时间优先 offset node.get(field_offset, 0) return max(0, int(now_epoch) - int(offset)) # 否则 now - offset实现见 bin/seed-json-to-proto.py这样无论 fixture 何时生成加载到设备上的 NodeDB 都呈现最近刚刚听到的对端。需要为 CI 产出逐字节一致的构建产物时可给编译步骤传入--now-epoch T钉死当前时刻。四、设备与角色白名单只生成真实活跃的配置为了让 fixture 贴近现实部署、避免污染测试语义种子生成对hw_model和role做了两层白名单约束。4.1 Active-board 设备白名单hw_model被限制为以下两个集合的交集在variants/*/*/platformio.ini中声明custom_meshtastic_support_level 1的板卡变体即官方一等公民支持板例如variants/esp32c3/heltec_esp32c3/platformio.ini、variants/esp32c6/m5stack_unitc6l/platformio.ini等HardwareModel枚举中存在的值。这样会自然排除已废弃/旧版板卡Heltec V1-V2、TLORA V1-V2、经典 TBEAM(4) 与 TBEAM_V0P7(6)、Nano G1、Station G1/G2 等以及仅供 fuzzer 使用的哨兵值PORTDUINO、ANDROID_SIM、DIY_V1、LORA_RELAY_V1 等。实际抽样的权重表HW_MODEL_WEIGHTS定义在 bin/gen-fake-nodedb-seed.pyHeltec V3 权重最高14.0T_DECK9.0、HELTEC_V4 / RAK46318.0次之其余板卡按 0.3 的均匀低权重构成长尾模拟真实网格中主流设备占比更高的分布。当新板卡晋升为 tier-1或旧板卡退役时需要同步刷新该权重表。README 提供了一行命令打印当前交集for f in $(find variants -name platformio.ini | xargs grep -lE custom_meshtastic_support_level 1); do grep custom_meshtastic_hw_model_slug $f | awk -F {print $2} | tr -d done | sort -u | comm -12 - ( bin/_generated/meshtastic_v25/__init__.py /dev/null 21 || ./bin/regen-py-protos.sh 2 python3 -c import sys; sys.path.insert(0,bin/_generated); \ from meshtastic_v25.mesh_pb2 import HardwareModel; \ print(\n.join(HardwareModel.keys())) | sort )注意该命令会先确保仓库内生成的 Python protobuf 绑定存在不存在则调用bin/regen-py-protos.sh。4.2 Role 角色白名单role从非废弃的Config.DeviceConfig.Role值中抽取权重表见 bin/gen-fake-nodedb-seed.py已排除ROUTER_CLIENTv2.3.15 起废弃、REPEATERv2.7.11 起废弃在册CLIENT权重 75.0占绝大多数、CLIENT_MUTE、ROUTER、TRACKER、SENSOR、TAK、CLIENT_HIDDEN、LOST_AND_FOUND、TAK_TRACKER、ROUTER_LATE、CLIENT_BASE。4.3 其他现实化细节种子生成器还模拟了大量真实细节bin/gen-fake-nodedb-seed.py名称池60 个首词 × 60 个尾词共 3600 种组合5% 概率附加类似呼号的后缀如KX7ABlong_name硬限制 24 字符对应 nanopbmax_size:25减去 NULshort_name10% 概率为纯 emoji其余为首字母 3 位字母数字emoji 池只选取 4 字节以内的如 、显式排除带变音选择符的 ❄️/☀️6 字节会撑爆 nanopbmax_size:5hops_away按近似几何分布0 跳 55%、1 跳 25%、2 跳 12%、3 跳 5%、4 跳 2%、5-7 跳 1%电池5% 概率为插电状态battery_level 101、voltage 4.20其余均匀分布在 10-100 并线性映射到 3.3-4.2V92% 节点携带 32 字节公钥8% 无密钥空字符串状态文本 92% 为健康词OK / online / running...8% 为告警词low-batt / no-gps / weak-signal...。五、快速上手四条常用操作路径5.1 用新鲜时间戳重新编译日常最常用./bin/regen-fake-nodedbs.sh该脚本bin/regen-fake-nodedbs.sh按固定尺寸/种子对SIZES(250 500 1000 2000)、SEEDS(20260511 20260512 20260513 20260514)循环只从已提交的 JSONL 重新编译四个.proto到build/fixtures/nodedb/时间戳使用当前墙钟。适合在设备刚刷机后想要看起来最近活跃的缓存状态时重跑。脚本同时负责首次运行自动调用./bin/regen-py-protos.sh生成仓库内 Python protobuf 绑定优先使用.venv/bin/python3否则回退系统python3需装有meshtastic依赖或通过uv run --with meshtastic执行。5.2 有意刷新种子重生成 JSONL 结构REGEN_SEEDSyes ./bin/regen-fake-nodedbs.sh设置环境变量REGEN_SEEDSyes后脚本会先用bin/gen-fake-nodedb-seed.py覆盖提交的 JSONL 文件再编译 proto。生成的结构性数据发生改变需将 JSONL 改动提交进仓库。5.3 手工编辑特定场景# 找到要调整的节点原地编辑该行。 $EDITOR test/fixtures/nodedb/seed_v25_0250.jsonl # 重新编译并推送。 ./bin/regen-fake-nodedbs.shJSONL 每行是一个节点首行是元数据。字段 schema 内联记录在 bin/gen-fake-nodedb-seed.py 中。若想覆盖某个时间戳直接把last_heard_offset_sec替换为last_heard绝对 epoch编译步骤会优先采用绝对时间。真实节点行示例取自seed_v25_0250.jsonl{bitfield: {has_is_unmessagable: true, has_user: true, is_favorite: false, is_ignored: false, is_key_manually_verified: false, is_licensed: false, is_muted: false, is_unmessagable: false, via_mqtt: false}, channel: 0, hops_away: 2, hw_model: HELTEC_WIRELESS_TRACKER_V2, last_heard_offset_sec: 4809, long_name: Drifting Phoenix, next_hop: 253, num: 0x0005e869, position: {altitude: 1338, latitude: 33.690292, location_source: LOC_INTERNAL, longitude: -106.436201, time_offset_sec: 4996}, public_key_hex: 056060d6ceae374c7ee39ffb5fb6c2503d238610f2277c47e7cc008a9a096dc5, role: CLIENT, short_name: DB5I, snr: 6.64, status: {status: ready}, telemetry: null}5.4 加载到 PortduinomacOS / Linux 原生模拟器cp build/fixtures/nodedb/nodes_v25_1000.proto ~/.portduino/default/prefs/nodes.proto # 运行原生二进制loadFromDisk 会在启动时读取该文件。Portduino 运行时节点上限来自配置文件portduino_config.MaxNodes默认 200见 variants/native/portduino/variant.h因此 250/500/1000/2000 档位的 fixture 正好可以分别验证等于上限、超过上限时的自护理行为加载后nodeDBSelfCare()会把超出的节点截断到MAX_NUM_NODESsrc/mesh/NodeDB.cpp并确保自身节点self被固定到索引 0。5.5 推送到 USB 硬件meshtastic-mcp在 meshtastic-mcp 工具面内调用push_fake_nodedbpush_fake_nodedb( size500, targethardware, port/dev/cu.usbmodem21301, # 通过 list_devices 发现 confirmTrue, # 门禁拦截破坏性写入 重启 )该工具把 proto 以XModem 协议流式传输到/prefs/nodes.proto然后触发 1 秒重启让loadFromDisk在下一次启动时读取。传输细节CRC16-CCITT 校验每个块每个块收到 NAK 后最多重试 5 次超过则发送CAN中止。六、JSONL Schema 参考num是十六进制字符串如0xa1b2c3d4public_key_hex为 64 个十六进制字符32 字节无密钥节点为空字符串hw_model与role使用枚举名称编译步骤通过HardwareModel.Value(name)/Config.DeviceConfig.Role.Value(name)解析未知名称会抛ValueError这正是指定的校验方式见 bin/seed-json-to-proto.py。6.1 bitfield命名布尔位打包bitfield是一组命名布尔值编译时按位位置打包成整数。位布局与固件侧 src/mesh/NodeDB.h 的NODEINFO_BITFIELD_*_SHIFT一一对应JSON 键位位置固件宏shiftis_key_manually_verified0NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIEDis_muted1NODEINFO_BITFIELD_IS_MUTEDvia_mqtt2NODEINFO_BITFIELD_VIA_MQTTis_favorite3NODEINFO_BITFIELD_IS_FAVORITEis_ignored4NODEINFO_BITFIELD_IS_IGNOREDhas_user5NODEINFO_BITFIELD_HAS_USERis_licensed6NODEINFO_BITFIELD_IS_LICENSEDis_unmessagable7NODEINFO_BITFIELD_IS_UNMESSAGABLEhas_is_unmessagable8NODEINFO_BITFIELD_HAS_IS_UNMESSAGABLE打包实现见 bin/seed-json-to-proto.py。固件侧对位标志的使用收藏、忽略、密钥手动验证等受保护标志可在 src/mesh/NodeDB.cpp 中看到读取示例。6.2 可空卫星数据与覆盖比率position/telemetry/environment/status均可为null种子生成时由覆盖比率参数决定哪些节点携带哪些卫星数据默认值也写死在regen-fake-nodedbs.sh调用中为--position-coverage0.8585% 节点有位置--telemetry-coverage0.70--environment-coverage0.25--status-coverage0.40编译后分别落入NodeDatabase的positions/telemetry/environment/status卫星数组v25 新增结构这正是seed-json-to-proto.py启动时断言NodeDatabase.DESCRIPTOR.fields_by_name中存在positions的原因——若加载到旧于 v25 的 protobuf 绑定会直接报错并提示运行bin/regen-py-protos.shbin/seed-json-to-proto.py。6.3 经纬度浮点度数 → 1e-7 整数latitude/longitude在 JSONL 中为浮点度数编译时按固件PositionLite的存储方式转换为int32微度pl.latitude_i int(round(float(pos[latitude]) * 1e7)) pl.longitude_i int(round(float(pos[longitude]) * 1e7))见 bin/seed-json-to-proto.py。海拔在种子生成时以 Truth or Consequences 谷底地形为基准按均值 1376 m、标准差 250 m 的高斯分布取样。6.4 其他种子生成参数bin/gen-fake-nodedb-seed.py支持完整的命令行参数bin/gen-fake-nodedb-seed.py参数默认值说明--count必填生成节点数--seed必填确定性随机种子--out必填JSONL 输出路径--centroid33.1284,-107.2528经纬度中心--spread-km60.0高斯分布标准差km--position/--telemetry/--environment/--status-coverage0.85 / 0.70 / 0.25 / 0.40各卫星数据覆盖比率--my-node-num无从生成集合中排除的本机 NodeNum十六进制或十进制--last-heard-mean-sec3600last_heard_offset_sec的指数分布均值--last-heard-max-sec7 * 86400最近听到偏移的最大上限节点num生成范围为[4, 0x80000000)固件保留 0-3见 bin/gen-fake-nodedb-seed.py输出按num升序排列保证顺序不依赖集合哈希。七、适用前提与边界本文所有命令与参数均以当前仓库内容为准Python 侧依赖仓库内生成的meshtastic_v25绑定由bin/regen-py-protos.sh生成PyPI 上的meshtastic包仅作为回退且可能滞后于固件分支的 v25 卫星数据库 schemabin/seed-json-to-proto.py编译产物build/fixtures/nodedb/*.proto被.gitignore忽略属于构建期生成物只有test/fixtures/nodedb/*.jsonl是提交进仓库的种子源文件设备端加载行为与固件实现强绑定v24 及以下版本文件会触发迁移低于DEVICESTATE_MIN_VER会被整体丢弃重建默认数据库src/mesh/NodeDB.cpp超过平台上限的节点会在启动自护理阶段被截断或降级到 warm tier手工编辑 JSONL 时请遵守_validate_node的硬约束bin/seed-json-to-proto.pylong_name不超过 24 字符、short_name不超过 4 个 UTF-8 字节、public_key_hex为空或恰好 64 个十六进制字符否则编译会直接报错而非静默通过。通过这套流水线开发者可以用 250/500/1000/2000 四个档位的确定性 fixture系统性地覆盖节点数据库的容量边界、迁移、自护理与卫星数据裁剪等固件路径既保证 CI 可复现又让设备端测试数据始终保持新鲜。赞分享物联网嵌入式通信智能硬件【免费下载链接】firmwareThe official firmware for Meshtastic, an open-source, off-grid mesh communication system.项目地址https://gitcode.com/GitHub_Trending/fi/firmware点击查看免费下载相关推荐Doctrine Data Fixtures 数据库测试数据加载工具详解Doctrine Data Fixtures 数据库测试数据加载工具详解 概述 Doctrine Data Fixtures 是一个专为 Doctrine ORsocial-auto-upload Bilibili上传详细教程使用biliup集成自动化投稿social auto upload Bilibili上传详细教程使用biliup集成自动化投稿 social auto upload是一款强大的视频自动化上后端RPA工作流自动化AI 技能超级指南Superagent测试数据管理的终极方案 — 从Fixtures到动态生成超级指南Superagent测试数据管理的终极方案 — 从Fixtures到动态生成 在现代JavaScript开发中可靠的API测试离不开高质量的测试数据开发工具上一篇3步让2011年的旧Mac跑上macOS SequoiaOpenCore Legacy Patcher完整上手指南下一篇从零玩转OBS的VST插件直播声音从此告别塑料感创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表