VibeEngineering-LLC/atomfast-esp32

GitHub: VibeEngineering-LLC/atomfast-esp32

该项目是一套 ESP32 BLE 网关固件,将 AtomFast Plus2 辐射剂量计的数据通过蓝牙采集后以本地 Web UI 和 Home Assistant 接口实时呈现,实现无云端的持续辐射监测。

Stars: 2 | Forks: 0

# AtomFast → ESP32 → Web UI 基于 ESP32 的 **AtomFast** 辐射剂量计 BLE 网关。通过 Bluetooth Low Energy 连接设备,解析专有的 13 字节 on-air 协议,并直接在浏览器中的 ESPHome Web UI 发布 实时读数(**S3 baseline 中包含 7 个图表 / 经典固件中包含 6 个图表**)——无需应用程序、无需 Home Assistant、无需云端。 ![схема](https://img.shields.io/badge/ESP32-DevKitC%20%2F%20S3-blue) ![ESPHome](https://img.shields.io/badge/ESPHome-2026.5+-green) ![Framework](https://img.shields.io/badge/Framework-arduino%20%7C%20esp--idf-yellowgreen) ![BLE](https://img.shields.io/badge/BLE-AtomFast-orange) ## 技能中的两份固件 —— 该选哪一个 `firmware/` 目录下有针对不同硬件的**两份现成 YAML**。它们互不兼容 —— 不同的开发板、不同的框架、不同的妥协: | YAML | 开发板 | 框架 | 适用人群 | |---|---|---|---| | **`atomfast_gateway_s3.yaml`** ⭐ | **ESP32-S3-DevKitC-1 N16R8** (16 MB Flash + 8 MB embedded octal PSRAM, **U.FL/IPEX** 外置天线接口, USB-C) | **esp-idf** | **推荐的 baseline。** 当前的主要配置。复制自 `esphome/bluetooth-proxies` upstream (esp-idf 框架),并针对 AtomFast 进行了适配:移除了 `bluetooth_proxy:`,设置了 `web_server.log: true` (8 MB PSRAM —— heap 资源充足),Narodmon 开关为 `ALWAYS_OFF`。**Wi-Fi + Bluetooth 稳定** —— 在 S3 上不会复现 INC-09/12 问题 **(类似于 Radex S3 的情况**;目前还没有针对 AtomFast 进行过长时间设备级 S3 测试;关于通过 S3 芯片从根本上解决 coex 问题的结论是从 Radex 移植过来的;请参阅下文的“稳定性”章节)。 | | **`atomfast_gateway.yaml`** | ESP32-DevKitC v4 (WROOM-32, 4 MB flash, 无 PSRAM) | **arduino** | 针对用户手中已有的旧开发板的**归档构建**。在 arduino 框架上经过了长时间的无退化运行测试,但在 esp-idf 上不稳定 —— **不要将经典的 DevKitC 与 esp-idf 搭配使用**。对于全新安装,最好选择 S3 N16R8。 | **推荐:在 ESP32-S3-DevKitC-1 N16R8 上使用 `atomfast_gateway_s3.yaml`。** 稳定、最新,内存充足并支持外置天线。 ## 这能解决什么问题 AtomFast 应用程序界面精美,但是: - **封闭** —— 没有 API,数据仅存在于手机中; - **基于会话** —— 仅在应用程序开启时记录; - **仅限 Android/iOS** —— 无法集成到智能家居中。 这份固件可以将任何 ESP32 变成一个**全天候工作的网关**: 它 24/7 与设备保持连接,将图表保存在 ESP 内存中,通过 HTTP 提供 JSON,并且可以根据需要连接到 Home Assistant。 ## 测量内容 设备每 **2 秒**发送一次完整状态包(与应用程序看到的内容相同)。固件逐字节解析并将其发布到 Web UI: | 指标 | 单位 | 数据来源 | |---|---|---| | CPS (脉冲/秒) | cps | 2秒计数 ÷ 2 | | 剂量率 | µSv/h | float32 LE, bytes 5..8 | | 剂量率 | µR/h | 同上 × 100 | | 2秒脉冲数 | imp/2s | 原始计数器 uint16 LE | | 累积剂量 | µSv | float32 LE, bytes 1..4, ×1000 | | 电池 | % | int8, byte 11 | | 温度 | °C | int8 signed, byte 12 | | RSSI BLE | dBm | 来自 advertise 包 | 解码结果与解析来源的协议一致 —— 即制造商官方应用 **AtomSwift** (`Am6er/atomswift`,私有 repo)。“应用屏幕 vs 网关 Web UI 每一项指标”的 详尽并排对比尚未进行,但字节布局(`val_dose`, `val_intensity`, `pulses_2s`, `battery`, `temperature`)与 AtomSwift `AtomDeviceNRF.java` 中的 upstream 代码完全一致。 ## 准备工作 **硬件:** - **推荐**:ESP32-S3-DevKitC-1 **N16R8** (16 MB Flash + 8 MB embedded octal PSRAM, U.FL/IPEX 外置天线接口, Wi-Fi + Bluetooth, USB-C)。在 esp-idf-baseline 上非常稳定。 - *备选(归档)*:带 CH340 的经典 ESP32-DevKitC v4 (WROOM-32) —— 仅适用于 arduino-baseline `atomfast_gateway.yaml`。**在 esp-idf 上无法稳定运行。** - USB-C 数据线(用于 S3)或 Micro-USB 数据线(用于经典 v4)→ PC,用于首次刷写 - 5 V USB 电源或 powerbank,用于长期运行 - **AtomFast** 辐射剂量计(支持 BLE 的 5xx 型号) **软件:** - Python 3.10+ - ESPHome ≥ 2026.5:`pip install esphome` - CH340 驱动程序 (Windows:[WCH-CH340 驱动程序](https://www.wch-ic.com/downloads/CH341SER_ZIP.html)) ## 部署(5 分钟) ``` # 1. 复制固件到本地 git clone https://github.com/VibeEngineering-LLC/atomfast-esp32.git cd atomfast-esp32/firmware # 2. 填写 secrets cp secrets.example.yaml secrets.yaml # 在编辑器中打开 secrets.yaml,输入 SSID、WiFi 密码、设备 MAC # 3. 在 substitution 中填入 AtomFast 的 MAC(用于 RSSI sensor) # 打开 atomfast_gateway.yaml 或 atomfast_gateway_s3.yaml, # 找到 substitutions.atomfast_mac_str 并将 # AA:BB:CC:DD:EE:FF 替换为您自己的 MAC。 # 4. 通过 USB 烧录 # a) ESP32-S3-DevKitC-1 N16R8,esp-idf,baseline bluetooth-proxies upstream(推荐): esphome run --device COM3 atomfast_gateway_s3.yaml # Windows esphome run --device /dev/ttyUSB0 atomfast_gateway_s3.yaml # Linux # b) 经典 ESP32-DevKitC v4(适用于旧板的存档版本,仅限 arduino): esphome run --device COM3 atomfast_gateway.yaml # 5. 打开 Web UI # http://atomfast-gw-s3.local/ (mDNS,适用于 esp-idf S3 baseline — 推荐) # http://atomfast-gw.local/ (mDNS,适用于经典 DevKitC 上的 arduino 固件) # 或 http://<局域网内的-ESP-IP>/ ``` 首次刷写后,后续更新 —— **通过无线更新 (OTA)**: ``` esphome run --device atomfast-gw-s3.local atomfast_gateway_s3.yaml # esp-idf S3 (рекомендуется) esphome run --device atomfast-gw.local atomfast_gateway.yaml # arduino (архивная) ``` ## 在 Web UI 中会看到什么 ESPHome Web UI v3 会在每个卡片上绘制**迷你图**,点击时会显示 **全尺寸图表**。分组: **AtomFast — 读数**(主页) - CPS(瞬时) - 剂量率 µSv/h - 剂量率 µR/h - 2秒脉冲数 - 累积剂量 µSv - CPS(窗口平均值) - 剂量率(窗口平均值) **设置** - “聚合间隔”滑块 (1..60 秒, 初始值 5) —— CPS/剂量的平均窗口。 **仅在 S3 baseline 中可用**(`atomfast_gateway_s3.yaml`, `number.agg_interval_s`)。 在经典固件中,没有滑块 —— 只有固定窗口。 - “重新读取 GATT”按钮(用于调试 BLE) —— **仅在经典固件中可用** (`atomfast_gateway.yaml`,通过 `include/gatt_dump.h`)。S3 baseline 中没有 GATT-UI。 **RE / BLE 调试**(**仅在经典固件中**) - 最后一个 notify 包的原始 hex - 设备的 GATT 表转储 **诊断** - AtomFast 电池 - AtomFast 温度 - RSSI BLE - WiFi 信号 - uptime ## 图表数据存在哪里 存在 **ESP 的内存**中。ESPHome Web UI v3 会存储自上次重启以来的 sensor 历史记录 (在典型卡片上约为过去一小时)。如果 需要永久历史记录 —— 请通过 ESPHome API 连接 Home Assistant (`encryption.key` 已经在 `secrets.yaml` 中生成)。 要在 PC 上记录 CSV 日志 —— 需要一个单独的 Python daemon(参见原项目中的 `scripts/`, 或者连接到 JSON endpoint `/sensor/cps_instant`)。 ## 架构 ``` ┌────────────┐ BLE notify ┌──────────────┐ HTTP/WiFi ┌───────────┐ │ AtomFast │ ──────────► │ ESP32-DevKit │ ──────────► │ Браузер, │ │ (Plus2) │ 13 байт │ (ESPHome) │ JSON + │ HA, Python│ │ │ раз в 2 с │ │ Web UI v3 │ │ └────────────┘ └──────────────┘ └───────────┘ │ I/O ▼ ┌──────────────┐ │ парсер │ │ 13 байт → │ │ 7 sensors │ └──────────────┘ ``` 没有云端,不需要账号。一切都在你的本地网络上运行。 ## AtomFast 协议 完整的 BLE GATT 图 + on-air payload 解析 — [references/atomfast-onair-protocol.md](references/atomfast-onair-protocol.md)。 简要说明:通过 characteristic `70BC767E-7A1A-4304-81ED-14B9AF54F7BD`(属于 service `63462a4a-c28c-4ffd-87a4-2d23a1c72581`)每 2 秒发送 13 个字节 —— 包含标志位 + 2 个 float32 LE (累积剂量 mSv,剂量率 µSv/h)+ uint16 LE(脉冲数)+ 电池 + 温度。 ## BLE 拓扑与 BT 信号 ### 拓扑结构 ``` [AtomSwift app на телефоне (опционально)] │ BLE single-central — выйти из app перед запуском шлюза! │ ▼ ┌─────────────────────┐ │ AtomFast Plus2 │ ◄── BLE notify push (0.5 Hz, 13 байт) │ Service 63462a4a...│ │ bond не требуется │ └─────────────────────┘ │ │ BLE advertise + connect │ ▼ ┌─────────────────────┐ │ ESP32-DevKitC │ │ (ESPHome │ │ atomfast_gateway) │ └─────────────────────┘ │ │ WiFi 2.4 GHz (co-existence с BLE) │ ├──► Web UI — http://atomfast-gw.local/ :80 (sparkline + 7 графиков) ├──► Home Assistant — ESPHome API :6053 (encrypted) └──► Народмон — http://narodmon.ru/get каждые 5 мин (R1/D1/T1/BAT1) ``` ### 广告 | 参数 | 值 | |---|---| | 名称 | `AtomFast XXXX` (XXXX — 序列号后缀) | | PDU 类型 | ADV_IND | | 间隔 | 广播之间约 1.1 秒 (ESP32 观测值) | | Manufacturer data | 待定 (存在,但未完全逆向 layout) | | adv 中的 Service UUIDs | 会广播 `63462a4a-c28c-4ffd-87a4-2d23a1c72581` | | 5 米外 RSSI | −37..−68 dBm (ESP32 观测值,取决于天线方向) | | Pairing/bonding | 不需要 | ### 连接 | 参数 | 值 | 来源 | |---|---|---| | Bonding/pairing | 不需要 | 实测 | | MTU | 23 (默认值,不会增加) | ESP32 实测 — AtomFast 不响应 MTU exchange | | Scan interval / window | 600 / 600 ms (100% duty) | `AtomDeviceNRF.java:59 retry_delay = 600` | | Connection timeout | 24000 ms | `AtomDeviceNRF.java connect_timeout = 24000L` | | Reconnect delay | 3300 ms | `reconnect_after_failed_connect_delay = 3300L` | | Notify cadence | 0.500 Hz (每 2 秒一次) | 设备固件 | | Single-central | 单一 host — 其他设备会被拒绝 | 实测 | ### GATT 结构 (来自 Am6er/atomswift GattAttributes.java) | Service | UUID | 类型 | 用途 | |---|---|---|---| | GAP | `0x1800` | std | Generic Access | | GATT | `0x1801` | std | Generic Attribute | | Device Information | `0x180A` | std | 型号、序列号、固件/硬件版本 (`0x2A24..0x2A29`) | | **ATOMTAG_SERVICE** | `63462a4a-c28c-4ffd-87a4-2d23a1c72581` | custom | AtomFast 主服务 | | Characteristic (Java 符号) | UUID | Props | 用途 | |---|---|---|---| | ATOMTAG_MEASUREMENT | `70BC767E-7A1A-4304-81ED-14B9AF54F7BD` | Notify | **主数据流** (每 2 秒 13 字节) | | ATOMTAG_MEASUREMENT2 | `8E26EDC8-A1E9-4C06-9BD0-97B97E7B3FB9` | Notify | 次要 measurement (可能是 CPM 流,待定) | | ATOMTAG_THRESHOLD1 | `3F71E820-1D98-46D4-8ED6-324C8428868C` | Write | 警报阈值 1 | | ATOMTAG_THRESHOLD2 | `2E95D467-4DB7-4D7F-9D82-4CD5C102FA05` | Write | 警报阈值 2 | | ATOMTAG_THRESHOLD3 | `F8DE242F-8D84-4C12-9A2F-9C64A31CA7CA` | Write | 警报阈值 3 | | ATOMTAG_CONFIG | `EA50CFCD-AC4A-4A48-BF0E-879E548AE157` | Write | 设备配置 | | **ATOMTAG_CALIBRATION** | `57F7031F-03C1-4016-8749-BAABAA58612D` | Write | ⚠ 校准 — 请勿改动 | | ATOMTAG_CONFIG2 | `E2423A67-7541-4080-8B5A-59449454A873` | Write | 次要配置 | | ATOMTAG_TEXT | `BB6C9C06-C37D-49B0-94CA-83623622573B` | TBD | 文本描述符 | ### 交互模式 — Notify push (无命令) **类型**:纯 push-only Notify。Host 通过D 订阅 `70BC767E-...`,设备每 2 秒自动发送一个数据包。无需发送 任何 opcode / 命令 —— 在向 CCCD write `01 00` 后数据即会开始传输。 ### Payload — 13 字节 on-air (来源:Am6er/atomswift) | Offset | 大小 | 类型 | 字段 | 描述 | |---|---|---|---|---| | 0 | 1 | uint8 | flags | 标志位 (bit 3 = 重新读取配置请求) | | 1..4 | 4 | float32 LE | val_dose | 累积剂量, **mSv** | | 5..8 | 4 | float32 LE | val_intensity | 瞬时剂量率, **µSv/h**. `>1000` — 错误数据包,忽略 | | 9..10 | 2 | uint16 LE | pulses_last_2sec | 过去 2 秒的脉冲数 | | 11 | 1 | int8 | valBattery | 电池电量百分比 | | 12 | 1 | int8 | valTemperature | 温度 °C (signed) | 实测验证:`00 EE EE E1 3C 07 7A BA 3D 26 00 40 19` → 剂量 27.58 µSv, 剂量率 0.091 µSv/h, 38 imp/2s (19 cps), 64% 电池, 25 °C (参见 [`references/atomfast-onair-protocol.md`](references/atomfast-onair-protocol.md)). ### ESPHome 中的 stability 参数 ``` esp32_ble_tracker: scan_parameters: active: true # defaults (320/30 ms ≈ 9 % duty) ble_client: - mac_address: !secret atomfast_mac id: ble_atomfast auto_connect: true # AtomFast advertise'ит регулярно services: - uuid: "63462a4a-c28c-4ffd-87a4-2d23a1c72581" characteristics: - uuid: "70BC767E-7A1A-4304-81ED-14B9AF54F7BD" on_notify: then: - lambda: |- // parse 13-byte payload, publish 7 sensors ``` **历史记录**:在 atomfast v0.4.x 中使用了手动的 `scan_parameters: { interval: 600ms, window: 600ms, active: true }` (取自 AtomSwift 固件中的 `retry_delay = 600`)。这在**单一的 ble_client 且没有 HA 负载的情况下** 可以正常工作。一旦固件中出现了第二个服务 (ESPHome API + Web UI + Narodmon HTTP),就必须使用默认值 —— 参见 [`esp32-dev/SKILL.md`](../esp32-dev/SKILL.md) → "scan_parameters defaults for WiFi co-existence" 以及 radex v0.1.2 → v0.1.3 的事件。 ## 平台稳定性 —— 为什么选择 ESP32-S3-DevKitC-1 N16R8,而不是经典 DevKitC 搭配 esp-idf **简而言之**:ESP32-S3-DevKitC-1 **N16R8** (16 MB Flash + 8 MB embedded octal PSRAM, U.FL/IPEX, USB-C) **+ esp-idf** 是稳定且推荐的配置。经典(“蓝色”)ESP32-DevKitC 搭配 WROOM-32 / 4 MB flash / 无 PSRAM **+ esp-idf 不稳定**:WiFi/BLE coexistence 会破坏重连机制,没有 PSRAM 的 web_server 会陷入 `json:111` 错误。在同一块经典 DevKitC 上,arduino 框架可以工作,但这是为手中已有开发板提供的历史 baseline,并不是对全新安装的推荐。 这一点已通过本项目在 2026 年 6 月的一系列事件得到验证: ### INC-09:esp-idf 导致连接缓慢和 `rsn 0x3e` 在尝试将 AtomFast 网关从 arduino 迁移到 esp-idf 时 (`v0.7.0`–`v0.7.1`),在同一块 DevKitC 开发板上使用相同的 scan 参数,操作者遇到了: - **`rsn 0x3e × 2`** — 连接建立失败:ESP 的 HCI 尝试建立链接,设备无响应,重试。 - **CONNECTED #7** — 仅在重启后**第七次尝试**才成功连接(而在 arduino 上是第一次就成功)。 - **会话维持 7 秒,重连耗时 13 秒** — 在 arduino 上会话可以持续数小时。 回滚到 arduino (`v0.7.2`,同样的 600 ms / 180 ms scan) → **40 分钟运行测试:约 21 秒内 CONNECTED #1,0× rsn 0x3e,0 次重启**。退化纯粹是由 esp-idf 引起的。 **根源**:esp-idf 启用了内置的 BLE/WiFi coexistence 机制 (`CONFIG_ESP_COEX_SW_COEXIST_ENABLE`),该机制会动态削减 BLE 扫描器的时序以保护 WiFi 射频。这些削减与试图维持 GATT 会话的活跃 `ble_client` 产生冲突 —— 并最终失败。 ### INC-12:esp-idf coex 破坏了固定的 `scan_parameters: 600/180` 在 esp-idf 上使用标准的“arduino 稳定版” `interval: 600ms, window: 180ms` (30% duty) 刷写 RadonEye HA Gateway 时 —— 开发板在关联到 WiFi 后立即**陷入 `Auth Expired` 错误**: - Ping 丢包率达 50%; - Web server 死亡 (curl exit 28 — 拒绝连接); - UART 疯狂输出 `wifi: STA_DISCONNECTED reason=15 (AUTH_EXPIRE)`。 **根源**:在 arduino 上,这 600/180 是你个人的 scan 窗口,ESP 的 BLE 栈只是监听它们。而在 esp-idf 上,coex 子系统期望使用默认的“短”窗口,并在此基础上应用自己的校正;手动的 `interval`/`window` 破坏了它的模型,迫使 BLE 按照死板的时间表占用射频。WiFi 射频(在同一个芯片上!)无法获得足够的占用时间,从而无法更新授权密钥。 **根据 INC-12 得出的硬性规则**:在带有活动 `ble_client` 的 esp-idf 上 —— 使用 **`640ms / 32ms` (~5% duty)**,或者干脆只设置 `active: false` (esp-idf 会自行平衡)。在 arduino 上 —— 使用 **600 ms / 180 ms (30% duty)**。 在 `atomfast_gateway_s3.yaml` 中使用的是 640/32 —— 遵守了该规则。 ### INC-05:`web_server.log: true` → 在 DevKitC 上出现 `json:111` 当 ESPHome v3 Web UI 中开启 Debug Log 面板时,它会订阅与 sensor 状态相同的 SSE 流 `/events`。在基于 esp-idf 编译的 ESP32-DevKitC (320 KB RAM,无 PSRAM) 上,每一条日志消息都是一个独立的 JSON-event。在 5 秒的 sensor 轮询间隔 + WiFi 抖动 + DEBUG 日志的情况下,这会产生每秒数十个 event,导致 ArduinoJSON document 溢出: ``` [E][json:111]: JSON document overflow [W][component:522] web_server took a long time (73 ms) ``` 单次突发 = ~20 行/秒,只要浏览器开着就会持续,有时会将可用 heap 消耗至 ~12 KB。Web UI 左侧边栏变空就是这个原因。 **解决办法(只需一行)**:`web_server: log: false` —— 浏览器中的 Debug Log 面板会消失,state-events 正常传输。对于 `atomfast_gateway.yaml` 来说这是默认设置。 **为什么 `atomfast_gateway_s3.yaml` 仍然使用 `log: true`**:ESP32-S3-DevKitC-1 N16R8 拥有 **8 MB embedded octal PSRAM**。heap 容量比经典 DevKitC 高出一个数量级;刷新(F5)时不会达到 json:111。回退条件(写在 YAML 注释中):出现任何重启 / json:111 / OOM → 须改回 `log: false` 且不要重新激活。 ### 结论:该选什么 - ⭐ **ESP32-S3-DevKitC-1 N16R8** (16 MB Flash + 8 MB embedded octal PSRAM, U.FL/IPEX, USB-C) → `atomfast_gateway_s3.yaml` (esp-idf, 640/32, log:true)。**推荐使用的当前配置。** 通过 IPEX 的外置天线提高了与设备之间的 BLE 传输距离,embedded octal PSRAM 解决了 INC-05,S3 芯片解开了 coex 死结(结论是**基于 Radex S3 的类比**得出:在 Radex 端,S3 芯片消除了 `rsn 0x3e` / `Auth Expired`;目前还没有针对 AtomFast 进行过同等时长的设备级 S3 测试,“S3 解决了 INC-09/12”这一论点属于假设性移植)。 - **经典 ESP32-DevKitC v4** (WROOM-32, 4 MB flash, 无 PSRAM) → `atomfast_gateway.yaml` (arduino, 600/180, log:false)。仅能在 arduino-baseline 上运行。在这块开发板上使用 esp-idf 会导致 INC-09 (rsn 0x3e,连接缓慢) 和 INC-12 (Auth Expired)。仅在你手头已有这块开发板且不想购买 S3 时才有意义。 - **没有 PSRAM 的 ESP32-S3 或者使用 QSPI 而非 octal 的廉价克隆板** → 需将 `psram: mode: octal` 改为 `quad` 或者直接移除该代码块;并设置 `web_server: log: false`。最好的选择是购买 Espressif 原装 N16R8。 **不要在经典 DevKitC 上使用 esp-idf。** 重连表现会比 arduino 更糟,而且在这块开发板上根本无法解决 BLE/WiFi coex 和 RAM 不足的问题。 ## 已知限制 - **MTU 23** — AtomFast 不响应增加 MTU 的请求;不过 13 字节的 payload 反正也能装下。 - **一个 ESP 对应一台设备** —— 在当前版本中。ESP32 支持最多同时连接 3 个 BLE 客户端,参见 `multi-device` 分支 (TODO)。 - **Service UUID 和 payload 格式** 适用于 AtomFast Plus2 系列; 对于旧型号(Plus、普通版),格式可能有所不同 —— 欢迎 提交有关逆向工程的 pull request。 - **`gatt_dump.h` 辅助脚本**通过 `esp_ble_gattc_get_attr_count` 显示 "count=0", 即使 `ble_client` 已经订阅也是如此 —— 这是一个已知 bug,但不影响 主固件的运行。 ## 许可证 MIT,参见 repo 根目录。 ## 致谢 - **AtomFast** (`youratom.com`) — 出色的便携式辐射剂量计。 - **Am6er/atomswift** (私有 repo) — 权威的来源 GATT 图和 on-air payload 解析公式。 - **ESPHome** — 在我们的世界中用于 ESP32 的最佳框架。 - 深度协议逆向工程:同 repo 中的 skill [`atomfast-tester`](../atomfast-tester/)。
标签:ESP32, ESPHome, Home Assistant, 智能家居, 物联网, 蓝牙网关, 辐射探测器, 逆向工具