|
1 | 1 | # brunata-api |
2 | 2 |
|
3 | | -Async Python client for the Brunata Munich user portal (`nutzerportal.brunata-muenchen.de`), |
4 | | -intended for Home Assistant integrations. |
| 3 | +Python-Client zum Abrufen von Verbrauchsdaten aus dem Brunata München Nutzerportal |
| 4 | +(`nutzerportal.brunata-muenchen.de`). Gedacht als Basis für eine Home-Assistant-Integration. |
5 | 5 |
|
6 | 6 | ## Status |
7 | 7 |
|
8 | | -This is an **early / experimental** project. The Munich portal uses **SAP OData** behind a UI5 |
9 | | -frontend. Login is performed via `NP_REG_LOGON_SRV_01` and subsequent data calls use SAP OData |
10 | | -services like `NP_DASHBOARD_SRV`. |
| 8 | +Frühes/experimentelles Projekt. Die Münchner Instanz nutzt **SAP OData** (UI5 Frontend). |
11 | 9 |
|
12 | | -## Setup |
| 10 | +- **Login**: `NP_REG_LOGON_SRV_01` (`CredentialSet` via `$batch`) |
| 11 | +- **Daten**: `NP_APPLAUNCHER_SRV`, `NP_DASHBOARD_SRV` (z.B. monatliche Werte) |
13 | 12 |
|
14 | | -1) Install dependencies: |
| 13 | +## Installation (Poetry) |
15 | 14 |
|
16 | 15 | ```bash |
17 | 16 | poetry install |
18 | 17 | ``` |
19 | 18 |
|
20 | | -2) Create `.env` in the project root (this file is ignored by git): |
| 19 | +## Konfiguration |
| 20 | + |
| 21 | +Lege eine `.env` im Projekt-Root an (wird durch `.gitignore` nicht committet): |
21 | 22 |
|
22 | 23 | ```env |
23 | 24 | BRUNATA_USERNAME=you@example.com |
24 | 25 | BRUNATA_PASSWORD=your-password |
25 | | -``` |
26 | | - |
27 | | -Optional: |
28 | | - |
29 | | -```env |
30 | 26 | BRUNATA_BASE_URL=https://nutzerportal.brunata-muenchen.de |
31 | | -``` |
32 | | - |
33 | | -Optional (usually `201` for Munich): |
34 | | - |
35 | | -```env |
36 | 27 | BRUNATA_SAP_CLIENT=201 |
37 | 28 | ``` |
38 | 29 |
|
39 | 30 | ## CLI |
40 | 31 |
|
41 | | -Try a login: |
| 32 | +Login testen: |
42 | 33 |
|
43 | 34 | ```bash |
44 | 35 | poetry run brunata login |
45 | 36 | ``` |
46 | 37 |
|
47 | | -Dump key OData responses (account + available periods/cost types): |
| 38 | +Account + verfügbare Perioden/CostTypes dumpen (Achtung: kann persönliche Daten enthalten): |
48 | 39 |
|
49 | 40 | ```bash |
50 | 41 | poetry run brunata dump-pages --output-dir .brunata-dump |
51 | 42 | ``` |
52 | 43 |
|
53 | | -Fetch readings: |
| 44 | +Verbrauchsdaten abrufen: |
54 | 45 |
|
55 | 46 | ```bash |
56 | 47 | poetry run brunata readings --kind heating |
57 | 48 | poetry run brunata readings --kind hot_water |
58 | 49 | ``` |
59 | 50 |
|
60 | | -## Home Assistant usage |
| 51 | +## Nutzung als Library (Home Assistant) |
| 52 | + |
| 53 | +Der Client ist async und für HA-Coordinator-Patterns geeignet: |
61 | 54 |
|
62 | | -Home Assistant integrations typically need an async client that provides a stable interface. |
63 | | -This package exposes: |
| 55 | +```python |
| 56 | +from brunata_api import BrunataClient, ReadingKind |
| 57 | + |
| 58 | +async def fetch(): |
| 59 | + async with BrunataClient( |
| 60 | + base_url="https://nutzerportal.brunata-muenchen.de", |
| 61 | + username="...", |
| 62 | + password="...", |
| 63 | + sap_client="201", |
| 64 | + ) as client: |
| 65 | + await client.login() |
| 66 | + heating = await client.get_readings(ReadingKind.heating) |
| 67 | + hot_water = await client.get_readings(ReadingKind.hot_water) |
| 68 | + return heating, hot_water |
| 69 | +``` |
64 | 70 |
|
| 71 | +Wichtige Methoden: |
65 | 72 | - `BrunataClient.login()` |
66 | 73 | - `BrunataClient.get_account()` |
67 | 74 | - `BrunataClient.get_supported_cost_types()` |
68 | | -- `BrunataClient.get_readings(ReadingKind.heating|ReadingKind.hot_water)` |
| 75 | +- `BrunataClient.get_readings(...)` |
69 | 76 | - `BrunataClient.get_monthly_consumption(cost_type=..., in_kwh=...)` |
70 | 77 |
|
71 | | -## Packaging (later) |
72 | | - |
73 | | -- Build: `poetry build` |
74 | | -- Publish: `poetry publish` (or `poetry publish --build`) |
75 | | - |
76 | | -# Brunata München API |
77 | | - |
78 | | -Python-API zum Abrufen von Verbrauchsdaten vom Brunata München Nutzerportal. |
79 | | - |
80 | | -## Installation |
81 | | - |
82 | | -1. Repository klonen oder Dateien herunterladen |
83 | | -2. Dependencies installieren: |
84 | | - |
85 | | -```bash |
86 | | -pip install -r requirements.txt |
87 | | -``` |
88 | | - |
89 | | -3. Umgebungsvariablen einrichten: |
90 | | - |
91 | | -```bash |
92 | | -cp .env.example .env |
93 | | -``` |
94 | | - |
95 | | -Dann die `.env` Datei bearbeiten und deine Login-Daten eintragen: |
96 | | - |
97 | | -``` |
98 | | -BRUNATA_USERNAME=dein_benutzername |
99 | | -BRUNATA_PASSWORD=dein_passwort |
100 | | -BRUNATA_CLIENT=201 |
101 | | -``` |
102 | | - |
103 | | -## Verwendung |
104 | | - |
105 | | -### Test-Skript |
106 | | - |
107 | | -Schnelltest mit deinen Login-Daten: |
| 78 | +## Entwicklung |
108 | 79 |
|
109 | 80 | ```bash |
110 | | -python test_client.py <username> <password> [client_id] |
| 81 | +poetry run ruff check src tests |
| 82 | +poetry run pytest |
111 | 83 | ``` |
112 | 84 |
|
113 | | -### Als Python-Modul |
114 | | - |
115 | | -```python |
116 | | -from brunata_client import BrunataClient |
117 | | - |
118 | | -# Client erstellen |
119 | | -client = BrunataClient("username", "password") |
120 | | - |
121 | | -# Einloggen |
122 | | -if client.login(): |
123 | | - # Verbrauchsdaten abrufen |
124 | | - data = client.get_consumption_data( |
125 | | - start_date="2024-01-01", |
126 | | - end_date="2024-12-31" |
127 | | - ) |
128 | | - print(data) |
129 | | - |
130 | | - # Verfügbare Entity Sets anzeigen |
131 | | - entities = client.get_all_entities() |
132 | | - print(entities) |
133 | | - |
134 | | - client.close() |
135 | | -``` |
136 | | - |
137 | | -### Als Flask API Server |
| 85 | +## Packaging (optional) |
138 | 86 |
|
139 | 87 | ```bash |
140 | | -python api.py |
| 88 | +poetry build |
| 89 | +poetry publish --build |
141 | 90 | ``` |
142 | 91 |
|
143 | | -Die API läuft dann auf `http://localhost:5000` |
144 | | - |
145 | | -#### API Endpoints |
146 | | - |
147 | | -- `GET /health` - Health Check |
148 | | -- `POST /login` - Login mit Credentials |
149 | | - ```json |
150 | | - { |
151 | | - "username": "dein_username", |
152 | | - "password": "dein_passwort", |
153 | | - "client": "201" |
154 | | - } |
155 | | - ``` |
156 | | -- `GET /consumption?start_date=2024-01-01&end_date=2024-12-31` - Verbrauchsdaten abrufen |
157 | | -- `GET /entities` - Alle verfügbaren Entity Sets abrufen |
158 | | - |
159 | | -## Aktueller Status |
160 | | - |
161 | | -✅ **Login funktioniert** - Login via OData `NP_REG_LOGON_SRV_01/CredentialSet` |
162 | | -✅ **Datenzugriff funktioniert** - Verbrauchsdaten via `NP_DASHBOARD_SRV` (monatlich) |
163 | | - |
164 | | -### Gefundene Services: |
165 | | -- `NP_GENERIC_SRV`: PlaceholderSet, InfoTextSet, PageModuleSet, UserContextSet, UserContextRoleSet, FAQSet |
166 | | -- `NP_REG_LOGON_SRV_01`: PortalUserSet, TitleSet, InfoTextSet, FAQSet, CredentialSet |
167 | | -- `NP_APPLAUNCHER_SRV`: UserContextSet, ModuleSet, NavigationMenueSet, ... |
168 | | -- `NP_DASHBOARD_SRV`: DatesSet, ValueHelpUnitOfMeasureSet, CumuConsumptionMonSet, ... |
169 | | - |
170 | | -### Nächste Schritte: |
171 | | -Optional (für eine HA-Integration): |
172 | | - |
173 | | -1. Aus `Reading` stabile Sensor-IDs ableiten (z.B. `heating_monthly_kwh`, `hot_water_monthly_kwh`) |
174 | | -2. Optional weitere Endpoints aus `NP_DASHBOARD_SRV` hinzufügen (z.B. `CumuConsumptionSet` Summen) |
175 | | -3. Caching/Throttling auf HA-Seite (Coordinator) ergänzen |
176 | | - |
177 | | -## Fehlerbehebung |
178 | | - |
179 | | -- **Login fehlschlägt**: Überprüfe deine Credentials in der `.env` Datei |
180 | | -- **Keine Daten gefunden**: Prüfe `BRUNATA_SAP_CLIENT` (Munich meist `201`) und ob in `DatesSet` die CostTypes (`HZ..`, `WW..`) vorhanden sind |
181 | | -- **401 Fehler**: Login liefert SAP Basic-Auth Credentials, die für nachfolgende OData Requests nötig sind (wird im Client automatisch gemacht) |
182 | | - |
183 | | -## Entwicklung |
184 | | - |
185 | | -Die Authentifizierung läuft in zwei Phasen: |
186 | | - |
187 | | -1. **OData Credential Login**: `NP_REG_LOGON_SRV_01` (`CredentialSet` via `$batch`) |
188 | | -2. **SAP Basic Auth**: danach werden alle OData Calls (z.B. `NP_DASHBOARD_SRV`) mit Basic Auth durchgeführt |
189 | | - |
190 | | -Falls das Portal spezielle Anforderungen hat, müssen diese im `BrunataClient` angepasst werden. |
191 | | - |
0 commit comments