mathiasmholm/ivt-aero-pointt-discovery

GitHub: mathiasmholm/ivt-aero-pointt-discovery

一套独立的 Python 脚本工具,用于验证 Bosch PoinTT 云 API 的 OAuth2 令牌并自动发现与映射不同设备系列的资源树结构。

Stars: 0 | Forks: 0

# ivt-aero-pointt-discovery 用于验证 OAuth2 token 并映射 Bosch PoinTT cloud API (`pointt-api.bosch-thermotechnology.com`) resource schema 的独立 Python 工具,该 API 被 Bosch/IVT/Buderus **K30/K40 wifi gateway** 系列设备(IVT Aero、Bosch Climate 3000i/5000i/8000i、Buderus、Junkers、Worceus 等同等产品)使用。 本工具是在调试通过 **K30** gateway 连接的 **IVT Aero** 空气源热泵的 Home Assistant 设置时编写的。 需要 Python 3.10+(使用了 `X | None` union-type 语法)。 ## 快速开始 ``` pip install truststore # 获取 secrets/ivt_token_entry.json — 选择一个: python scripts/get_tokens.py # A: from scratch, browser login only # ...或者手动从现有集成的存储令牌中编写, # 有关确切的格式,请参阅下文的“Getting a token file”。 python scripts/verify_token.py # confirms your tokens work python scripts/crawl_tree.py # maps the resource tree for your device python scripts/discover_endpoints.py # sweeps a fixed list of known paths ``` `get_tokens.py` 将引导您完成登录并为您写入 token 文件——无需现有的 Home Assistant 设置。容易让人绊倒的一点是:authorization code 的有效期很短(观察发现:远不到一分钟)且只能使用一次,因此请执行浏览器步骤并**立即**将代码粘贴回来——不要先把它留在聊天窗口或笔记中。如果交换失败并提示 `invalid_grant` 或类似错误,说明代码已过期——请获取一个新的并直接重试。 ## 关键发现 PoinTT API 的 resource tree 对于不同的设备系列是**不同**的: - **Hydronic systems**(锅炉、地源/水源热泵)暴露了 `/heatingCircuits/hc1/...`、`/dhwCircuits/dhw1/...`、`/heatSources/...`。 - **RAC 设备**(Residential Air Conditioning —— 无管道分体式/空气源设备,也就是“IVT Aero”的实际身份,内部运行 ECHONET Lite)在 `/airConditioning/...` 下暴露了一个完全不同的 tree。在这些设备上,hydronic 路径全部返回 404 错误,反之亦然。 您可以从账户的设备列表中判断出 gateway 属于哪个系列(参见 [`scripts/pointt_client.py`](scripts/pointt_client.py) 和 [`results/endpoint_discovery.json`](results/endpoint_discovery.json)): ``` GET https://pointt-api.bosch-thermotechnology.com/pointt-api/api/v1/gateways -> [{"deviceId": "...", "deviceType": "rac"}] # RAC = airConditioning schema ``` 实际观察到的 `deviceType` 值(通过 [`homecom_alt`](https://pypi.org/project/homecom-alt/) 库,本项目对此进行了交叉参考):`rac`、`k30`/`k40`(锅炉)、`wddw2`(热水器)、`icom`(热泵)、`rrc2`(温控器)、`commodule`(EV 充电桩)。 ## device_id 陷阱 一些社区针对此 API 开发的 Home Assistant 集成会要求用户在设置期间手动输入“设备 ID / 序列号”。**印在设备标签上的物理序列号与 API 预期的 `deviceId` 不是一回事**——这是一个独立的、较短的数字 gateway ID,仅出现在账户的 `/gateways` 列表中(参见上文)。将标签序列号用作 `deviceId` 会导致: ``` {"code": 400, "httpStatus": "BAD_REQUEST", "message": "invalid or missing parameter [deviceId]: "} ``` 如果您遇到了这个问题,请使用有效的 token 获取 `/gateways`(有关可用的授权流程,请参见 `scripts/verify_token.py`),并改用其中的 `deviceId`。 ## 推荐的 Home Assistant 集成 对于 RAC 设备(IVT Aero、Bosch Climate 5000i 等),请使用 [serbanb11/bosch-homecom-hass](https://github.com/serbanb11/bosch-homecom-hass) —— 这是一个积极维护的集成,基于已发布的 [`homecom_alt`](https://pypi.org/project/homecom-alt/) 库构建,该库已经实现了此处记录的 `/airConditioning/*` schema。本仓库的脚本用于在采用该集成之前,针对真实设备独立验证该 schema。 ## 脚本 所有脚本均为独立的(无需 Home Assistant runtime),且仅依赖于 Python 标准库和 [`truststore`](https://pypi.org/project/truststore/)(让 Python 使用 OS 证书库 —— 如果本地 proxy/AV 进行了 TLS 检查,这会很有用)。 ``` pip install truststore ``` - **`pointt_client.py`** —— 极简的 OAuth2 + REST 客户端。从 `secrets/ivt_token_entry.json` 加载 token(已被 gitignore,切勿提交此文件 —— 获取方法见下文),并自动刷新过期的 access token。 - **`get_tokens.py`** —— 从零开始获取 `secrets/ivt_token_entry.json`:打印 SingleKey ID 登录 URL,接收您返回的 authorization code,将其交换为 token,查询您账户的 gateway(s),并保存该文件。无需现有的 HA 设置。 - **`verify_token.py`** —— 健全性检查:对 `/gateway/versionFirmware` 发起一次 GET 请求,以确认 token 有效。 - **`discover_endpoints.py`** —— 通过 GET 请求扫描固定的候选 resource 路径列表,记录每个路径的 200 与 400/403/404 状态,并写入 `results/endpoint_discovery_.json`。 - **`crawl_tree.py`** —— 递归跟随 API 自描述的 `refEnum`/`bulk` 类别节点(例如,`GET /system` 返回其真实子节点的列表),而不是猜测路径,并写入 `results/resource_tree_.json`。这是两种发现方法中更可靠的一种,因为 403 被笼统地用于表示“存在但被禁止”和“虚构的顶级路径”——它不能用于暴力破解未知的顶级类别,但如果您知道某个类别的真实入口点,它的效果会很好。 ### 获取 token 文件 所有脚本都需要 `secrets/ivt_token_entry.json`(已被 gitignore,由 `get_tokens.py` 自动创建 —— 参见上文的快速开始)。其格式如下: ``` { "device_id": "", "access_token": "...", "refresh_token": "...", "token_expires_at": "2026-01-01T00:00:00+00:00" } ``` 有两种方法可以获取: - **从零开始:** 运行 `python scripts/get_tokens.py` 并按照提示操作(浏览器登录,粘贴回代码)。请参阅上文快速开始中关于代码过期的提示 —— 这是最可能需要重试的步骤。 - **从现有集成获取:** 如果您已经有一个针对此 API 的可用的、基于 OAuth2 的集成(Home Assistant 或其他),其存储的 config entry / token 缓存中会在不同的键名下包含这相同的四个字段 —— 请手动将它们复制到这种格式中。 ## 结果 [`results/endpoint_discovery.json`](results/endpoint_discovery.json) 和 [`results/resource_tree.json`](results/resource_tree.json) 是针对真实的 IVT Aero + K30 gateway 运行这些脚本的实际输出。用于标识账户的字段(`device_id`、`serialId`、MAC 地址、wifi SSID)已被脱敏;其他所有内容(路径、类型、允许的值、单位)均与 API 返回的结果完全一致。 ## 免责声明 本项目使用的是非官方的、观察到的 API。Bosch 可以随时更改 endpoints、scopes 或 payloads,恕不另行通知。
标签:Python, 博世, 无后门, 智能家居, 物联网, 逆向工具