@impact0815/node-red-contrib-home-connect 0.0.0-stage → 0.2.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/BUILD-INFO.json +23 -0
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/NOTICE +19 -0
- package/README.de.md +326 -0
- package/README.md +325 -2
- package/SECURITY.md +47 -0
- package/docs/API-COVERAGE.md +59 -0
- package/docs/ARCHITECTURE.md +95 -0
- package/docs/DASHBOARD.de.md +121 -0
- package/docs/DASHBOARD.md +121 -0
- package/docs/FIRST-PUSH.md +42 -0
- package/docs/LOCAL-LAN.de.md +150 -0
- package/docs/LOCAL-LAN.md +150 -0
- package/docs/MESSAGE-API.md +111 -0
- package/docs/RELEASE.md +78 -0
- package/docs/TROUBLESHOOTING.de.md +230 -0
- package/docs/TROUBLESHOOTING.md +230 -0
- package/docs/images/README.md +10 -0
- package/docs/images/dashboard-details-en.png +0 -0
- package/docs/images/dashboard-overview-en.png +0 -0
- package/docs/official-api-contract.json +418 -0
- package/examples/01-first-steps-device-list.json +148 -0
- package/examples/02-events.json +165 -0
- package/examples/03-safe-read-write.json +155 -0
- package/examples/04-local-read-only.json +214 -0
- package/examples/dashboard-dishwasher-washer-oven.json +628 -0
- package/examples/dashboard-screenshot-simulated.json +405 -0
- package/examples/demo-home-connect-flowfuse-1.34.1-scriptless.json +390 -0
- package/lib/client.js +600 -0
- package/lib/constants.js +66 -0
- package/lib/dashboard-i18n.js +255 -0
- package/lib/device-label.js +39 -0
- package/lib/errors.js +51 -0
- package/lib/health.js +525 -0
- package/lib/local-client.js +1014 -0
- package/lib/local-crypto.js +122 -0
- package/lib/local-diagnostics.js +115 -0
- package/lib/local-profile.js +706 -0
- package/lib/local-trace.js +103 -0
- package/lib/oauth.js +23 -0
- package/lib/rate-limiter.js +186 -0
- package/lib/simulator.js +290 -0
- package/lib/sse.js +58 -0
- package/lib/validation.js +194 -0
- package/lib/websocket-transport.js +374 -0
- package/nodes/home-connect.html +795 -0
- package/nodes/home-connect.js +699 -0
- package/nodes/locales/de/home-connect.html +19 -0
- package/nodes/locales/de/home-connect.json +10 -0
- package/nodes/locales/en-US/home-connect.json +10 -0
- package/package.json +71 -4
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
4
|
+
"type": "tab",
|
|
5
|
+
"label": "Demo Home Connect FlowFuse 1.34.1",
|
|
6
|
+
"disabled": false,
|
|
7
|
+
"info": "Demo only: deterministic simulated appliances, no credentials, real IDs, IPs, profiles or network calls.",
|
|
8
|
+
"wires": []
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "demo-hc-ff1341-fix2-comment",
|
|
12
|
+
"type": "comment",
|
|
13
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
14
|
+
"name": "Demo FlowFuse 1.34.1 · vollständig simuliert · skriptfreie UI-Templates",
|
|
15
|
+
"info": "Requires @flowfuse/node-red-dashboard and node-red-contrib-home-connect. Health schema: home-connect-health/v1. Device information only; no firmware endpoint is used.",
|
|
16
|
+
"x": 360,
|
|
17
|
+
"y": 40,
|
|
18
|
+
"wires": []
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "demo-hc-ff1341-fix2-ui-base",
|
|
22
|
+
"type": "ui-base",
|
|
23
|
+
"name": "Demo Home Connect FlowFuse 1.34.1",
|
|
24
|
+
"path": "/demo-home-connect-ff1341-fix2",
|
|
25
|
+
"appIcon": "",
|
|
26
|
+
"includeClientData": true,
|
|
27
|
+
"acceptsClientConfig": [
|
|
28
|
+
"ui-notification",
|
|
29
|
+
"ui-control"
|
|
30
|
+
],
|
|
31
|
+
"showPathInSidebar": false,
|
|
32
|
+
"headerContent": "page",
|
|
33
|
+
"navigationStyle": "default",
|
|
34
|
+
"titleBarStyle": "default",
|
|
35
|
+
"showReconnectNotification": true,
|
|
36
|
+
"notificationDisplayTime": 1,
|
|
37
|
+
"showDisconnectNotification": true,
|
|
38
|
+
"allowInstall": false,
|
|
39
|
+
"wires": []
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "demo-hc-ff1341-fix2-ui-theme",
|
|
43
|
+
"type": "ui-theme",
|
|
44
|
+
"name": "Demo Home Connect FlowFuse 1.34.1",
|
|
45
|
+
"colors": {
|
|
46
|
+
"surface": "#ffffff",
|
|
47
|
+
"primary": "#00629B",
|
|
48
|
+
"bgPage": "#f3f6f9",
|
|
49
|
+
"groupBg": "#ffffff",
|
|
50
|
+
"groupOutline": "#d8e2eb"
|
|
51
|
+
},
|
|
52
|
+
"sizes": {
|
|
53
|
+
"density": "default",
|
|
54
|
+
"pagePadding": "12px",
|
|
55
|
+
"groupGap": "12px",
|
|
56
|
+
"groupBorderRadius": "6px",
|
|
57
|
+
"widgetGap": "12px"
|
|
58
|
+
},
|
|
59
|
+
"wires": []
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "demo-hc-ff1341-fix2-ui-page",
|
|
63
|
+
"type": "ui-page",
|
|
64
|
+
"name": "Demo Gerätedetails",
|
|
65
|
+
"ui": "demo-hc-ff1341-fix2-ui-base",
|
|
66
|
+
"path": "/demo-details",
|
|
67
|
+
"icon": "home",
|
|
68
|
+
"layout": "grid",
|
|
69
|
+
"theme": "demo-hc-ff1341-fix2-ui-theme",
|
|
70
|
+
"breakpoints": [
|
|
71
|
+
{
|
|
72
|
+
"name": "Default",
|
|
73
|
+
"px": "0",
|
|
74
|
+
"cols": "3"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "Tablet",
|
|
78
|
+
"px": "576",
|
|
79
|
+
"cols": "6"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "Small Desktop",
|
|
83
|
+
"px": "768",
|
|
84
|
+
"cols": "9"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "Desktop",
|
|
88
|
+
"px": "1024",
|
|
89
|
+
"cols": "12"
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"order": 2,
|
|
93
|
+
"className": "",
|
|
94
|
+
"visible": "true",
|
|
95
|
+
"disabled": "false",
|
|
96
|
+
"wires": []
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"id": "demo-hc-ff1341-fix2-group-dw",
|
|
100
|
+
"type": "ui-group",
|
|
101
|
+
"name": "Demo Geschirrspüler",
|
|
102
|
+
"page": "demo-hc-ff1341-fix2-ui-page",
|
|
103
|
+
"width": "4",
|
|
104
|
+
"height": "1",
|
|
105
|
+
"order": 1,
|
|
106
|
+
"showTitle": false,
|
|
107
|
+
"className": "",
|
|
108
|
+
"visible": "true",
|
|
109
|
+
"disabled": "false",
|
|
110
|
+
"wires": []
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "demo-hc-ff1341-fix2-group-wm",
|
|
114
|
+
"type": "ui-group",
|
|
115
|
+
"name": "Demo Waschmaschine",
|
|
116
|
+
"page": "demo-hc-ff1341-fix2-ui-page",
|
|
117
|
+
"width": "4",
|
|
118
|
+
"height": "1",
|
|
119
|
+
"order": 2,
|
|
120
|
+
"showTitle": false,
|
|
121
|
+
"className": "",
|
|
122
|
+
"visible": "true",
|
|
123
|
+
"disabled": "false",
|
|
124
|
+
"wires": []
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"id": "demo-hc-ff1341-fix2-group-ov",
|
|
128
|
+
"type": "ui-group",
|
|
129
|
+
"name": "Demo Backofen",
|
|
130
|
+
"page": "demo-hc-ff1341-fix2-ui-page",
|
|
131
|
+
"width": "4",
|
|
132
|
+
"height": "1",
|
|
133
|
+
"order": 3,
|
|
134
|
+
"showTitle": false,
|
|
135
|
+
"className": "",
|
|
136
|
+
"visible": "true",
|
|
137
|
+
"disabled": "false",
|
|
138
|
+
"wires": []
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"id": "demo-hc-ff1341-fix2-ui-dw",
|
|
142
|
+
"type": "ui-template",
|
|
143
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
144
|
+
"group": "demo-hc-ff1341-fix2-group-dw",
|
|
145
|
+
"page": "",
|
|
146
|
+
"ui": "",
|
|
147
|
+
"name": "Demo Geschirrspüler",
|
|
148
|
+
"order": 1,
|
|
149
|
+
"width": 0,
|
|
150
|
+
"height": 0,
|
|
151
|
+
"head": "",
|
|
152
|
+
"format": "<template>\n <v-card id=\"demo-hc-dishwasher\" class=\"demo-hc-card\" elevation=\"2\">\n <v-card-title>\n <v-icon class=\"mr-2\">mdi-dishwasher</v-icon>{{ msg?.payload?.deviceTitle || 'Demo Geschirrspüler' }}\n <v-spacer></v-spacer>\n <v-chip color=\"secondary\" size=\"small\" class=\"mr-2\">{{ msg?.payload?.simulatedLabel || 'SIMULIERT' }}</v-chip>\n <v-chip :color=\"msg?.payload?.healthColor || 'grey'\" size=\"small\">{{ msg?.payload?.healthLabel || '—' }}</v-chip>\n </v-card-title>\n <v-card-text>\n <div class=\"demo-hc-device-info\">\n <b>{{ msg?.payload?.deviceTitle || 'Demo Geschirrspüler' }}</b><br>\n {{ msg?.payload?.brand || '—' }} · {{ msg?.payload?.typeLabel || '—' }}<br>\n <span v-if=\"msg?.payload?.vib\">VIB/E-Nummer: {{ msg.payload.vib }}</span><br>\n <span>{{ msg?.payload?.ui?.connection || '—' }}: {{ msg?.payload?.connectionText || '—' }}</span>\n </div>\n <v-alert v-if=\"msg?.payload?.warningText\" :type=\"msg?.payload?.warningType || 'info'\" density=\"compact\" variant=\"tonal\" class=\"mb-2\">\n <b>{{ msg.payload.warningText }}</b>\n </v-alert>\n <div><b>{{ msg?.payload?.ui?.status || '—' }}:</b> {{ msg?.payload?.statusText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.door || '—' }}:</b> {{ msg?.payload?.doorText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.active || '—' }}:</b> {{ msg?.payload?.activeText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.selected || '—' }}:</b> {{ msg?.payload?.selectedText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remaining || '—' }}:</b> {{ msg?.payload?.remainingText || '—' }}</div>\n <div class=\"demo-hc-panel\">\n <div class=\"demo-hc-panel-title\">{{ msg?.payload?.ui?.simulatedValues || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remoteControl || '—' }}:</b> {{ msg?.payload?.remoteControlText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remoteStart || '—' }}:</b> {{ msg?.payload?.remoteStartText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.localControl || '—' }}:</b> {{ msg?.payload?.localControlText || '—' }}</div>\n <div v-if=\"msg?.payload?.options?.length\" class=\"mt-2\">\n <b>{{ msg?.payload?.ui?.currentOptions || '—' }}:</b>\n <div v-for=\"item in msg.payload.options\" :key=\"item.key\" class=\"demo-hc-option\">\n <span :title=\"item.key\">{{ item.label }}</span>: {{ item.valueText }}<span v-if=\"item.unit\"> {{ item.unit }}</span>\n </div>\n </div>\n <div v-if=\"msg?.payload?.programsText\" class=\"mt-2\"><b>{{ msg?.payload?.ui?.availablePrograms || '—' }}:</b> {{ msg.payload.programsText }}</div>\n </div>\n </v-card-text>\n <v-card-actions>\n <v-btn variant=\"text\" @click=\"send({payload:{action:'refresh'}})\">{{ msg?.payload?.ui?.refresh || 'Refresh' }}</v-btn>\n </v-card-actions>\n </v-card>\n</template>\n<style>\n.demo-hc-card{border-top:4px solid rgb(var(--v-theme-primary));height:100%;scroll-margin-top:72px}\n.demo-hc-device-info{padding:8px 0 12px;color:rgba(var(--v-theme-on-surface),.75)}\n.demo-hc-panel{margin-top:14px;padding:12px;border:1px solid rgba(var(--v-theme-on-surface),.18);border-radius:6px;background:rgba(var(--v-theme-on-surface),.035)}\n.demo-hc-panel-title{font-weight:600;margin-bottom:8px}\n.demo-hc-option{padding-left:10px}\n</style>",
|
|
153
|
+
"storeOutMessages": true,
|
|
154
|
+
"passthru": false,
|
|
155
|
+
"resendOnRefresh": true,
|
|
156
|
+
"templateScope": "local",
|
|
157
|
+
"className": "",
|
|
158
|
+
"x": 670,
|
|
159
|
+
"y": 260,
|
|
160
|
+
"wires": [
|
|
161
|
+
[
|
|
162
|
+
"demo-hc-ff1341-fix2-data"
|
|
163
|
+
]
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"id": "demo-hc-ff1341-fix2-ui-wm",
|
|
168
|
+
"type": "ui-template",
|
|
169
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
170
|
+
"group": "demo-hc-ff1341-fix2-group-wm",
|
|
171
|
+
"page": "",
|
|
172
|
+
"ui": "",
|
|
173
|
+
"name": "Demo Waschmaschine",
|
|
174
|
+
"order": 1,
|
|
175
|
+
"width": 0,
|
|
176
|
+
"height": 0,
|
|
177
|
+
"head": "",
|
|
178
|
+
"format": "<template>\n <v-card id=\"demo-hc-washer\" class=\"demo-hc-card\" elevation=\"2\">\n <v-card-title>\n <v-icon class=\"mr-2\">mdi-washing-machine</v-icon>{{ msg?.payload?.deviceTitle || 'Demo Waschmaschine' }}\n <v-spacer></v-spacer>\n <v-chip color=\"secondary\" size=\"small\" class=\"mr-2\">{{ msg?.payload?.simulatedLabel || 'SIMULIERT' }}</v-chip>\n <v-chip :color=\"msg?.payload?.healthColor || 'grey'\" size=\"small\">{{ msg?.payload?.healthLabel || '—' }}</v-chip>\n </v-card-title>\n <v-card-text>\n <div class=\"demo-hc-device-info\">\n <b>{{ msg?.payload?.deviceTitle || 'Demo Waschmaschine' }}</b><br>\n {{ msg?.payload?.brand || '—' }} · {{ msg?.payload?.typeLabel || '—' }}<br>\n <span v-if=\"msg?.payload?.vib\">VIB/E-Nummer: {{ msg.payload.vib }}</span><br>\n <span>{{ msg?.payload?.ui?.connection || '—' }}: {{ msg?.payload?.connectionText || '—' }}</span>\n </div>\n <v-alert v-if=\"msg?.payload?.warningText\" :type=\"msg?.payload?.warningType || 'info'\" density=\"compact\" variant=\"tonal\" class=\"mb-2\">\n <b>{{ msg.payload.warningText }}</b>\n </v-alert>\n <div><b>{{ msg?.payload?.ui?.status || '—' }}:</b> {{ msg?.payload?.statusText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.door || '—' }}:</b> {{ msg?.payload?.doorText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.active || '—' }}:</b> {{ msg?.payload?.activeText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.selected || '—' }}:</b> {{ msg?.payload?.selectedText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remaining || '—' }}:</b> {{ msg?.payload?.remainingText || '—' }}</div>\n <div class=\"demo-hc-panel\">\n <div class=\"demo-hc-panel-title\">{{ msg?.payload?.ui?.simulatedValues || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remoteControl || '—' }}:</b> {{ msg?.payload?.remoteControlText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remoteStart || '—' }}:</b> {{ msg?.payload?.remoteStartText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.localControl || '—' }}:</b> {{ msg?.payload?.localControlText || '—' }}</div>\n <div v-if=\"msg?.payload?.options?.length\" class=\"mt-2\">\n <b>{{ msg?.payload?.ui?.currentOptions || '—' }}:</b>\n <div v-for=\"item in msg.payload.options\" :key=\"item.key\" class=\"demo-hc-option\">\n <span :title=\"item.key\">{{ item.label }}</span>: {{ item.valueText }}<span v-if=\"item.unit\"> {{ item.unit }}</span>\n </div>\n </div>\n <div v-if=\"msg?.payload?.programsText\" class=\"mt-2\"><b>{{ msg?.payload?.ui?.availablePrograms || '—' }}:</b> {{ msg.payload.programsText }}</div>\n </div>\n </v-card-text>\n <v-card-actions>\n <v-btn variant=\"text\" @click=\"send({payload:{action:'refresh'}})\">{{ msg?.payload?.ui?.refresh || 'Refresh' }}</v-btn>\n </v-card-actions>\n </v-card>\n</template>\n<style>\n.demo-hc-card{border-top:4px solid rgb(var(--v-theme-primary));height:100%;scroll-margin-top:72px}\n.demo-hc-device-info{padding:8px 0 12px;color:rgba(var(--v-theme-on-surface),.75)}\n.demo-hc-panel{margin-top:14px;padding:12px;border:1px solid rgba(var(--v-theme-on-surface),.18);border-radius:6px;background:rgba(var(--v-theme-on-surface),.035)}\n.demo-hc-panel-title{font-weight:600;margin-bottom:8px}\n.demo-hc-option{padding-left:10px}\n</style>",
|
|
179
|
+
"storeOutMessages": true,
|
|
180
|
+
"passthru": false,
|
|
181
|
+
"resendOnRefresh": true,
|
|
182
|
+
"templateScope": "local",
|
|
183
|
+
"className": "",
|
|
184
|
+
"x": 670,
|
|
185
|
+
"y": 380,
|
|
186
|
+
"wires": [
|
|
187
|
+
[
|
|
188
|
+
"demo-hc-ff1341-fix2-data"
|
|
189
|
+
]
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"id": "demo-hc-ff1341-fix2-ui-ov",
|
|
194
|
+
"type": "ui-template",
|
|
195
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
196
|
+
"group": "demo-hc-ff1341-fix2-group-ov",
|
|
197
|
+
"page": "",
|
|
198
|
+
"ui": "",
|
|
199
|
+
"name": "Demo Backofen",
|
|
200
|
+
"order": 1,
|
|
201
|
+
"width": 0,
|
|
202
|
+
"height": 0,
|
|
203
|
+
"head": "",
|
|
204
|
+
"format": "<template>\n <v-card id=\"demo-hc-oven\" class=\"demo-hc-card\" elevation=\"2\">\n <v-card-title>\n <v-icon class=\"mr-2\">mdi-stove</v-icon>{{ msg?.payload?.deviceTitle || 'Demo Backofen' }}\n <v-spacer></v-spacer>\n <v-chip color=\"secondary\" size=\"small\" class=\"mr-2\">{{ msg?.payload?.simulatedLabel || 'SIMULIERT' }}</v-chip>\n <v-chip :color=\"msg?.payload?.healthColor || 'grey'\" size=\"small\">{{ msg?.payload?.healthLabel || '—' }}</v-chip>\n </v-card-title>\n <v-card-text>\n <div class=\"demo-hc-device-info\">\n <b>{{ msg?.payload?.deviceTitle || 'Demo Backofen' }}</b><br>\n {{ msg?.payload?.brand || '—' }} · {{ msg?.payload?.typeLabel || '—' }}<br>\n <span v-if=\"msg?.payload?.vib\">VIB/E-Nummer: {{ msg.payload.vib }}</span><br>\n <span>{{ msg?.payload?.ui?.connection || '—' }}: {{ msg?.payload?.connectionText || '—' }}</span>\n </div>\n <v-alert v-if=\"msg?.payload?.warningText\" :type=\"msg?.payload?.warningType || 'info'\" density=\"compact\" variant=\"tonal\" class=\"mb-2\">\n <b>{{ msg.payload.warningText }}</b>\n </v-alert>\n <div><b>{{ msg?.payload?.ui?.status || '—' }}:</b> {{ msg?.payload?.statusText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.door || '—' }}:</b> {{ msg?.payload?.doorText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.active || '—' }}:</b> {{ msg?.payload?.activeText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.selected || '—' }}:</b> {{ msg?.payload?.selectedText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remaining || '—' }}:</b> {{ msg?.payload?.remainingText || '—' }}</div>\n <div class=\"demo-hc-panel\">\n <div class=\"demo-hc-panel-title\">{{ msg?.payload?.ui?.simulatedValues || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remoteControl || '—' }}:</b> {{ msg?.payload?.remoteControlText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.remoteStart || '—' }}:</b> {{ msg?.payload?.remoteStartText || '—' }}</div>\n <div><b>{{ msg?.payload?.ui?.localControl || '—' }}:</b> {{ msg?.payload?.localControlText || '—' }}</div>\n <div v-if=\"msg?.payload?.options?.length\" class=\"mt-2\">\n <b>{{ msg?.payload?.ui?.currentOptions || '—' }}:</b>\n <div v-for=\"item in msg.payload.options\" :key=\"item.key\" class=\"demo-hc-option\">\n <span :title=\"item.key\">{{ item.label }}</span>: {{ item.valueText }}<span v-if=\"item.unit\"> {{ item.unit }}</span>\n </div>\n </div>\n <div v-if=\"msg?.payload?.programsText\" class=\"mt-2\"><b>{{ msg?.payload?.ui?.availablePrograms || '—' }}:</b> {{ msg.payload.programsText }}</div>\n </div>\n </v-card-text>\n <v-card-actions>\n <v-btn variant=\"text\" @click=\"send({payload:{action:'refresh'}})\">{{ msg?.payload?.ui?.refresh || 'Refresh' }}</v-btn>\n </v-card-actions>\n </v-card>\n</template>\n<style>\n.demo-hc-card{border-top:4px solid rgb(var(--v-theme-primary));height:100%;scroll-margin-top:72px}\n.demo-hc-device-info{padding:8px 0 12px;color:rgba(var(--v-theme-on-surface),.75)}\n.demo-hc-panel{margin-top:14px;padding:12px;border:1px solid rgba(var(--v-theme-on-surface),.18);border-radius:6px;background:rgba(var(--v-theme-on-surface),.035)}\n.demo-hc-panel-title{font-weight:600;margin-bottom:8px}\n.demo-hc-option{padding-left:10px}\n</style>",
|
|
205
|
+
"storeOutMessages": true,
|
|
206
|
+
"passthru": false,
|
|
207
|
+
"resendOnRefresh": true,
|
|
208
|
+
"templateScope": "local",
|
|
209
|
+
"className": "",
|
|
210
|
+
"x": 670,
|
|
211
|
+
"y": 500,
|
|
212
|
+
"wires": [
|
|
213
|
+
[
|
|
214
|
+
"demo-hc-ff1341-fix2-data"
|
|
215
|
+
]
|
|
216
|
+
]
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"id": "demo-hc-ff1341-fix2-ui-overview-page",
|
|
220
|
+
"type": "ui-page",
|
|
221
|
+
"name": "Demo Übersicht",
|
|
222
|
+
"ui": "demo-hc-ff1341-fix2-ui-base",
|
|
223
|
+
"path": "/demo-overview",
|
|
224
|
+
"icon": "home",
|
|
225
|
+
"layout": "grid",
|
|
226
|
+
"theme": "demo-hc-ff1341-fix2-ui-theme",
|
|
227
|
+
"breakpoints": [
|
|
228
|
+
{
|
|
229
|
+
"name": "Default",
|
|
230
|
+
"px": "0",
|
|
231
|
+
"cols": "3"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"name": "Tablet",
|
|
235
|
+
"px": "576",
|
|
236
|
+
"cols": "6"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"name": "Small Desktop",
|
|
240
|
+
"px": "768",
|
|
241
|
+
"cols": "9"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"name": "Desktop",
|
|
245
|
+
"px": "1024",
|
|
246
|
+
"cols": "12"
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
"order": 1,
|
|
250
|
+
"className": "",
|
|
251
|
+
"visible": "true",
|
|
252
|
+
"disabled": "false",
|
|
253
|
+
"wires": []
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"id": "demo-hc-ff1341-fix2-ui-overview-group",
|
|
257
|
+
"type": "ui-group",
|
|
258
|
+
"name": "Demo Übersicht",
|
|
259
|
+
"page": "demo-hc-ff1341-fix2-ui-overview-page",
|
|
260
|
+
"width": "12",
|
|
261
|
+
"height": "1",
|
|
262
|
+
"order": 1,
|
|
263
|
+
"showTitle": false,
|
|
264
|
+
"className": "",
|
|
265
|
+
"visible": "true",
|
|
266
|
+
"disabled": "false",
|
|
267
|
+
"wires": []
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"id": "demo-hc-ff1341-fix2-ui-overview",
|
|
271
|
+
"type": "ui-template",
|
|
272
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
273
|
+
"group": "demo-hc-ff1341-fix2-ui-overview-group",
|
|
274
|
+
"page": "",
|
|
275
|
+
"ui": "",
|
|
276
|
+
"name": "Demo Gerätekarten",
|
|
277
|
+
"order": 1,
|
|
278
|
+
"width": 0,
|
|
279
|
+
"height": 0,
|
|
280
|
+
"head": "",
|
|
281
|
+
"format": "<template>\n <div>\n <div class=\"demo-hc-toolbar\">\n <div class=\"demo-hc-heading\">{{ msg?.payload?.ui?.overview || 'Demo Übersicht' }}</div>\n <v-select\n :model-value=\"msg?.payload?.locale || 'de'\"\n :items=\"msg?.payload?.languageItems || [{title:'Deutsch',value:'de'},{title:'English',value:'en'}]\"\n item-title=\"title\" item-value=\"value\"\n :label=\"msg?.payload?.ui?.language || 'Sprache'\"\n density=\"compact\" hide-details class=\"demo-hc-language\"\n @update:model-value=\"send({payload:{action:'set-language',locale:$event}})\">\n </v-select>\n </div>\n <div class=\"demo-hc-grid\">\n <v-card v-for=\"device in msg?.payload?.cards || []\" :key=\"device.key\" class=\"demo-hc-overview-card\" elevation=\"2\" :href=\"device.href\">\n <v-card-title>\n <v-icon class=\"mr-2\">{{ device.icon }}</v-icon>{{ device.title }}\n <v-spacer></v-spacer>\n <v-chip color=\"secondary\" size=\"small\" class=\"mr-2\">{{ msg?.payload?.simulatedLabel || 'SIMULIERT' }}</v-chip>\n <v-chip :color=\"device.healthColor\" size=\"small\">{{ device.healthLabel }}</v-chip>\n </v-card-title>\n <v-card-text>\n <div class=\"demo-hc-meta\">{{ device.brand }} · {{ device.typeLabel }}</div>\n <div><b>{{ msg?.payload?.ui?.status || '—' }}:</b> {{ device.statusText }}</div>\n <div><b>{{ msg?.payload?.ui?.program || '—' }}:</b> {{ device.activeText }}</div>\n <div><b>{{ msg?.payload?.ui?.remaining || '—' }}:</b> {{ device.remainingText }}</div>\n <v-alert v-if=\"device.warningText\" :type=\"device.warningType\" density=\"compact\" variant=\"tonal\" class=\"mt-2\"><b>{{ device.warningText }}</b></v-alert>\n <div class=\"demo-hc-open\">{{ msg?.payload?.ui?.openDetails || 'Details' }} →</div>\n </v-card-text>\n </v-card>\n </div>\n </div>\n</template>\n<style>\n.demo-hc-toolbar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px}\n.demo-hc-heading{font-size:1.35rem;font-weight:600}.demo-hc-language{max-width:180px}\n.demo-hc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:12px}\n.demo-hc-overview-card{border-top:4px solid rgb(var(--v-theme-primary));transition:transform .12s}\n.demo-hc-overview-card:hover,.demo-hc-overview-card:focus{transform:translateY(-2px);outline:2px solid rgb(var(--v-theme-primary))}\n.demo-hc-meta{color:rgba(var(--v-theme-on-surface),.7);margin-bottom:8px}\n.demo-hc-open{margin-top:12px;color:rgb(var(--v-theme-primary));font-weight:600}\n</style>",
|
|
282
|
+
"storeOutMessages": true,
|
|
283
|
+
"passthru": false,
|
|
284
|
+
"resendOnRefresh": true,
|
|
285
|
+
"templateScope": "local",
|
|
286
|
+
"className": "",
|
|
287
|
+
"x": 930,
|
|
288
|
+
"y": 190,
|
|
289
|
+
"wires": [
|
|
290
|
+
[
|
|
291
|
+
"demo-hc-ff1341-fix2-data"
|
|
292
|
+
]
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"id": "demo-hc-ff1341-fix2-ui-nav-group",
|
|
297
|
+
"type": "ui-group",
|
|
298
|
+
"name": "Demo Navigation",
|
|
299
|
+
"page": "demo-hc-ff1341-fix2-ui-page",
|
|
300
|
+
"width": "12",
|
|
301
|
+
"height": "1",
|
|
302
|
+
"order": 0,
|
|
303
|
+
"showTitle": false,
|
|
304
|
+
"className": "",
|
|
305
|
+
"visible": "true",
|
|
306
|
+
"disabled": "false",
|
|
307
|
+
"wires": []
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"id": "demo-hc-ff1341-fix2-ui-nav",
|
|
311
|
+
"type": "ui-template",
|
|
312
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
313
|
+
"group": "demo-hc-ff1341-fix2-ui-nav-group",
|
|
314
|
+
"page": "",
|
|
315
|
+
"ui": "",
|
|
316
|
+
"name": "Demo Zur Übersicht",
|
|
317
|
+
"order": 1,
|
|
318
|
+
"width": 0,
|
|
319
|
+
"height": 0,
|
|
320
|
+
"head": "",
|
|
321
|
+
"format": "<template>\n <div class=\"demo-hc-nav\">\n <v-btn variant=\"text\" prepend-icon=\"mdi-arrow-left\" :href=\"msg?.payload?.overviewPath || '/demo-home-connect-ff1341-fix2/demo-overview'\">\n {{ msg?.payload?.ui?.backToOverview || 'Demo Übersicht' }}\n </v-btn>\n <v-select\n :model-value=\"msg?.payload?.locale || 'de'\"\n :items=\"msg?.payload?.languageItems || [{title:'Deutsch',value:'de'},{title:'English',value:'en'}]\"\n item-title=\"title\" item-value=\"value\"\n :label=\"msg?.payload?.ui?.language || 'Sprache'\"\n density=\"compact\" hide-details class=\"demo-hc-language\"\n @update:model-value=\"send({payload:{action:'set-language',locale:$event}})\">\n </v-select>\n </div>\n</template>\n<style>.demo-hc-nav{display:flex;align-items:center;justify-content:space-between;gap:16px}.demo-hc-language{max-width:180px}</style>",
|
|
322
|
+
"storeOutMessages": true,
|
|
323
|
+
"passthru": false,
|
|
324
|
+
"resendOnRefresh": true,
|
|
325
|
+
"templateScope": "local",
|
|
326
|
+
"className": "",
|
|
327
|
+
"x": 930,
|
|
328
|
+
"y": 240,
|
|
329
|
+
"wires": [
|
|
330
|
+
[
|
|
331
|
+
"demo-hc-ff1341-fix2-data"
|
|
332
|
+
]
|
|
333
|
+
]
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"id": "demo-hc-ff1341-fix2-inject",
|
|
337
|
+
"type": "inject",
|
|
338
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
339
|
+
"name": "Demo Daten laden",
|
|
340
|
+
"props": [
|
|
341
|
+
{
|
|
342
|
+
"p": "payload"
|
|
343
|
+
}
|
|
344
|
+
],
|
|
345
|
+
"repeat": "",
|
|
346
|
+
"crontab": "",
|
|
347
|
+
"once": true,
|
|
348
|
+
"onceDelay": 0.5,
|
|
349
|
+
"topic": "",
|
|
350
|
+
"payload": "",
|
|
351
|
+
"payloadType": "date",
|
|
352
|
+
"x": 130,
|
|
353
|
+
"y": 120,
|
|
354
|
+
"wires": [
|
|
355
|
+
[
|
|
356
|
+
"demo-hc-ff1341-fix2-data"
|
|
357
|
+
]
|
|
358
|
+
]
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"id": "demo-hc-ff1341-fix2-data",
|
|
362
|
+
"type": "function",
|
|
363
|
+
"z": "demo-hc-ff1341-fix2-dashboard-flow",
|
|
364
|
+
"name": "Demo Beispielgeräte erzeugen",
|
|
365
|
+
"func": "let locale = context.get('demoLocale') || 'de';\nconst input = msg && msg.payload && typeof msg.payload === 'object' ? msg.payload : {};\nif (input.action === 'set-language' && (input.locale === 'de' || input.locale === 'en')) {\n locale = input.locale;\n context.set('demoLocale', locale);\n}\nconst text = {\n de: {\n overview:'Demo Übersicht',language:'Sprache',connection:'Verbindung',status:'Status',door:'Tür',active:'Aktiv',selected:'Ausgewählt',remaining:'Restzeit',program:'Programm',\n remoteControl:'Fernsteuerung',remoteStart:'Fernstart',localControl:'Lokale Bedienung',currentOptions:'Aktuelle Optionen',availablePrograms:'Verfügbare Programme',\n simulated:'SIMULIERT',simulatedValues:'Simulierte Beispielwerte · nur Anzeige',refresh:'Aktualisieren',openDetails:'Details öffnen',backToOverview:'Zur Demo Übersicht',\n online:'online',yes:'Ja',no:'Nein',running:'Läuft',ready:'Bereit',closed:'Geschlossen',warning:'Warnung',detergent:'Dosierbehälter fast leer.',\n dishwasher:'Demo Geschirrspüler',washer:'Demo Waschmaschine',oven:'Demo Backofen',dishwasherType:'Geschirrspüler',washerType:'Waschmaschine',ovenType:'Backofen',\n eco50:'Eco 50 °C',cotton:'Baumwolle',hotAir:'Heißluft',intensive70:'Intensiv 70 °C',auto:'Automatik 45–65 °C',glass40:'Glas 40 °C',quick45:'Kurz 45 °C',\n easyCare:'Pflegeleicht',mix:'Mix',delicates:'Fein/Seide',wool:'Wolle',super15:'Super 15',topBottom:'Ober-/Unterhitze',pizza:'Pizzastufe',grill:'Umluftgrill',slowCook:'Sanftgaren',\n progress:'Programmfortschritt',energy:'Energieprognose',water:'Wasserprognose',hygiene:'Hygiene Plus',intensiveZone:'Intensivzone',vario:'varioSpeed Plus',brilliance:'Glanztrocknen',temperature:'Temperatur',spin:'Schleuderdrehzahl',target:'Solltemperatur',fastPreheat:'Schnellaufheizen'\n },\n en: {\n overview:'Demo Overview',language:'Language',connection:'Connection',status:'Status',door:'Door',active:'Active',selected:'Selected',remaining:'Remaining',program:'Program',\n remoteControl:'Remote control',remoteStart:'Remote start',localControl:'Local control',currentOptions:'Current options',availablePrograms:'Available programs',\n simulated:'SIMULATED',simulatedValues:'Simulated example values · display only',refresh:'Refresh',openDetails:'Open details',backToOverview:'Back to Demo Overview',\n online:'online',yes:'Yes',no:'No',running:'Running',ready:'Ready',closed:'Closed',warning:'Warning',detergent:'Detergent dispenser nearly empty.',\n dishwasher:'Demo Dishwasher',washer:'Demo Washer',oven:'Demo Oven',dishwasherType:'Dishwasher',washerType:'Washer',ovenType:'Oven',\n eco50:'Eco 50 °C',cotton:'Cotton',hotAir:'Hot air',intensive70:'Intensive 70 °C',auto:'Auto 45–65 °C',glass40:'Glass 40 °C',quick45:'Quick 45 °C',\n easyCare:'Easy-care',mix:'Mix',delicates:'Delicates/Silk',wool:'Wool',super15:'Super 15',topBottom:'Top/bottom heat',pizza:'Pizza setting',grill:'Hot-air grilling',slowCook:'Slow cook',\n progress:'Program progress',energy:'Energy forecast',water:'Water forecast',hygiene:'Hygiene Plus',intensiveZone:'Intensive zone',vario:'varioSpeed Plus',brilliance:'Brilliance dry',temperature:'Temperature',spin:'Spin speed',target:'Target temperature',fastPreheat:'Fast preheat'\n }\n}[locale];\nconst languageItems = [{title:'Deutsch',value:'de'},{title:'English',value:'en'}];\nconst ui = {overview:text.overview,language:text.language,connection:text.connection,status:text.status,door:text.door,active:text.active,selected:text.selected,remaining:text.remaining,program:text.program,remoteControl:text.remoteControl,remoteStart:text.remoteStart,localControl:text.localControl,currentOptions:text.currentOptions,availablePrograms:text.availablePrograms,simulatedValues:text.simulatedValues,refresh:text.refresh,openDetails:text.openDetails,backToOverview:text.backToOverview};\nconst base = '/demo-home-connect-ff1341-fix2';\nconst common = (key, applianceType, title, typeLabel, healthLabel, healthColor, statusText, activeText, selectedText, remainingText, options, programs, warningText='') => ({\n key, applianceType, locale, languageItems, ui, simulated:true, simulatedLabel:text.simulated, deviceTitle:title, brand:'SIEMENS', typeLabel,\n vib:'DEMO-'+key.toUpperCase()+'-2026', connectionText:text.online, healthLabel, healthColor, statusText, doorText:text.closed,\n activeText, selectedText, remainingText, remoteControlText:text.yes, remoteStartText:key==='washer'?text.no:text.yes, localControlText:text.no,\n options, programsText:programs.join(', '), warningText, warningType:warningText?'warning':'info', href:base+'/demo-details#demo-hc-'+key\n});\nconst opt = (key,label,valueText,unit='') => ({key,label,valueText,unit});\nconst dishwasher = common('dishwasher','Dishwasher',text.dishwasher,text.dishwasherType,text.running,'info',text.running,text.eco50,text.eco50,'62 min',[\n opt('BSH.Common.Option.ProgramProgress',text.progress,'43','%'),opt('BSH.Common.Option.EnergyForecast',text.energy,'62','%'),opt('BSH.Common.Option.WaterForecast',text.water,'48','%'),\n opt('Dishcare.Dishwasher.Option.HygienePlus',text.hygiene,text.yes),opt('Dishcare.Dishwasher.Option.IntensivZone',text.intensiveZone,text.no),opt('Dishcare.Dishwasher.Option.VarioSpeedPlus',text.vario,text.yes),opt('Dishcare.Dishwasher.Option.BrillianceDry',text.brilliance,text.yes)\n],[text.intensive70,text.auto,text.eco50,text.glass40,text.quick45]);\nconst washer = common('washer','Washer',text.washer,text.washerType,text.warning,'warning',text.ready,'—',text.cotton,'—',[\n opt('LaundryCare.Washer.Option.Temperature',text.temperature,'40','°C'),opt('LaundryCare.Washer.Option.SpinSpeed',text.spin,'1400','rpm')\n],[text.cotton,text.easyCare,text.mix,text.delicates,text.wool,text.super15],text.detergent);\nconst oven = common('oven','Oven',text.oven,text.ovenType,text.running,'info',text.running,text.hotAir,text.hotAir,'28 min',[\n opt('Cooking.Oven.Option.SetpointTemperature',text.target,'180','°C'),opt('Cooking.Oven.Option.FastPreHeat',text.fastPreheat,text.no),opt('BSH.Common.Option.ProgramProgress',text.progress,'68','%')\n],[text.hotAir,text.topBottom,text.pizza,text.grill,text.slowCook]);\nconst detail = device => ({topic:'demo-'+device.key,payload:device});\nconst overview = {topic:'demo-overview',payload:{locale,languageItems,ui,simulatedLabel:text.simulated,overviewPath:base+'/demo-overview',cards:[dishwasher,washer,oven]}};\nreturn [detail(dishwasher), detail(washer), detail(oven), overview];",
|
|
366
|
+
"outputs": 4,
|
|
367
|
+
"timeout": 0,
|
|
368
|
+
"noerr": 0,
|
|
369
|
+
"initialize": "",
|
|
370
|
+
"finalize": "",
|
|
371
|
+
"libs": [],
|
|
372
|
+
"x": 360,
|
|
373
|
+
"y": 120,
|
|
374
|
+
"wires": [
|
|
375
|
+
[
|
|
376
|
+
"demo-hc-ff1341-fix2-ui-dw"
|
|
377
|
+
],
|
|
378
|
+
[
|
|
379
|
+
"demo-hc-ff1341-fix2-ui-wm"
|
|
380
|
+
],
|
|
381
|
+
[
|
|
382
|
+
"demo-hc-ff1341-fix2-ui-ov"
|
|
383
|
+
],
|
|
384
|
+
[
|
|
385
|
+
"demo-hc-ff1341-fix2-ui-overview",
|
|
386
|
+
"demo-hc-ff1341-fix2-ui-nav"
|
|
387
|
+
]
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
]
|