# 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 (`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=&appSecret=&nonceStr=&timeStamp=" ) x-app-key: ETag: # random hex, new per request Date: # must match the timeStamp used in the hash ``` ## Setup 1. Register at , 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.