@noob-stupid/dsh-breadboard
DSH hardware sandbox plugin: assemble a 3D scene of ESP32 / BME280 / PIR / LED components with protocol- and voltage-checked port wiring, run real Python project code in the loop against simulated I2C/GPIO hardware with fault injection, let networked device simulators report over HTTP to a real back
Install
dsh plugin --profile web add @noob-stupid/dsh-breadboard
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✗ |
| 2 list | — |
| 3 mount | — |
| 4 boot | — |
dsh: initialized profile web at /home/node/.dsh/profiles/webFour stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
<sub><b>Web</b> profile 插件 —— 宿主半 + 浏览器半。</sub>
English: [README.md](README.md) | 中文: [README.zh.md](README.zh.md)
DSH 硬件沙盒
给 DSH 的 3D 硬件沙盒:把装配摆出来、接上线,然后让你自己项目的代码跑在虚拟硬件上。
<!-- 收录徽章位:awesome-dsh-plugin / DSH 社区列表 / dsh.so / dsh-plugin.org / …(收录通过后逐个补上官方徽章;徽章图片本身不自制) -->
安装(从 GitHub 源码装;本包未发布到 npm)
dsh plugin --profile web add github:Noob-stupid/dsh-breadboard
装完刷新页面即可。沙盒注册进 main 槽(3D 视图)与 sidebar.panellist 槽(各面板);
skill/SKILL.md 随插件一起注册,装了这个插件的 agent 已经知道该怎么用它。
喜欢的话:在插件管理里打开这个插件的详情页,内容最下方靠右有一行小字,可以到
GitHub 点个 Star。它就是透明的一行字
—— 没有底色、没有边框、没有阴影,也只在本插件自己的页面上出现。
这一行能生效靠三件事,三件都在本仓库里:
要求 · 位置 · 说明
仓库 topic dsh-plugin · GitHub 仓库 topics · 社区列表据此发现本仓库
dsh.bundle 清单 · package.json → "dsh": { "bundle": { "patch": "./cordis.patch.yml" } } · 没有它 dsh plugin add 装不进任何东西 —— 而且界面上的症状极具误导性:插件列表说「没有声明组合包」,真正被挡住的却是装配本身,于是所有 /api/* 返回 404,面板干脆不出现
导出 apply(ctx) · src/index.ts(宿主半)/ src/client/index.ts(浏览器半) · 宿主半注册路由、工具与仿真引擎;浏览器半注册上面那两个槽
这是什么 / 解决什么问题
一个软硬件项目里,只有真机能试的那几段,是接线本身、传感器在寄存器层的语义、以及出错时的处理。
本插件把它们搬进一个真能跑起来的虚拟场景:
- 3D 装配 —— 从内置模型库放器件(ESP32、树莓派 4B、BME280、HC-SR501 PIR、LED 模块、
MPL3115A2、面包板),按端口逐个连线,得到一份活的 SSOT(唯一真相)装配状态,带拓扑与电气校验。
- 项目级硬件在环 —— 一个真实 Python 进程跑你自己项目的代码。Python shim 拦截它的
smbus/I2C 访问,由虚拟设备应答,所以被测项目读到的是寄存器级的值
(例如它自己拿虚拟芯片的数据做真正的 BME280 补偿计算)。
- 联网设备模拟(并列的第二类虚拟硬件)—— 一台按真实节拍主动向你的外部 HTTP 后端
上报的设备:注册 → 拉配置 → 周期上报。已在真实的智能选座系统上全链路验证
(设备 → HTTP → 服务端状态机 → 数据库)。
- 故障注入 —— 拔线、返回 NACK、强制读数、让设备掉线,然后看项目的异常处理到底抓没抓住。
- 项目级便利 —— 扫描一个真实项目文件夹,得出它需要哪些硬件;再一键换掉整套硬件。
依赖 DSH 的 web profile 与 webServer、tools、subprocess 三个服务。宿主半把它们声明为
硬 inject 依赖(刻意如此):缺任何一个,插件根本不激活,而不是"激活了但工具没注册 /
界面空白 / 仿真起不来"。
没有真实项目也想看效果
examples/zhizuo-virtual-esp32/ 是虚拟 ESP32 座位传感器的独立脚本版。
hw_list_projects 会列出内置演示项目(zhizuo-seat-node)以及它当前是否软硬件连通;
hw_import_project 一次把它的器件、连线与联网绑定摆好。
界面导览
界面目前只有中文,下表用的就是屏幕上那行字。
面板 · 作用
③ 项目(一键换整套硬件) · 主工作流。每个项目本体显示:文件数(采样跳过时为「N 个文件(采样时跳过 M 个)」)、扫描需求、删除;底部还有:+ 导入项目本体(选文件夹)、⤓ 导出建模组(存成一个 .json)、+ 导入建模组(选 .json)、+ 添加型号定义(选 .json)、✎ 让 agent 帮我写
① 添加器件 · 点一下型号键,把它放进场景。只列有真几何的型号(默认收起)
② 换装模型 · 搜模型 / 导入文件,给某个型号换装;没有几何的型号渲染为占位盒。外部(数据驱动)型号带「[数据驱动]」标记(默认收起)
④ 真机观察 · 显示真实硬件的状态(只读),并能从界面开始/停止观察(默认收起)
统计 · 渲染统计(绘制次数 / 三角形数 / 帧率)—— 纯读取,默认关
中央 3D 视图 · 已放置器件(带世界变换)、端口之间的蓝色连线、在带 warn/error 告警的器件上就地面出的告警框、变换手柄 / 右键菜单(钉住、删除)、端口悬浮提示
面板浮层输入框 · 不离开面板就能给当前会话发消息;宿主没提供 agents 服务时该输入框直接隐藏(capabilities.chat 缺省)
其中两条要点名:
- 「扫描需求」只是界面按钮。 它没有对应的 agent 工具 —— agent 侧没有这一步。agent 能做的是
它后面的事:摆器件、连线、建项目图纸、跑仿真。
- 删除项目只删掉项目定义(那一份 JSON)。它不动场景,所以删项目永远不会把你眼前的硬件清掉。
快速上手:三步
1. 导入项目本体 —— 点 + 导入项目本体(选文件夹),选一个完整的项目文件夹
(前后端 + 硬件代码)。它不带建模;宿主读它来判断需要哪些硬件。
2. 扫描需要哪些硬件 —— ③ 面板里的 扫描需求 按钮(界面专属,见上)。报告会列出每个候选
型号键,并给出证据(在哪几个文件里看到的),让你自己判断对不对;扫描时如果做了采样,
它会说出来,而不会让你以为整个项目都扫过了。
3. 导入建模组 —— 点 + 导入建模组(选文件夹),布局是 <型号键>/model.glb。
没补的型号继续渲染为占位盒。
或者干脆跳过 1–3:把系统用话讲给 agent,让它用 hw_save_project 写成图纸,
再用 hw_import_project 一次把器件、连线、联网绑定全部摆好。
Agent 工具:16 个 hw_*
以下是实际注册的清单(未增未删)。「什么时候用」这一列才是表格的意义 —— 这些工具并不通用互换。
项目
工具 · 作用 · 什么时候用
hw_list_projects · 列内置软硬件项目:器件、接线、联网配置,以及当前是否软硬件连通 · 在手工摆器件之前先用它 —— 一张图纸是一次调用;手工摆是四步,少一步就不通且不报错
hw_import_project · 导入项目:先清空当前装配,再摆器件、连线、挂绑定 · 换掉整套硬件时用;注意它是替换,不是往上加
hw_save_project · 新建或覆盖项目图纸(存进 $DSH_HOME/dsh-hardware-sandbox/projects/) · 用户用话描述了一个系统 —— 先写成图纸,再导入
装配
工具 · 作用 · 什么时候用
hw_get_assembly · 读 SSOT 摘要:revision、组件、连线、告警(连 message 一起给,不只是码)、供电、虚拟设备 · 每次改动前都先读 —— 你需要真实的端口 id;端口 id 是引脚身份(E4),不是丝印名(GPIO23)
hw_edit_assembly · 一个工具覆盖契约里的 ClientAction 联合:放器件 / 移动 / 旋转 / 连线 / 拔线 / 删除 / 钉住 · 任何对场景的修改。它收一个 action 对象,先读工具描述里的样例
仿真
工具 · 作用 · 什么时候用
hw_run_simulation · 在虚拟硬件上运行真实的 Python 项目;duration 是虚拟秒数;返回项目输出与虚拟/真实耗时 · 真正的硬件在环那一跑。accelerated(默认)远快于真实时间;realtime 按真实节拍限速,便于观察
hw_get_sim_log · 读最近一次(或进行中)那跑的项目输出,可只取 tail 行 · 当 hw_run_simulation 的输出被截断时
hw_inject_fault · 对设备 id 或 型号:地址 目标注入 disconnect / nack / busy / set_reading / clear · 验证项目的异常处理真的看到了故障(例如断线后的 OSError),而不是假定它会看到
联网设备
工具 · 作用 · 什么时候用
hw_network_add · 添加一台联网设备(协议适配器 + endpoint + 设备自报身份)。它不会启动 · 第一次把设备模拟器接上你的后端
hw_network_devices · 列设备:协议、外部系统地址、在线状态、上报/失败次数、当前读数、服务端下发的配置 · 确认设备到底连上没有、有没有在真的上报 —— 否则"已添加但停着"看起来也很正常
hw_network_control · start / stop / disconnect(掉线故障)/ clear · 只有 start 会让请求真的发出去 —— 这是刻意的,默认不该有外部副作用;disconnect 用来验对面能否识别离线
hw_network_set_reading · 设置物理读数(如 { ir_front: true, ir_back: true },true = 被遮挡) · 单独验协议层对不对,与硬件通路无关。电平由协议按配置(如 ir_active_high)翻译,极性搞反的责任留在协议侧,不在调用方
hw_set_occlusion · 遮挡 / 移开装配里的某个器件,并沿实际接线把影响传导到联网设备的读数上 · 验硬件通路:PIR 没接上、或接错了脚,就什么都不会发生 —— 真机就是这样
型号定义(数据驱动)
工具 · 作用 · 什么时候用
hw_scan_board_pins · 从本机 PlatformIO 的权威文件推导引脚表草稿:boards/<board>.json → build.variant → variants/<variant>/pins_arduino.h(编译器实际用的那份映射)。list:true 列出本机能找到的板子 · 要加一块新板子时先跑它。★★ 它给的是草稿 + 缺口清单(缺:物理排布 / 电气语义 / 丝印),不是成品 —— 缺口按数据手册补齐后再用 hw_save_model_definition
hw_save_model_definition · 保存一条型号定义(引脚表:portId/丝印/协议/电压/方向 + 尺寸 + 排布)。校验通过才落盘,落盘后立即生效 · 需要一块插件还不认识的板子时。引脚表必须有权威来源(厂商数据手册 / PlatformIO 的 variant 文件 / 项目自己的工程文件);找不到就问用户,不要凭记忆编
真机在环(只读观察)
工具 · 作用 · 什么时候用
hw_watch_device · 观察一台真机:定时只读查询外部系统(智座用 GET /api/admin/sensor/devices),把真机状态映射到场景器件上。action = start / stop / status · 想知道"**真机现在到底连
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::6,最后更新 2026-10-16