KRoperUK/uw-py

GitHub: KRoperUK/uw-py

用于 Utility Warehouse 客户门户 API 的异步 Python 客户端,封装认证与 GraphQL 查询以获取能源账单和账户数据。

Stars: 0 | Forks: 0

# uw-api 用于 Utility Warehouse 客户门户 API 的异步 Python 客户端。 Endpoint 是硬编码的(从 `myaccount.uw.co.uk/` 发现)并且不需要 配置——只需提供凭证。 ## 安装说明 ``` pip install uw-api ``` ## 用法 ``` import asyncio from uw_api import UWClient async def main(): async with UWClient(email="user@example.com", password="secret") as client: await client.login() account = await client.gql.get_account() print(f"Account: {account.account_number}") bills = await client.gql.get_bills() for bill in bills: print(f"Bill {bill.bill_id}: £{bill.total_amount_gbp}") consumption = await client.gql.get_consumption() print(f"Electricity: {consumption.electricity_kwh} kWh") print(f"Gas: {consumption.gas_kwh} kWh") meters = await client.gql.get_meters() for meter in meters: print(f"{meter.meter_type}: {meter.meter_number} (smart={meter.is_smart})") tariff = await client.gql.get_tariff() if tariff: print(f"Tariff: {tariff.tariff_name}") asyncio.run(main()) ``` ## API 参考 ### 认证 ``` client = UWClient(email="...", password="...") await client.login() ``` 通过 `account.uw.co.uk/v2/login` 的 OAuth2 PKCE 进行身份验证。Session cookie 会 自动管理。该库会在收到 401 响应时自动重新进行身份验证。 ### 账户 ``` account = await client.gql.get_account() ``` 返回包含 `account_id` 和 `account_number` 的 `UWAccount`。 ### 能源 ``` consumption = await client.gql.get_consumption() services = await client.gql.get_energy_services() usage = await client.gql.get_energy_usage() ``` - `get_consumption()` → `EnergyConsumption`(最新的用电量/用气量 kWh) - `get_energy_services()` → 能源服务 dict 的原始列表 - `get_energy_usage()` → 包含各表读数的 `EnergyUsage` 列表 ### 仪表 ``` meters = await client.gql.get_meters() readings = await client.gql.get_meter_readings() ``` - `get_meters()` → `Meter` 列表(类型、序列号、智能状态、最后读数日期) - `get_meter_readings()` → `MeterReading` 列表(数值、类型、日期、来源) ### 账单 ``` bills = await client.gql.get_bills() pdf_url = await client.gql.get_pdf_url(month=1, year=2026) ``` - `get_bills()` → `Bill` 列表(ID、日期、金额、状态、PDF URL) - `get_pdf_url(month, year)` → 账单 PDF 的字符串 URL ### 财务 ``` balance = await client.gql.get_balance() services = await client.gql.get_live_services() tariff = await client.gql.get_tariff() ``` - `get_balance()` → `{"due": float, "overdue": float}` - `get_live_services()` → 服务状态的 dict - `get_tariff()` → `EnergyTariff`(名称、代码、费率) ## 硬编码 Endpoint | 用途 | URL | |---------|-----| | 登录页面 | `https://account.uw.co.uk/v2/login` | | GraphQL API | `https://myaccount.uw.co.uk/server/graphql` | 11 个 GraphQL 操作被嵌入在 `uw_api/graphql/queries.py` 中。 ## 发现脚本(可选) 包含一个基于 HAR 的发现脚本,用于验证或重新发现 endpoint: ``` python scripts/discover_api.py parse-har capture.har ``` 这在正常使用中**不是必需的**——该库自带了 2026 年 7 月从 `myaccount.uw.co.uk/` 发现的 硬编码 endpoint。 ## 架构 ``` UWClient → UWAuth (OAuth2 PKCE) → UWGraphQL → /server/graphql (POST) → Pydantic v2 models ``` - **认证**:从登录页面 HTML 中提取 CSRF token,使用 Castle.io 设备 token 进行表单编码的 POST 请求 - **GraphQL**:所有数据均通过 `POST /server/graphql` 以面向操作的查询获取 - **重试**:收到 429/5xx 时进行 3 次指数退避重试,收到 401 时重新认证 - **模型**:`UWAccount`、`EnergyUsage`、`EnergyConsumption`、`EnergyTariff`、 `Meter`、`MeterReading`、`Bill`、`BillPDFMetadata`
标签:API客户端, OAuth2, Python, 异步编程, 无后门, 智能家居, 能源管理, 计算机取证, 逆向工具