iobroker.grohe-smarthome 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 patricknitsch <patricknitsch@web.de>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,282 @@
1
+ ![Logo](admin/grohe-smarthome.png)
2
+ # ioBroker.grohe-smarthome
3
+
4
+ [![NPM version](https://img.shields.io/npm/v/iobroker.grohe-smarthome.svg)](https://www.npmjs.com/package/iobroker.grohe-smarthome)
5
+ [![Downloads](https://img.shields.io/npm/dm/iobroker.grohe-smarthome.svg)](https://www.npmjs.com/package/iobroker.grohe-smarthome)
6
+ ![Number of Installations](https://iobroker.live/badges/grohe-smarthome-installed.svg)
7
+ ![Current version in stable repository](https://iobroker.live/badges/grohe-smarthome-stable.svg)
8
+
9
+ [![NPM](https://nodei.co/npm/iobroker.grohe-smarthome.png?downloads=true)](https://nodei.co/npm/iobroker.grohe-smarthome/)
10
+
11
+ **Tests:** ![Test and Release](https://github.com/patricknitsch/ioBroker.grohe-smarthome/workflows/Test%20and%20Release/badge.svg)
12
+
13
+ # ioBroker Grohe Smarthome Adapter
14
+
15
+ This adapter connects ioBroker to the **Grohe Smarthome / Ondus** cloud and exposes Grohe devices as states (and some controls) inside ioBroker.
16
+
17
+ It supports:
18
+
19
+ - **Grohe Sense** (type `101`)
20
+ - **Grohe Sense Guard** (type `103`)
21
+ - **Grohe Blue Home** (type `104`)
22
+ - **Grohe Blue Professional** (type `105`)
23
+
24
+ The adapter logs in via Grohe’s OIDC/Keycloak flow, stores a **refresh token encrypted** in a state, and polls the Grohe cloud API on a configurable interval.
25
+
26
+ ---
27
+
28
+ ## Features
29
+
30
+ - Cloud login with **email/password** (initial) and automatic **token refresh**
31
+ - Refresh token is persisted **encrypted** in `grohe-smarthome.0.auth.refreshToken`
32
+ - Periodic polling of the Grohe dashboard:
33
+ - discovers locations → rooms → appliances
34
+ - creates ioBroker devices/channels/states automatically
35
+ - Device data exposed as readable states (measurements, status, notifications)
36
+ - **Controls** (writable states) for:
37
+ - Sense Guard valve open/close
38
+ - Sense Guard start pressure measurement
39
+ - Grohe Blue dispensing + CO₂/filter resets
40
+ - Optional creation of a `.raw` channel with all raw measurement fields
41
+
42
+ ---
43
+
44
+ ## Configuration
45
+
46
+ In the adapter instance settings:
47
+
48
+ - **Email**: your Grohe/Ondus account email
49
+ - **Password**: your Grohe/Ondus account password
50
+ - **Poll interval (seconds)**: polling interval in seconds
51
+ - minimum is **30 seconds**
52
+ - default fallback is **300 seconds**
53
+ - **Raw states** (`rawStates`): if enabled, the adapter writes all measurement fields to `<device>.raw.*`
54
+
55
+ > Note: The adapter does **not** store the refresh token in the config because writing the config triggers an instance restart. Instead it is stored in a state (`auth.refreshToken`) and encrypted using ioBroker’s built-in encryption helpers.
56
+
57
+ ---
58
+
59
+ ## Authentication and Token Handling
60
+
61
+ On startup:
62
+
63
+ 1. The adapter reads the stored refresh token from `auth.refreshToken`.
64
+ 2. If available, it tries to refresh tokens.
65
+ 3. If refresh fails or no token exists, it performs a full login with email/password.
66
+ 4. The obtained refresh token is stored **encrypted** (`enc:<...>`) in `auth.refreshToken`.
67
+
68
+ If an old (unencrypted) token is found, the adapter automatically migrates it to encrypted storage.
69
+
70
+ The HTTP client automatically retries requests once if it receives **401 Unauthorized** (refresh + retry).
71
+
72
+ ---
73
+
74
+ ## Device Structure in ioBroker
75
+
76
+ Devices are created under the adapter namespace:
77
+
78
+ ```
79
+ grohe-smarthome.0.<applianceId>.*
80
+ ```
81
+
82
+ Each appliance becomes a **device object**, with additional channels depending on type.
83
+
84
+ ### Common states for all devices
85
+
86
+ #### Status channel
87
+
88
+ ```
89
+ <applianceId>.status.online (boolean)
90
+ <applianceId>.status.updateAvailable (boolean)
91
+ <applianceId>.status.wifiQuality (number, if available)
92
+ ```
93
+
94
+ #### Notifications channel (latest entry)
95
+
96
+ ```
97
+ <applianceId>.notifications.latestMessage (string)
98
+ <applianceId>.notifications.latestTimestamp (string/date)
99
+ <applianceId>.notifications.latestCategory (number)
100
+ <applianceId>.notifications.latestCategoryName (string)
101
+ ```
102
+
103
+ Notification categories are mapped like:
104
+
105
+ - `10` Information
106
+ - `20` Warning
107
+ - `30` Alarm
108
+ - `40` WebURL
109
+
110
+ ---
111
+
112
+ ## Grohe Sense (type 101)
113
+
114
+ States:
115
+
116
+ ```
117
+ <applianceId>.temperature (°C)
118
+ <applianceId>.humidity (%)
119
+ <applianceId>.battery (%)
120
+ <applianceId>.lastMeasurement (date string)
121
+ ```
122
+
123
+ Optional raw data (if enabled):
124
+
125
+ ```
126
+ <applianceId>.raw.*
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Grohe Sense Guard (type 103)
132
+
133
+ States:
134
+
135
+ ```
136
+ <applianceId>.temperature (°C, water temp)
137
+ <applianceId>.flowRate (l/h)
138
+ <applianceId>.pressure (bar)
139
+ <applianceId>.lastMeasurement (date string)
140
+ <applianceId>.valveOpen (boolean indicator)
141
+ ```
142
+
143
+ Consumption channel:
144
+
145
+ ```
146
+ <applianceId>.consumption.daily
147
+ <applianceId>.consumption.averageDaily
148
+ <applianceId>.consumption.averageMonthly
149
+ <applianceId>.consumption.totalWaterConsumption
150
+ <applianceId>.consumption.lastWaterConsumption
151
+ <applianceId>.consumption.lastMaxFlowRate
152
+ ```
153
+
154
+ Pressure measurement channel (only if the API provides data; may be missing initially):
155
+
156
+ ```
157
+ <applianceId>.pressureMeasurement.dropOfPressure (bar)
158
+ <applianceId>.pressureMeasurement.isLeakage (boolean)
159
+ <applianceId>.pressureMeasurement.leakageLevel (string)
160
+ <applianceId>.pressureMeasurement.startTime (date string)
161
+ ```
162
+
163
+ Controls (writable “button” states, auto-reset back to `false` after execution):
164
+
165
+ ```
166
+ <applianceId>.controls.valveOpen (boolean button)
167
+ <applianceId>.controls.valveClose (boolean button)
168
+ <applianceId>.controls.startPressureMeasurement (boolean button)
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Grohe Blue Home / Professional (type 104 / 105)
174
+
175
+ States:
176
+
177
+ ```
178
+ <applianceId>.remainingCo2 (%)
179
+ <applianceId>.remainingFilter (%)
180
+ <applianceId>.remainingCo2Liters (l)
181
+ <applianceId>.remainingFilterLiters (l)
182
+
183
+ <applianceId>.cyclesCarbonated
184
+ <applianceId>.cyclesStill
185
+
186
+ <applianceId>.operatingTime (min)
187
+ <applianceId>.pumpRunningTime (min)
188
+ <applianceId>.maxIdleTime (min)
189
+ <applianceId>.timeSinceRestart (min)
190
+
191
+ <applianceId>.waterRunningCarbonated (min)
192
+ <applianceId>.waterRunningMedium (min)
193
+ <applianceId>.waterRunningStill (min)
194
+
195
+ <applianceId>.dateCleaning (date string)
196
+ <applianceId>.dateCo2Replacement (date string)
197
+ <applianceId>.dateFilterReplacement (date string)
198
+ <applianceId>.lastMeasurement (date string)
199
+
200
+ <applianceId>.cleaningCount
201
+ <applianceId>.filterChangeCount
202
+ <applianceId>.powerCutCount
203
+ <applianceId>.pumpCount
204
+ ```
205
+
206
+ Controls:
207
+
208
+ ```
209
+ <applianceId>.controls.tapType (number) 1=still, 2=medium, 3=carbonated
210
+ <applianceId>.controls.tapAmount (number) amount in ml (multiples of 50 recommended)
211
+ <applianceId>.controls.dispenseTrigger (boolean button)
212
+
213
+ <applianceId>.controls.resetCo2 (boolean button)
214
+ <applianceId>.controls.resetFilter (boolean button)
215
+ ```
216
+
217
+ When `dispenseTrigger` is set to `true`, the adapter reads `tapType` and `tapAmount`, triggers dispensing, and resets `dispenseTrigger` back to `false`.
218
+
219
+ ---
220
+
221
+ ## Polling and Discovery
222
+
223
+ - The adapter polls the endpoint `/dashboard` and iterates:
224
+ - `locations[] → rooms[] → appliances[]`
225
+ - Appliances with `registration_complete === false` are skipped.
226
+ - For each appliance it also tries to fetch:
227
+ - `/status` (online/update/wifi)
228
+ - `/command` (used for Sense Guard `valve_open`)
229
+ - `/pressuremeasurement` (Sense Guard; may return HTTP 404 if never executed)
230
+
231
+ ---
232
+
233
+ ## Error Handling Notes
234
+
235
+ - If polling fails, `info.connection` is set to `false`.
236
+ - Special handling for **HTTP 403**: the adapter logs a message suggesting to verify that the Grohe app/account is still working/active.
237
+ - Token refresh is automatic on **401** and then the request is retried once.
238
+
239
+ ---
240
+
241
+ ## Development Notes
242
+
243
+ Core modules:
244
+
245
+ - `main.js`: ioBroker adapter logic (objects, polling, state updates, command handling)
246
+ - `lib/groheClient.js`: Grohe API wrapper with authenticated requests
247
+ - `lib/auth.js`: OAuth/Keycloak login + refresh handling (manual redirect chain, cookie jar)
248
+
249
+ ---
250
+
251
+ ## Changelog
252
+ <!--
253
+ Placeholder for the next version (at the beginning of the line):
254
+ ### **WORK IN PROGRESS**
255
+ -->
256
+ ### 0.1.0 (2026-02-07)
257
+ * (patricknitsch) initial release
258
+ * (patricknitsch) first functional version
259
+ * (patricknitsch) a lot of debug to see where the problems are
260
+
261
+ ## License
262
+ MIT License
263
+
264
+ Copyright (c) 2026 patricknitsch <patricknitsch@web.de>
265
+
266
+ Permission is hereby granted, free of charge, to any person obtaining a copy
267
+ of this software and associated documentation files (the "Software"), to deal
268
+ in the Software without restriction, including without limitation the rights
269
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
270
+ copies of the Software, and to permit persons to whom the Software is
271
+ furnished to do so, subject to the following conditions:
272
+
273
+ The above copyright notice and this permission notice shall be included in all
274
+ copies or substantial portions of the Software.
275
+
276
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
277
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
278
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
279
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
280
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
281
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
282
+ SOFTWARE.
Binary file
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Grohe Smarthome Adaptereinstellungen"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Grohe Smarthome adapter settings"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Ajustes del adaptador Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Paramètres de l'adaptateur Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Impostazioni dell'adattatore Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Grohe Smarthome adapterinstellingen"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Ustawienia adaptera Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Configurações do adaptador Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Настройки адаптера Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Налаштування адаптера Grohe Smarthome"
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "grohe_smarthome adapter settings": "Grohe Smarthome 适配器设置"
3
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "i18n": true,
3
+ "items": {
4
+ "email": {
5
+ "type": "text",
6
+ "label": { "en": "Grohe email / username", "de": "Grohe E-Mail / Benutzername" },
7
+ "xs": 12,
8
+ "sm": 12,
9
+ "md": 6,
10
+ "lg": 6,
11
+ "xl": 6
12
+ },
13
+ "password": {
14
+ "type": "password",
15
+ "label": { "en": "Grohe password", "de": "Grohe Passwort" },
16
+ "xs": 12,
17
+ "sm": 12,
18
+ "md": 6,
19
+ "lg": 6,
20
+ "xl": 6
21
+ },
22
+ "pollInterval": {
23
+ "type": "number",
24
+ "label": { "en": "Polling interval (seconds)", "de": "Abfrageintervall (Sekunden)" },
25
+ "min": 30,
26
+ "default": 300,
27
+ "xs": 12,
28
+ "sm": 6,
29
+ "md": 4,
30
+ "lg": 3,
31
+ "xl": 2
32
+ },
33
+ "rawStates": {
34
+ "type": "checkbox",
35
+ "label": { "en": "Create raw measurement states", "de": "Rohdaten-States erstellen" },
36
+ "default": false,
37
+ "xs": 12,
38
+ "sm": 6,
39
+ "md": 4,
40
+ "lg": 3,
41
+ "xl": 2
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,129 @@
1
+ {
2
+ "common": {
3
+ "name": "grohe-smarthome",
4
+ "version": "0.1.0",
5
+ "news": {
6
+ "0.1.0": {
7
+ "en": "initial release\nfirst functional version\na lot of debug to see where the problems are",
8
+ "de": "erstausstrahlung\nerste funktionsversion\nviel debug zu sehen, wo die probleme sind",
9
+ "ru": "первоначальное освобождение\nпервая функциональная версия\nмного отладки, чтобы увидеть, где проблемы",
10
+ "pt": "libertação inicial\nprimeira versão funcional\num monte de depuração para ver onde os problemas estão",
11
+ "nl": "eerste release\neerste functionele versie\nveel debug om te zien waar de problemen zijn",
12
+ "fr": "libération initiale\npremière version fonctionnelle\nbeaucoup de débogage pour voir où sont les problèmes",
13
+ "it": "rilascio iniziale\nprima versione funzionale\nun sacco di debug per vedere dove i problemi sono",
14
+ "es": "liberación inicial\nprimera versión funcional\nmucha depuración para ver dónde están los problemas",
15
+ "pl": "początkowe zwolnienie\npierwsza wersja funkcjonalna\ndużo debug, aby zobaczyć, gdzie są problemy",
16
+ "uk": "початковий реліз\nперший функціонал\nбагато абвуг, щоб побачити, де проблеми є",
17
+ "zh-cn": "初步释放\n第一个功能版本\n很多调试,看看问题在哪里"
18
+ },
19
+ "0.0.1": {
20
+ "en": "initial release",
21
+ "de": "Erstveröffentlichung",
22
+ "ru": "Начальная версия",
23
+ "pt": "lançamento inicial",
24
+ "nl": "Eerste uitgave",
25
+ "fr": "Première version",
26
+ "it": "Versione iniziale",
27
+ "es": "Versión inicial",
28
+ "pl": "Pierwsze wydanie",
29
+ "uk": "Початкова версія",
30
+ "zh-cn": "首次出版"
31
+ }
32
+ },
33
+ "titleLang": {
34
+ "en": "Grohe Smarthome",
35
+ "de": "Grohe Smarthome",
36
+ "ru": "Умный дом Grohe",
37
+ "pt": "Casa inteligente Grohe",
38
+ "nl": "Grohe Smarthome",
39
+ "fr": "Maison intelligente Grohe",
40
+ "it": "Grohe Smarthome",
41
+ "es": "Grohe Smarthome",
42
+ "pl": "Grohe Smarthome",
43
+ "uk": "Grohe Smarthome",
44
+ "zh-cn": "高仪智能家居"
45
+ },
46
+ "desc": {
47
+ "en": "Connect to Grohe Guard / Sense / Blue Systems",
48
+ "de": "Verbinden Sie sich mit Grohe Guard / Sense / Blue Systems",
49
+ "ru": "Подключение к системам Grohe Guard/Sense/Blue",
50
+ "pt": "Conecte-se aos sistemas Grohe Guard / Sense / Blue",
51
+ "nl": "Maak verbinding met Grohe Guard/Sense/Blue Systems",
52
+ "fr": "Connectez-vous aux systèmes Grohe Guard / Sense / Blue",
53
+ "it": "Connettiti ai sistemi Grohe Guard/Sense/Blue",
54
+ "es": "Conéctese a los sistemas Grohe Guard/Sense/Blue",
55
+ "pl": "Połącz się z systemami Grohe Guard / Sense / Blue",
56
+ "uk": "Підключіться до Grohe Guard / Sense / Blue Systems",
57
+ "zh-cn": "连接到 Grohe Guard / Sense / Blue 系统"
58
+ },
59
+ "authors": [
60
+ "patricknitsch <patricknitsch@web.de>"
61
+ ],
62
+ "keywords": [
63
+ "grohe",
64
+ "water"
65
+ ],
66
+ "licenseInformation": {
67
+ "type": "free",
68
+ "license": "MIT"
69
+ },
70
+ "platform": "Javascript/Node.js",
71
+ "icon": "grohe-smarthome.png",
72
+ "enabled": true,
73
+ "extIcon": "https://raw.githubusercontent.com/patricknitsch/ioBroker.grohe-smarthome/main/admin/grohe-smarthome.png",
74
+ "readme": "https://github.com/patricknitsch/ioBroker.grohe-smarthome/blob/main/README.md",
75
+ "loglevel": "info",
76
+ "tier": 3,
77
+ "mode": "daemon",
78
+ "type": "metering",
79
+ "compact": true,
80
+ "connectionType": "cloud",
81
+ "dataSource": "poll",
82
+ "adminUI": {
83
+ "config": "json"
84
+ },
85
+ "dependencies": [
86
+ {
87
+ "js-controller": ">=6.0.11"
88
+ }
89
+ ],
90
+ "globalDependencies": [
91
+ {
92
+ "admin": ">=7.6.17"
93
+ }
94
+ ]
95
+ },
96
+ "native": {
97
+ "email": "",
98
+ "password": "",
99
+ "pollInterval": 300,
100
+ "rawStates": false
101
+ },
102
+ "encryptedNative": [
103
+ "password"
104
+ ],
105
+ "objects": [],
106
+ "instanceObjects": [
107
+ {
108
+ "_id": "info",
109
+ "type": "channel",
110
+ "common": {
111
+ "name": "Information"
112
+ },
113
+ "native": {}
114
+ },
115
+ {
116
+ "_id": "info.connection",
117
+ "type": "state",
118
+ "common": {
119
+ "role": "indicator.connected",
120
+ "name": "Device or service connected",
121
+ "type": "boolean",
122
+ "read": true,
123
+ "write": false,
124
+ "def": false
125
+ },
126
+ "native": {}
127
+ }
128
+ ]
129
+ }
@@ -0,0 +1,19 @@
1
+ // This file extends the AdapterConfig type from "@iobroker/types"
2
+ // using the actual properties present in io-package.json
3
+ // in order to provide typings for adapter.config properties
4
+
5
+ import { native } from '../io-package.json';
6
+
7
+ type _AdapterConfig = typeof native;
8
+
9
+ // Augment the globally declared type ioBroker.AdapterConfig
10
+ declare global {
11
+ namespace ioBroker {
12
+ interface AdapterConfig extends _AdapterConfig {
13
+ // Do not enter anything here!
14
+ }
15
+ }
16
+ }
17
+
18
+ // this is required so the above AdapterConfig is found by TypeScript / type checking
19
+ export {};