61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
# Bluetti Cloud (Open Platform) client
|
||
|
||
A tiny Node.js client for reading device telemetry from Bluetti's **cloud** Open
|
||
Platform API. Use this for the **newer encrypted models** (Elite 300 / EL300, V2,
|
||
EP600, AC180, AC200L …) where the local BLE channel is locked — the cloud path
|
||
works today and needs no AES key.
|
||
|
||
> This is *not* the ESP32 library — it's a separate, optional helper that talks to
|
||
> Bluetti's cloud over HTTPS. For older/plaintext models read locally with
|
||
> `BluettiBLE`; `BluettiADV` will cover newer models locally once Bluetti exposes
|
||
> the broadcast AES key.
|
||
|
||
Implemented from the official spec at <https://open.bluetti.com/developers>
|
||
(`basePath: https://open.bluetti.com/open`).
|
||
|
||
## Auth: signed requests (not OAuth)
|
||
|
||
Each request carries four headers; the **AppSecret is hashed in, never sent**:
|
||
|
||
```
|
||
Authorization = SHA-256( "appKey=<AppKey>&appSecret=<AppSecret>&nonceStr=<nonce>&timeStamp=<unixSeconds>" )
|
||
x-app-key: <AppKey>
|
||
ETag: <nonce> # random hex, new per request
|
||
Date: <unixSeconds> # must match the timeStamp used in the hash
|
||
```
|
||
|
||
## Setup
|
||
|
||
1. Register at <https://open.bluetti.com/developers>, create an application to get
|
||
an **AppKey** and **AppSecret**, and **apply for the IoT/telemetry API
|
||
permission**. Your device SN must also be authorized to the account, or the
|
||
telemetry endpoints return a permission error even with a valid signature.
|
||
2. Run it (Node 18+, no `npm install`):
|
||
|
||
```bash
|
||
BLUETTI_APPKEY=xxx BLUETTI_APPSECRET=yyy BLUETTI_SN=EL3002546110146262 node bluetti.mjs
|
||
```
|
||
|
||
## Endpoints used
|
||
|
||
| Purpose | Path (POST) | Body |
|
||
|---|---|---|
|
||
| List devices | `/open/bluiotdata/device/telemetry/v1/userTelemetryDeviceList` | `{pageNo, pageSize}` |
|
||
| Reported data | `/open/bluiotdata/device/telemetry/v1/telemetryDeviceReportedData` | `{deviceSn, beginTimestamp, endTimestamp, pageNo, pageSize}` (ms) |
|
||
| Control (set) | `/open/bluiotdata/device/telemetry/v1/telemetryDeviceSetUp` | `{deviceSn, functionCode, setValue}` |
|
||
|
||
Responses use the `UnifyResponse` envelope — `{ code, msgCode, message, data, ... }`,
|
||
where `msgCode == 0` means success. `data` for reported data is a paginated list
|
||
(`content[]`) of `key→value` telemetry maps.
|
||
|
||
## When it works / doesn't
|
||
|
||
- **403 / permission error** → your app lacks the telemetry permission, or the SN
|
||
isn't authorized to your account. Apply on the developer portal.
|
||
- **Signature failure** → check that the `Date` header equals the `timeStamp`
|
||
string used inside the SHA‑256 input, and that you hashed the literal
|
||
`appKey=…&appSecret=…&nonceStr=…&timeStamp=…` string.
|
||
|
||
Once you can see a sample telemetry response, paste it back and the script can be
|
||
tightened into a poller that pulls out SoC/power and logs on change.
|