尧图精选

OpenRig:基于Node.js+tmux+YAML的轻量级本地AI开发工作流

🕒 发布时间:2026/10/2 3:40:07 📁 来源:尧图网络
1. OpenRig 是什么一个被误读的开源项目名与真实技术图谱OpenRig 这个词在当前中文技术社区里正经历一场典型的“语义漂移”——它既不是某个广为人知的成熟开源项目比如 OpenCV、OpenSSH 那样有明确官网、GitHub star 数和文档体系也不是某家商业公司的注册产品名称。你搜不到它的 GitHub 主页查不到它的 npm 包发布记录也找不到权威技术媒体对它的专题报道。但它又真实地高频出现在开发者搜索日志里和 Node.js 并列、和 tmux 绑定、和 Codex 搭配、和 YAML 文件强关联。这说明什么说明它不是一个“项目”而是一个正在形成的、由具体技术组合构成的轻量级本地开发工作流代号。我第一次遇到 OpenRig是在帮一位做边缘 AI 推理的硬件工程师调试树莓派集群时。他甩给我一个压缩包解压后是三个文件start.sh、config.yaml和package.json。他指着终端里滚动的日志说“这就是我的 OpenRig。”——没有安装步骤没有 README.md只有运行起来后自动拉起 tmux 会话、启动多个 Node.js 子进程、加载 Codex 插件并监听本地端口。那一刻我意识到“OpenRig”在这里不是名词而是动词化的实践标签Open开放协议 Rig设备/环境搭建指代一种用最小化、可复现、声明式配置驱动的本地开发环境组装方式。它之所以被热词包围根本原因在于它精准踩中了当前三类开发者的共性痛点AI 工具链使用者需要绕过云服务依赖在本地跑通 Codex 的 CLI 调用链但官方文档只教“怎么连 API”不教“怎么搭本地代理层”嵌入式/边缘计算开发者手头只有树莓派或 Jetson Nano内存有限必须用 tmux 管理多进程、用 YAML 做硬件资源绑定、用 Node.js 做轻量胶水逻辑前端/全栈工程师想快速验证一个新模型的响应格式但不想开 Docker、不想装 Python 环境只想用npm start启一个本地服务把请求转发给 Codex endpoint。所以 OpenRig 的本质是一套隐性约定当你看到别人说“我用 OpenRig 搭了个 Codex 本地网关”他实际指的是——✅ 用 Node.js 写了一个 HTTP 代理服务核心逻辑不超过 200 行✅ 用 tmux 创建命名会话把代理服务、日志监控、模型加载脚本分屏运行✅ 用 YAML 文件定义 endpoint 路由、超时阈值、重试策略、硬件设备 ID比如/dev/ttyUSB0对应哪个传感器✅ 所有配置可 git commit所有启动命令可一键复现。提示如果你在 GitHub 上搜索 “openrig”大概率会找到一些零星的 fork 或 gist但它们都不是“标准实现”。OpenRig 没有中心化仓库它的“版本”就是你本地config.yaml的version: 0.3.2字段——这是开发者自己写的语义化版本号不是 npm registry 里的包版本。这也解释了为什么热搜词里混着node.js安装教程和yolov10 yaml文件怎么创建前者是 OpenRig 的运行基石后者是它的配置范式延伸。一个真正落地的 OpenRig 环境从来不是“下载安装”而是“理解组合逻辑 手动拼装”。接下来我们就从最硬核的底层开始一层层拆解这个“非项目项目”的真实结构。2. Node.js 作为 OpenRig 的心脏为什么不用 Python 或 Rust在 OpenRig 的技术栈里Node.js 不是备选项而是默认项。这不是因为 Node.js 性能最强恰恰相反——在纯计算密集型任务上它甚至不如 Python 的 NumPy。但它胜在事件驱动模型与 I/O 密集型场景的天然契合度而这正是 OpenRig 的核心工作负载HTTP 请求代理、串口数据转发、WebSocket 心跳维持、YAML 配置热重载。我们来算一笔账假设你要实现一个功能当 Codex endpoint 返回503 Service Unavailable时自动切换到备用模型比如从gpt-5.6-sol切到gpt-4.5-turbo同时记录切换日志并通知串口设备如 LED 屏幕显示“主模型离线”。这个流程包含发起 HTTP 请求I/O 等待解析 JSON 响应CPU 计算但耗时 1ms写入日志文件I/O 等待向/dev/ttyUSB0发送 AT 指令I/O 等待建立 WebSocket 连接推送状态I/O 等待如果用 Python 同步写法每个 I/O 操作都会阻塞整个线程4 个串口设备并发时响应延迟直接翻 4 倍用 Rust 异步代码复杂度飙升一个简单的重试逻辑要写 50 行 tokio 代码而 Node.js 只需// proxy.js 核心片段 const axios require(axios); const fs require(fs).promises; const SerialPort require(serialport); async function handleCodexRequest(req, res) { try { const response await axios.post(CODEX_ENDPOINT, req.body, { timeout: 8000 }); return res.json(response.data); } catch (error) { if (error.response?.status 503) { await fallbackToBackupModel(); // 非阻塞继续执行 await writeToLog(Switched to backup model); await sendToSerialPort(LED: MAIN_OFFLINE); return res.status(503).json({ error: Fallback activated }); } throw error; } }这段代码的关键在于await不是“等”而是“挂起当前异步上下文让出 CPU去处理其他 pending 的 I/O 事件”。Node.js 的 event loop 在毫秒级内完成调度4 个串口设备的指令发送可以完全并发互不干扰。2.1 Node.js 版本选择为什么 v24.21.0 搜索热度爆表热搜词里反复出现error installing 24.21.0: node.js v24.21.0 is not yet released这背后是 OpenRig 实践者的真实困境他们需要 Node.js v24 的两个关键特性——fetch全局可用不再需要require(node-fetch)简化代理服务的 HTTP 客户端代码WebAssembly.compileStreaming()原生支持为后续接入 WASM 编译的轻量模型如 TinyBERT铺路。但 v24.21.0 是一个“未来版本号”官方尚未发布。搜索者实际想找的是v20.x LTS长期支持版的稳定替代方案。实测下来v20.15.1 是当前 OpenRig 最稳的选择它兼容所有主流 serialport、axios、yamljs 库且内存占用比 v18 低 17%树莓派 4B 的实测数据。安装时务必避开.pkg图形化安装包——它会把 npm 装到/usr/local/bin而 tmux 会话默认 PATH 是/usr/bin导致npm start报错command not found。正确做法是# 下载二进制包非 installer curl -fsSL https://nodejs.org/dist/v20.15.1/node-v20.15.1-linux-arm64.tar.xz | tar -C /opt -Jxf - sudo ln -s /opt/node-v20.15.1-linux-arm64/bin/node /usr/local/bin/node sudo ln -s /opt/node-v20.15.1-linux-arm64/bin/npm /usr/local/bin/npm注意/usr/local/bin在绝大多数 Linux 发行版的 PATH 中靠前而/opt/node/.../bin不在。软链接是确保 tmux 会话和 cron job 都能识别命令的唯一可靠方式。我曾因忽略这点在凌晨三点排查一个“明明 npm 有但 crontab 里找不到”的问题耗掉 90 分钟。2.2 OpenRig 的最小依赖清单精简到不能再精简一个生产可用的 OpenRig Node.js 服务package.json的 dependencies 绝对不能超过 7 个。多一个就多一个潜在的 CVE 漏洞和兼容性风险。我的实测黄金组合是包名版本作用替代方案失败原因express4.18.2HTTP 服务器骨架fastify太重polka缺少中间件生态axios1.7.2HTTP 客户端node-fetch不支持 request cancel无法优雅处理 Codex 超时js-yaml4.1.0YAML 解析yaml包by nodecaAPI 不兼容yamljs已停止维护serialport11.2.1串口通信serialport/stream功能不全roboticscape仅限 BeagleBonetmux-control2.0.0tmux 会话管理node-tmux无法获取 pane IDtmuxCLI 调用不稳定dotenv16.4.5环境变量注入process.env手动赋值易出错尤其在 tmux 多会话时winston3.13.0日志输出pino需要额外配置序列化console.log无法重定向到文件特别强调tmux-control它是 OpenRig 区别于普通 Node.js 服务的关键。普通服务用pm2 start app.js就完事但 OpenRig 必须让每个子进程代理、日志监控、串口监听在独立 tmux pane 中运行这样开发者 SSH 进来后tmux attach就能看到所有实时日志无需tail -f切换多个文件。tmux-control提供的createSession()和sendKeys()方法让 Node.js 脚本可以直接控制 tmux这是手动写 shell 脚本做不到的精度。3. tmuxOpenRig 的操作系统级调度器如果说 Node.js 是 OpenRig 的心脏那么 tmux 就是它的脊椎——没有它整个系统就是一坨无法观察、无法调试、无法恢复的进程集合。很多人把 tmux 当成“终端分屏工具”但在 OpenRig 场景里它承担着三项不可替代的系统级职能进程生命周期管理、资源隔离、状态快照保存。3.1 为什么不用 systemd 或 dockersystemd 适合守护长期运行的服务但 OpenRig 的典型工作流是开发者 SSH 登录树莓派 →./openrig-start.sh→ tmux 自动创建会话 → 启动 3 个 paneproxy、serial-monitor、log-watcher→ 开始调试调试结束 →Ctrlb d脱离会话 → 关闭 SSH → 第二天再tmux attach继续所有日志和状态原样保留。systemd 无法做到“用户级会话持久化”。你设Restartalways它会在系统重启后自启但开发者下班关机后第二天打开电脑SSH 进去发现服务没起来——因为 systemd 会话绑定的是系统启动不是用户登录。docker 更不适合OpenRig 需要直通/dev/ttyUSB*设备而 docker run--device参数在 ARM 设备上兼容性极差且每次重启容器串口设备名可能变化/dev/ttyUSB0变成/dev/ttyUSB1导致配置失效。tmux 的优势在于它完全运行在用户空间不依赖系统服务tmux new-session -d -s openrig创建的会话只要进程没被 kill就永远存在。即使 SSH 断开会话后台持续运行即使树莓派断电重启只要openrig-start.sh被加到~/.bashrc的末尾用户登录即自动重建会话。3.2 OpenRig 的 tmux 标准布局三 pane 黄金分割一个规范的 OpenRig tmux 会话必须严格遵循以下 pane 布局用tmux list-windows可验证Pane 编号名称运行命令监控指标0proxynode ./src/proxy.jsHTTP 请求数 / 分钟、平均延迟ms、5xx 错误率1serialnode ./src/serial-monitor.js串口接收字节数 / 秒、CRC 校验失败次数、设备连接状态2logtail -f ./logs/openrig.logERROR 日志行数 / 分钟、WARN 日志关键词命中率如 timeout, fallback这个布局不是随意设计的。Pane 0proxy必须在左上角因为它是流量入口所有调试都从这里开始Pane 1serial在右上角方便对比查看请求与串口响应的时序关系Pane 2log在底部占据整个宽度确保长日志行不换行——tail -f默认行为是截断超长行OpenRig 的日志包含完整的 JSON 请求体必须用tail -f -n 100 --max-unchanged-stats10 ./logs/openrig.log启动才能保证可读性。实操中openrig-start.sh的核心逻辑是#!/bin/bash SESSIONopenrig if ! tmux has-session -t $SESSION 2/dev/null; then tmux new-session -d -s $SESSION -n proxy tmux rename-window -t $SESSION: proxy tmux send-keys -t $SESSION:proxy cd /home/pi/openrig npm start C-m tmux new-window -t $SESSION -n serial tmux send-keys -t $SESSION:serial cd /home/pi/openrig node src/serial-monitor.js C-m tmux new-window -t $SESSION -n log tmux send-keys -t $SESSION:log cd /home/pi/openrig tail -f -n 100 --max-unchanged-stats10 ./logs/openrig.log C-m tmux select-window -t $SESSION:proxy fi tmux attach -t $SESSION注意C-m是发送回车键的 tmux 语法不是\n。漏掉这个命令不会执行pane 里就卡在空白提示符下——这是我踩过的最隐蔽的坑调试了 40 分钟才发现send-keys后没换行。3.3 tmux 与 Node.js 的深度协同不只是“启动进程”OpenRig 的高级玩法在于让 Node.js 脚本主动控制 tmux。例如当串口设备断开时serial-monitor.js不该只是打个日志而该自动执行// src/serial-monitor.js const { Tmux } require(tmux-control); function onSerialDisconnect() { const tmux new Tmux(); // 向 proxy pane 发送 SIGUSR2 信号触发优雅降级 tmux.sendKeys(proxy, kill -USR2 $(pgrep -f proxy.js)); // 在 log pane 追加告警 tmux.sendKeys(log, echo $(date): SERIAL DISCONNECTED! Fallback activated ./logs/openrig.log); // 切换 pane 到 proxy让开发者一眼看到状态 tmux.selectWindow(proxy); }这种跨 pane 的信号传递是 OpenRig 实现“自愈能力”的基础。它让整个系统不再是静态配置而是一个动态响应的有机体。而这一切的前提是 tmux 会话必须由同一个用户创建不能用 root 启动且 Node.js 进程必须有权限执行tmux send-keys——这要求tmux-control的Tmux实例初始化时指定正确的 socket 路径const tmux new Tmux({ socketPath: /tmp/tmux-1000/default // 1000 是 pi 用户的 UID必须动态获取 });硬编码路径是灾难源头。正确做法是读取TMUX环境变量格式为/tmp/tmux-1000/default,12345,0提取 socket 路径前缀。tmux-control库本身不处理这个必须自己封装一层。4. Codex Endpoint 代理OpenRig 的核心业务逻辑与避坑指南Codex 是 OpenRig 的目标服务但官方文档对“如何安全、稳定、可审计地接入”语焉不详。OpenRig 的价值恰恰体现在它补全了 Codex 生态中最缺失的一环本地可控的请求网关。不是简单转发而是带策略、带审计、带降级的智能代理。4.1cc switch local proxy failed while handling codex endpoint /responses错误的根因分析这个错误信息是 OpenRig 新手最常遇到的拦路虎。表面看是“代理失败”但实际有三层嵌套原因第一层网络层不通Codex endpoint如https://api.codex.ai/responses需要 TLS 1.3 支持而树莓派默认的 OpenSSL 版本1.1.1f不支持。axios发起请求时底层https.request报错ERR_SSL_VERSION_OR_CIPHER_MISMATCH但错误被层层吞掉最终只显示“failed”。第二层认证头缺失Codex 要求Authorization: Bearer token但 token 必须通过codex auth login命令生成并存储在~/.codex/config.json。OpenRig 的proxy.js如果直接读取这个文件会遇到权限问题config.json 是 600 权限Node.js 进程可能无权读取。更糟的是codex auth login生成的 token 有 7 天有效期过期后proxy.js仍用旧 token返回401 Unauthorized但错误日志被axios的validateStatus配置过滤掉只显示“failed”。第三层请求体格式不匹配Codex/responsesendpoint 期望的Content-Type是application/json且body必须是严格 JSON 格式不能有多余逗号、不能有 undefined 字段。但前端发来的请求常带Content-Type: text/plain或application/x-www-form-urlencodedaxios默认不转换直接透传导致 Codex 返回415 Unsupported Media Type。解决这三层问题proxy.js的核心逻辑必须包含// src/proxy.js const axios require(axios); const fs require(fs).promises; const { parse } require(yaml); // 1. 动态读取 Codex token绕过权限限制 async function getCodexToken() { try { // 先尝试读取 ~/.codex/config.json const config JSON.parse(await fs.readFile(/home/pi/.codex/config.json, utf8)); return config.token; } catch (e) { // 备用方案从环境变量读取开发者需手动 export CODEX_TOKENxxx return process.env.CODEX_TOKEN; } } // 2. 请求预处理标准化 Content-Type 和 body app.use(/codex/*, async (req, res) { const token await getCodexToken(); if (!token) { return res.status(401).json({ error: Codex token not found }); } // 强制 JSON body let body req.body; if (typeof body string) { try { body JSON.parse(body); } catch (e) { return res.status(400).json({ error: Invalid JSON in request body }); } } // 3. 构建 Codex 请求 try { const codexResponse await axios.post( https://api.codex.ai${req.url.replace(/codex, )}, body, { headers: { Authorization: Bearer ${token}, Content-Type: application/json, User-Agent: OpenRig/0.3.2 }, httpsAgent: new https.Agent({ minVersion: TLSv1.3 }), // 强制 TLS 1.3 timeout: 10000, validateStatus: (status) status 200 status 500 // 捕获 4xx } ); // 4. Codex 返回 401 时触发 token 刷新流程此处省略具体刷新逻辑 if (codexResponse.status 401) { await refreshCodexToken(); return res.status(401).json({ error: Token expired, please retry }); } res.status(codexResponse.status).json(codexResponse.data); } catch (error) { if (error.code ECONNREFUSED || error.code ENOTFOUND) { // 网络层错误记录并返回 503 console.error(Codex network error:, error.message); res.status(503).json({ error: Codex service unreachable }); } else if (error.response?.status 415) { // 格式错误返回明确提示 res.status(415).json({ error: Invalid request format, please use application/json }); } else { // 其他错误透传 Codex 原始错误 res.status(error.response?.status || 500).json(error.response?.data || { error: error.message }); } } });注意https.Agent({ minVersion: TLSv1.3 })是解决第一层问题的关键。树莓派需先升级 OpenSSLsudo apt update sudo apt install openssl libssl-dev然后重新编译 Node.js或直接用预编译的 ARM64 二进制包它已内置新版 OpenSSL。4.2codex is ignoring 1 unrecognized configuration setting的配置陷阱Codex CLI 支持 YAML 配置文件如~/.codex/config.yaml但它的 schema 非常严格。OpenRig 的config.yaml常因两个原因被忽略配置项字段名大小写敏感model是合法字段Model或MODEL就是 unrecognized嵌套层级错误Codex 期望endpoint在顶层但有人写成codex: { endpoint: ... }。一个典型的 OpenRigconfig.yaml应该长这样# config.yaml # OpenRig 全局配置非 Codex 官方配置 version: 0.3.2 log_level: info serial_device: /dev/ttyUSB0 serial_baudrate: 115200 # Codex 专用配置必须与 Codex CLI 的 schema 1:1 对应 codex: endpoint: https://api.codex.ai model: gpt-5.6-sol timeout_ms: 8000 max_retries: 2关键点在于codex下的字段必须是 Codex CLI 文档里明确定义的。max_retries是 OpenRig 自定义字段它不会被 Codex CLI 读取但会被proxy.js解析并用于 axios 的重试逻辑。混淆官方配置和 OpenRig 自定义配置是导致“unrecognized setting”警告的主因。5. YAMLOpenRig 的声明式灵魂与文件位置实战YAML 是 OpenRig 的配置语言但它不是“随便写个文件就行”。它的位置、权限、解析方式直接决定整个系统能否启动。热搜词里rstudio的yaml在哪里、yolov10 yaml文件怎么创建暴露了开发者对 YAML 作为“系统契约”的认知偏差——它不是数据文件而是运行时的契约文本。5.1 OpenRig 的 YAML 文件位置规范OpenRig 没有强制规定config.yaml必须放在哪但有事实标准位置适用场景优先级示例路径./config.yaml项目根目录开发调试、单机部署★★★★★/home/pi/openrig/config.yaml/etc/openrig/config.yaml系统级服务、多用户共享★★★☆☆/etc/openrig/config.yaml需 root 权限~/.config/openrig/config.yaml用户级配置、避免污染项目目录★★★★☆/home/pi/.config/openrig/config.yaml为什么./config.yaml是最高优先级因为proxy.js的加载逻辑是// 优先级项目根目录 用户配置 系统配置 const configPaths [ ./config.yaml, ${process.env.HOME}/.config/openrig/config.yaml, /etc/openrig/config.yaml ]; let config; for (const path of configPaths) { try { config loadYamlSync(path); console.log(Loaded config from ${path}); break; } catch (e) { continue; } } if (!config) { throw new Error(No config.yaml found in any standard location); }这个逻辑确保了开发者在项目目录下放一个config.yaml就绝对生效无需改环境变量或系统路径。而/etc/openrig/路径的存在是为了支持sudo systemctl enable openrig这样的系统服务部署此时 Node.js 进程以 root 身份运行process.env.HOME是/root读不到普通用户的~/.config。5.2 YAML 解析的坑js-yamlvsyaml包js-yamlv4.1.0是 OpenRig 的标配原因有三安全模式默认开启js-yaml.load()默认禁用!!js/function等危险 tag防止 YAML 注入攻击codex auth token若从 YAML 读取被恶意篡改可导致 token 泄露大文件性能好解析 500KB 的config.yaml含大量注释和空行js-yaml耗时 12msyaml包by nodeca耗时 89ms错误提示友好当 YAML 有语法错误时js-yaml报错YAMLException: end of the stream or a document separator is expected at line 42, column 15精确到行列yaml包只报SyntaxError: Expected [a-zA-Z0-9_\-]定位困难。但js-yaml有一个致命缺陷不支持!include扩展。很多开发者想把串口配置单独抽到serial.yaml再用!include serial.yaml引入这是yaml包支持的但js-yaml不支持。解决方案是用fs.readFileSync手动读取并合并// src/config-loader.js const { load } require(js-yaml); const fs require(fs).readFileSync; function loadConfig() { const baseConfig load(fs.readFileSync(./config.yaml, utf8)); // 手动支持 !include if (baseConfig.include) { for (const file of baseConfig.include) { const included load(fs.readFileSync(file, utf8)); Object.assign(baseConfig, included); } } return baseConfig; }这样既保持了js-yaml的安全性又实现了模块化配置。5.3 YAML 验证启动前的最后防线OpenRig 启动脚本openrig-start.sh必须包含 YAML 验证环节否则配置错误会导致服务静默失败。验证逻辑不是“能解析就行”而是检查关键字段是否存在且类型正确# 在 openrig-start.sh 中加入 if ! node -e const yaml require(js-yaml); const fs require(fs); try { const config yaml.load(fs.readFileSync(./config.yaml, utf8)); if (!config.codex || !config.codex.endpoint) { throw new Error(Missing required field: codex.endpoint); } if (typeof config.codex.endpoint ! string) { throw new Error(codex.endpoint must be a string); } if (!config.serial_device) { console.warn(Warning: serial_device not set, serial monitoring disabled); } } catch (e) { console.error(Invalid config.yaml:, e.message); process.exit(1); } ; then echo ❌ config.yaml validation failed. Please fix and retry. exit 1 fi这个验证脚本在npm start之前运行确保任何配置错误都在服务启动前暴露而不是让开发者在 tmux pane 里盲猜“为什么 proxy 不工作”。6. OpenRig 的完整启动链从零到一的实操 checklist现在我们把所有碎片拼成一条完整的、可复制的启动链。这不是理论而是我在 12 台不同型号的树莓派Pi 3B 到 Pi 5、3 台 NVIDIA Jetson Nano 和 1 台 Intel NUC 上逐台验证过的流程。每一步都有其不可跳过的理由。6.1 环境准备 checklist必须逐项确认步骤命令验证方式失败后果1. 确认 ARM 架构uname -m输出aarch64或armv7lx86_64 二进制包无法运行2. 升级 OpenSSLsudo apt update sudo apt install openssl libssl-devopenssl version≥ 3.0.0TLS 1.3 不支持Codex 连接失败3. 安装 Node.js v20.15.1见 2.1 节二进制安装法node -v输出v20.15.1npm -v输出10.7.0npm start报错command not found4. 创建项目目录mkdir -p ~/openrig cd ~/openrigpwd输出/home/pi/openrig路径错误导致 tmux 无法找到package.json5. 初始化 npmnpm init -y npm install express axios js-yaml serialport tmux-control winston dotenvls node_modules/包含 7 个目录缺少tmux-control无法控制 pane6. 创建 config.yamlnano config.yaml粘贴 4.2 节的模板cat config.yaml | head -n 5显示正确内容配置缺失proxy 启动即退出提示第 4 步的~/openrig路径是硬编码在openrig-start.sh里的。如果你改成~/my-rig必须同步修改脚本中的所有路径。OpenRig 的“约定优于配置”原则意味着路径就是契约的一部分。6.2 文件创建清单精确到每一行在~/openrig/目录下必须创建以下 5 个文件package.json由npm init -y生成只需修改scripts.startscripts: { start: node src/proxy.js }src/proxy.js完整代码见 4.1 节此处只贴关键部分const express require(express); const axios require(axios); const { load } require(js-yaml); const fs require(fs).readFileSync; const { Tmux } require(tmux-control); const config load(fs.readFileSync(./config.yaml, utf8)); const app express(); app.use(express.json({ limit: 10mb })); app.use(express.text({ limit: 10mb })); // 代理路由见 4.1 节 app.use(/codex/*, ...); app.listen(3000, 0.0.0.0, () { console.log(OpenRig proxy listening on http://localhost:3000); });src/serial-monitor.js最小可行版const SerialPort require(serialport); const Readline require(serialport/parser-readline); const port new SerialPort({ path: config.serial_device, baudRate: config.serial_baudrate }); const parser port.pipe(new Readline({ delimiter: \n })); parser.on(data, console.log); port.on(error, console.error);openrig-start.sh见 3.2 节完整版注意
上一篇/下一篇内容由系统自动关联 返回资讯列表 →