Files
mijia-go-api/docs/compose/plans/2026-07-16-mijia-go-api.md
2026-07-18 22:40:40 +08:00

116 lines
6.1 KiB
Markdown

# mijia-api Go Refactor Implementation Plan
> [!NOTE]
> This document may not reflect the current implementation.
> See the final report for up-to-date state:
> [Final Report](../reports/mijia-go-api.md)
> **For agentic workers:** REQUIRED SUB-SKILL: Use compose:subagent (recommended) or compose:execute to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Build a pure Go library equivalent to the Python mijia-api core and high-level device API, excluding CLI, skills, MCP, and packet-decryption tools.
**Architecture:** A single `mijia` package separates deterministic cryptography, authenticated HTTP transport, public API methods, and MIoT device metadata. Public methods accept `context.Context`; flexible Xiaomi payloads use typed request structures plus `json.RawMessage` results where schemas vary.
**Tech Stack:** Go 1.22+, standard library, `github.com/mdp/qrterminal/v3` only for terminal QR rendering.
## Global Constraints
- Module path is `git.misaka.ren/m1saka/mijia-go-api` and package name is `mijia`.
- Preserve Python v4.1.2 endpoints, compact JSON encoding, ordered signing parameters, and RC4-drop-1024 behavior.
- Include login/token refresh, homes, devices, shared devices, scenes, consumables, properties, actions, statistics, and high-level device access.
- Exclude CLI, MCP, skills, documentation site, and HAR/decrypt utilities.
- Keep network dependencies injectable through `*http.Client`; tests must not require Xiaomi services.
---
### Task 1: Module, errors, and encryption
**Covers:** [S2, S3, S4, S7, S8]
**Files:**
- Create: `go.mod`
- Create: `errors.go`
- Create: `crypto.go`
- Test: `crypto_test.go`
**Interfaces:**
- Produces: `APIError`, device error types, `generateNonce`, `signedNonce`, `encryptRC4`, `decryptPayload`, `generateEncryptedParams`.
- [ ] Write table-driven tests using the fixed vector `ssecurity=MDEyMzQ1Njc4OWFiY2RlZg==`, `nonce=AAECAwQFBgcICQoL`, signed nonce `16/CeTzC9IqVVbiZ01Hy/Qd8rtVo5ybLo+ph/Vvh52k=`, and RC4 ciphertext `9ve6riTrkW1oJUE=`.
- [ ] Run `go test ./...`; expect failure because encryption functions are undefined.
- [ ] Implement SHA-256 signed nonce, RC4-drop-1024, SHA-1 ordered signatures, encrypted form parameters, plain/gzip response decryption, and the Xiaomi error-code map.
- [ ] Run `gofmt -w errors.go crypto.go crypto_test.go && go test ./...`; expect PASS.
### Task 2: Client transport and QR authentication
**Covers:** [S3, S4, S7]
**Files:**
- Create: `client.go`
- Create: `auth.go`
- Test: `client_test.go`
- Test: `auth_test.go`
**Interfaces:**
- Consumes: `generateEncryptedParams`, `decryptPayload`, `APIError`.
- Produces: `Client`, `AuthData`, `NewClient(authPath string, options ...Option)`, `WithHTTPClient`, `Login(context.Context)`, `Available(context.Context)`, and internal `request`.
- [ ] Add `httptest.Server` tests for encrypted POST form fields, decrypted JSON responses, API errors, `&&&START&&&` parsing, auth persistence, and cookie/header construction.
- [ ] Run `go test ./...`; expect failures for missing client/auth symbols.
- [ ] Implement auth-file loading, generated UA/device ID/pass_o, API session headers, compact request JSON, response decoding, and 60-second availability caching.
- [ ] Implement service-login discovery, passToken refresh, QR login data retrieval, terminal QR rendering, 120-second long polling, callback cookies, and atomic auth-file persistence.
- [ ] Run `gofmt -w client.go auth.go client_test.go auth_test.go && go test ./...`; expect PASS.
### Task 3: Public Xiaomi API methods
**Covers:** [S3, S5, S7]
**Files:**
- Create: `types.go`
- Create: `api.go`
- Test: `api_test.go`
**Interfaces:**
- Consumes: `Client.request`.
- Produces: `GetHomes`, `GetDevices`, `GetSharedDevices`, `GetScenes`, `RunScene`, `GetConsumables`, `GetProperties`, `SetProperties`, `RunActions`, `GetStatistics`, and `CheckNewMessages` with typed parameters/results.
- [ ] Add HTTP fixture tests asserting every URI and exact decoded request body, including device pagination and one-request-per-action/statistic behavior.
- [ ] Run `go test ./...`; expect failures for missing API methods.
- [ ] Define stable public structs for homes/devices/property/action/statistic calls while preserving unknown response fields in `json.RawMessage` where needed.
- [ ] Implement all endpoint methods, owner lookup, all-home aggregation, home ID annotation, pagination, and Xiaomi result-code messages.
- [ ] Run `gofmt -w types.go api.go api_test.go && go test ./...`; expect PASS.
### Task 4: High-level MIoT device API
**Covers:** [S3, S6, S7]
**Files:**
- Create: `device.go`
- Test: `device_test.go`
- Create: `testdata/miot-spec.html`
**Interfaces:**
- Consumes: `Client.GetDevices`, `Client.GetProperties`, `Client.SetProperties`, `Client.RunActions`.
- Produces: `Device`, `DeviceInfo`, `PropertySpec`, `ActionSpec`, `NewDevice`, `GetDeviceInfo`, `Device.Get`, `Device.Set`, and `Device.RunAction`.
- [ ] Add local HTML fixture tests for MIoT embedded JSON parsing, duplicate-name qualification, underscore aliases, cache read/write, device selection, value conversion, range/step checks, and API error propagation.
- [ ] Run `go test ./...`; expect failures for missing device symbols.
- [ ] Implement spec download/parsing/cache and high-level device construction by DID or unique name.
- [ ] Implement readable/writable checks, bool/number/string conversion, range/value-list validation, property calls, action calls, and configurable post-command delay.
- [ ] Run `gofmt -w device.go device_test.go && go test ./...`; expect PASS.
### Task 5: Documentation and final verification
**Covers:** [S1, S2, S7, S8]
**Files:**
- Create: `README.md`
**Interfaces:**
- Consumes: all exported package APIs.
- Produces: install, login, low-level property/action, and high-level device usage examples.
- [ ] Write concise Go examples and explicitly document unsupported CLI/MCP/skills features and auth-file security.
- [ ] Run `gofmt -w *.go && go vet ./... && go test -race ./...`; expect all commands to pass.
- [ ] Review exported API names with `go doc ./...` and remove any unused or speculative surface.