Het (grote?) hewalex warmtepomp(boiler) avontuur

Pagina: 1 ... 19 ... 22 Laatste
Acties:

Acties:
  • 0 Henk 'm!

  • Batavia
  • Registratie: Mei 2011
  • Laatst online: 19:38
andre75 schreef op maandag 27 mei 2024 @ 21:30:
[...]


Ik gebruik de Hewalex puur voor hoofdverwarming, omdat ik beperkt vermogen nodig heb. Ik verwarm er alleen een woonkamer mee 55m2 met 2 LTV convectoren. Het vermogen is maar 3 kW en daar moet je goed rekening mee houden en alles goed uitrekenen dat het daadwerkelijk ook kan. Bij vorst draait de Hewalex 16 uur op een dag non stop.
Heb je hem in binnen buiten opstelling staan? Of buiten buiten?

Acties:
  • 0 Henk 'm!

  • oje
  • Registratie: April 2017
  • Laatst online: 09-11-2024

oje

k gebruik de Hewalex puur voor hoofdverwarming
Interessant!! Kan je aub wat meer vertellen over de aanleg en de ervaringen?

[ Voor 76% gewijzigd door oje op 28-05-2024 08:03 ]


Acties:
  • 0 Henk 'm!

  • Tim123
  • Registratie: Mei 2022
  • Laatst online: 11-09 20:25
@oje en @Batavia
Bij ons staat hij (1 van de 2) ook als hoofdverwarming, van zowel bij @andre75 als bij mij staan er al erg veel berichten in dit forum over de opstellingen.
Wellicht deze even doorlezen, en bij vragen deze stellen.
Anders hebben we alle informatie er straks x keer opstaan.

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Batavia schreef op dinsdag 28 mei 2024 @ 07:03:
[...]


Heb je hem in binnen buiten opstelling staan? Of buiten buiten?
De aanzuiglucht wordt van de zolder gehaald en gedeeltelijk van buiten. Het 1e jaar was volledig van buiten, maar dat vond ik niet zo'n succes. Als het buiten de temperatuur < 4gr is dan maakt de compressor meer herrie en ook het vermogen en rendement zakt in. Ik heb de luchtaanzuig losgehaald en de doorvoer laten zitten. Omdat de Hewalex in een afgesloten ruimte zit wordt een menglucht gecréeerd. (lucht uit de omgeving en lucht van buiten) Hierdoor maark de compressor veel minder herrie en de rendement en vermogen blijft goed.

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
oje schreef op dinsdag 28 mei 2024 @ 08:01:
[...]

Interessant!! Kan je aub wat meer vertellen over de aanleg en de ervaringen?
Ik ervaar de Hewalex als prima, maar er zijn wel wat aandachtspunten waar je rekening mee moet houden.

* Vermogen, deze is maar max. 3kW waar je met het ontwerp rekening mee moet houden
* Geluid kan een issue zijn. Ik heb zelf andere geluiddempers toegepast i.p.v de standaard geluiddempers.
* Monteer de warmtepomp goed horizontaal, anders krijg je lekkage omdat de rand van de condensbak niet zo hoog is waardoor het condenswater over de rand loopt. Dit was mijn ervaring.
* Voor de aanleg begin met een goed ontwerp. Wat is het afgiftesysteem radiatoren of vloerverwarming?
* Maak ook een plan hoe je de Hewalex regeltechnisch gaat regelen. De Hewalex zelf heeft zelf weinig instellingen. Het watertemperatuur instellen en dat is het.

[ Voor 16% gewijzigd door andre75 op 28-05-2024 21:23 ]


Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
@andre75 je zegt de Hewalex als hoofdverwarming te gebruiken, maar waar komt je warme zolderlucht vandaan? De Hewalex zelf voegt netto natuurlijk maar 750 W toe. Of heb je nog andere warmtebronnen in huis?

Acties:
  • +1 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Martin7182 schreef op dinsdag 28 mei 2024 @ 21:05:
@andre75 je zegt de Hewalex als hoofdverwarming te gebruiken, maar waar komt je warme zolderlucht vandaan? De Hewalex zelf voegt netto natuurlijk maar 750 W toe. Of heb je nog andere warmtebronnen in huis?
De zolder wordt niet verwarmd en ik haal gedeeltelijk aanzuiglucht van de zolder en een deel van buiten. De menglucht is dan ongeveer 11gr. De temperatuur op de zolder is in de winter ongeveer 17gr. De badkamer wordt verwarmd met een elektrische radiator op kloktijden. 1 slaapkamer wordt verwarmd met een infrarood paneel en ik heb nog 2 slaapkamers, maar die worden niet verwarmd.

Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Bedankt voor de details. Energetisch vind het wel tricky; je pompt 3 kW warmte rond met COP ~4, maar een deel van die warmte snuift de Hewalex zelf weer op. In het totaalplaatje zal de efficiency een stuk lager moeten zijn. Dat blijkt ook denk ik wel uit het gegeven dat je bij vorst 16 uur per etmaal draait. Dat is ~12 kWh/d.

Acties:
  • 0 Henk 'm!

  • Batavia
  • Registratie: Mei 2011
  • Laatst online: 19:38
Martin7182 schreef op woensdag 29 mei 2024 @ 10:29:
Bedankt voor de details. Energetisch vind het wel tricky; je pompt 3 kW warmte rond met COP ~4, maar een deel van die warmte snuift de Hewalex zelf weer op. In het totaalplaatje zal de efficiency een stuk lager moeten zijn. Dat blijkt ook denk ik wel uit het gegeven dat je bij vorst 16 uur per etmaal draait. Dat is ~12 kWh/d.
Zo gek is dat nog niet. Vergeet niet dat je andere ook warmteverlies hebt aan ventilatie (of je moet een apart wtw systeem aanleggen.

Eigenlijk is de markt van de ventilatiewarmtepomp de set van mensen met geen balans ventilatie waarbij je binnenkomende lucht opwarmt maar je warmt weer op door het in je leiding te stoppen

Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Batavia schreef op woensdag 29 mei 2024 @ 12:37:
[...]


Zo gek is dat nog niet. Vergeet niet dat je andere ook warmteverlies hebt aan ventilatie (of je moet een apart wtw systeem aanleggen.

Eigenlijk is de markt van de ventilatiewarmtepomp de set van mensen met geen balans ventilatie waarbij je binnenkomende lucht opwarmt maar je warmt weer op door het in je leiding te stoppen
12 kWh elektrisch vind ik behoorlijk veel voor een (goed geïsoleerde?) woonkamer. Het WTW-deel snap ik wel, maar welke warmte win je precies terug als je verder geen verwarming hebt? Ik vind het bewonderenswaardig wat @andre75 doet, maar zo gebruik je de Hewalex feitelijk als WTW en niet als verwarming, voor het deel lucht dat van binnen aangezogen wordt. Ik wil later ook de Hewalex gaan gebruiken om zolderwarmte terug te pompen naar beneden. Maar wel met een 3 kW L/L WP erbij die de warmte eerst het huis inbrengt.

Acties:
  • 0 Henk 'm!

  • oje
  • Registratie: April 2017
  • Laatst online: 09-11-2024

oje

Gezien de ervaringen van @andre75 komt bij mij de vraag op hoe de Hewalex als verwarming via CV systeem zou functioneren wanneer je in de woonkamer de lucht aanzuigt, en in de gang weer uitblaast (met filter ertussen)....

(ik heb een centrale afzuiging van het complex, en die blijft in werking)

[ Voor 14% gewijzigd door oje op 30-05-2024 22:32 ]


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
oje schreef op donderdag 30 mei 2024 @ 22:15:
Gezien de ervaringen van @andre75 komt bij mij de vraag op hoe de Hewalex als verwarming via CV systeem zou functioneren wanneer je in de woonkamer de lucht aanzuigt, en in de gang weer uitblaast (met filter ertussen)....

(ik heb een centrale afzuiging van het complex, en die blijft in werking)
De Hewalex zuigt 500m3/h aan lucht aan wat je niet wilt voor een woonkamer. Als je de lucht aanzuigt uit de woonkamer dat veroorzaakt tocht, geluid en kou. Een woonkamer met openkeuken in mijn geval 55m2 heeft een kamerinhoud van 137m3. De luchtinhoud van de woonkamer wordt op deze manier 3,6 maal per uur ververst. Lucht wat je afzuigt moet ook ergens toegevoerd worden, anders creëer je een onderdruk.
De uitblaaslucht uitblazen in de gang is ook niet zo'n goed idee, omdat de uitblaaslucht 10graden kouder is dan de aanzuiglucht. Stel dat de aanzuiglucht 20gr is, dan wordt er 10gr koude lucht met 500m3/h de gang in geblazen. Voor een zomersituatie zou dit wel kunnen als de Hewalex een boiler opwarmt voor warmwater.

Acties:
  • +1 Henk 'm!

  • oje
  • Registratie: April 2017
  • Laatst online: 09-11-2024

oje

Dankje voor je verheldering @andre75 .

Als 500 m3 afzuigen al voor hinderlijke tocht zorgt bij 55m2/137m3 zal dat bij mijn 41m2/105m3 niet minder zijn. Met de bijkamerdeur open komt er nog 18m2/46m3 bij, maar toch(t). Een dergelijke tocht-waarschuwing las ik al bij de spaarpomp/warmtewinner https://www.huisenergieneutraalmaken.nl/warmtewinner-2/ https://www.bouweninstall...warmtewinner-vallen-tegen

Dat betekent dat in een appartementencomplex de Hewalex niet toepasbaar is op de gebruikelijke manier. Ook niet met afvoer via het veelgenoemde T stuk op de afvoer van de ventilatiebox, want daar moet de af te voeren lucht nog 10 mtr door een 125 mm pijp naar buiten wringen, samen met de 24x7 afvoer van de CVU ventilatiebox.

De Hewalex mag niet buiten op een balcon, lees ik in een post.
Blijft over plaatsing binnen tegen de buitengevel, bijv. bij balkon, met aanzuig naar en afvoer naar buiten. Maar dan zie ik de meerwaarde niet t.o.v. airco of split wp.

[ Voor 4% gewijzigd door oje op 31-05-2024 08:31 ]


Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
oje schreef op vrijdag 31 mei 2024 @ 08:20:
De Hewalex mag niet buiten op een balcon, lees ik in een post.
Blijft over plaatsing binnen tegen de buitengevel, bijv. bij balkon, met aanzuig naar en afvoer naar buiten. Maar dan zie ik de meerwaarde niet t.o.v. airco of split wp.
Geen idee of het mag, maar elke plaatsing buiten vind ik een zot idee. De unit heeft een veel kleinere warmtewisselaar en ventilator dan een split- of monoblock buitenunit. Dus loopt veel minder efficiënt en kan ook niet met flinke vorst overweg.
Het voordeel van plaatsing binnen is dat je geen buitenunit hebt :) Wel tegen een prijs uiteraard; het wordt nooit zo efficiënt als een echte buitenunit. N.B. het gaat hier alleen over het verwarmen v.d. woning, niet over het opwarmen van een boilervat.

Acties:
  • +1 Henk 'm!

  • Surfari
  • Registratie: Mei 2021
  • Laatst online: 16:46
oje schreef op maandag 13 mei 2024 @ 19:30:
Bedenk dat installateurs alles willen verkopen en plaatsen, zolang de factuur maar wordt betaald, en je voor storing binnen de werktijden belt. De branche organisatie pust jaar in jaar uit aantrekkelijke subsidieregelingen om nóg meer omzet te genereren. Ze staan niet garant voor subsidietoekenning. Als jij maar koopt en de installatie en het onderhoudsabonnement betaalt...

Al sinds 1980 worden warmtapwater zonnepanelen gesubsidieerd. Talloze daken lagen in de vorige eeuw vol met 3 solarcollectors (dus géén PV panelen), met op zolder een 120 a 180 liter heet water opslagvat, waar je 4 vrouwen in huis serieel 3x daags mee kon laten douchen. En ook sinds 2000 worden warmtepompen gepust, met dezelfde marketing buzzwords. Maar ik lees nooit of dat warme water werkelijk volledig gebruikt wordt....

Maar als je nou alleen woont, senior bent, of alleen zoons hebt die op de sportclub douchen, en alles met de Cooker doet, dan koop je iets waar je qua rendement niets aan hebt.

Energie/water besparen is als eerste kijken wat je kunt verminderen, vóór je overweegt iets te vermeerderen. een electrische doorstroomboiler is óók van het gas af.
Mooi verhaal maar ik ben happy met 2x zonnecollector plus 200 litervat.
Ook geen problemen met terugleveren op een overbelast net(t.o.v. zonnepanelen).
Het is heerlijk om zoals nu de boiler te zien laden(hij staat in de keuken in het zicht). Daar is geen prijs of rendements cijfer voor, het is gewoon lekker. De 4 Watt die de pomp nodig heeft mag de pret niet drukken.
En op hele zonnige dagen verplicht langer douchen, ook heerlijk.

Acties:
  • 0 Henk 'm!

  • Woody130
  • Registratie: Augustus 2021
  • Laatst online: 16:45
Afbeeldingslocatie: https://tweakers.net/i/oTmPpI7dU5wZUjeHFiuIbO9Ewws=/x800/filters:strip_icc():strip_exif()/f/image/rDQjGSQvCSFWXkxsRT7xM79q.jpg?f=fotoalbum_large
Inmiddels is het CV-gedeelte ook operationeel. Ik heb een Wilo Yonos Pico 1-6 op Marktplaats gescoord. Deze laat het water circuleren door een radiator en een convector, beide met thermostaatknop. Als ik deze thermostaatknoppen dichtdraai, dan stopt de doorstroming. Pompje staat op proportionele druk en verbruikt dan 3W. Hij wordt niet warm bij dichte thermostaatknopen. Eventueel kan ik hem schakelen met de drukschakelaar die daar naar boven uitsteekt.

Acties:
  • 0 Henk 'm!

  • oje
  • Registratie: April 2017
  • Laatst online: 09-11-2024

oje

Surfari schreef op maandag 3 juni 2024 @ 09:51:
[...]
En op hele zonnige dagen verplicht langer douchen, ook heerlijk.
Verplicht? https://www.bd.nl/gezond/...onte-aangeleerd~aacdb3d8/

Acties:
  • 0 Henk 'm!

  • Surfari
  • Registratie: Mei 2021
  • Laatst online: 16:46
Misschien had ik beter een knipoog-emoji erbij gezet?
Het dwaalt nu ver af voor een Hewalex forum, maar vooruit, het is nou eenmaal een grote speler in de collector markt.
Des zomers als de boiler makkelijk heet wordt, dat is niet de periode dat schimmels makkelijk toeslaan want dan zit ik niet de hele dag met dikke sokken in warme schoenen of op vloerverwarming(ook een genot hoor, vloerverwarming met de wp😀).

Acties:
  • 0 Henk 'm!

  • oje
  • Registratie: April 2017
  • Laatst online: 09-11-2024

oje

"How to sell a bug?"

Laten we ons concentreren op de techniek van warmtepompen - en in dit geval die van Hewalex - om die in te zetten op momenten dat we warmte nodig hebben.

Zomers vaten vol met heet douchewater is een leuke feature, maar niet zo zinvol. Beter het focus op de koudere periodes waarbij de Hewalex het huis voorverwarmt. Ik heb het tapwatervat losgekoppeld en ingezet als buffervat voor de CV, zodat de weinige zon overdag een voorraadje warm CV water oplevert voor verwarming in de zonloze avond en nacht. Ik ben benieuwd naar Hewalex ervaringen daarmee.

[ Voor 4% gewijzigd door oje op 10-06-2024 08:56 ]


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Woody130 schreef op vrijdag 7 juni 2024 @ 08:29:
[Afbeelding]
Inmiddels is het CV-gedeelte ook operationeel. Ik heb een Wilo Yonos Pico 1-6 op Marktplaats gescoord. Deze laat het water circuleren door een radiator en een convector, beide met thermostaatknop. Als ik deze thermostaatknoppen dichtdraai, dan stopt de doorstroming. Pompje staat op proportionele druk en verbruikt dan 3W. Hij wordt niet warm bij dichte thermostaatknopen. Eventueel kan ik hem schakelen met de drukschakelaar die daar naar boven uitsteekt.
Ik ben benieuwd hoe dit gaat werken met een drukschakelaar.

Acties:
  • 0 Henk 'm!

  • Woody130
  • Registratie: Augustus 2021
  • Laatst online: 16:45
andre75 schreef op maandag 10 juni 2024 @ 21:52:
[...]


Ik ben benieuwd hoe dit gaat werken met een drukschakelaar.
Tsja, dat weet ik ook nog niet precies. Het idee is dat de pomp bij dichte thermostaatknoppen de druk in de aanvoerleiding naar de radiatoren laat oplopen, waardoor de drukschakelaar de pomp uit zet. Om de druk na het stoppen van de pomp niet te laten dalen zit er een keerklep na de pomp.

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Zijn er ervaringen met de Hewalex mqtt in home-assistant? Ik heb een paar temperaturen via een omweg werkend gekregen. De mqtt loopt via Domoticz. Nu loopt de data via RS485 naar Domoticz. Van Domoticz wordt het in MQTT gepusht naar home assiatant.
Nu wil ik het rechtstreeks in home-assistant inlezen. Welke ervaringen hebben jullie en hoe is dit ingesteld?

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op zondag 23 juni 2024 @ 21:26:
Zijn er ervaringen met de Hewalex mqtt in home-assistant? Ik heb een paar temperaturen via een omweg werkend gekregen. De mqtt loopt via Domoticz. Nu loopt de data via RS485 naar Domoticz. Van Domoticz wordt het in MQTT gepusht naar home assiatant.
Nu wil ik het rechtstreeks in home-assistant inlezen. Welke ervaringen hebben jullie en hoe is dit ingesteld?
Ik heb het rechtstreeks via mqtt in HA. Ik kan echter alleen data uitlezen, maar (nog) niet schrijven. Ik lees alle temperaturen (inclusief instellingen).

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op zondag 23 juni 2024 @ 21:51:
[...]

Ik heb het rechtstreeks via mqtt in HA. Ik kan echter alleen data uitlezen, maar (nog) niet schrijven. Ik lees alle temperaturen (inclusief instellingen).
Ik wil ook alleen maar de data uitlezen. Wat heb jij gebruikt om de data uit de Hewalex te lezen en hoe is het omgezet in MQTT? Ik wil het ook via mqtt rechtstreeks in HA inlezen. Ik gebruikte in het verleden Domoticz en daar wil ik nu vanaf. Domoticz wordt nu alleen nog gebruikt om de data van de Hewalex uit te lezen.

Acties:
  • +1 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op zondag 23 juni 2024 @ 22:05:
[...]


Ik wil ook alleen maar de data uitlezen. Wat heb jij gebruikt om de data uit de Hewalex te lezen en hoe is het omgezet in MQTT? Ik wil het ook via mqtt rechtstreeks in HA inlezen. Ik gebruikte in het verleden Domoticz en daar wil ik nu vanaf. Domoticz wordt nu alleen nog gebruikt om de data van de Hewalex uit te lezen.
Ik gebruik een Waveshare voor RS485 naar eth. Daarnaast gebruik ik appdeamon in HA. Vervolgens is het uit te lezen via mqtt in HA.

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op zondag 23 juni 2024 @ 23:03:
[...]

Ik gebruik een Waveshare voor RS485 naar eth. Daarnaast gebruik ik appdeamon in HA. Vervolgens is het uit te lezen via mqtt in HA.
Ik heb ook een Waveshare voor RS485 neer eth. Deze wil ik gaan omzetten naar MQTT en heb jij nog tips en tricks waar ik op moet letten om de MQTT aan de gang te krijgen? Het je ook nog een script nodig? Ik heb nu wat in Yaml staan wat bedoeld is voor de ontvangen berichten vanuit Domoticz. In Domoticz heb ik het script van MV klip gebruikt en in Domoticz was het heelsimpel om het werkend te krijgen.
Ik ben bekend met de MQTT broker en de explorer om de berichten te kunnen zien.
Ik heb wel gelezen dat ik iets moet doen met firmware.

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op maandag 24 juni 2024 @ 19:37:
[...]


Ik heb ook een Waveshare voor RS485 neer eth. Deze wil ik gaan omzetten naar MQTT en heb jij nog tips en tricks waar ik op moet letten om de MQTT aan de gang te krijgen? Het je ook nog een script nodig? Ik heb nu wat in Yaml staan wat bedoeld is voor de ontvangen berichten vanuit Domoticz. In Domoticz heb ik het script van MV klip gebruikt en in Domoticz was het heelsimpel om het werkend te krijgen.
Ik ben bekend met de MQTT broker en de explorer om de berichten te kunnen zien.
Ik heb wel gelezen dat ik iets moet doen met firmware.
Ik heb niets hoeven te doen met de firmware. Wel moet je een script gebruiken. Ik heb daarvoor appdeamon gebruikt om met een soort pyscript de seriële berichten om te zetten in MQTT. Ik heb daarvoor de Scripts van bijvoorbeeld krzysztof1111111111 iets moeten aanpassen.

Zie bijvoorbeeld de onderstaande code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
from binascii import hexlify, unhexlify

import logging

from ..crc import *

# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


class BaseDevice:
    def __init__(self, conHardId, conSoftId, devHardId, devSoftId, onMessage=None):
        self.logger = logging.getLogger(__name__)
        self.conHardId = conHardId  # G-426 controller - physical address
        self.conSoftId = conSoftId  # G-426 controller - logical address
        self.devHardId = devHardId  # Hewalex device - physical address
        self.devSoftId = devSoftId  # Hewalex device - logical address
        self.onMessage = onMessage  # Callback - onMessage(obj, h, sh, m)

    def parseHardHeader(self, m):
        if len(m) < 8:
            raise Exception("Too short message")
        calcCrc = crc8(m[:7])
        return {
            "StartByte": m[0],
            "To": m[1],
            "From": m[2],
            "ConstBytes": (m[5] << 16) | (m[4] << 8) | m[3],
            "Payload": m[6],
            "CRC8": m[7],
            "CalcCRC8": calcCrc
        }

    def validateHardHeader(self, h):
        if h["StartByte"] != 0x69:
            raise Exception("Invalid Start Byte")
        if h["CRC8"] != h["CalcCRC8"]:
            raise Exception("Invalid Hard CRC8")
        if h["ConstBytes"] != 0x84:
            raise Exception("Invalid Const Bytes")
        if h["From"] != self.conHardId and h["From"] != self.devHardId:
            raise Exception("Invalid From Hard Address: " + str(h["From"]))
        if h["To"] != self.conHardId and h["To"] != self.devHardId:
            raise Exception("Invalid To Hard Address: " + str(h["To"]))
        if h["To"] == h["From"]:
            raise Exception("From and To Hard Address Equal")

    def getWord(self, w):
        return (w[1] << 8) | w[0]

    def getWordReverse(self, w):
        return (w[0] << 8) | w[1]

    def getDWord(self, w):
        return (w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]

    def parseSoftHeader(self, h, m):
        if len(m) != h["Payload"]:
            raise Exception("Invalid soft message len")
        if len(m) < 12:
            raise Exception("Too short soft message")
        calcCrc = crc16(m[:h["Payload"]-2])
        return {
            "To": self.getWord(m[0:]),
            "From": self.getWord(m[2:]),
            "FNC": m[4],
            "ConstByte": self.getWord(m[5:]),
            "RegLen": m[7],
            "RegStart": self.getWord(m[8:]),
            "RestMessage": m[10:h["Payload"]-2],
            "CRC16": self.getWordReverse(m[h["Payload"]-2:]),
            "CalcCRC16": calcCrc
        }

    def validateSoftHeader(self, h, sh):
        if sh["CRC16"] != sh["CalcCRC16"]:
            raise Exception("Invalid Soft CRC16")
        if sh["ConstByte"] != 0x80:
            raise Exception("Invalid Const Soft Byte 0x80")
        if (h["From"] == self.conHardId and sh["From"] != self.conSoftId) or (h["From"] == self.devHardId and sh["From"] != self.devSoftId):
            raise Exception("Invalid From Address")
        if (h["To"] == self.conHardId and sh["To"] != self.conSoftId) or (h["To"] == self.devHardId and sh["To"] != self.devSoftId):
            raise Exception("Invalid To Address")

    def getTemp(self, w, divisor):
        w = self.getWord(w)
        if w & 0x8000:
            w = w - 0x10000
        return w / divisor

    def parseBitMask(self, val, names, ret):
        for name in names:
            if name is not None:
                ret[name] = bool(val & 1)
            val = val >> 1

    def parseRegisters(self, m, regstart, reglen, unknown=False):
        ret = {}

        skip = 0
        for regnum in range(regstart, regstart + reglen, 2):
            if skip > 0:
                skip = skip - 1
                continue
            reg = self.registers.get(regnum, None)
            adr = regnum - regstart
            if reg:
                val = None
                if reg['type'] == 'date':
                    val = "20{:02d}-{:02d}-{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'time':
                    val = "{:02d}:{:02d}:{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'word':
                    val = self.getWord(m[adr:])
                elif reg['type'] == 'rwrd':
                    val = self.getWordReverse(m[adr:])
                elif reg['type'] == 'dwrd':
                    val = self.getDWord(m[adr:])
                    skip = 1
                elif reg['type'] == 'temp':
                    val = self.getTemp(m[adr:], 1.0)
                elif reg['type'] == 'te10':
                    val = self.getTemp(m[adr:], 10.0)
                elif reg['type'] == 'fl10':
                    val = self.getWord(m[adr:]) / 10.0
                elif reg['type'] == 'f100':
                    val = self.getWord(m[adr:]) / 100.0
                elif reg['type'] == 'bool':
                    val = bool(self.getWord(m[adr:]))
                elif reg['type'] == 'mask':
                    self.parseBitMask(self.getWord(m[adr:]), reg['name'], ret)
                    continue
                elif reg['type'] == 'tprg':
                    val = {}
                    self.parseBitMask(self.getDWord(m[adr:]), range(0, 24), val)
                    skip = 1
                ret[reg['name']] = val
            elif unknown:
                ret["Reg%d" % regnum] = self.getWord(m[adr:])

        return ret

    def printMessage(self, h, sh):
        print ({
            'hard': {
                "StartByte": hex(h["StartByte"]),
                "To": h["To"],
                "From": h["From"],
                "ConstBytes": hex(h["ConstBytes"]),
                "Payload": h["Payload"],
                "CRC8": hex(h["CRC8"])
            },
            'soft': {
                "To": sh["To"],
                "From": sh["From"],
                "FNC": hex(sh["FNC"]),
                "ConstByte": hex(sh["ConstByte"]),
                "RegLen": sh["RegLen"],
                "RegStart": str(sh["RegStart"]) + " (" + hex(sh["RegStart"]) + ")",
                "RestMessage": hexlify(sh["RestMessage"]),
                "CRC16": hex(sh["CRC16"])
            }
        })

    def processMessage(self, m, ignoreTooShort):
        h = self.parseHardHeader(m)
        self.validateHardHeader(h)
        ml = h["Payload"]
        if ignoreTooShort and ml + 8 > len(m):
            return m
        sh = self.parseSoftHeader(h, m[8:ml+8])
        self.validateSoftHeader(h, sh)
        if self.onMessage:
            self.onMessage(self, h, sh, m)
        return m[ml+8:]

    def processAllMessages(self, m, returnRemainingBytes=False):
        minLen = 8 if returnRemainingBytes else 0
        prevLen = len(m)
        while prevLen > minLen:
            m = self.processMessage(m, returnRemainingBytes)
            if len(m) == prevLen:
                if returnRemainingBytes:
                    return m
                else:
                    raise Exception("Something wrong")
            prevLen = len(m)
        return m

    # Process all messages in X cycles of device to controller comms
    #
    # 1. The device sends a query to the controller to read 20 registers starting from address 100.
    # 2. The controller responds, it always seems to be the same. It's hard to say if there is a controller model or a serial number.
    # 3. The device sends a record of registers starting at address 120. This is the main message, there are temperatures there. After this message there is a long pause (which is quite a large part of the 140ms for a series of messages), probably the controller is not too fast to write it to memory and it takes longer. The exact number of records depends on the model and firmware of the device.
    # 4. The controller replies with the standard message 0x70 that the bytes have been written successfully.
    # 5. The device requests to read 4 bytes starting from address 252.
    # 6. The controller responds and returns 4 bytes. By default they are: 10000000 and they mean that the controller is working normally, there are no changes. The value 08000000 means that the controller is turned off. However, the value 11000000 means that the user has changed a parameter in the menu, at this point the communication scheme is different, described in the docs.
    #
    def eavesDrop(self, ser, numCycles=None):
        # window size and time (based on 140ms cycle and 360ms wait)
        winSize = 1000
        winTime = 0.4

        # determine start of cycle marker to look for
        # (device requesting to read 20 registers from address 100)
        s1 = unhexlify('69%02x%02x8400000c' % (self.devHardId, self.conHardId))
        s2 = unhexlify('%02x' % crc8(s1))
        s3 = unhexlify('%02x%02x%02x%02x' % (
            (self.devSoftId & 0xff),
            (self.devSoftId & 0xff00) >> 8,
            (self.conSoftId & 0xff),
            (self.conSoftId & 0xff00) >> 8,
        ))
        s4 = unhexlify('408000146400')
        s = s1 + s2 + s3 + s4

        ser.flushInput()
        cnt = 0
        while (numCycles is None) or (cnt < numCycles):
            cnt += 1

            # read until first char after start marker
            ser.timeout = 1
            m = ser.read_until(s, winSize)

            # read the rest within window
            ser.timeout = winTime
            m = ser.read(winSize)

            # process
            self.processAllMessages(s + m)

    def createReadRegistersMessage(self, start, num):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x40, 0x80, 0, num & 0xff, start & 0xff, (start >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def createWriteRegisterMessage(self, reg, val):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x60, 0x80, 0, 2, reg & 0xff, (reg >> 8) & 0xff, val & 0xff, (val >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def readRegisters(self, ser, start, num):
        m = self.createReadRegistersMessage(start, num)
        self.logger.debug(f'Sending message to the heat pump: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def readStatusRegisters(self, ser):
        self.logger.info('readStatusRegisters')
        start = self.REG_STATUS_START
        return self.readRegisters(ser, start, self.REG_CONFIG_START - start)

    def readConfigRegisters(self, ser):
        start = self.REG_CONFIG_START
        while start < self.REG_MAX_ADR:
            num = min(self.REG_MAX_ADR + 2 - start, self.REG_MAX_NUM)
            self.readRegisters(ser, start, num)
            start = start + num

    def writeRegister(self, ser, reg, val):
        m = self.createWriteRegisterMessage(reg, val)
        self.logger.debug(f'Sending message to the heat pump writeRegister: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def write(self, ser, registername, val):
        regnum = 0        
        # look for register based on name        
        for k, v in self.registers.items():
            if v['name'] == registername:
                regnum = k
                break      
        reg = self.registers.get(regnum, None)
        if reg:
            val = self.parseRegisterValue(reg, val)
            if val is not None:
                #print('self.writeRegister(ser, ' + str(regnum) + ', '+ str(val) + ')')
                return self.writeRegister(ser, regnum, val)
        return None
        
    def parseRegisterValue(self, reg, val):
        if val:                
            if reg['type'] == 'date':
                val = None
            elif reg['type'] == 'time':
                val = None
            elif reg['type'] == 'word':
                val = int(val)
            elif reg['type'] == 'rwrd':
                val = int(val)
            elif reg['type'] == 'dwrd':
                val = int(val)
            elif reg['type'] == 'temp':
                val = int(val)
            elif reg['type'] == 'te10':
                val = int(val) * 10
            elif reg['type'] == 'fl10':
                val = float(val) * 10
            elif reg['type'] == 'f100':
                val = float(val) * 100
            elif reg['type'] == 'bool':
                if val == 'True' or val == '1':
                    val = 1
                elif val == 'False' or val == '0':
                    val = 0
            elif reg['type'] == 'mask':
                val = None
            elif reg['type'] == 'tprg':
                val = None
            if reg['options'] and val not in reg['options']:
                print ('invalid option ' + str(val))
                val = None
            return val

# Interface to implement in child classes
#########################################

    # Registers are divided in read-only status registers and read/write config registers

    # The lowest readable register always seems to be 100
    REG_MIN_ADR = 100

    # The highest readable register varies per device
    REG_MAX_ADR = 536 #None

    # The number of registers which can be read in one message varies per device
    REG_MAX_NUM = 100 #None

    # Status registers start at 120 usually
    REG_STATUS_START = 120

    # The number of statusregisters which can be read in one message varies per device
    REG_STATUS_NUM = 104

    # Config registers start at a register which varies per device
    REG_CONFIG_START = 302 #None

    registers = {
#
#        # Status registers
#        120: { 'type': 'date', 'name': 'date' },                        # Date
#        124: { 'type': 'time', 'name': 'time' },                        # Time
#        128: { 'type': 'te10', 'name': 'T1' },                          # T1
#        130: { 'type': 'te10', 'name': 'T2' },                          # T2
#        132: { 'type': 'te10', 'name': 'T3' },                          # T3
#        ...
#
#        # Config registers
#        XXX: { 'type': 'word', 'name': 'InstallationScheme' },          # Installation Scheme
#        ...
#
    }

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op dinsdag 25 juni 2024 @ 06:29:
[...]

Ik heb niets hoeven te doen met de firmware. Wel moet je een script gebruiken. Ik heb daarvoor appdeamon gebruikt om met een soort pyscript de seriële berichten om te zetten in MQTT. Ik heb daarvoor de Scripts van bijvoorbeeld krzysztof1111111111 iets moeten aanpassen.

Zie bijvoorbeeld de onderstaande code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
from binascii import hexlify, unhexlify

import logging

from ..crc import *

# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


class BaseDevice:
    def __init__(self, conHardId, conSoftId, devHardId, devSoftId, onMessage=None):
        self.logger = logging.getLogger(__name__)
        self.conHardId = conHardId  # G-426 controller - physical address
        self.conSoftId = conSoftId  # G-426 controller - logical address
        self.devHardId = devHardId  # Hewalex device - physical address
        self.devSoftId = devSoftId  # Hewalex device - logical address
        self.onMessage = onMessage  # Callback - onMessage(obj, h, sh, m)

    def parseHardHeader(self, m):
        if len(m) < 8:
            raise Exception("Too short message")
        calcCrc = crc8(m[:7])
        return {
            "StartByte": m[0],
            "To": m[1],
            "From": m[2],
            "ConstBytes": (m[5] << 16) | (m[4] << 8) | m[3],
            "Payload": m[6],
            "CRC8": m[7],
            "CalcCRC8": calcCrc
        }

    def validateHardHeader(self, h):
        if h["StartByte"] != 0x69:
            raise Exception("Invalid Start Byte")
        if h["CRC8"] != h["CalcCRC8"]:
            raise Exception("Invalid Hard CRC8")
        if h["ConstBytes"] != 0x84:
            raise Exception("Invalid Const Bytes")
        if h["From"] != self.conHardId and h["From"] != self.devHardId:
            raise Exception("Invalid From Hard Address: " + str(h["From"]))
        if h["To"] != self.conHardId and h["To"] != self.devHardId:
            raise Exception("Invalid To Hard Address: " + str(h["To"]))
        if h["To"] == h["From"]:
            raise Exception("From and To Hard Address Equal")

    def getWord(self, w):
        return (w[1] << 8) | w[0]

    def getWordReverse(self, w):
        return (w[0] << 8) | w[1]

    def getDWord(self, w):
        return (w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]

    def parseSoftHeader(self, h, m):
        if len(m) != h["Payload"]:
            raise Exception("Invalid soft message len")
        if len(m) < 12:
            raise Exception("Too short soft message")
        calcCrc = crc16(m[:h["Payload"]-2])
        return {
            "To": self.getWord(m[0:]),
            "From": self.getWord(m[2:]),
            "FNC": m[4],
            "ConstByte": self.getWord(m[5:]),
            "RegLen": m[7],
            "RegStart": self.getWord(m[8:]),
            "RestMessage": m[10:h["Payload"]-2],
            "CRC16": self.getWordReverse(m[h["Payload"]-2:]),
            "CalcCRC16": calcCrc
        }

    def validateSoftHeader(self, h, sh):
        if sh["CRC16"] != sh["CalcCRC16"]:
            raise Exception("Invalid Soft CRC16")
        if sh["ConstByte"] != 0x80:
            raise Exception("Invalid Const Soft Byte 0x80")
        if (h["From"] == self.conHardId and sh["From"] != self.conSoftId) or (h["From"] == self.devHardId and sh["From"] != self.devSoftId):
            raise Exception("Invalid From Address")
        if (h["To"] == self.conHardId and sh["To"] != self.conSoftId) or (h["To"] == self.devHardId and sh["To"] != self.devSoftId):
            raise Exception("Invalid To Address")

    def getTemp(self, w, divisor):
        w = self.getWord(w)
        if w & 0x8000:
            w = w - 0x10000
        return w / divisor

    def parseBitMask(self, val, names, ret):
        for name in names:
            if name is not None:
                ret[name] = bool(val & 1)
            val = val >> 1

    def parseRegisters(self, m, regstart, reglen, unknown=False):
        ret = {}

        skip = 0
        for regnum in range(regstart, regstart + reglen, 2):
            if skip > 0:
                skip = skip - 1
                continue
            reg = self.registers.get(regnum, None)
            adr = regnum - regstart
            if reg:
                val = None
                if reg['type'] == 'date':
                    val = "20{:02d}-{:02d}-{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'time':
                    val = "{:02d}:{:02d}:{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'word':
                    val = self.getWord(m[adr:])
                elif reg['type'] == 'rwrd':
                    val = self.getWordReverse(m[adr:])
                elif reg['type'] == 'dwrd':
                    val = self.getDWord(m[adr:])
                    skip = 1
                elif reg['type'] == 'temp':
                    val = self.getTemp(m[adr:], 1.0)
                elif reg['type'] == 'te10':
                    val = self.getTemp(m[adr:], 10.0)
                elif reg['type'] == 'fl10':
                    val = self.getWord(m[adr:]) / 10.0
                elif reg['type'] == 'f100':
                    val = self.getWord(m[adr:]) / 100.0
                elif reg['type'] == 'bool':
                    val = bool(self.getWord(m[adr:]))
                elif reg['type'] == 'mask':
                    self.parseBitMask(self.getWord(m[adr:]), reg['name'], ret)
                    continue
                elif reg['type'] == 'tprg':
                    val = {}
                    self.parseBitMask(self.getDWord(m[adr:]), range(0, 24), val)
                    skip = 1
                ret[reg['name']] = val
            elif unknown:
                ret["Reg%d" % regnum] = self.getWord(m[adr:])

        return ret

    def printMessage(self, h, sh):
        print ({
            'hard': {
                "StartByte": hex(h["StartByte"]),
                "To": h["To"],
                "From": h["From"],
                "ConstBytes": hex(h["ConstBytes"]),
                "Payload": h["Payload"],
                "CRC8": hex(h["CRC8"])
            },
            'soft': {
                "To": sh["To"],
                "From": sh["From"],
                "FNC": hex(sh["FNC"]),
                "ConstByte": hex(sh["ConstByte"]),
                "RegLen": sh["RegLen"],
                "RegStart": str(sh["RegStart"]) + " (" + hex(sh["RegStart"]) + ")",
                "RestMessage": hexlify(sh["RestMessage"]),
                "CRC16": hex(sh["CRC16"])
            }
        })

    def processMessage(self, m, ignoreTooShort):
        h = self.parseHardHeader(m)
        self.validateHardHeader(h)
        ml = h["Payload"]
        if ignoreTooShort and ml + 8 > len(m):
            return m
        sh = self.parseSoftHeader(h, m[8:ml+8])
        self.validateSoftHeader(h, sh)
        if self.onMessage:
            self.onMessage(self, h, sh, m)
        return m[ml+8:]

    def processAllMessages(self, m, returnRemainingBytes=False):
        minLen = 8 if returnRemainingBytes else 0
        prevLen = len(m)
        while prevLen > minLen:
            m = self.processMessage(m, returnRemainingBytes)
            if len(m) == prevLen:
                if returnRemainingBytes:
                    return m
                else:
                    raise Exception("Something wrong")
            prevLen = len(m)
        return m

    # Process all messages in X cycles of device to controller comms
    #
    # 1. The device sends a query to the controller to read 20 registers starting from address 100.
    # 2. The controller responds, it always seems to be the same. It's hard to say if there is a controller model or a serial number.
    # 3. The device sends a record of registers starting at address 120. This is the main message, there are temperatures there. After this message there is a long pause (which is quite a large part of the 140ms for a series of messages), probably the controller is not too fast to write it to memory and it takes longer. The exact number of records depends on the model and firmware of the device.
    # 4. The controller replies with the standard message 0x70 that the bytes have been written successfully.
    # 5. The device requests to read 4 bytes starting from address 252.
    # 6. The controller responds and returns 4 bytes. By default they are: 10000000 and they mean that the controller is working normally, there are no changes. The value 08000000 means that the controller is turned off. However, the value 11000000 means that the user has changed a parameter in the menu, at this point the communication scheme is different, described in the docs.
    #
    def eavesDrop(self, ser, numCycles=None):
        # window size and time (based on 140ms cycle and 360ms wait)
        winSize = 1000
        winTime = 0.4

        # determine start of cycle marker to look for
        # (device requesting to read 20 registers from address 100)
        s1 = unhexlify('69%02x%02x8400000c' % (self.devHardId, self.conHardId))
        s2 = unhexlify('%02x' % crc8(s1))
        s3 = unhexlify('%02x%02x%02x%02x' % (
            (self.devSoftId & 0xff),
            (self.devSoftId & 0xff00) >> 8,
            (self.conSoftId & 0xff),
            (self.conSoftId & 0xff00) >> 8,
        ))
        s4 = unhexlify('408000146400')
        s = s1 + s2 + s3 + s4

        ser.flushInput()
        cnt = 0
        while (numCycles is None) or (cnt < numCycles):
            cnt += 1

            # read until first char after start marker
            ser.timeout = 1
            m = ser.read_until(s, winSize)

            # read the rest within window
            ser.timeout = winTime
            m = ser.read(winSize)

            # process
            self.processAllMessages(s + m)

    def createReadRegistersMessage(self, start, num):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x40, 0x80, 0, num & 0xff, start & 0xff, (start >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def createWriteRegisterMessage(self, reg, val):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x60, 0x80, 0, 2, reg & 0xff, (reg >> 8) & 0xff, val & 0xff, (val >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def readRegisters(self, ser, start, num):
        m = self.createReadRegistersMessage(start, num)
        self.logger.debug(f'Sending message to the heat pump: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def readStatusRegisters(self, ser):
        self.logger.info('readStatusRegisters')
        start = self.REG_STATUS_START
        return self.readRegisters(ser, start, self.REG_CONFIG_START - start)

    def readConfigRegisters(self, ser):
        start = self.REG_CONFIG_START
        while start < self.REG_MAX_ADR:
            num = min(self.REG_MAX_ADR + 2 - start, self.REG_MAX_NUM)
            self.readRegisters(ser, start, num)
            start = start + num

    def writeRegister(self, ser, reg, val):
        m = self.createWriteRegisterMessage(reg, val)
        self.logger.debug(f'Sending message to the heat pump writeRegister: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def write(self, ser, registername, val):
        regnum = 0        
        # look for register based on name        
        for k, v in self.registers.items():
            if v['name'] == registername:
                regnum = k
                break      
        reg = self.registers.get(regnum, None)
        if reg:
            val = self.parseRegisterValue(reg, val)
            if val is not None:
                #print('self.writeRegister(ser, ' + str(regnum) + ', '+ str(val) + ')')
                return self.writeRegister(ser, regnum, val)
        return None
        
    def parseRegisterValue(self, reg, val):
        if val:                
            if reg['type'] == 'date':
                val = None
            elif reg['type'] == 'time':
                val = None
            elif reg['type'] == 'word':
                val = int(val)
            elif reg['type'] == 'rwrd':
                val = int(val)
            elif reg['type'] == 'dwrd':
                val = int(val)
            elif reg['type'] == 'temp':
                val = int(val)
            elif reg['type'] == 'te10':
                val = int(val) * 10
            elif reg['type'] == 'fl10':
                val = float(val) * 10
            elif reg['type'] == 'f100':
                val = float(val) * 100
            elif reg['type'] == 'bool':
                if val == 'True' or val == '1':
                    val = 1
                elif val == 'False' or val == '0':
                    val = 0
            elif reg['type'] == 'mask':
                val = None
            elif reg['type'] == 'tprg':
                val = None
            if reg['options'] and val not in reg['options']:
                print ('invalid option ' + str(val))
                val = None
            return val

# Interface to implement in child classes
#########################################

    # Registers are divided in read-only status registers and read/write config registers

    # The lowest readable register always seems to be 100
    REG_MIN_ADR = 100

    # The highest readable register varies per device
    REG_MAX_ADR = 536 #None

    # The number of registers which can be read in one message varies per device
    REG_MAX_NUM = 100 #None

    # Status registers start at 120 usually
    REG_STATUS_START = 120

    # The number of statusregisters which can be read in one message varies per device
    REG_STATUS_NUM = 104

    # Config registers start at a register which varies per device
    REG_CONFIG_START = 302 #None

    registers = {
#
#        # Status registers
#        120: { 'type': 'date', 'name': 'date' },                        # Date
#        124: { 'type': 'time', 'name': 'time' },                        # Time
#        128: { 'type': 'te10', 'name': 'T1' },                          # T1
#        130: { 'type': 'te10', 'name': 'T2' },                          # T2
#        132: { 'type': 'te10', 'name': 'T3' },                          # T3
#        ...
#
#        # Config registers
#        XXX: { 'type': 'word', 'name': 'InstallationScheme' },          # Installation Scheme
#        ...
#
    }
Ik heb de Appdaemon geïnstalleerd in HA en het dashboard is te zien op poort 5050. De Waveshare leest de gegevens in uit de Hewelex, en HA moet de seriële gegevens inlezen en deze omzetten via de Appdeamon in MQTT.
Moet er nog instellingen in de Waveshare aangepast worden? Het destination-IP is het Ip-adres waar HA op draait. De destination-poort is nu 502 (modbus poort) moet deze nog aangepast worden?
Het script wat je gestuurd hebt hoe zet je deze in de Appdeamon? Kan het script zo 1 op 1 in de Appdeamon gezet worden, of moet er nog wat aangepast worden?


Afbeeldingslocatie: https://tweakers.net/i/1vf7RZBRi9nuIZ16KgeBFvhOCdM=/800x/filters:strip_exif()/f/image/OqY5D3K4LcQoiQQ7eaRObciA.png?f=fotoalbum_large

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op dinsdag 25 juni 2024 @ 20:02:
[...]


Ik heb de Appdaemon geïnstalleerd in HA en het dashboard is te zien op poort 5050. De Waveshare leest de gegevens in uit de Hewelex, en HA moet de seriële gegevens inlezen en deze omzetten via de Appdeamon in MQTT.
Moet er nog instellingen in de Waveshare aangepast worden? Het destination-IP is het Ip-adres waar HA op draait. De destination-poort is nu 502 (modbus poort) moet deze nog aangepast worden?
Het script wat je gestuurd hebt hoe zet je deze in de Appdeamon? Kan het script zo 1 op 1 in de Appdeamon gezet worden, of moet er nog wat aangepast worden?


[Afbeelding]
Dit zijn allemaal detail vragen welke ik nu niet kan beantwoorden, aangezien ik op vakantie ben. Als ik weer terug ben zal ik de vragen beantwoorden.

Ik weet nog wel dat in appdeamon je moet aangeven welke yaml je moet inlezen.

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op dinsdag 25 juni 2024 @ 22:18:
[...]

Dit zijn allemaal detail vragen welke ik nu niet kan beantwoorden, aangezien ik op vakantie ben. Als ik weer terug ben zal ik de vragen beantwoorden.

Ik weet nog wel dat in appdeamon je moet aangeven welke yaml je moet inlezen.
Geniet van je vakantie, het heeft geen haast.

Acties:
  • 0 Henk 'm!

  • mijgmae
  • Registratie: December 2014
  • Laatst online: 17:47
Ik heb dit topic grotendeels doorgelezen & gezocht met de zoekfunctie, maar ik kan het niet vinden:
Stookt iedereen hun boilervat direct vanuit de Hewalex? Ik denk er namelijk aan om een Hewalex opstelling te maken (puur voor SWW) die indirect een vat stookt (300 liter); het voordeel tegenover direct stoken is dat het vat weer opgewarmd kan worden zonder dat er water getapt hoeft te worden.

Hebben mensen daar ervaring mee?

Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Direct inderdaad omdat Hewalex dat ook voorschrijft.

Waarom denk je dat er water getapt zou moeten worden bij het opwarmen van het vat?

In plaats van indirect stoken zou ik eerder indirect tappen (met RVS spiraal), dan heb je tenminste het voordeel dat je anti-legionelleruns achterwege kunt laten. Maar goed, dat is een andere discussie.

Acties:
  • +3 Henk 'm!

  • Geert68
  • Registratie: Juli 2024
  • Laatst online: 14-07-2024
Hallo allemaal,

Ik ben nieuw hier maar heb al ongeveer 4 jaar een Hewalex systeem met 300L boiler met 4 zonnecollectoren (op West) en de 3Kw WP.
Ik heb mijn systeem als volgend geïnstalleerd.
Ik heb een lage staande 300L boiler met 2 spiralen op zolder.
Op de onderste spiraal zitten de zonnecollectoren.
Vanwege de plaatsing van de collectoren op West (geen ruimte meer op het dak i.v.m. 22 zonnepanelen) heb ik pas vanaf 12 uur directe zon op de panelen.
Normaal wordt 1 paneel per 100L geadviseerd maar ik ben een beetje eigenwijs en ik heb 1 extra geplaatst.
In het voor en najaar zorgt dit voor extra productie maar in de zomer met een buitentemp. van boven de 25gr wordt de installatie te heet. (ik was hiervoor door de leverancier gewaarschuwd)
Om dit te voorkomen plaats ik bij warme periodes een speciaal op maat gemaakte witte hoes van vrachtwagenzeil over 1 van de collectoren en dan is mijn oververhittingsprobleem verholpen.
Ik heb nog gekeken om i.p.v. de hoes een rolluik met afstandsbediening te plaatsen maar dat ging toch wel flink in de papieren lopen.
Op de 2e spiraal zit mijn CV aangesloten met een 3-wegklep en een extra tempsensor die door het Hewalex systeem wordt aangestuurd.
Zodra mijn CV-water temp hoger is dan het boilerwater dan gaat de klep open en gaat het CV-water door de bovenste spiraal lopen.
Mijn CV is een 20Kw pelletkachel in de woonkamer met CV aansluiting die dus alle radiatoren, de vloerverwarming op de begane grond en in de winter de zonneboiler verwarmd.
De WP staat naast de boiler op zolder en hij pakt daar gewoon direct binnenlucht (meestal rond de 24gr.) die gefilterd wordt door een stuk afzuigkapfilter die ik in de aanzuig heb geplaatst.
Elke zomer vervang dit filter en die is dan flink vuil door alle aangezogen stof.
De afvoer met koude lucht gaat direct door het dak (50cm) de wijde wereld in.
Ook ik heb door de plaatsing van de boiler op zolder een probleem met de staafanode.
Ik had dit al voorzien en ik heb bij plaatsing gelijk een kettinganode gemonteerd.
Vorig jaar (na 3 jaar productie) heb ik deze voor de eerste keer vervangen.
Hij was ongeveer voor de helft weg. Dit viel mij mee maar misschien komt dit ook doordat ik in de binnenkomende waterleiding in mijn huis een ontkalkingsinstallatie heb staan.
Wel heb ik door het montagegat in de zijkant van de boiler een flinke berg anoderesten onder uit de boiler gehaald. (waar een waterstofzuiger al niet goed voor is)
Het water van de WP staat afgesteld op 55gr. en komt via een aansluiting halverwege de boiler in het vat zodat het onderste koude water niet te veel verstoord wordt.
Zodra de watertemp. onder de 50gr zakt dan gaat de WP aan.
Mocht door een storing de WP niet aanslaan dan gaat er onder de 40gr een 3000W. elektrisch verwarmingselement aan.
Maar dat is puur backup, die kost te veel stroom.

Acties:
  • 0 Henk 'm!

  • Snoekie
  • Registratie: Juli 2022
  • Laatst online: 11-05 16:15
Hoi Geert, interessante installatie. Wordt het in de winter niet te koud op zolder? Ik heb nu een nibe savent maar die is wat lichter, 1,6 kw. Met 3kw zou ik prima mijn huis op temperatuur kunnen houden dus ben naar de hewalex aan het kijken.

Ook heb ik een zonneboiler die net als bij jou in de zomer snel op temperatuur is, als de temperatuur in de boiler 70 graden is gaat er een klep open naar een radiator die buiten staat om de warmte af te voeren.

[ Voor 30% gewijzigd door Snoekie op 08-07-2024 16:10 ]


Acties:
  • +4 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op dinsdag 25 juni 2024 @ 20:02:
[...]


Ik heb de Appdaemon geïnstalleerd in HA en het dashboard is te zien op poort 5050. De Waveshare leest de gegevens in uit de Hewelex, en HA moet de seriële gegevens inlezen en deze omzetten via de Appdeamon in MQTT.
Moet er nog instellingen in de Waveshare aangepast worden? Het destination-IP is het Ip-adres waar HA op draait. De destination-poort is nu 502 (modbus poort) moet deze nog aangepast worden?
Het script wat je gestuurd hebt hoe zet je deze in de Appdeamon? Kan het script zo 1 op 1 in de Appdeamon gezet worden, of moet er nog wat aangepast worden?


[Afbeelding]
Zoals beloofd de antwoorden:

Afbeeldingslocatie: https://tweakers.net/i/9vJwYPUlcP8l8nKXtNF5smLUrrc=/800x/filters:strip_exif()/f/image/incA0Vwza4Ygfgk7tyIjUEIM.png?f=fotoalbum_large

Bij IP address vul je het IP adres in van de Waveshare
Bij Gateway het IP adres van je modem
Bij Dest. IP/Domain het IP adres van je server waar HA op draait

Voor het overige kun je de instellingen gebruiken zoals in het plaatje hierboven.

Voor wat betreft AppDeamon:

De scripts moeten tegenwoordig in addon/configs geplaatst worden.

Afbeeldingslocatie: https://tweakers.net/i/Amvf5wrp6fK5WPL8R86rcwJCfs8=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/VCl4bEQAw8FUzG0chIfKob7g.png?f=user_large

Dan in appdeamon.yaml een aantal algemene instellingen:

Afbeeldingslocatie: https://tweakers.net/i/tuf-JnoDY6dICQgJsNlcW1KX0q0=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/dq57Sz5ETbqFnIPvGlDVOzfv.png?f=user_large

Afbeeldingslocatie: https://tweakers.net/i/1hHbbNDE_ndsZIZf7E2JTyTw03k=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/C5Srl5Axq01bxwbmuOdD8Gs8.png?f=user_large

Dan in de folder apps in apps.yaml aangeven welke bestanden moeten worden gebruikt:

Afbeeldingslocatie: https://tweakers.net/i/O3LO1mutWJz1HbCCkFkgBygMl6I=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/JRaJkueOkjUjx2upzfZhKSbY.png?f=user_large

Afbeeldingslocatie: https://tweakers.net/i/mfSCAFVtbNQ1qR3bg198liq4y8M=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/AZlFrcFKNkhrbmJ9w4zXBLrk.png?f=user_large

hewalex2mqttconfig.ini:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[MQTT]
MQTT_ip = 192.168.178.x                                #Vul hier het IP adres in van HA
MQTT_port = 1883
MQTT_authentication = True
MQTT_user = mqtt
MQTT_pass = mqtt
MQTT_GatewayDevice_Topic = HewaGate

[Pcwu]
#-----------------------------------------------------------------------------------------------
Device_Pcwu_Enabled = True
Device_Pcwu_Address = 192.168.178.xx            #Vul hier het IP adres in van de Waveshare
Device_Pcwu_Port = 8899
Device_Pcwu_MqttTopic = Heatpump
#-----------------------------------------------------------------------------------------------


hewalex2mqtt.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import appdaemon.plugins.hass.hassapi as hass
import os
import threading
import configparser
import serial
from hewalex_geco.devices import PCWU
import paho.mqtt.client as mqtt
import logging
import sys

# The class definition for the AppDaemon app
class MyApp(hass.Hass):
    # Declare dev as a class attribute
    dev = None

    # Your app initialization logic here
    def initialize(self):
        # polling interval
        self.get_status_interval = 30.0
        
        # Controller (Master)
        conHardId = 1
        conSoftId = 1
        
        # PCWU (Slave)
        devHardId = 3
        devSoftId = 3

        #mqtt
        self.flag_connected_mqtt = 0
        self.MessageCache = {}

        # Initialize the logger
        self.initLogger()

        # Initialize the configuration first
        self.initConfiguration()

        # Start MQTT connection
        self.start_mqtt()

        # Declare dev as a class attribute
        self.dev = PCWU(conHardId, conSoftId, devHardId, devSoftId, self.on_message_serial)

        # Call device_readregisters_enqueue to start the periodic task
        self.device_readregisters_enqueue()

    def initLogger(self):
        # Set up the logger
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s')
        stream_handler = logging.StreamHandler(sys.stdout)
        stream_handler.setFormatter(formatter)
        stream_handler.setLevel(logging.DEBUG)
        self.logger.addHandler(stream_handler)
        self.logger.info("Initializing Hewalex 2 Mqtt")

    # Read Configs
    def initConfiguration(self):
        self.logger.info("reading config")
        config_file = os.path.join(os.path.dirname(__file__), 'hewalex2mqttconfig.ini')
        config = configparser.ConfigParser()
        config.read(config_file)
    
        # Mqtt
        self._MQTT_ip = config.get('MQTT', 'MQTT_ip')
        self._MQTT_port = config.getint('MQTT', 'MQTT_port')
        self._MQTT_authentication = config.getboolean('MQTT', 'MQTT_authentication')
        self._MQTT_user = config.get('MQTT', 'MQTT_user')
        self._MQTT_pass = config.get('MQTT', 'MQTT_pass')
        self.logger.info(f'MQTT ip: {self._MQTT_ip}')
        self.logger.info(f'MQTT port: {self._MQTT_port}')
        self.logger.info(f'MQTT authentication: {self._MQTT_authentication}')
        self.logger.info(f'MQTT user: {self._MQTT_user}')
        self.logger.info(f'MQTT pass: {self._MQTT_pass}')

        # PCWU Device
        self._Device_Pcwu_Enabled = config.getboolean('Pcwu', 'Device_Pcwu_Enabled')
        if self._Device_Pcwu_Enabled:
            self._Device_Pcwu_Address = config.get('Pcwu', 'Device_Pcwu_Address')
            self._Device_Pcwu_Port = config.getint('Pcwu', 'Device_Pcwu_Port')
            self._Device_Pcwu_MqttTopic = config.get('Pcwu', 'Device_Pcwu_MqttTopic')
            self.logger.info(f'Device_Pcwu_MqttTopic: {self._Device_Pcwu_MqttTopic}')
    
        # Use the values as needed in your app
        if self._Device_Pcwu_Enabled:
            # Create the serial connection with the correct baudrate
            # Do something with self._Device_Pcwu_Address, self._Device_Pcwu_Port, and self._Device_Pcwu_MqttTopic
            # For example, assign them to class attributes
            pass
        else:
            # Handle the case when Pcwu is not enabled
            pass

    def on_message_mqtt(self, client, userdata, message):    
        self.logger.info("Received message with topic: {}".format(message.topic))
        self.logger.info("Received command: {}".format(message.payload.decode('utf-8')))

        if message.topic == self._Device_Pcwu_MqttTopic + '/Command':
            command = message.payload.decode('utf-8')
            self.logger.info("Received message with topic:", message.topic)
            self.logger.info("Received command:", command)
            # Add your code to process the received command here
        else:
            # Handle other MQTT messages if needed
            pass

    # Define flag_connected_mqtt as a global variable at the beginning of the script
    #flag_connected_mqtt = 0
    def log_mqtt_status(self, kwargs):
        if self.flag_connected_mqtt == 1:
            self.logger.info("MQTT Broker is connected.")
        else:
            self.logger.info("MQTT Broker is disconnected.")

    def start_mqtt(self):
        self.mqtt_client = mqtt.Client()
        if self._MQTT_authentication:
            self.mqtt_client.username_pw_set(username=self._MQTT_user, password=self._MQTT_pass)
        self.mqtt_client.on_connect = self.on_mqtt_connect
        self.mqtt_client.on_disconnect = self.on_mqtt_disconnect
        self.mqtt_client.on_message = self.on_message_mqtt
        self.mqtt_client.enable_logger(self.logger)
        self.mqtt_client.connect(self._MQTT_ip, self._MQTT_port)
        if self._Device_Pcwu_Enabled:
            self.logger.info('Subscribed to: ' + self._Device_Pcwu_MqttTopic + '/Command')
            self.mqtt_client.subscribe(self._Device_Pcwu_MqttTopic + '/Command', qos=1)

        self.mqtt_client.loop_start()
    
    def on_mqtt_connect(self, client, userdata, flags, rc):
        self.logger.info("Connected to MQTT Broker with result code: {}".format(rc))
        self.mqtt_client.subscribe("HewaGate")  # Update this to your desired topic
        self.flag_connected_mqtt = 1
    
    def on_mqtt_disconnect(self, client, userdata, rc):
        self.logger.info("Disconnected from MQTT Broker with result code: {}".format(rc))
        self.flag_connected_mqtt = 0
    
    def on_message_serial(self, obj, h, sh, m):
        #self.logger.info(f'on_message_serial flag_connected_mqtt: {self.flag_connected_mqtt}')
        #self.logger.info('on_message_serial')
        #self.logger.info(f'MessageCache obj: {obj}')
        #self.logger.info(f'MessageCache h: {h}')
        #self.logger.info(f'MessageCache sh: {sh}')
        #self.logger.info(f'MessageCache m: {m}')
        try:    
            if self.flag_connected_mqtt != 1:
                self.logger.info('on_message_serial not connected to mqtt')
                return False
            
            global MessageCache
            topic = self._Device_Pcwu_MqttTopic
            if sh["FNC"] == 0x50:
                mp = obj.parseRegisters(sh["RestMessage"], sh["RegStart"], sh["RegLen"])        
                for item in mp.items():
                    if isinstance(item[1], dict): # skipping dictionaries (time program) 
                        continue
                    key = topic + '/' + str(item[0])
                    val = str(item[1])
                    if key not in self.MessageCache or self.MessageCache[key] != val:
                        self.MessageCache[key] = val
                        self.logger.info(key + " " + val)
                        self.mqtt_client.publish(key, val)
    
        except Exception as e:
            self.logger.info('Exception in on_message_serial: '+ str(e))
    
    def device_readregisters_enqueue(self):
        """Get device status every x seconds"""
        #self.logger.info('Get device status')
        #self.logger.info(f'device_readregisters_enqueue flag_connected_mqtt: {self.flag_connected_mqtt}')
        threading.Timer(self.get_status_interval, self.device_readregisters_enqueue).start()
        if self._Device_Pcwu_Enabled:        
            self.readPCWU()
            self.readPcwuConfig()

    def readPCWU(self):    
        #self.logger.info(f'readPCWU flag_connected_mqtt: {self.flag_connected_mqtt}')
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        #self.logger.info(f'readPCWU: {ser}')
        self.dev.readStatusRegisters(ser)    
        ser.close()   
    
    def readPcwuConfig(self):    
        #self.logger.info(f'readPcwuConfig flag_connected_mqtt: {self.flag_connected_mqtt}')
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        #self.logger.info(f'readPCWUConfig: {ser}')
        self.dev.readConfigRegisters(ser)
        ser.close()
    
    def writePcwuConfig(self, registerName, payload):    
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        self.logger.info(f'writePcwuConfig: {ser}')
        self.dev.write(ser, registerName, payload)
        ser.close()
    
    def printPcwuMqttTopics(self):        
        print('| Topic | Type | Description | ')
        print('| ----------------------- | ----------- | ---------------------------')
        dev = PCWU(conHardId, conSoftId, devHardId, devSoftId, on_message_serial)
        for k, v in dev.registers.items():
            if isinstance(v['name'] , list):
                for i in v['name']:
                    if i:
                        print('| ' + _Device_Pcwu_MqttTopic + '/' + str(i) + ' | ' + v['type'] + ' | ' + str(v.get('desc')))
            else:
                print('| ' +_Device_Pcwu_MqttTopic + '/' + str(v['name'])+ ' | ' + v['type'] + ' | ' + str(v.get('desc')))
            if k > dev.REG_CONFIG_START:          
                print('| ' + _Device_Pcwu_MqttTopic + '/Command/' + str(v['name']) + ' | ' + v.get('type') + ' | ' + str(v.get('desc')))



if __name__ == "__main__":
    # Create an instance of your AppDaemon app
    app = MyApp()
    # Initialize the configuration
    app.initConfiguration()
    # Start MQTT connection
    app.start_mqtt()
    # Add this line to log the MQTT status periodically (e.g., every 60 seconds)
    app.run_every(app.log_mqtt_status, datetime.datetime.now(), 20)
    # Run the AppDaemon app
    app.run()


Dan nog een aantal bestanden in de onderliggende folder hewalex_geco/

Afbeeldingslocatie: https://tweakers.net/i/q0dDP6uyDuZQMTQww_Ph9-0ZDdw=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/NElNB9h15ENQAvkEbhyEp4sC.png?f=user_large

__init__.py kan leeg blijven

crc.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


POLY = 0xD5
def crc8(buf):
    if len(buf) == 0:
        return 0

    accum = 0
    for i in buf:
        accum = accum ^ i
        for _ in range(8):
            if accum & 0x80:
                accum = (((accum << 1) & 0xff) ^ POLY) & 0xff
            else:
                accum = (accum << 1) & 0xff

    return accum

POLY16 = 0x1021
def crc16(buf):
    if len(buf) == 0:
        return 0

    accum = 0
    for i in buf:
        accum = accum ^ (i << 8)
        for _ in range(8):
            if accum & 0x8000:
                accum = (((accum << 1) & 0xffff) ^ POLY16) & 0xffff
            else:
                accum = (accum << 1) & 0xffff

    return accum


requirements.txt

code:
1
pyserial


Dan nog wat bestanden in de folder Devices:

Afbeeldingslocatie: https://tweakers.net/i/onzPhvsWE4Mef1FTx4BYzEQJleg=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/FC5NgxdkyOtzWYeNM983qAA5.png?f=user_large

__init__.py

code:
1
2
from .pcwu import PCWU
from .zps import ZPS


base.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
from binascii import hexlify, unhexlify
import logging

from ..crc import *

# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


class BaseDevice:
    def __init__(self, conHardId, conSoftId, devHardId, devSoftId, onMessage=None):
        self.logger = logging.getLogger(__name__)
        self.conHardId = conHardId  # G-426 controller - physical address
        self.conSoftId = conSoftId  # G-426 controller - logical address
        self.devHardId = devHardId  # Hewalex device - physical address
        self.devSoftId = devSoftId  # Hewalex device - logical address
        self.onMessage = onMessage  # Callback - onMessage(obj, h, sh, m)

    def parseHardHeader(self, m):
        if len(m) < 8:
            raise Exception("Too short message")
        calcCrc = crc8(m[:7])
        return {
            "StartByte": m[0],
            "To": m[1],
            "From": m[2],
            "ConstBytes": (m[5] << 16) | (m[4] << 8) | m[3],
            "Payload": m[6],
            "CRC8": m[7],
            "CalcCRC8": calcCrc
        }

    def validateHardHeader(self, h):
        if h["StartByte"] != 0x69:
            raise Exception("Invalid Start Byte")
        if h["CRC8"] != h["CalcCRC8"]:
            raise Exception("Invalid Hard CRC8")
        if h["ConstBytes"] != 0x84:
            raise Exception("Invalid Const Bytes")
        if h["From"] != self.conHardId and h["From"] != self.devHardId:
            raise Exception("Invalid From Hard Address: " + str(h["From"]))
        if h["To"] != self.conHardId and h["To"] != self.devHardId:
            raise Exception("Invalid To Hard Address: " + str(h["To"]))
        if h["To"] == h["From"]:
            raise Exception("From and To Hard Address Equal")

    def getWord(self, w):
        return (w[1] << 8) | w[0]

    def getWordReverse(self, w):
        return (w[0] << 8) | w[1]

    def getDWord(self, w):
        return (w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]

    def parseSoftHeader(self, h, m):
        if len(m) != h["Payload"]:
            raise Exception("Invalid soft message len")
        if len(m) < 12:
            raise Exception("Too short soft message")
        calcCrc = crc16(m[:h["Payload"]-2])
        return {
            "To": self.getWord(m[0:]),
            "From": self.getWord(m[2:]),
            "FNC": m[4],
            "ConstByte": self.getWord(m[5:]),
            "RegLen": m[7],
            "RegStart": self.getWord(m[8:]),
            "RestMessage": m[10:h["Payload"]-2],
            "CRC16": self.getWordReverse(m[h["Payload"]-2:]),
            "CalcCRC16": calcCrc
        }

    def validateSoftHeader(self, h, sh):
        if sh["CRC16"] != sh["CalcCRC16"]:
            raise Exception("Invalid Soft CRC16")
        if sh["ConstByte"] != 0x80:
            raise Exception("Invalid Const Soft Byte 0x80")
        if (h["From"] == self.conHardId and sh["From"] != self.conSoftId) or (h["From"] == self.devHardId and sh["From"] != self.devSoftId):
            raise Exception("Invalid From Address")
        if (h["To"] == self.conHardId and sh["To"] != self.conSoftId) or (h["To"] == self.devHardId and sh["To"] != self.devSoftId):
            raise Exception("Invalid To Address")

    def getTemp(self, w, divisor):
        w = self.getWord(w)
        if w & 0x8000:
            w = w - 0x10000
        return w / divisor

    def parseBitMask(self, val, names, ret):
        for name in names:
            if name is not None:
                ret[name] = bool(val & 1)
            val = val >> 1

    def parseRegisters(self, m, regstart, reglen, unknown=False):
        ret = {}

        skip = 0
        for regnum in range(regstart, regstart + reglen, 2):
            if skip > 0:
                skip = skip - 1
                continue
            reg = self.registers.get(regnum, None)
            adr = regnum - regstart
            if reg:
                val = None
                if reg['type'] == 'date':
                    val = "20{:02d}-{:02d}-{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'time':
                    val = "{:02d}:{:02d}:{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'word':
                    val = self.getWord(m[adr:])
                elif reg['type'] == 'rwrd':
                    val = self.getWordReverse(m[adr:])
                elif reg['type'] == 'dwrd':
                    val = self.getDWord(m[adr:])
                    skip = 1
                elif reg['type'] == 'temp':
                    val = self.getTemp(m[adr:], 1.0)
                elif reg['type'] == 'te10':
                    val = self.getTemp(m[adr:], 10.0)
                elif reg['type'] == 'fl10':
                    val = self.getWord(m[adr:]) / 10.0
                elif reg['type'] == 'f100':
                    val = self.getWord(m[adr:]) / 100.0
                elif reg['type'] == 'bool':
                    val = bool(self.getWord(m[adr:]))
                elif reg['type'] == 'mask':
                    self.parseBitMask(self.getWord(m[adr:]), reg['name'], ret)
                    continue
                elif reg['type'] == 'tprg':
                    val = {}
                    self.parseBitMask(self.getDWord(m[adr:]), range(0, 24), val)
                    skip = 1
                ret[reg['name']] = val
            elif unknown:
                ret["Reg%d" % regnum] = self.getWord(m[adr:])

        return ret

    def printMessage(self, h, sh):
        print ({
            'hard': {
                "StartByte": hex(h["StartByte"]),
                "To": h["To"],
                "From": h["From"],
                "ConstBytes": hex(h["ConstBytes"]),
                "Payload": h["Payload"],
                "CRC8": hex(h["CRC8"])
            },
            'soft': {
                "To": sh["To"],
                "From": sh["From"],
                "FNC": hex(sh["FNC"]),
                "ConstByte": hex(sh["ConstByte"]),
                "RegLen": sh["RegLen"],
                "RegStart": str(sh["RegStart"]) + " (" + hex(sh["RegStart"]) + ")",
                "RestMessage": hexlify(sh["RestMessage"]),
                "CRC16": hex(sh["CRC16"])
            }
        })

    def processMessage(self, m, ignoreTooShort):
        h = self.parseHardHeader(m)
        self.validateHardHeader(h)
        ml = h["Payload"]
        if ignoreTooShort and ml + 8 > len(m):
            return m
        sh = self.parseSoftHeader(h, m[8:ml+8])
        self.validateSoftHeader(h, sh)
        if self.onMessage:
            self.onMessage(self, h, sh, m)
        return m[ml+8:]

    def processAllMessages(self, m, returnRemainingBytes=False):
        minLen = 8 if returnRemainingBytes else 0
        prevLen = len(m)
        while prevLen > minLen:
            m = self.processMessage(m, returnRemainingBytes)
            if len(m) == prevLen:
                if returnRemainingBytes:
                    return m
                else:
                    raise Exception("Something wrong")
            prevLen = len(m)
        return m

    # Process all messages in X cycles of device to controller comms
    #
    # 1. The device sends a query to the controller to read 20 registers starting from address 100.
    # 2. The controller responds, it always seems to be the same. It's hard to say if there is a controller model or a serial number.
    # 3. The device sends a record of registers starting at address 120. This is the main message, there are temperatures there. After this message there is a long pause (which is quite a large part of the 140ms for a series of messages), probably the controller is not too fast to write it to memory and it takes longer. The exact number of records depends on the model and firmware of the device.
    # 4. The controller replies with the standard message 0x70 that the bytes have been written successfully.
    # 5. The device requests to read 4 bytes starting from address 252.
    # 6. The controller responds and returns 4 bytes. By default they are: 10000000 and they mean that the controller is working normally, there are no changes. The value 08000000 means that the controller is turned off. However, the value 11000000 means that the user has changed a parameter in the menu, at this point the communication scheme is different, described in the docs.
    #
    def eavesDrop(self, ser, numCycles=None):
        # window size and time (based on 140ms cycle and 360ms wait)
        winSize = 1000
        winTime = 0.4

        # determine start of cycle marker to look for
        # (device requesting to read 20 registers from address 100)
        s1 = unhexlify('69%02x%02x8400000c' % (self.devHardId, self.conHardId))
        s2 = unhexlify('%02x' % crc8(s1))
        s3 = unhexlify('%02x%02x%02x%02x' % (
            (self.devSoftId & 0xff),
            (self.devSoftId & 0xff00) >> 8,
            (self.conSoftId & 0xff),
            (self.conSoftId & 0xff00) >> 8,
        ))
        s4 = unhexlify('408000146400')
        s = s1 + s2 + s3 + s4

        ser.flushInput()
        cnt = 0
        while (numCycles is None) or (cnt < numCycles):
            cnt += 1

            # read until first char after start marker
            ser.timeout = 1
            m = ser.read_until(s, winSize)

            # read the rest within window
            ser.timeout = winTime
            m = ser.read(winSize)

            # process
            self.processAllMessages(s + m)

    def createReadRegistersMessage(self, start, num):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x40, 0x80, 0, num & 0xff, start & 0xff, (start >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def createWriteRegisterMessage(self, reg, val):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x60, 0x80, 0, 2, reg & 0xff, (reg >> 8) & 0xff, val & 0xff, (val >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def readRegisters(self, ser, start, num):
        m = self.createReadRegistersMessage(start, num)
        self.logger.debug(f'Sending message to the heat pump: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def readStatusRegisters(self, ser):
        self.logger.info('readStatusRegisters')
        start = self.REG_STATUS_START
        return self.readRegisters(ser, start, self.REG_CONFIG_START - start)

    def readConfigRegisters(self, ser):
        start = self.REG_CONFIG_START
        while start < self.REG_MAX_ADR:
            num = min(self.REG_MAX_ADR + 2 - start, self.REG_MAX_NUM)
            self.readRegisters(ser, start, num)
            start = start + num

    def writeRegister(self, ser, reg, val):
        m = self.createWriteRegisterMessage(reg, val)
        self.logger.debug(f'Sending message to the heat pump writeRegister: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def write(self, ser, registername, val):
        regnum = 0        
        # look for register based on name        
        for k, v in self.registers.items():
            if v['name'] == registername:
                regnum = k
                break      
        reg = self.registers.get(regnum, None)
        if reg:
            val = self.parseRegisterValue(reg, val)
            if val is not None:
                #print('self.writeRegister(ser, ' + str(regnum) + ', '+ str(val) + ')')
                return self.writeRegister(ser, regnum, val)
        return None
        
    def parseRegisterValue(self, reg, val):
        if val:                
            if reg['type'] == 'date':
                val = None
            elif reg['type'] == 'time':
                val = None
            elif reg['type'] == 'word':
                val = int(val)
            elif reg['type'] == 'rwrd':
                val = int(val)
            elif reg['type'] == 'dwrd':
                val = int(val)
            elif reg['type'] == 'temp':
                val = int(val)
            elif reg['type'] == 'te10':
                val = int(val) * 10
            elif reg['type'] == 'fl10':
                val = float(val) * 10
            elif reg['type'] == 'f100':
                val = float(val) * 100
            elif reg['type'] == 'bool':
                if val == 'True' or val == '1':
                    val = 1
                elif val == 'False' or val == '0':
                    val = 0
            elif reg['type'] == 'mask':
                val = None
            elif reg['type'] == 'tprg':
                val = None
            if reg['options'] and val not in reg['options']:
                print ('invalid option ' + str(val))
                val = None
            return val

# Interface to implement in child classes
#########################################

    # Registers are divided in read-only status registers and read/write config registers

    # The lowest readable register always seems to be 100
    REG_MIN_ADR = 100

    # The highest readable register varies per device
    REG_MAX_ADR = 536 #None

    # The number of registers which can be read in one message varies per device
    REG_MAX_NUM = 100 #None

    # Status registers start at 120 usually
    REG_STATUS_START = 120

    # The number of statusregisters which can be read in one message varies per device
    REG_STATUS_NUM = 104

    # Config registers start at a register which varies per device
    REG_CONFIG_START = 302 #None

    registers = {
#
#        # Status registers
#        120: { 'type': 'date', 'name': 'date' },                        # Date
#        124: { 'type': 'time', 'name': 'time' },                        # Time
#        128: { 'type': 'te10', 'name': 'T1' },                          # T1
#        130: { 'type': 'te10', 'name': 'T2' },                          # T2
#        132: { 'type': 'te10', 'name': 'T3' },                          # T3
#        ...
#
#        # Config registers
#        XXX: { 'type': 'word', 'name': 'InstallationScheme' },          # Installation Scheme
#        ...
#
    }


pcwu.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from .base import BaseDevice

# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


class PCWU(BaseDevice):

    # PCWU is driven by PG-426-P01 (controller) and MG-426-P01 (executive module)
    # Below are the registers for the executive module, so no controller settings
    REG_MAX_ADR = 536
    REG_MAX_NUM = 100
    REG_CONFIG_START = 302
    REG_STATUS_NUM = 104

    # Interaction between status register 202 and config register 304:
    #
    # When talking to the executive module directly the heat pump can be (manually)
    # disabled and enabled through config register 304 and the result of this is visible
    # in status register 202. With the controller on this works as expected, the heat
    # pump can be put into a waiting mode where it will not turn on until enabled again
    # through register 304. With the controller off however this doesn't work. Maybe
    # the executive module is hardcoded to not turn the heat pump on when the controller
    # is off? See eavesDrop function in base device to learn how the executive module
    # knows that the controller is off. What makes this especially weird is that register
    # 202 changes its value to 0 when the controller is off even if register 304 says
    # otherwise. It would be great if we could detect the 'controller is off' situation
    # through one of the registers, but I haven't found a way yet.

    registers = {

        # Status registers
        120: { 'type': 'date', 'name': 'date', 'desc': 'Date' },                      
        124: { 'type': 'time', 'name': 'time', 'desc': 'Time' },                     
        128: { 'type': 'te10', 'name': 'T1', 'desc': 'T1 (Ambient temp)' },                        
        130: { 'type': 'te10', 'name': 'T2', 'desc': 'T2 (Tank bottom temp)' },                         
        132: { 'type': 'te10', 'name': 'T3', 'desc': 'T3 (Tank top temp)' },                        
        138: { 'type': 'te10', 'name': 'T6', 'desc': 'T6 (HP water inlet temp)' },                         
        140: { 'type': 'te10', 'name': 'T7', 'desc': 'T7 (HP water outlet temp)' },                         
        142: { 'type': 'te10', 'name': 'T8', 'desc': 'T8 (HP evaporator temp)' },                          
        144: { 'type': 'te10', 'name': 'T9', 'desc': 'T9 (HP before compressor temp)' },                          
        146: { 'type': 'te10', 'name': 'T10', 'desc': 'T10 (HP after compressor temp)' },                         

        194: { 'type': 'bool', 'name': 'IsManual' },
        196: { 'type': 'mask', 'name': [
            'FanON',                                                    # Fan ON (True/False)
            None,
            'CirculationPumpON',                                        # Circulation pump ON (True/False)
            None,
            None,
            'HeatPumpON',                                               # Heat pump ON (True/False)
            None,
            None,
            None,
            None,
            None,
            'CompressorON',                                             # Compressor ON (True/False)
            'HeaterEON',                                                # Heater E ON (True/False)
        ]},
        198: { 'type': 'word', 'name': 'EV1', 'desc': 'Expansion valve' },
        202: { 'type': 'word', 'name': 'WaitingStatus', 'desc': ' 0 when available for operation, 2 when disabled through register 304' },               #

        # Config registers
        302: { 'type': 'word', 'name': 'InstallationScheme', 'options': [1,2,3,4,5,6,7,8,9], 'desc': 'Installation Scheme (1-9)' },
        304: { 'type': 'bool', 'name': 'HeatPumpEnabled', 'options': [0,1], 'desc': 'Heat Pump Enabled (True/False)'},
        306: { 'type': 'word', 'name': 'TapWaterSensor', 'options': [0,1,2], 'desc': 'Temp. sensor controlling heat pump operation [T2,T3,T7, factory setting T2]' },                                  #
        308: { 'type': 'te10', 'name': 'TapWaterTemp', 'options':  [100,110,112,130,140,150,160,170,180,190,    #
                                                                    200,210,220,230,240,250,260,270,280,290,
                                                                    300,310,320,330,340,350,360,370,380,390,
                                                                    400,410,420,430,440,450,460,470,480,490,
                                                                    500,510,520,530,540,550,560,570,580,590,
                                                                    600] , 'desc': 'HUW temperature for heat pump [10-60°C, factory setting 50°C]'},                                 
        310: { 'type': 'te10', 'name': 'TapWaterHysteresis', 'options': [20,30,40,50,60,70,80,90,100] , 'desc': 'Heat pump start-up hysteresis [2-10°C, factory setting 5°C]'},        # 
        312: { 'type': 'te10', 'name': 'AmbientMinTemp', 'options': [-100,-90,-80,-70,-60,-50,-40,-30,-20,-10,  # 
                                                                     10,20,30,40,50,60,70,80,90,100] , 'desc': 'Minimum ambient temperature (T1) [-10-10°C] ' },                                                
        314: { 'type': 'tprg', 'name': 'TimeProgramHPM-F', 'desc': 'Time Program HP M-F (True/False per hour of the day)' },                                                    # 
        318: { 'type': 'tprg', 'name': 'TimeProgramHPSat', 'desc': 'Time Program HP Sat (True/False per hour of the day)' },                                                    # 
        322: { 'type': 'tprg', 'name': 'TimeProgramHPSun', 'desc': 'Time Program HP Sun (True/False per hour of the day)' },                                                    # 

        326: { 'type': 'bool', 'name': 'AntiFreezingEnabled', 'options': [0,1], 'desc': 'Function protecting against freezing [YES/NO], factory setting YES' },                               # 
        328: { 'type': 'word', 'name': 'WaterPumpOperationMode', 'options': [0,1], 'desc': 'Water Pump Operation Mode (0=Continuous, 1=Synchronous)' },                            # 
        330: { 'type': 'word', 'name': 'FanOperationMode', 'options': [0,1,2], 'desc': 'Fan Operation Mode (0=Max, 1=Min, 2=Day/Night), factory MAX' },                                # 
        332: { 'type': 'word', 'name': 'DefrostingInterval', 'desc': 'Defrosting cycle start-up delay [30-90 min., factory setting 45 min.]' },                                                  # 
        334: { 'type': 'te10', 'name': 'DefrostingStartTemp', 'desc': 'Temperature activating defrosting [-30 - 0°C, factory setting -7°C]' },                                                 # 
        336: { 'type': 'te10', 'name': 'DefrostingStopTemp', 'desc': 'Temperature finishing defrosting [2-30°C, factory setting 13°C]' }, 
        338: { 'type': 'word', 'name': 'DefrostingMaxTime', 'desc': 'Maximum defrosting duration [1-12 min., factory setting 8 min.]' },

        #374                                                            # Time Program? Heat pump
        #406                                                            # Time Program? Heater E
        #432                                                            # Time Program? Circulating pump [shown in diagrams no. 2,3,4,6,7,8,9]
        #476                                                            # Time Program? Gas-fired boiler D [shown in diagrams no. 4,7,9]

        #???                                                            # Anti-Legionella [shown in diagrams no. 3-9]
        #???                                                            # Anti-Legionella function activation [YES/NO, factory setting YES]
        #???                                                            # Protection carried out by heater E [YES/NO, factory setting YES]
        #???                                                            # Protection carried out by heater P [YES/NO, factory setting YES]
        #???                                                            # Protection carried out by gas-fired boiler [YES/NO, factory setting YES, shown in diagrams no. 4,7,9]

        516: { 'type': 'bool', 'name': 'ExtControllerHPOFF', 'desc': 'Heat pump deactivation [YES/NO, factory setting YES]' },          
        #518                                                            # ?? Electric heater E deactivation [YES/NO, factory setting YES]
        #520                                                            # ?? Electric heater P deactivation [YES/NO, factory setting YES]
        #522                                                            # ?? Gas-fired boiler shutdown [YES/NO, factory setting YES, shown in diagrams no. 4,7,9]
        #524                                                            # ?? Shutdown of pump F for solid fuel fired boiler B [YES/NO, factory setting YES, shown in diagrams no. 3,8,9]

    }

    def disable(self, ser):
        return self.writeRegister(ser, 304, 0)

    def enable(self, ser):
        return self.writeRegister(ser, 304, 1)


zps.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from .base import BaseDevice

# Based on work by aelias-eu
# https://github.com/aelias-eu/hewalex-geco-protocol


class ZPS(BaseDevice):

    # ZPS is driven by G-422-P09 (controller)
    # Below are the registers for the controller, so including controller settings
    REG_MAX_ADR = 330
    REG_MAX_NUM = 76
    REG_CONFIG_START = 170

    registers = {

        # Status registers
        120: { 'type': 'date', 'name': 'date', 'desc': 'Date'},
        124: { 'type': 'time', 'name': 'time', 'desc': 'Time'},
        128: { 'type': 'temp', 'name': 'T1', 'desc': 'T1 (Collectors temp)'},
        130: { 'type': 'temp', 'name': 'T2', 'desc': 'T2 (Tank bottom temp)'},
        132: { 'type': 'temp', 'name': 'T3', 'desc': 'T3 (Air separator temp)'},
        134: { 'type': 'temp', 'name': 'T4', 'desc': 'T4 (Tank top temp)'},
        136: { 'type': 'temp', 'name': 'T5', 'desc': 'T5 (Boiler outlet temp)'},
        138: { 'type': 'temp', 'name': 'T6', 'desc': 'T6'},
        144: { 'type': 'word', 'name': 'CollectorPower', 'desc': 'Collector Power (W)'},
        148: { 'type': 'fl10', 'name': 'Consumption', 'desc': 'Consumption (W)'},
        150: { 'type': 'bool', 'name': 'CollectorActive', 'desc': 'Collector Active (True/False)'},
        152: { 'type': 'fl10', 'name': 'FlowRate', 'desc': 'Flow Rate (l/min)'},
        154: { 'type': 'mask', 'name': [
            'CollectorPumpON',                                          # Collector Pump (P) ON (True/False)
            None,                                                       # Boiler Pump (K) ON?
            'CirculationPumpON',                                        # Circulation Pump (C) ON (True/False)
        ]},
        156: { 'type': 'word', 'name': 'CollectorPumpSpeed', 'desc': 'Collector Pump Speed (0-15)'},
        166: { 'type': 'fl10', 'name': 'TotalEnergy', 'desc': 'Total Energy (kWh)'},

        # Config registers
        170: { 'type': 'word', 'name': 'InstallationScheme', 'desc': 'Installation Scheme (1-19)'},
        172: { 'type': 'word', 'name': 'DisplayTimeout', 'desc': 'Display Timeout (1-10 min)'},
        174: { 'type': 'word', 'name': 'DisplayBrightness', 'desc': 'Display Brightness (1-10)'},
        176: { 'type': 'bool', 'name': 'AlarmSoundEnabled', 'desc': 'Alarm Sound Enabled (True/False)'},
        178: { 'type': 'bool', 'name': 'KeySoundEnabled', 'desc': 'Key Sound Enabled (True/False)'},
        180: { 'type': 'word', 'name': 'DisplayLanguage', 'desc': 'Display Language (0=PL, 1=EN, 2=DE, 3=FR, 4=PT, 5=ES, 6=NL, 7=IT, 8=CZ, 9=SL, ...)'},
        182: { 'type': 'temp', 'name': 'FluidFreezingTemp', 'desc': 'Fluid Freezing Temp'},
        186: { 'type': 'fl10', 'name': 'FlowRateNominal', 'desc': 'Flow Rate Nominal (l/min)'},
        188: { 'type': 'word', 'name': 'FlowRateMeasurement', 'desc': 'Flow Rate Measurement (0=Rotameter, 1=Electronic G916, 2=Electronic)'},
        190: { 'type': 'f100', 'name': 'FlowRateWeight', 'desc': 'Flow Rate Weight (imp/l)'},
        192: { 'type': 'bool', 'name': 'HolidayEnabled', 'desc': 'Holiday Enabled (True/False)'},
        194: { 'type': 'word', 'name': 'HolidayStartDay', 'desc': 'Holiday Start Day'},
        196: { 'type': 'word', 'name': 'HolidayStartMonth', 'desc': 'Holiday Start Month'},
        198: { 'type': 'word', 'name': 'HolidayStartYear', 'desc': 'Holiday Start Year'},
        200: { 'type': 'word', 'name': 'HolidayEndDay', 'desc': 'Holiday End Day'},
        202: { 'type': 'word', 'name': 'HolidayEndMonth', 'desc': 'Holiday End Month'},
        204: { 'type': 'word', 'name': 'HolidayEndYear', 'desc': 'Holiday End Year'},
        206: { 'type': 'word', 'name': 'CollectorType', 'desc': 'Collector Type (0=Flat, 1=Tube)'},
        208: { 'type': 'temp', 'name': 'CollectorPumpHysteresis', 'desc': 'Collector Pump Hysteresis (Difference between T1 and T2 to turn on collector pump)'},
        210: { 'type': 'temp', 'name': 'ExtraPumpHysteresis', 'desc': 'Extra Pump Hysteresis (Temp difference to turn on extra pump)'},
        212: { 'type': 'temp', 'name': 'CollectorPumpMaxTemp', 'desc': 'Collector Pump Max Temp (Maximum T2 temp to turn off collector pump)'},
        214: { 'type': 'word', 'name': 'BoilerPumpMinTemp', 'desc': 'Boiler Pump Min Temp (Minimum T5 temp to turn on boiler pump)'},
        218: { 'type': 'word', 'name': 'HeatSourceMaxTemp', 'desc': 'Heat Source Max Temp (Maximum T4 temp to turn off heat sources)'},
        220: { 'type': 'word', 'name': 'BoilerPumpMaxTemp', 'desc': 'Boiler Pump Max Temp (Maximum T4 temp to turn off boiler pump)'},
        222: { 'type': 'bool', 'name': 'PumpRegulationEnabled', 'desc': 'Pump Regulation Enabled (True/False)'},
        226: { 'type': 'word', 'name': 'HeatSourceMaxCollectorPower', 'desc': 'Heat Source Max Collector Power (Maximum collector power to turn off heat sources) (100-9900W)'},
        228: { 'type': 'bool', 'name': 'CollectorOverheatProtEnabled', 'desc': 'Collector Overheat Protection Enabled (True/False)'},
        230: { 'type': 'temp', 'name': 'CollectorOverheatProtMaxTemp', 'desc': 'Collector Overheat Protection Max Temp (Maximum T2 temp for overheat protection)'},
        232: { 'type': 'bool', 'name': 'CollectorFreezingProtEnabled', 'desc': 'Collector Freezing Protection Enabled (True/False)'},
        234: { 'type': 'word', 'name': 'HeatingPriority', 'desc': 'Heating Priority'},
        236: { 'type': 'bool', 'name': 'LegionellaProtEnabled', 'desc': 'Legionella Protection Enabled (True/False)'},
        238: { 'type': 'bool', 'name': 'LockBoilerKWithBoilerC', 'desc': 'Lock Boiler K With Boiler C (True/False)'},
        240: { 'type': 'bool', 'name': 'NightCoolingEnabled', 'desc': 'Night Cooling Enabled (True/False)'},
        242: { 'type': 'temp', 'name': 'NightCoolingStartTemp', 'desc': 'Night Cooling Start Temp'},
        244: { 'type': 'temp', 'name': 'NightCoolingStopTemp', 'desc': 'Night Cooling Stop Temp'},
        246: { 'type': 'word', 'name': 'NightCoolingStopTime', 'desc': 'Night Cooling Stop Time (hr)'},
        248: { 'type': 'tprg', 'name': 'TimeProgramCM-F', 'desc': 'Time Program C M-F (True/False per hour of the day)'},
        252: { 'type': 'tprg', 'name': 'TimeProgramCSat', 'desc': 'Time Program C Sat (True/False per hour of the day)'},
        256: { 'type': 'tprg', 'name': 'TimeProgramCSun', 'desc': 'Time Program C Sun (True/False per hour of the day)'},
        260: { 'type': 'tprg', 'name': 'TimeProgramKM-F', 'desc': 'Time Program K M-F (True/False per hour of the day)'},
        264: { 'type': 'tprg', 'name': 'TimeProgramKSat', 'desc': 'Time Program K Sat (True/False per hour of the day)'},
        268: { 'type': 'tprg', 'name': 'TimeProgramKSun', 'desc': 'Time Program K Sun (True/False per hour of the day)'},
        278: { 'type': 'word', 'name': 'CollectorPumpMinRev', 'desc': 'Collector Pump Min Rev (rev/min)'},
        280: { 'type': 'word', 'name': 'CollectorPumpMaxRev', 'desc': 'Collector Pump Max Rev (rev/min)'},
        282: { 'type': 'word', 'name': 'CollectorPumpMinIncTime', 'desc': 'Collector Pump Min Increase Time (s)'},
        284: { 'type': 'word', 'name': 'CollectorPumpMinDecTime', 'desc': 'Collector Pump Min Decrease Time (s)'},
        286: { 'type': 'word', 'name': 'CollectorPumpStartupSpeed', 'desc': 'Collector Pump Startup Speed (1-15)'},
        288: { 'type': 'bool', 'name': 'PressureSwitchEnabled', 'desc': 'Pressure Switch Enabled (True/False)'},
        290: { 'type': 'bool', 'name': 'TankOverheatProtEnabled', 'desc': 'Tank Overheat Protection Enabled (True/False)'},
        322: { 'type': 'bool', 'name': 'CirculationPumpEnabled', 'desc': 'Circulation Pump Enabled (True/False)'},
        324: { 'type': 'word', 'name': 'CirculationPumpMode', 'desc': 'Circulation Pump Mode (0=Discontinuous, 1=Continuous)'},
        326: { 'type': 'temp', 'name': 'CirculationPumpMinTemp', 'desc': 'Circulation Pump Min Temp (Minimum T4 temp to turn on circulation pump)'},
        328: { 'type': 'word', 'name': 'CirculationPumpONTime', 'desc': 'Circulation Pump ON Time (1-59 min)'},
        330: { 'type': 'word', 'name': 'CirculationPumpOFFTime', 'desc': 'Circulation Pump OFF Time (1-59 min)'},

        # Weird registers
        312: { 'type': 'dwrd', 'name': 'TotalOperationTime', 'desc': 'Total Operation Time (min) - lives in config space but is status register'},
        320: { 'type': 'word', 'name': 'Reg320', 'desc': 'Unknown register - value changes constantly'}
    }

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op dinsdag 9 juli 2024 @ 20:24:
[...]

Zoals beloofd de antwoorden:

[Afbeelding]

Bij IP address vul je het IP adres in van de Waveshare
Bij Gateway het IP adres van je modem
Bij Dest. IP/Domain het IP adres van je server waar HA op draait

Voor het overige kun je de instellingen gebruiken zoals in het plaatje hierboven.

Voor wat betreft AppDeamon:

De scripts moeten tegenwoordig in addon/configs geplaatst worden.

[Afbeelding]

Dan in appdeamon.yaml een aantal algemene instellingen:

[Afbeelding]

[Afbeelding]

Dan in de folder apps in apps.yaml aangeven welke bestanden moeten worden gebruikt:

[Afbeelding]

[Afbeelding]

hewalex2mqttconfig.ini:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[MQTT]
MQTT_ip = 192.168.178.x                                #Vul hier het IP adres in van HA
MQTT_port = 1883
MQTT_authentication = True
MQTT_user = mqtt
MQTT_pass = mqtt
MQTT_GatewayDevice_Topic = HewaGate

[Pcwu]
#-----------------------------------------------------------------------------------------------
Device_Pcwu_Enabled = True
Device_Pcwu_Address = 192.168.178.xx            #Vul hier het IP adres in van de Waveshare
Device_Pcwu_Port = 8899
Device_Pcwu_MqttTopic = Heatpump
#-----------------------------------------------------------------------------------------------


hewalex2mqtt.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import appdaemon.plugins.hass.hassapi as hass
import os
import threading
import configparser
import serial
from hewalex_geco.devices import PCWU
import paho.mqtt.client as mqtt
import logging
import sys

# The class definition for the AppDaemon app
class MyApp(hass.Hass):
    # Declare dev as a class attribute
    dev = None

    # Your app initialization logic here
    def initialize(self):
        # polling interval
        self.get_status_interval = 30.0
        
        # Controller (Master)
        conHardId = 1
        conSoftId = 1
        
        # PCWU (Slave)
        devHardId = 3
        devSoftId = 3

        #mqtt
        self.flag_connected_mqtt = 0
        self.MessageCache = {}

        # Initialize the logger
        self.initLogger()

        # Initialize the configuration first
        self.initConfiguration()

        # Start MQTT connection
        self.start_mqtt()

        # Declare dev as a class attribute
        self.dev = PCWU(conHardId, conSoftId, devHardId, devSoftId, self.on_message_serial)

        # Call device_readregisters_enqueue to start the periodic task
        self.device_readregisters_enqueue()

    def initLogger(self):
        # Set up the logger
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s')
        stream_handler = logging.StreamHandler(sys.stdout)
        stream_handler.setFormatter(formatter)
        stream_handler.setLevel(logging.DEBUG)
        self.logger.addHandler(stream_handler)
        self.logger.info("Initializing Hewalex 2 Mqtt")

    # Read Configs
    def initConfiguration(self):
        self.logger.info("reading config")
        config_file = os.path.join(os.path.dirname(__file__), 'hewalex2mqttconfig.ini')
        config = configparser.ConfigParser()
        config.read(config_file)
    
        # Mqtt
        self._MQTT_ip = config.get('MQTT', 'MQTT_ip')
        self._MQTT_port = config.getint('MQTT', 'MQTT_port')
        self._MQTT_authentication = config.getboolean('MQTT', 'MQTT_authentication')
        self._MQTT_user = config.get('MQTT', 'MQTT_user')
        self._MQTT_pass = config.get('MQTT', 'MQTT_pass')
        self.logger.info(f'MQTT ip: {self._MQTT_ip}')
        self.logger.info(f'MQTT port: {self._MQTT_port}')
        self.logger.info(f'MQTT authentication: {self._MQTT_authentication}')
        self.logger.info(f'MQTT user: {self._MQTT_user}')
        self.logger.info(f'MQTT pass: {self._MQTT_pass}')

        # PCWU Device
        self._Device_Pcwu_Enabled = config.getboolean('Pcwu', 'Device_Pcwu_Enabled')
        if self._Device_Pcwu_Enabled:
            self._Device_Pcwu_Address = config.get('Pcwu', 'Device_Pcwu_Address')
            self._Device_Pcwu_Port = config.getint('Pcwu', 'Device_Pcwu_Port')
            self._Device_Pcwu_MqttTopic = config.get('Pcwu', 'Device_Pcwu_MqttTopic')
            self.logger.info(f'Device_Pcwu_MqttTopic: {self._Device_Pcwu_MqttTopic}')
    
        # Use the values as needed in your app
        if self._Device_Pcwu_Enabled:
            # Create the serial connection with the correct baudrate
            # Do something with self._Device_Pcwu_Address, self._Device_Pcwu_Port, and self._Device_Pcwu_MqttTopic
            # For example, assign them to class attributes
            pass
        else:
            # Handle the case when Pcwu is not enabled
            pass

    def on_message_mqtt(self, client, userdata, message):    
        self.logger.info("Received message with topic: {}".format(message.topic))
        self.logger.info("Received command: {}".format(message.payload.decode('utf-8')))

        if message.topic == self._Device_Pcwu_MqttTopic + '/Command':
            command = message.payload.decode('utf-8')
            self.logger.info("Received message with topic:", message.topic)
            self.logger.info("Received command:", command)
            # Add your code to process the received command here
        else:
            # Handle other MQTT messages if needed
            pass

    # Define flag_connected_mqtt as a global variable at the beginning of the script
    #flag_connected_mqtt = 0
    def log_mqtt_status(self, kwargs):
        if self.flag_connected_mqtt == 1:
            self.logger.info("MQTT Broker is connected.")
        else:
            self.logger.info("MQTT Broker is disconnected.")

    def start_mqtt(self):
        self.mqtt_client = mqtt.Client()
        if self._MQTT_authentication:
            self.mqtt_client.username_pw_set(username=self._MQTT_user, password=self._MQTT_pass)
        self.mqtt_client.on_connect = self.on_mqtt_connect
        self.mqtt_client.on_disconnect = self.on_mqtt_disconnect
        self.mqtt_client.on_message = self.on_message_mqtt
        self.mqtt_client.enable_logger(self.logger)
        self.mqtt_client.connect(self._MQTT_ip, self._MQTT_port)
        if self._Device_Pcwu_Enabled:
            self.logger.info('Subscribed to: ' + self._Device_Pcwu_MqttTopic + '/Command')
            self.mqtt_client.subscribe(self._Device_Pcwu_MqttTopic + '/Command', qos=1)

        self.mqtt_client.loop_start()
    
    def on_mqtt_connect(self, client, userdata, flags, rc):
        self.logger.info("Connected to MQTT Broker with result code: {}".format(rc))
        self.mqtt_client.subscribe("HewaGate")  # Update this to your desired topic
        self.flag_connected_mqtt = 1
    
    def on_mqtt_disconnect(self, client, userdata, rc):
        self.logger.info("Disconnected from MQTT Broker with result code: {}".format(rc))
        self.flag_connected_mqtt = 0
    
    def on_message_serial(self, obj, h, sh, m):
        #self.logger.info(f'on_message_serial flag_connected_mqtt: {self.flag_connected_mqtt}')
        #self.logger.info('on_message_serial')
        #self.logger.info(f'MessageCache obj: {obj}')
        #self.logger.info(f'MessageCache h: {h}')
        #self.logger.info(f'MessageCache sh: {sh}')
        #self.logger.info(f'MessageCache m: {m}')
        try:    
            if self.flag_connected_mqtt != 1:
                self.logger.info('on_message_serial not connected to mqtt')
                return False
            
            global MessageCache
            topic = self._Device_Pcwu_MqttTopic
            if sh["FNC"] == 0x50:
                mp = obj.parseRegisters(sh["RestMessage"], sh["RegStart"], sh["RegLen"])        
                for item in mp.items():
                    if isinstance(item[1], dict): # skipping dictionaries (time program) 
                        continue
                    key = topic + '/' + str(item[0])
                    val = str(item[1])
                    if key not in self.MessageCache or self.MessageCache[key] != val:
                        self.MessageCache[key] = val
                        self.logger.info(key + " " + val)
                        self.mqtt_client.publish(key, val)
    
        except Exception as e:
            self.logger.info('Exception in on_message_serial: '+ str(e))
    
    def device_readregisters_enqueue(self):
        """Get device status every x seconds"""
        #self.logger.info('Get device status')
        #self.logger.info(f'device_readregisters_enqueue flag_connected_mqtt: {self.flag_connected_mqtt}')
        threading.Timer(self.get_status_interval, self.device_readregisters_enqueue).start()
        if self._Device_Pcwu_Enabled:        
            self.readPCWU()
            self.readPcwuConfig()

    def readPCWU(self):    
        #self.logger.info(f'readPCWU flag_connected_mqtt: {self.flag_connected_mqtt}')
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        #self.logger.info(f'readPCWU: {ser}')
        self.dev.readStatusRegisters(ser)    
        ser.close()   
    
    def readPcwuConfig(self):    
        #self.logger.info(f'readPcwuConfig flag_connected_mqtt: {self.flag_connected_mqtt}')
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        #self.logger.info(f'readPCWUConfig: {ser}')
        self.dev.readConfigRegisters(ser)
        ser.close()
    
    def writePcwuConfig(self, registerName, payload):    
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        self.logger.info(f'writePcwuConfig: {ser}')
        self.dev.write(ser, registerName, payload)
        ser.close()
    
    def printPcwuMqttTopics(self):        
        print('| Topic | Type | Description | ')
        print('| ----------------------- | ----------- | ---------------------------')
        dev = PCWU(conHardId, conSoftId, devHardId, devSoftId, on_message_serial)
        for k, v in dev.registers.items():
            if isinstance(v['name'] , list):
                for i in v['name']:
                    if i:
                        print('| ' + _Device_Pcwu_MqttTopic + '/' + str(i) + ' | ' + v['type'] + ' | ' + str(v.get('desc')))
            else:
                print('| ' +_Device_Pcwu_MqttTopic + '/' + str(v['name'])+ ' | ' + v['type'] + ' | ' + str(v.get('desc')))
            if k > dev.REG_CONFIG_START:          
                print('| ' + _Device_Pcwu_MqttTopic + '/Command/' + str(v['name']) + ' | ' + v.get('type') + ' | ' + str(v.get('desc')))



if __name__ == "__main__":
    # Create an instance of your AppDaemon app
    app = MyApp()
    # Initialize the configuration
    app.initConfiguration()
    # Start MQTT connection
    app.start_mqtt()
    # Add this line to log the MQTT status periodically (e.g., every 60 seconds)
    app.run_every(app.log_mqtt_status, datetime.datetime.now(), 20)
    # Run the AppDaemon app
    app.run()


Dan nog een aantal bestanden in de onderliggende folder hewalex_geco/

[Afbeelding]

__init__.py kan leeg blijven

crc.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


POLY = 0xD5
def crc8(buf):
    if len(buf) == 0:
        return 0

    accum = 0
    for i in buf:
        accum = accum ^ i
        for _ in range(8):
            if accum & 0x80:
                accum = (((accum << 1) & 0xff) ^ POLY) & 0xff
            else:
                accum = (accum << 1) & 0xff

    return accum

POLY16 = 0x1021
def crc16(buf):
    if len(buf) == 0:
        return 0

    accum = 0
    for i in buf:
        accum = accum ^ (i << 8)
        for _ in range(8):
            if accum & 0x8000:
                accum = (((accum << 1) & 0xffff) ^ POLY16) & 0xffff
            else:
                accum = (accum << 1) & 0xffff

    return accum


requirements.txt

code:
1
pyserial


Dan nog wat bestanden in de folder Devices:

[Afbeelding]

__init__.py

code:
1
2
from .pcwu import PCWU
from .zps import ZPS


base.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
from binascii import hexlify, unhexlify
import logging

from ..crc import *

# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


class BaseDevice:
    def __init__(self, conHardId, conSoftId, devHardId, devSoftId, onMessage=None):
        self.logger = logging.getLogger(__name__)
        self.conHardId = conHardId  # G-426 controller - physical address
        self.conSoftId = conSoftId  # G-426 controller - logical address
        self.devHardId = devHardId  # Hewalex device - physical address
        self.devSoftId = devSoftId  # Hewalex device - logical address
        self.onMessage = onMessage  # Callback - onMessage(obj, h, sh, m)

    def parseHardHeader(self, m):
        if len(m) < 8:
            raise Exception("Too short message")
        calcCrc = crc8(m[:7])
        return {
            "StartByte": m[0],
            "To": m[1],
            "From": m[2],
            "ConstBytes": (m[5] << 16) | (m[4] << 8) | m[3],
            "Payload": m[6],
            "CRC8": m[7],
            "CalcCRC8": calcCrc
        }

    def validateHardHeader(self, h):
        if h["StartByte"] != 0x69:
            raise Exception("Invalid Start Byte")
        if h["CRC8"] != h["CalcCRC8"]:
            raise Exception("Invalid Hard CRC8")
        if h["ConstBytes"] != 0x84:
            raise Exception("Invalid Const Bytes")
        if h["From"] != self.conHardId and h["From"] != self.devHardId:
            raise Exception("Invalid From Hard Address: " + str(h["From"]))
        if h["To"] != self.conHardId and h["To"] != self.devHardId:
            raise Exception("Invalid To Hard Address: " + str(h["To"]))
        if h["To"] == h["From"]:
            raise Exception("From and To Hard Address Equal")

    def getWord(self, w):
        return (w[1] << 8) | w[0]

    def getWordReverse(self, w):
        return (w[0] << 8) | w[1]

    def getDWord(self, w):
        return (w[3] << 24) | (w[2] << 16) | (w[1] << 8) | w[0]

    def parseSoftHeader(self, h, m):
        if len(m) != h["Payload"]:
            raise Exception("Invalid soft message len")
        if len(m) < 12:
            raise Exception("Too short soft message")
        calcCrc = crc16(m[:h["Payload"]-2])
        return {
            "To": self.getWord(m[0:]),
            "From": self.getWord(m[2:]),
            "FNC": m[4],
            "ConstByte": self.getWord(m[5:]),
            "RegLen": m[7],
            "RegStart": self.getWord(m[8:]),
            "RestMessage": m[10:h["Payload"]-2],
            "CRC16": self.getWordReverse(m[h["Payload"]-2:]),
            "CalcCRC16": calcCrc
        }

    def validateSoftHeader(self, h, sh):
        if sh["CRC16"] != sh["CalcCRC16"]:
            raise Exception("Invalid Soft CRC16")
        if sh["ConstByte"] != 0x80:
            raise Exception("Invalid Const Soft Byte 0x80")
        if (h["From"] == self.conHardId and sh["From"] != self.conSoftId) or (h["From"] == self.devHardId and sh["From"] != self.devSoftId):
            raise Exception("Invalid From Address")
        if (h["To"] == self.conHardId and sh["To"] != self.conSoftId) or (h["To"] == self.devHardId and sh["To"] != self.devSoftId):
            raise Exception("Invalid To Address")

    def getTemp(self, w, divisor):
        w = self.getWord(w)
        if w & 0x8000:
            w = w - 0x10000
        return w / divisor

    def parseBitMask(self, val, names, ret):
        for name in names:
            if name is not None:
                ret[name] = bool(val & 1)
            val = val >> 1

    def parseRegisters(self, m, regstart, reglen, unknown=False):
        ret = {}

        skip = 0
        for regnum in range(regstart, regstart + reglen, 2):
            if skip > 0:
                skip = skip - 1
                continue
            reg = self.registers.get(regnum, None)
            adr = regnum - regstart
            if reg:
                val = None
                if reg['type'] == 'date':
                    val = "20{:02d}-{:02d}-{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'time':
                    val = "{:02d}:{:02d}:{:02d}".format(m[adr], m[adr+1], m[adr+2])
                    skip = 1
                elif reg['type'] == 'word':
                    val = self.getWord(m[adr:])
                elif reg['type'] == 'rwrd':
                    val = self.getWordReverse(m[adr:])
                elif reg['type'] == 'dwrd':
                    val = self.getDWord(m[adr:])
                    skip = 1
                elif reg['type'] == 'temp':
                    val = self.getTemp(m[adr:], 1.0)
                elif reg['type'] == 'te10':
                    val = self.getTemp(m[adr:], 10.0)
                elif reg['type'] == 'fl10':
                    val = self.getWord(m[adr:]) / 10.0
                elif reg['type'] == 'f100':
                    val = self.getWord(m[adr:]) / 100.0
                elif reg['type'] == 'bool':
                    val = bool(self.getWord(m[adr:]))
                elif reg['type'] == 'mask':
                    self.parseBitMask(self.getWord(m[adr:]), reg['name'], ret)
                    continue
                elif reg['type'] == 'tprg':
                    val = {}
                    self.parseBitMask(self.getDWord(m[adr:]), range(0, 24), val)
                    skip = 1
                ret[reg['name']] = val
            elif unknown:
                ret["Reg%d" % regnum] = self.getWord(m[adr:])

        return ret

    def printMessage(self, h, sh):
        print ({
            'hard': {
                "StartByte": hex(h["StartByte"]),
                "To": h["To"],
                "From": h["From"],
                "ConstBytes": hex(h["ConstBytes"]),
                "Payload": h["Payload"],
                "CRC8": hex(h["CRC8"])
            },
            'soft': {
                "To": sh["To"],
                "From": sh["From"],
                "FNC": hex(sh["FNC"]),
                "ConstByte": hex(sh["ConstByte"]),
                "RegLen": sh["RegLen"],
                "RegStart": str(sh["RegStart"]) + " (" + hex(sh["RegStart"]) + ")",
                "RestMessage": hexlify(sh["RestMessage"]),
                "CRC16": hex(sh["CRC16"])
            }
        })

    def processMessage(self, m, ignoreTooShort):
        h = self.parseHardHeader(m)
        self.validateHardHeader(h)
        ml = h["Payload"]
        if ignoreTooShort and ml + 8 > len(m):
            return m
        sh = self.parseSoftHeader(h, m[8:ml+8])
        self.validateSoftHeader(h, sh)
        if self.onMessage:
            self.onMessage(self, h, sh, m)
        return m[ml+8:]

    def processAllMessages(self, m, returnRemainingBytes=False):
        minLen = 8 if returnRemainingBytes else 0
        prevLen = len(m)
        while prevLen > minLen:
            m = self.processMessage(m, returnRemainingBytes)
            if len(m) == prevLen:
                if returnRemainingBytes:
                    return m
                else:
                    raise Exception("Something wrong")
            prevLen = len(m)
        return m

    # Process all messages in X cycles of device to controller comms
    #
    # 1. The device sends a query to the controller to read 20 registers starting from address 100.
    # 2. The controller responds, it always seems to be the same. It's hard to say if there is a controller model or a serial number.
    # 3. The device sends a record of registers starting at address 120. This is the main message, there are temperatures there. After this message there is a long pause (which is quite a large part of the 140ms for a series of messages), probably the controller is not too fast to write it to memory and it takes longer. The exact number of records depends on the model and firmware of the device.
    # 4. The controller replies with the standard message 0x70 that the bytes have been written successfully.
    # 5. The device requests to read 4 bytes starting from address 252.
    # 6. The controller responds and returns 4 bytes. By default they are: 10000000 and they mean that the controller is working normally, there are no changes. The value 08000000 means that the controller is turned off. However, the value 11000000 means that the user has changed a parameter in the menu, at this point the communication scheme is different, described in the docs.
    #
    def eavesDrop(self, ser, numCycles=None):
        # window size and time (based on 140ms cycle and 360ms wait)
        winSize = 1000
        winTime = 0.4

        # determine start of cycle marker to look for
        # (device requesting to read 20 registers from address 100)
        s1 = unhexlify('69%02x%02x8400000c' % (self.devHardId, self.conHardId))
        s2 = unhexlify('%02x' % crc8(s1))
        s3 = unhexlify('%02x%02x%02x%02x' % (
            (self.devSoftId & 0xff),
            (self.devSoftId & 0xff00) >> 8,
            (self.conSoftId & 0xff),
            (self.conSoftId & 0xff00) >> 8,
        ))
        s4 = unhexlify('408000146400')
        s = s1 + s2 + s3 + s4

        ser.flushInput()
        cnt = 0
        while (numCycles is None) or (cnt < numCycles):
            cnt += 1

            # read until first char after start marker
            ser.timeout = 1
            m = ser.read_until(s, winSize)

            # read the rest within window
            ser.timeout = winTime
            m = ser.read(winSize)

            # process
            self.processAllMessages(s + m)

    def createReadRegistersMessage(self, start, num):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x40, 0x80, 0, num & 0xff, start & 0xff, (start >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def createWriteRegisterMessage(self, reg, val):
        header = [0x69, self.devHardId, self.conHardId, 0x84, 0, 0]
        payload = [(self.devSoftId & 0xff), ((self.devSoftId >> 8) & 0xff), (self.conSoftId & 0xff), ((self.conSoftId >> 8) & 0xff), 0x60, 0x80, 0, 2, reg & 0xff, (reg >> 8) & 0xff, val & 0xff, (val >> 8) & 0xff]
        calcCrc16 = crc16(payload)
        payload.append((calcCrc16 >> 8) & 0xff)
        payload.append(calcCrc16 & 0xff)
        header.append(len(payload))
        calcCrc8 = crc8(header)
        header.append(calcCrc8)
        return bytearray(header + payload)

    def readRegisters(self, ser, start, num):
        m = self.createReadRegistersMessage(start, num)
        self.logger.debug(f'Sending message to the heat pump: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def readStatusRegisters(self, ser):
        self.logger.info('readStatusRegisters')
        start = self.REG_STATUS_START
        return self.readRegisters(ser, start, self.REG_CONFIG_START - start)

    def readConfigRegisters(self, ser):
        start = self.REG_CONFIG_START
        while start < self.REG_MAX_ADR:
            num = min(self.REG_MAX_ADR + 2 - start, self.REG_MAX_NUM)
            self.readRegisters(ser, start, num)
            start = start + num

    def writeRegister(self, ser, reg, val):
        m = self.createWriteRegisterMessage(reg, val)
        self.logger.debug(f'Sending message to the heat pump writeRegister: {m}')
        ser.flushInput()
        ser.timeout = 0.4
        ser.write(m)
        r = ser.read(1000)
        return self.processAllMessages(r)

    def write(self, ser, registername, val):
        regnum = 0        
        # look for register based on name        
        for k, v in self.registers.items():
            if v['name'] == registername:
                regnum = k
                break      
        reg = self.registers.get(regnum, None)
        if reg:
            val = self.parseRegisterValue(reg, val)
            if val is not None:
                #print('self.writeRegister(ser, ' + str(regnum) + ', '+ str(val) + ')')
                return self.writeRegister(ser, regnum, val)
        return None
        
    def parseRegisterValue(self, reg, val):
        if val:                
            if reg['type'] == 'date':
                val = None
            elif reg['type'] == 'time':
                val = None
            elif reg['type'] == 'word':
                val = int(val)
            elif reg['type'] == 'rwrd':
                val = int(val)
            elif reg['type'] == 'dwrd':
                val = int(val)
            elif reg['type'] == 'temp':
                val = int(val)
            elif reg['type'] == 'te10':
                val = int(val) * 10
            elif reg['type'] == 'fl10':
                val = float(val) * 10
            elif reg['type'] == 'f100':
                val = float(val) * 100
            elif reg['type'] == 'bool':
                if val == 'True' or val == '1':
                    val = 1
                elif val == 'False' or val == '0':
                    val = 0
            elif reg['type'] == 'mask':
                val = None
            elif reg['type'] == 'tprg':
                val = None
            if reg['options'] and val not in reg['options']:
                print ('invalid option ' + str(val))
                val = None
            return val

# Interface to implement in child classes
#########################################

    # Registers are divided in read-only status registers and read/write config registers

    # The lowest readable register always seems to be 100
    REG_MIN_ADR = 100

    # The highest readable register varies per device
    REG_MAX_ADR = 536 #None

    # The number of registers which can be read in one message varies per device
    REG_MAX_NUM = 100 #None

    # Status registers start at 120 usually
    REG_STATUS_START = 120

    # The number of statusregisters which can be read in one message varies per device
    REG_STATUS_NUM = 104

    # Config registers start at a register which varies per device
    REG_CONFIG_START = 302 #None

    registers = {
#
#        # Status registers
#        120: { 'type': 'date', 'name': 'date' },                        # Date
#        124: { 'type': 'time', 'name': 'time' },                        # Time
#        128: { 'type': 'te10', 'name': 'T1' },                          # T1
#        130: { 'type': 'te10', 'name': 'T2' },                          # T2
#        132: { 'type': 'te10', 'name': 'T3' },                          # T3
#        ...
#
#        # Config registers
#        XXX: { 'type': 'word', 'name': 'InstallationScheme' },          # Installation Scheme
#        ...
#
    }


pcwu.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from .base import BaseDevice

# Based on work by krzysztof1111111111
# https://www.elektroda.pl/rtvforum/topic3499254.html


class PCWU(BaseDevice):

    # PCWU is driven by PG-426-P01 (controller) and MG-426-P01 (executive module)
    # Below are the registers for the executive module, so no controller settings
    REG_MAX_ADR = 536
    REG_MAX_NUM = 100
    REG_CONFIG_START = 302
    REG_STATUS_NUM = 104

    # Interaction between status register 202 and config register 304:
    #
    # When talking to the executive module directly the heat pump can be (manually)
    # disabled and enabled through config register 304 and the result of this is visible
    # in status register 202. With the controller on this works as expected, the heat
    # pump can be put into a waiting mode where it will not turn on until enabled again
    # through register 304. With the controller off however this doesn't work. Maybe
    # the executive module is hardcoded to not turn the heat pump on when the controller
    # is off? See eavesDrop function in base device to learn how the executive module
    # knows that the controller is off. What makes this especially weird is that register
    # 202 changes its value to 0 when the controller is off even if register 304 says
    # otherwise. It would be great if we could detect the 'controller is off' situation
    # through one of the registers, but I haven't found a way yet.

    registers = {

        # Status registers
        120: { 'type': 'date', 'name': 'date', 'desc': 'Date' },                      
        124: { 'type': 'time', 'name': 'time', 'desc': 'Time' },                     
        128: { 'type': 'te10', 'name': 'T1', 'desc': 'T1 (Ambient temp)' },                        
        130: { 'type': 'te10', 'name': 'T2', 'desc': 'T2 (Tank bottom temp)' },                         
        132: { 'type': 'te10', 'name': 'T3', 'desc': 'T3 (Tank top temp)' },                        
        138: { 'type': 'te10', 'name': 'T6', 'desc': 'T6 (HP water inlet temp)' },                         
        140: { 'type': 'te10', 'name': 'T7', 'desc': 'T7 (HP water outlet temp)' },                         
        142: { 'type': 'te10', 'name': 'T8', 'desc': 'T8 (HP evaporator temp)' },                          
        144: { 'type': 'te10', 'name': 'T9', 'desc': 'T9 (HP before compressor temp)' },                          
        146: { 'type': 'te10', 'name': 'T10', 'desc': 'T10 (HP after compressor temp)' },                         

        194: { 'type': 'bool', 'name': 'IsManual' },
        196: { 'type': 'mask', 'name': [
            'FanON',                                                    # Fan ON (True/False)
            None,
            'CirculationPumpON',                                        # Circulation pump ON (True/False)
            None,
            None,
            'HeatPumpON',                                               # Heat pump ON (True/False)
            None,
            None,
            None,
            None,
            None,
            'CompressorON',                                             # Compressor ON (True/False)
            'HeaterEON',                                                # Heater E ON (True/False)
        ]},
        198: { 'type': 'word', 'name': 'EV1', 'desc': 'Expansion valve' },
        202: { 'type': 'word', 'name': 'WaitingStatus', 'desc': ' 0 when available for operation, 2 when disabled through register 304' },               #

        # Config registers
        302: { 'type': 'word', 'name': 'InstallationScheme', 'options': [1,2,3,4,5,6,7,8,9], 'desc': 'Installation Scheme (1-9)' },
        304: { 'type': 'bool', 'name': 'HeatPumpEnabled', 'options': [0,1], 'desc': 'Heat Pump Enabled (True/False)'},
        306: { 'type': 'word', 'name': 'TapWaterSensor', 'options': [0,1,2], 'desc': 'Temp. sensor controlling heat pump operation [T2,T3,T7, factory setting T2]' },                                  #
        308: { 'type': 'te10', 'name': 'TapWaterTemp', 'options':  [100,110,112,130,140,150,160,170,180,190,    #
                                                                    200,210,220,230,240,250,260,270,280,290,
                                                                    300,310,320,330,340,350,360,370,380,390,
                                                                    400,410,420,430,440,450,460,470,480,490,
                                                                    500,510,520,530,540,550,560,570,580,590,
                                                                    600] , 'desc': 'HUW temperature for heat pump [10-60°C, factory setting 50°C]'},                                 
        310: { 'type': 'te10', 'name': 'TapWaterHysteresis', 'options': [20,30,40,50,60,70,80,90,100] , 'desc': 'Heat pump start-up hysteresis [2-10°C, factory setting 5°C]'},        # 
        312: { 'type': 'te10', 'name': 'AmbientMinTemp', 'options': [-100,-90,-80,-70,-60,-50,-40,-30,-20,-10,  # 
                                                                     10,20,30,40,50,60,70,80,90,100] , 'desc': 'Minimum ambient temperature (T1) [-10-10°C] ' },                                                
        314: { 'type': 'tprg', 'name': 'TimeProgramHPM-F', 'desc': 'Time Program HP M-F (True/False per hour of the day)' },                                                    # 
        318: { 'type': 'tprg', 'name': 'TimeProgramHPSat', 'desc': 'Time Program HP Sat (True/False per hour of the day)' },                                                    # 
        322: { 'type': 'tprg', 'name': 'TimeProgramHPSun', 'desc': 'Time Program HP Sun (True/False per hour of the day)' },                                                    # 

        326: { 'type': 'bool', 'name': 'AntiFreezingEnabled', 'options': [0,1], 'desc': 'Function protecting against freezing [YES/NO], factory setting YES' },                               # 
        328: { 'type': 'word', 'name': 'WaterPumpOperationMode', 'options': [0,1], 'desc': 'Water Pump Operation Mode (0=Continuous, 1=Synchronous)' },                            # 
        330: { 'type': 'word', 'name': 'FanOperationMode', 'options': [0,1,2], 'desc': 'Fan Operation Mode (0=Max, 1=Min, 2=Day/Night), factory MAX' },                                # 
        332: { 'type': 'word', 'name': 'DefrostingInterval', 'desc': 'Defrosting cycle start-up delay [30-90 min., factory setting 45 min.]' },                                                  # 
        334: { 'type': 'te10', 'name': 'DefrostingStartTemp', 'desc': 'Temperature activating defrosting [-30 - 0°C, factory setting -7°C]' },                                                 # 
        336: { 'type': 'te10', 'name': 'DefrostingStopTemp', 'desc': 'Temperature finishing defrosting [2-30°C, factory setting 13°C]' }, 
        338: { 'type': 'word', 'name': 'DefrostingMaxTime', 'desc': 'Maximum defrosting duration [1-12 min., factory setting 8 min.]' },

        #374                                                            # Time Program? Heat pump
        #406                                                            # Time Program? Heater E
        #432                                                            # Time Program? Circulating pump [shown in diagrams no. 2,3,4,6,7,8,9]
        #476                                                            # Time Program? Gas-fired boiler D [shown in diagrams no. 4,7,9]

        #???                                                            # Anti-Legionella [shown in diagrams no. 3-9]
        #???                                                            # Anti-Legionella function activation [YES/NO, factory setting YES]
        #???                                                            # Protection carried out by heater E [YES/NO, factory setting YES]
        #???                                                            # Protection carried out by heater P [YES/NO, factory setting YES]
        #???                                                            # Protection carried out by gas-fired boiler [YES/NO, factory setting YES, shown in diagrams no. 4,7,9]

        516: { 'type': 'bool', 'name': 'ExtControllerHPOFF', 'desc': 'Heat pump deactivation [YES/NO, factory setting YES]' },          
        #518                                                            # ?? Electric heater E deactivation [YES/NO, factory setting YES]
        #520                                                            # ?? Electric heater P deactivation [YES/NO, factory setting YES]
        #522                                                            # ?? Gas-fired boiler shutdown [YES/NO, factory setting YES, shown in diagrams no. 4,7,9]
        #524                                                            # ?? Shutdown of pump F for solid fuel fired boiler B [YES/NO, factory setting YES, shown in diagrams no. 3,8,9]

    }

    def disable(self, ser):
        return self.writeRegister(ser, 304, 0)

    def enable(self, ser):
        return self.writeRegister(ser, 304, 1)


zps.py:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from .base import BaseDevice

# Based on work by aelias-eu
# https://github.com/aelias-eu/hewalex-geco-protocol


class ZPS(BaseDevice):

    # ZPS is driven by G-422-P09 (controller)
    # Below are the registers for the controller, so including controller settings
    REG_MAX_ADR = 330
    REG_MAX_NUM = 76
    REG_CONFIG_START = 170

    registers = {

        # Status registers
        120: { 'type': 'date', 'name': 'date', 'desc': 'Date'},
        124: { 'type': 'time', 'name': 'time', 'desc': 'Time'},
        128: { 'type': 'temp', 'name': 'T1', 'desc': 'T1 (Collectors temp)'},
        130: { 'type': 'temp', 'name': 'T2', 'desc': 'T2 (Tank bottom temp)'},
        132: { 'type': 'temp', 'name': 'T3', 'desc': 'T3 (Air separator temp)'},
        134: { 'type': 'temp', 'name': 'T4', 'desc': 'T4 (Tank top temp)'},
        136: { 'type': 'temp', 'name': 'T5', 'desc': 'T5 (Boiler outlet temp)'},
        138: { 'type': 'temp', 'name': 'T6', 'desc': 'T6'},
        144: { 'type': 'word', 'name': 'CollectorPower', 'desc': 'Collector Power (W)'},
        148: { 'type': 'fl10', 'name': 'Consumption', 'desc': 'Consumption (W)'},
        150: { 'type': 'bool', 'name': 'CollectorActive', 'desc': 'Collector Active (True/False)'},
        152: { 'type': 'fl10', 'name': 'FlowRate', 'desc': 'Flow Rate (l/min)'},
        154: { 'type': 'mask', 'name': [
            'CollectorPumpON',                                          # Collector Pump (P) ON (True/False)
            None,                                                       # Boiler Pump (K) ON?
            'CirculationPumpON',                                        # Circulation Pump (C) ON (True/False)
        ]},
        156: { 'type': 'word', 'name': 'CollectorPumpSpeed', 'desc': 'Collector Pump Speed (0-15)'},
        166: { 'type': 'fl10', 'name': 'TotalEnergy', 'desc': 'Total Energy (kWh)'},

        # Config registers
        170: { 'type': 'word', 'name': 'InstallationScheme', 'desc': 'Installation Scheme (1-19)'},
        172: { 'type': 'word', 'name': 'DisplayTimeout', 'desc': 'Display Timeout (1-10 min)'},
        174: { 'type': 'word', 'name': 'DisplayBrightness', 'desc': 'Display Brightness (1-10)'},
        176: { 'type': 'bool', 'name': 'AlarmSoundEnabled', 'desc': 'Alarm Sound Enabled (True/False)'},
        178: { 'type': 'bool', 'name': 'KeySoundEnabled', 'desc': 'Key Sound Enabled (True/False)'},
        180: { 'type': 'word', 'name': 'DisplayLanguage', 'desc': 'Display Language (0=PL, 1=EN, 2=DE, 3=FR, 4=PT, 5=ES, 6=NL, 7=IT, 8=CZ, 9=SL, ...)'},
        182: { 'type': 'temp', 'name': 'FluidFreezingTemp', 'desc': 'Fluid Freezing Temp'},
        186: { 'type': 'fl10', 'name': 'FlowRateNominal', 'desc': 'Flow Rate Nominal (l/min)'},
        188: { 'type': 'word', 'name': 'FlowRateMeasurement', 'desc': 'Flow Rate Measurement (0=Rotameter, 1=Electronic G916, 2=Electronic)'},
        190: { 'type': 'f100', 'name': 'FlowRateWeight', 'desc': 'Flow Rate Weight (imp/l)'},
        192: { 'type': 'bool', 'name': 'HolidayEnabled', 'desc': 'Holiday Enabled (True/False)'},
        194: { 'type': 'word', 'name': 'HolidayStartDay', 'desc': 'Holiday Start Day'},
        196: { 'type': 'word', 'name': 'HolidayStartMonth', 'desc': 'Holiday Start Month'},
        198: { 'type': 'word', 'name': 'HolidayStartYear', 'desc': 'Holiday Start Year'},
        200: { 'type': 'word', 'name': 'HolidayEndDay', 'desc': 'Holiday End Day'},
        202: { 'type': 'word', 'name': 'HolidayEndMonth', 'desc': 'Holiday End Month'},
        204: { 'type': 'word', 'name': 'HolidayEndYear', 'desc': 'Holiday End Year'},
        206: { 'type': 'word', 'name': 'CollectorType', 'desc': 'Collector Type (0=Flat, 1=Tube)'},
        208: { 'type': 'temp', 'name': 'CollectorPumpHysteresis', 'desc': 'Collector Pump Hysteresis (Difference between T1 and T2 to turn on collector pump)'},
        210: { 'type': 'temp', 'name': 'ExtraPumpHysteresis', 'desc': 'Extra Pump Hysteresis (Temp difference to turn on extra pump)'},
        212: { 'type': 'temp', 'name': 'CollectorPumpMaxTemp', 'desc': 'Collector Pump Max Temp (Maximum T2 temp to turn off collector pump)'},
        214: { 'type': 'word', 'name': 'BoilerPumpMinTemp', 'desc': 'Boiler Pump Min Temp (Minimum T5 temp to turn on boiler pump)'},
        218: { 'type': 'word', 'name': 'HeatSourceMaxTemp', 'desc': 'Heat Source Max Temp (Maximum T4 temp to turn off heat sources)'},
        220: { 'type': 'word', 'name': 'BoilerPumpMaxTemp', 'desc': 'Boiler Pump Max Temp (Maximum T4 temp to turn off boiler pump)'},
        222: { 'type': 'bool', 'name': 'PumpRegulationEnabled', 'desc': 'Pump Regulation Enabled (True/False)'},
        226: { 'type': 'word', 'name': 'HeatSourceMaxCollectorPower', 'desc': 'Heat Source Max Collector Power (Maximum collector power to turn off heat sources) (100-9900W)'},
        228: { 'type': 'bool', 'name': 'CollectorOverheatProtEnabled', 'desc': 'Collector Overheat Protection Enabled (True/False)'},
        230: { 'type': 'temp', 'name': 'CollectorOverheatProtMaxTemp', 'desc': 'Collector Overheat Protection Max Temp (Maximum T2 temp for overheat protection)'},
        232: { 'type': 'bool', 'name': 'CollectorFreezingProtEnabled', 'desc': 'Collector Freezing Protection Enabled (True/False)'},
        234: { 'type': 'word', 'name': 'HeatingPriority', 'desc': 'Heating Priority'},
        236: { 'type': 'bool', 'name': 'LegionellaProtEnabled', 'desc': 'Legionella Protection Enabled (True/False)'},
        238: { 'type': 'bool', 'name': 'LockBoilerKWithBoilerC', 'desc': 'Lock Boiler K With Boiler C (True/False)'},
        240: { 'type': 'bool', 'name': 'NightCoolingEnabled', 'desc': 'Night Cooling Enabled (True/False)'},
        242: { 'type': 'temp', 'name': 'NightCoolingStartTemp', 'desc': 'Night Cooling Start Temp'},
        244: { 'type': 'temp', 'name': 'NightCoolingStopTemp', 'desc': 'Night Cooling Stop Temp'},
        246: { 'type': 'word', 'name': 'NightCoolingStopTime', 'desc': 'Night Cooling Stop Time (hr)'},
        248: { 'type': 'tprg', 'name': 'TimeProgramCM-F', 'desc': 'Time Program C M-F (True/False per hour of the day)'},
        252: { 'type': 'tprg', 'name': 'TimeProgramCSat', 'desc': 'Time Program C Sat (True/False per hour of the day)'},
        256: { 'type': 'tprg', 'name': 'TimeProgramCSun', 'desc': 'Time Program C Sun (True/False per hour of the day)'},
        260: { 'type': 'tprg', 'name': 'TimeProgramKM-F', 'desc': 'Time Program K M-F (True/False per hour of the day)'},
        264: { 'type': 'tprg', 'name': 'TimeProgramKSat', 'desc': 'Time Program K Sat (True/False per hour of the day)'},
        268: { 'type': 'tprg', 'name': 'TimeProgramKSun', 'desc': 'Time Program K Sun (True/False per hour of the day)'},
        278: { 'type': 'word', 'name': 'CollectorPumpMinRev', 'desc': 'Collector Pump Min Rev (rev/min)'},
        280: { 'type': 'word', 'name': 'CollectorPumpMaxRev', 'desc': 'Collector Pump Max Rev (rev/min)'},
        282: { 'type': 'word', 'name': 'CollectorPumpMinIncTime', 'desc': 'Collector Pump Min Increase Time (s)'},
        284: { 'type': 'word', 'name': 'CollectorPumpMinDecTime', 'desc': 'Collector Pump Min Decrease Time (s)'},
        286: { 'type': 'word', 'name': 'CollectorPumpStartupSpeed', 'desc': 'Collector Pump Startup Speed (1-15)'},
        288: { 'type': 'bool', 'name': 'PressureSwitchEnabled', 'desc': 'Pressure Switch Enabled (True/False)'},
        290: { 'type': 'bool', 'name': 'TankOverheatProtEnabled', 'desc': 'Tank Overheat Protection Enabled (True/False)'},
        322: { 'type': 'bool', 'name': 'CirculationPumpEnabled', 'desc': 'Circulation Pump Enabled (True/False)'},
        324: { 'type': 'word', 'name': 'CirculationPumpMode', 'desc': 'Circulation Pump Mode (0=Discontinuous, 1=Continuous)'},
        326: { 'type': 'temp', 'name': 'CirculationPumpMinTemp', 'desc': 'Circulation Pump Min Temp (Minimum T4 temp to turn on circulation pump)'},
        328: { 'type': 'word', 'name': 'CirculationPumpONTime', 'desc': 'Circulation Pump ON Time (1-59 min)'},
        330: { 'type': 'word', 'name': 'CirculationPumpOFFTime', 'desc': 'Circulation Pump OFF Time (1-59 min)'},

        # Weird registers
        312: { 'type': 'dwrd', 'name': 'TotalOperationTime', 'desc': 'Total Operation Time (min) - lives in config space but is status register'},
        320: { 'type': 'word', 'name': 'Reg320', 'desc': 'Unknown register - value changes constantly'}
    }
Heel erg bedankt voor de info. Ik was al een beetje op weg. Van het weekend ga ik hiermee aan de slag. Ik dank dat ik hier wel uit kom.

Heel erg bedankt.

Acties:
  • 0 Henk 'm!

  • Woody130
  • Registratie: Augustus 2021
  • Laatst online: 16:45
huub66 schreef op maandag 14 augustus 2023 @ 11:41:
[...]


Ben op zoek naar hetzelfde @Emacee. Ik maak ook gebruik van het externe contact zoals @andre75 maar moet ook bij opstarten na stroomuitval toch de stand-by knop op het display indrukken om de w/p te activeren.

Wellicht dat de firmware versie verschil maakt? Bij mij geeft hij “PG-426-P05 version 01o” bij opstarten.
Is hier al eens iets uitgekomen? Of is de remedie om een tijdreleis aan de externe ingang te knopen. Dan zit je maximaal een dag zonder verwarming :)

Acties:
  • 0 Henk 'm!

  • Jan_De_Tuinman
  • Registratie: November 2011
  • Laatst online: 10-09 20:44
Jojan265 schreef op dinsdag 9 juli 2024 @ 20:24:
[...]

Zoals beloofd de antwoorden:
Gaaf! ik wil dit ook nog een keer voorelkaar gaan krijgen.

Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
Jojan265 schreef op dinsdag 9 juli 2024 @ 20:24:
[...]

Zoals beloofd de antwoorden:
Dank,
Ben er nu ook mee bezig, t werkt nog niet helemaal voor mij.
IIG heb in de AppDaemon configuration, bij Python packages "pyserial" toe moeten voegen:

Afbeeldingslocatie: https://tweakers.net/i/8WurE6WzmW5O976YcES8VXVJcrc=/800x/filters:strip_exif()/f/image/ojFgAQ4FYcyoIeeD6lRUSqVp.png?f=fotoalbum_large

S.J.


Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
Sterke-Jerke schreef op zondag 14 juli 2024 @ 12:58:
[...]


Dank,
Ben er nu ook mee bezig, t werkt nog niet helemaal voor mij.
IIG heb in de AppDaemon configuration, bij Python packages "pyserial" toe moeten voegen:

[Afbeelding]
Inderdaad. Dit heb ik nog vergeten als screenshot mee te nemen. Ik zal het topic hiermee aanvullen, zodat anderen hier ook baat bij hebben.

Helaas gaat dat niet meer......

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
Jojan265 schreef op zondag 14 juli 2024 @ 13:29:
[...]

Inderdaad. Dit heb ik nog vergeten als screenshot mee te nemen. Ik zal het topic hiermee aanvullen, zodat anderen hier ook baat bij hebben.

Helaas gaat dat niet meer......
Nog 2 dingetjes, ik kreeg maar geen data binnen via de netwerk connectie.
Geen idee waarom, maar zal ooit wel een config aangepast hebben.
Ik moest:
code:
1
2
3
        # PCWU (Slave)
        devHardId = 3
        devSoftId = 3


Aanpassen naar
code:
1
2
3
        # PCWU (Slave)
        devHardId = 2
        devSoftId = 2


(Heeft me even wat tijd gekost)


En het klopt dat je code geen waarde's terugstuurt? Z nu en dan wil ik dmv HA de Hysteresis aanpassen, of de TapwaterTemp

[ Voor 8% gewijzigd door Sterke-Jerke op 14-07-2024 21:36 ]

S.J.


Acties:
  • 0 Henk 'm!

  • Erik_Rave
  • Registratie: Juni 2016
  • Laatst online: 27-04 19:20
Dag allemaal,

Onlangs attendeerde iemand mij op de Hewalex warmtepomp voor o.a. SWW.

Ikzelf ben niet bekend met met dit merk, en volgens mij meer mensen niet.

Ik zit met een aantal vragen die ik niet zo snel terug kan vinden in deze topic.

1. Hoe zit het met de betrouwbaarheid van dit product?
2. Ik wil het systeem puur voor SWW. Heeft iemand een dergelijke opstelling? Zonder collectoren etc. Hoe is dit aangesloten?
3. Kan ik het systeem in de toekomst uitbreiden door er vloerverwarming op aan te sluiten? Is een klein oppervlak.
4. Hoe efficient is een Hewalex in een SWW opstelling vergeleken met een warmtepompboiler (Auer Edel Air 270l bijvoorbeeld).
5. Welk soort, type of merk boilervat kan ik het beste gebruiken?

Hopelijk heeft iemand tijd en zin om mijn vragen (deels) te beantwoorden :)

Groetjes Erik!

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Ik wil @Jojan265 en @Sterke-Jerke heel erg bedanken voor de hulp. Het heeft wat uren gekost, maar het werkt. De Hewalex is nu geïntegreerd in Home assistant. De meeste entities zijn nu werkend.
De stappen van @Jojan265 goed gevolgd en met een paar aanpassingen is het gelukt. Bij mqtt in de hewalex2mqttcofig.ini file moest bij mqtt gebruikersnaam en wachtwoord ingevuld worden.

[ Voor 32% gewijzigd door andre75 op 19-07-2024 22:34 ]


Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op vrijdag 19 juli 2024 @ 22:07:
Ik wil @Jojan265 en @Sterke-Jerke heel erg bedanken voor de hulp. Het heeft wat uren gekost, maar het werkt. De Hewalex is nu geïntegreerd in Home assistant. De meeste entities zijn nu werkend.
De stappen van @Jojan265 goed gevolgd en met een paar aanpassingen is het gelukt. Bij mqtt in de hewalex2mqttcofig.ini file moest bij mqtt gebruikersnaam en wachtwoord ingevuld worden.
Mooi dat het gelukt is. Welke entities werken niet? Ik heb alle sensoren werkend:Afbeeldingslocatie: https://tweakers.net/i/5Nk8qaingjLLmGLNrttDl1CAamY=/800x/filters:strip_exif()/f/image/aWRDUHFylP4wvlqYojAhvY4W.png?f=fotoalbum_large

Bij mij werkt het aansturen echter nog niet. Nu ben ik dat ook niet echt nodig, maar als je dat wel voor elkaar kunt krijgen, hou ik me aanbevolen voor de oplossing. Al is het alleen maar om te weten waarom het bij mij niet werkt.

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op vrijdag 19 juli 2024 @ 22:40:
[...]

Mooi dat het gelukt is. Welke entities werken niet? Ik heb alle sensoren werkend:[Afbeelding]

Bij mij werkt het aansturen echter nog niet. Nu heb ik dat ook niet echt nodig, maar als je dat wel voor elkaar kunt krijgen, hou ik me aanbevolen voor de oplossing. Al is het alleen maar om te weten waarom het bij mij niet werkt.
Afbeeldingslocatie: https://tweakers.net/i/ZQfw-kcq52yVdBWgAGQnL4G9ZNQ=/800x/filters:strip_icc():strip_exif()/f/image/ymUfMB7HGtofQGSZy29j4a2U.jpg?f=fotoalbum_large

Het zijn eigenlijk de aanstuur enitities

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
Er staat een omschrijving in de PCWU.py file:
code:
1
        306: { 'type': 'word', 'name': 'TapWaterSensor', 'options': [0,1,2], 'desc': 'Temp. sensor controlling heat pump operation [T2,T3,T7, factory setting T2]' },                                  #

Dit is dus de sensor waarop gestart en gestopt wordt. Bij mij is dat T2. Aangezien dit een instelling is, welke ik niet snel zal veranderen heb ik hem niet meegenomen in de communicatie.

De TapwaterTemp geeft wel een vreemde waarde. Deze kan alleen maar tussen 10 en 60 zijn.

Als je AppDeamon een herstart geeft, kun je in de logfile van AppDeamon heel mooi zien welke waardes hij ophaalt bij opstart van de communicatie:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
2024-07-20 07:50:56,030 :: hewalex2mqtt :: INFO :: Heatpump/date 2024-07-20
2024-07-20 07:50:56,031 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m3), 'b'Heatpump/date'', ... (10 bytes)
2024-07-20 07:50:56,032 :: hewalex2mqtt :: INFO :: Heatpump/time 07:01:08
2024-07-20 07:50:56,032 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m4), 'b'Heatpump/time'', ... (8 bytes)
2024-07-20 07:50:56,032 :: hewalex2mqtt :: INFO :: Heatpump/T1 26.3
2024-07-20 07:50:56,032 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m5), 'b'Heatpump/T1'', ... (4 bytes)
2024-07-20 07:50:56,032 :: hewalex2mqtt :: INFO :: Heatpump/T2 53.4
2024-07-20 07:50:56,032 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m6), 'b'Heatpump/T2'', ... (4 bytes)
2024-07-20 07:50:56,033 :: hewalex2mqtt :: INFO :: Heatpump/T3 54.4
2024-07-20 07:50:56,033 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m7), 'b'Heatpump/T3'', ... (4 bytes)
2024-07-20 07:50:56,033 :: hewalex2mqtt :: INFO :: Heatpump/T6 26.3
2024-07-20 07:50:56,033 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m8), 'b'Heatpump/T6'', ... (4 bytes)
2024-07-20 07:50:56,033 :: hewalex2mqtt :: INFO :: Heatpump/T7 26.6
2024-07-20 07:50:56,034 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m9), 'b'Heatpump/T7'', ... (4 bytes)
2024-07-20 07:50:56,034 :: hewalex2mqtt :: INFO :: Heatpump/T8 25.1
2024-07-20 07:50:56,034 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m10), 'b'Heatpump/T8'', ... (4 bytes)
2024-07-20 07:50:56,034 :: hewalex2mqtt :: INFO :: Heatpump/T9 25.4
2024-07-20 07:50:56,034 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m11), 'b'Heatpump/T9'', ... (4 bytes)
2024-07-20 07:50:56,035 :: hewalex2mqtt :: INFO :: Heatpump/T10 25.5
2024-07-20 07:50:56,035 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m12), 'b'Heatpump/T10'', ... (4 bytes)
2024-07-20 07:50:56,035 :: hewalex2mqtt :: INFO :: Heatpump/IsManual True
2024-07-20 07:50:56,035 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m13), 'b'Heatpump/IsManual'', ... (4 bytes)
2024-07-20 07:50:56,035 :: hewalex2mqtt :: INFO :: Heatpump/FanON False
2024-07-20 07:50:56,036 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m14), 'b'Heatpump/FanON'', ... (5 bytes)
2024-07-20 07:50:56,036 :: hewalex2mqtt :: INFO :: Heatpump/CirculationPumpON False
2024-07-20 07:50:56,036 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m15), 'b'Heatpump/CirculationPumpON'', ... (5 bytes)
2024-07-20 07:50:56,037 :: hewalex2mqtt :: INFO :: Heatpump/HeatPumpON False
2024-07-20 07:50:56,037 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m16), 'b'Heatpump/HeatPumpON'', ... (5 bytes)
2024-07-20 07:50:56,037 :: hewalex2mqtt :: INFO :: Heatpump/CompressorON False
2024-07-20 07:50:56,037 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m17), 'b'Heatpump/CompressorON'', ... (5 bytes)
2024-07-20 07:50:56,038 :: hewalex2mqtt :: INFO :: Heatpump/HeaterEON False
2024-07-20 07:50:56,038 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m18), 'b'Heatpump/HeaterEON'', ... (5 bytes)
2024-07-20 07:50:56,038 :: hewalex2mqtt :: INFO :: Heatpump/EV1 173
2024-07-20 07:50:56,038 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m19), 'b'Heatpump/EV1'', ... (3 bytes)
2024-07-20 07:50:56,039 :: hewalex2mqtt :: INFO :: Heatpump/WaitingStatus 2
2024-07-20 07:50:56,039 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m20), 'b'Heatpump/WaitingStatus'', ... (1 bytes)
2024-07-20 07:50:56,747 :: hewalex2mqtt :: INFO :: Heatpump/InstallationScheme 1
2024-07-20 07:50:56,747 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m21), 'b'Heatpump/InstallationScheme'', ... (1 bytes)
2024-07-20 07:50:56,748 :: hewalex2mqtt :: INFO :: Heatpump/HeatPumpEnabled True
2024-07-20 07:50:56,748 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m22), 'b'Heatpump/HeatPumpEnabled'', ... (4 bytes)
2024-07-20 07:50:56,749 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterSensor 0
2024-07-20 07:50:56,750 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m23), 'b'Heatpump/TapWaterSensor'', ... (1 bytes)
2024-07-20 07:50:56,750 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterTemp 54.0
2024-07-20 07:50:56,750 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m24), 'b'Heatpump/TapWaterTemp'', ... (4 bytes)
2024-07-20 07:50:56,751 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterHysteresis 4.0
2024-07-20 07:50:56,751 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m25), 'b'Heatpump/TapWaterHysteresis'', ... (3 bytes)
2024-07-20 07:50:56,751 :: hewalex2mqtt :: INFO :: Heatpump/AmbientMinTemp 10.0
2024-07-20 07:50:56,751 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m26), 'b'Heatpump/AmbientMinTemp'', ... (4 bytes)
2024-07-20 07:50:56,752 :: hewalex2mqtt :: INFO :: Heatpump/AntiFreezingEnabled True
2024-07-20 07:50:56,752 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m27), 'b'Heatpump/AntiFreezingEnabled'', ... (4 bytes)
2024-07-20 07:50:56,752 :: hewalex2mqtt :: INFO :: Heatpump/WaterPumpOperationMode 1
2024-07-20 07:50:56,753 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m28), 'b'Heatpump/WaterPumpOperationMode'', ... (1 bytes)
2024-07-20 07:50:56,754 :: hewalex2mqtt :: INFO :: Heatpump/FanOperationMode 1
2024-07-20 07:50:56,754 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m29), 'b'Heatpump/FanOperationMode'', ... (1 bytes)
2024-07-20 07:50:56,755 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingInterval 45
2024-07-20 07:50:56,755 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m30), 'b'Heatpump/DefrostingInterval'', ... (2 bytes)
2024-07-20 07:50:56,755 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingStartTemp -7.0
2024-07-20 07:50:56,756 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m31), 'b'Heatpump/DefrostingStartTemp'', ... (4 bytes)
2024-07-20 07:50:56,756 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingStopTemp 13.0
2024-07-20 07:50:56,757 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m32), 'b'Heatpump/DefrostingStopTemp'', ... (4 bytes)
2024-07-20 07:50:56,757 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingMaxTime 8
2024-07-20 07:50:56,757 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m33), 'b'Heatpump/DefrostingMaxTime'', ... (1 bytes)
2024-07-20 07:50:57,562 :: hewalex2mqtt :: INFO :: Heatpump/ExtControllerHPOFF True
2024-07-20 07:50:57,562 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m34), 'b'Heatpump/ExtControllerHPOFF'', ... (4 bytes)
2024-07-20 07:50:57.865880 INFO AppDaemon: App initialization complete

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
Goed bezig allebei, heb wat aanpassingen gemaakt waardoor het aansturen ook werkt.
En nog wat extra debug info. Zodra het weer wart slechter wordt zal ik dat plaatsen.

S.J.


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
In Home Assistant heb ik een urenteller toegevoegd en een de aantal starts wordt geteld. Nu met de mqtt wordt de starts aangepast op de compressor. Het wordt nu gedaan op warmtevraag, wat op zich op werkt.
Ik heb ook een template gemaakt wat de COP uitgerekend.
@Jojan265 De TapwaterTemp geeft wel een vreemde waarde. Deze kan alleen maar tussen 10 en 60 zijn. Is dit niet het setpoint? Setpoint is instelbaar tussen de 10 en 60 graden.

[ Voor 37% gewijzigd door andre75 op 21-07-2024 15:41 ]


Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
andre75 schreef op zondag 21 juli 2024 @ 15:30:
In Home Assistant heb ik een urenteller toegevoegd en een de aantal starts wordt geteld. Nu met de mqtt wordt de starts aangepast op de compressor. Het wordt nu gedaan op warmtevraag, wat op zich op werkt.
Ik heb ook een template gemaakt wat de COP uitgerekend.
@Jojan265 De TapwaterTemp geeft wel een vreemde waarde. Deze kan alleen maar tussen 10 en 60 zijn. Is dit niet het setpoint? Setpoint is instelbaar tussen de 10 en 60 graden.
Is inderdaad het setpoint. Dus vandaar ook mijn opmerking over de vreemde waarde. 0.5 ligt namelijk niet tussen 10 en 60.

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
Sterke-Jerke schreef op zaterdag 20 juli 2024 @ 08:10:
Goed bezig allebei, heb wat aanpassingen gemaakt waardoor het aansturen ook werkt.
En nog wat extra debug info. Zodra het weer wart slechter wordt zal ik dat plaatsen.
Is het weer nu slecht genoeg?

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jojan265 schreef op vrijdag 23 augustus 2024 @ 13:51:
[...]

Is het weer nu slecht genoeg?
Top!! Laat maar weten als je nieuwe aanpassingen werkt. Ik kon vanaf 0 weer opnieuw beginnen. De Raspberry was gecrasht en nu overgestapt op een Mac mini server met een VMware virtual machine.

Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
Jojan265 schreef op vrijdag 23 augustus 2024 @ 13:51:
[...]

Is het weer nu slecht genoeg?
Zeker, maar ben op vakantie 8)

S.J.


Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
Dan hoop ik in ieder geval wel, dat je op je vakantiebestemming goed weer hebt.

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
Jojan265 schreef op zaterdag 24 augustus 2024 @ 19:32:
[...]

Dan hoop ik in ieder geval wel, dat je op je vakantiebestemming goed weer hebt.
Niet echt, even bezig geweest.

Het kan allemaal misschien wat netter, maar voorlopig is dit t.
ToDo:
- Op Github plaatsen https://github.com/HJKLMN/HomeAssistant-Hewalex2MQTT
- Gebruik gaan maken van een scheduler ipv "threading.Timer"
- Logging vebeteren met logniveaus
- Betere Error Handling en Recovery
- Iets meer info in de config bestanden (Hw ID)

In de loop van de week wil ik nog een tijd sync doen omdat mijn klolkje van de hewalex wel heel vaak misloopt.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
import appdaemon.plugins.hass.hassapi as hass
import os
import threading
import configparser
import serial
from hewalex_geco.devices import PCWU
import paho.mqtt.client as mqtt
import logging
import sys

# The class definition for the AppDaemon app
class Hewalex2MQTT(hass.Hass):
    # Declare dev as a class attribute
    dev = None

    # Your app initialization logic here
    def initialize(self):
        # polling interval
        self.get_status_interval = 30.0
        
        # Controller (Master)
        self.conHardId = 1
        self.conSoftId = 1
        
        # PCWU (Slave)
        self.devHardId = 2
        self.devSoftId = 2

        #mqtt
        self.flag_connected_mqtt = 0
        self.MessageCache = {}

        # Initialize the logger
        self.initLogger()

        # Initialize the configuration first
        self.initConfiguration()

        # Start MQTT connection
        self.start_mqtt()

        # Declare dev as a class attribute
        self.dev = PCWU(self.conHardId, self.conSoftId, self.devHardId, self.devSoftId, self.on_message_serial)

        # Call device_readregisters_enqueue to start the periodic task
        self.device_readregisters_enqueue()

    def initLogger(self):
        # Set up the logger
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s :: %(name)s :: %(levelname)s :: %(message)s')
        stream_handler = logging.StreamHandler(sys.stdout)
        stream_handler.setFormatter(formatter)
        stream_handler.setLevel(logging.DEBUG)
        self.logger.addHandler(stream_handler)
        self.logger.info("Initializing Hewalex 2 Mqtt")

    # Read Configs
    def initConfiguration(self):
        self.logger.info("reading config")
        config_file = os.path.join(os.path.dirname(__file__), 'hewalex2mqttconfig.ini')
        config = configparser.ConfigParser()
        config.read(config_file)
    
        # Mqtt
        self._MQTT_ip = config.get('MQTT', 'MQTT_ip')
        self._MQTT_port = config.getint('MQTT', 'MQTT_port')
        self._MQTT_authentication = config.getboolean('MQTT', 'MQTT_authentication')
        self._MQTT_user = config.get('MQTT', 'MQTT_user')
        self._MQTT_pass = config.get('MQTT', 'MQTT_pass')
        self.logger.info(f'MQTT ip: {self._MQTT_ip}')
        self.logger.info(f'MQTT port: {self._MQTT_port}')
        self.logger.info(f'MQTT authentication: {self._MQTT_authentication}')
        self.logger.info(f'MQTT user: {self._MQTT_user}')
        self.logger.info(f'MQTT pass: {self._MQTT_pass}')

        # PCWU Device
        self._Device_Pcwu_Enabled = config.getboolean('Pcwu', 'Device_Pcwu_Enabled')
        if self._Device_Pcwu_Enabled:
            self._Device_Pcwu_Address = config.get('Pcwu', 'Device_Pcwu_Address')
            self._Device_Pcwu_Port = config.getint('Pcwu', 'Device_Pcwu_Port')
            self._Device_Pcwu_MqttTopic = config.get('Pcwu', 'Device_Pcwu_MqttTopic')
            self.logger.info(f'Device_Pcwu_MqttTopic: {self._Device_Pcwu_MqttTopic}')
    
        # Use the values as needed in your app
        if self._Device_Pcwu_Enabled:
            # Create the serial connection with the correct baudrate
            # Do something with self._Device_Pcwu_Address, self._Device_Pcwu_Port, and self._Device_Pcwu_MqttTopic
            # For example, assign them to class attributes
            pass
        else:
            # Handle the case when Pcwu is not enabled
            pass

    def on_message_mqtt(self, client, userdata, message):
        self.logger.info("Received message with topic: {}".format(message.topic))
        self.logger.info("Received command: {}".format(message.payload.decode('utf-8')))

        # Verwerkt commando's bedoeld voor PCWU-apparaat
        if message.topic.startswith(f"{self._Device_Pcwu_MqttTopic}/Command/"):
            register_name = message.topic.split('/')[-1]  # Extract the register name from the topic
            command_value = message.payload.decode('utf-8')
            self.logger.info(f"Received command to set {register_name} to {command_value}")
            self.writePcwuConfig(register_name, command_value)
        else:
            # Handle other MQTT messages if needed
            self.logger.info("Received unrelated MQTT message, no action taken.")
        
    def writePcwuConfig(self, registerName, payload):
        # Log the attempt to write to the PCWU device
        self.logger.info(f"Attempting to write to register: {registerName} with value: {payload}")
        try:
        # Open the serial connection
            with serial.serial_for_url(f"socket://{self._Device_Pcwu_Address}:{self._Device_Pcwu_Port}") as ser:
                # Call the write function on the PCWU device
                result = self.dev.write(ser, registerName, payload)
                # Check if the write was successful
                if result:
                    self.logger.info(f"Successfully wrote {payload} to {registerName}")
                else:
                    self.logger.error(f"Failed to write {payload} to {registerName}")
        except Exception as e:
            self.logger.error(f"Error writing to PCWU: {e}")



    # Define flag_connected_mqtt as a global variable at the beginning of the script
    #flag_connected_mqtt = 0
    def log_mqtt_status(self, kwargs):
        if self.flag_connected_mqtt == 1:
            self.logger.info("MQTT Broker is connected.")
        else:
            self.logger.info("MQTT Broker is disconnected.")

    def start_mqtt(self):
        self.mqtt_client = mqtt.Client()
        if self._MQTT_authentication:
            self.mqtt_client.username_pw_set(username=self._MQTT_user, password=self._MQTT_pass)
            
        self.mqtt_client.on_connect = self.on_mqtt_connect
        self.mqtt_client.on_disconnect = self.on_mqtt_disconnect
        self.mqtt_client.on_message = self.on_message_mqtt
        self.mqtt_client.enable_logger(self.logger)
        self.mqtt_client.connect(self._MQTT_ip, self._MQTT_port)
        if self._Device_Pcwu_Enabled:
            self.logger.info('Subscribed to: ' + self._Device_Pcwu_MqttTopic + '/Command/#')
            self.mqtt_client.subscribe(self._Device_Pcwu_MqttTopic + '/Command/#', qos=1)

        self.mqtt_client.loop_start()
    
    def on_mqtt_connect(self, client, userdata, flags, rc):
        self.logger.info("Verbonden to MQTT Broker with result code: {}".format(rc))
        # Update dit om te abonneren op het correcte topic dat overeenkomt met je MQTT configuratie voor PCWU
        base_topic = f"{self._Device_Pcwu_MqttTopic}/#"  # Abonneer op alle subtopics onder je basis PCWU topic
        self.mqtt_client.subscribe(base_topic)
        self.logger.info(f"ABBOSubscribed to MQTT topic: {base_topic}")
        self.flag_connected_mqtt = 1
    
    def on_mqtt_disconnect(self, client, userdata, rc):
        self.logger.info("Disconnected from MQTT Broker with result code: {}".format(rc))
        self.flag_connected_mqtt = 0
    
    def on_message_serial(self, obj, h, sh, m):
        #self.logger.info(f'on_message_serial flag_connected_mqtt: {self.flag_connected_mqtt}')
        #self.logger.info('on_message_serial')
        #self.logger.info(f'MessageCache obj: {obj}')
        #self.logger.info(f'MessageCache h: {h}')
        #self.logger.info(f'MessageCache sh: {sh}')
        #self.logger.info(f'MessageCache m: {m}')
        try:    
            if self.flag_connected_mqtt != 1:
                self.logger.info('on_message_serial not connected to mqtt')
                return False
            
            global MessageCache
            topic = self._Device_Pcwu_MqttTopic
            if sh["FNC"] == 0x50:
                mp = obj.parseRegisters(sh["RestMessage"], sh["RegStart"], sh["RegLen"])        
                for item in mp.items():
                    if isinstance(item[1], dict): # skipping dictionaries (time program) 
                        continue
                    key = topic + '/' + str(item[0])
                    val = str(item[1])
                    if key not in self.MessageCache or self.MessageCache[key] != val:
                        self.MessageCache[key] = val
                        self.logger.info(key + " " + val)
                        self.mqtt_client.publish(key, val)
    
        except Exception as e:
            self.logger.info('Exception in on_message_serial: '+ str(e))
    
    def device_readregisters_enqueue(self):
        """Get device status every x seconds"""
        #self.logger.info('Get device status')
        #self.logger.info(f'device_readregisters_enqueue flag_connected_mqtt: {self.flag_connected_mqtt}')
        threading.Timer(self.get_status_interval, self.device_readregisters_enqueue).start()
        if self._Device_Pcwu_Enabled:        
            self.readPCWU()
            self.readPcwuConfig()

    def readPCWU(self):    
        # Controleer en log de waarden van de attributen
        self.logger.info(f"Connecting to PCWU at {self._Device_Pcwu_Address}:{self._Device_Pcwu_Port}")
        try:
            with serial.serial_for_url(f"socket://{self._Device_Pcwu_Address}:{self._Device_Pcwu_Port}") as ser:
                self.logger.info("Serial connection established.")
                self.dev = PCWU(self.conHardId, self.conSoftId, self.devHardId, self.devSoftId, self.on_message_serial)
                read_data = self.dev.readStatusRegisters(ser)
                # Log alleen of er data ontvangen is of niet, zonder de data zelf te tonen
                if read_data:
                    self.logger.info("Data successfully received from PCWU.")
                else:
                    self.logger.info("No data received from PCWU.")
        except Exception as e:
            self.logger.error(f"Error in readPCWU: {e}")

    
    def readPcwuConfig(self):    
        #self.logger.info(f'readPcwuConfig flag_connected_mqtt: {self.flag_connected_mqtt}')
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        #self.logger.info(f'readPCWUConfig: {ser}')
        self.dev.readConfigRegisters(ser)
        ser.close()
    
    def writePcwuConfig(self, registerName, payload):    
        ser = serial.serial_for_url("socket://%s:%s" % (self._Device_Pcwu_Address, self._Device_Pcwu_Port))
        self.logger.info(f'writePcwuConfig: {ser}')
        self.dev.write(ser, registerName, payload)
        ser.close()
    
    def printPcwuMqttTopics(self):        
        print('| Topic | Type | Description | ')
        print('| ----------------------- | ----------- | ---------------------------')
        dev = PCWU(self.conHardId, self.conSoftId, self.devHardId, self.devSoftId, on_message_serial)
        for k, v in dev.registers.items():
            if isinstance(v['name'] , list):
                for i in v['name']:
                    if i:
                        print('| ' + _Device_Pcwu_MqttTopic + '/' + str(i) + ' | ' + v['type'] + ' | ' + str(v.get('desc')))
            else:
                print('| ' +_Device_Pcwu_MqttTopic + '/' + str(v['name'])+ ' | ' + v['type'] + ' | ' + str(v.get('desc')))
            if k > dev.REG_CONFIG_START:          
                print('| ' + _Device_Pcwu_MqttTopic + '/Command/' + str(v['name']) + ' | ' + v.get('type') + ' | ' + str(v.get('desc')))



if __name__ == "__main__":
    # Create an instance of your AppDaemon app
    app = MyApp()
    # Initialize the configuration
    app.initConfiguration()
    # Start MQTT connection
    app.start_mqtt()
    # Add this line to log the MQTT status periodically (e.g., every 60 seconds)
    app.run_every(app.log_mqtt_status, datetime.datetime.now(), 20)
    # Run the AppDaemon app
    app.run()

S.J.


Acties:
  • 0 Henk 'm!

  • Jerra
  • Registratie: Oktober 2016
  • Laatst online: 20:36

Jerra

Beunhaas in wording

Dag allemaal,

Ook ik wil een Hewalex PCWU gaan inzetten om SWW te bereiden.
Hierbij ben ik in mijn oriëntatie fase wel geïnteresseerd geraakt in een hygiene boiler.

Ik kan daar echter weinig over vinden, kunnen jullie mij daar misschien wat meer over vertellen?
  • Hoe zit het met de aftapbaarheid van zo'n boiler?
  • hoef je hier echt nooit een legionella run mee te doen?
  • Ik kan zelf geen NEN1006 pdf vinden, zijn de eisen aan warmtapwater punten verschillend aan de hand van je installatie? (Geiser, boiler, etc.)
Alvast bedankt voor het meedenken!

Acties:
  • 0 Henk 'm!

  • fdbkc01
  • Registratie: Juni 2011
  • Laatst online: 18-05 19:57
Thermostaat aan/uit voor cv circuit met hewalex aansturen ipv alleen de controller.

Voor mijn collega heeft die frank de warmtepompspecialist (zit op marktplaats geloof ik) zo’n simpele regeling ontwikkeld voor degene met linkerhanden onder ons zoals ik.
Om daarmee de hewalex aan te sturen,

voor de overtollige zonne-energie aansturing via homewizard voor 1 euro per maand (dat vindt ik echt helemaal top) voor zowel de boiler als een cv-circuit.

of

voor de aansturing van het CV circuit via een aan/uit thermostaat (hij gebruikt bosch easy ofzo) al dan niet via draadloze home automation. Mijn collega gebruikt dat om gewoon “gestuurd” zijn huis te verwarmen. Als de hewalex de temperatuur bereikt op de thermostaat gaat hij in de stand-by of eerder als de vooraf ingestelde cv water temperatuur bereikt is ook.
Voor dat laatste (CV circuit aansturing) heb ik een vraag. Ik wist dit nog niet, ik denk erover omdat dit ook beide te gaan doen.

Iemand suggesties voor een simpele goedkope aan/uit (draadloze of bedraad) thermostaat die dan tussen de 30 en 230 volt afgeeft bij warmtebehoefte. Zodat de regeling van frank snapt dat de hewalex actief moet worden (vanuit standby). Ik wordt een beetje diffuus van al die thermostaten en het volgens mij niet direct aan/uit kunnen aansturen.

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
fdbkc01 schreef op zondag 25 augustus 2024 @ 10:24:
Thermostaat aan/uit voor cv circuit met hewalex aansturen ipv alleen de controller.

Voor mijn collega heeft die frank de warmtepompspecialist (zit op marktplaats geloof ik) zo’n simpele regeling ontwikkeld voor degene met linkerhanden onder ons zoals ik.
Om daarmee de hewalex aan te sturen,

voor de overtollige zonne-energie aansturing via homewizard voor 1 euro per maand (dat vindt ik echt helemaal top) voor zowel de boiler als een cv-circuit.

of

voor de aansturing van het CV circuit via een aan/uit thermostaat (hij gebruikt bosch easy ofzo) al dan niet via draadloze home automation. Mijn collega gebruikt dat om gewoon “gestuurd” zijn huis te verwarmen. Als de hewalex de temperatuur bereikt op de thermostaat gaat hij in de stand-by of eerder als de vooraf ingestelde cv water temperatuur bereikt is ook.
Voor dat laatste (CV circuit aansturing) heb ik een vraag. Ik wist dit nog niet, ik denk erover omdat dit ook beide te gaan doen.

Iemand suggesties voor een simpele goedkope aan/uit (draadloze of bedraad) thermostaat die dan tussen de 30 en 230 volt afgeeft bij warmtebehoefte. Zodat de regeling van frank snapt dat de hewalex actief moet worden (vanuit standby). Ik wordt een beetje diffuus van al die thermostaten en het volgens mij niet direct aan/uit kunnen aansturen.
Ik heb zelf een Tado aan/uit thermostaat gebruikt en deze aangesloten op het externe contact van de Hewalex, zie elektrisch schema in de handleiding "EXT" In het elektrische schema zit tussen aansluiting 7 en 8 een doorverbinding "external unit". Deze brug verwijderen en een kamerthermostaat er tussen zetten. Ik weet alleen niet meer wat de spanning is op dit contact, dacht 230V. Tado kan 24V als ook 230V schakelen.
Let goed op keuze thermostaat. Niet elke aan/uit is geschikt voor een warmtepomp. Vele "goedkope" aan/uit thermostaten maken best wat schakelingen in een uur, wat niet bevordelijk is voor de warmtepomp.

[ Voor 5% gewijzigd door andre75 op 25-08-2024 23:32 ]


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Jerra schreef op zondag 25 augustus 2024 @ 10:08:
Dag allemaal,

Ook ik wil een Hewalex PCWU gaan inzetten om SWW te bereiden.
Hierbij ben ik in mijn oriëntatie fase wel geïnteresseerd geraakt in een hygiene boiler.

Ik kan daar echter weinig over vinden, kunnen jullie mij daar misschien wat meer over vertellen?
  • Hoe zit het met de aftapbaarheid van zo'n boiler?
  • hoef je hier echt nooit een legionella run mee te doen?
  • Ik kan zelf geen NEN1006 pdf vinden, zijn de eisen aan warmtapwater punten verschillend aan de hand van je installatie? (Geiser, boiler, etc.)
Alvast bedankt voor het meedenken!
Misschien een gekke vraag. Als je de Hewalex puur voor SWW gaat gebruiken, is een standalone warmtepompboiler geen betere keuze?

Acties:
  • 0 Henk 'm!

  • Tim123
  • Registratie: Mei 2022
  • Laatst online: 11-09 20:25
andre75 schreef op zondag 25 augustus 2024 @ 23:12:
[...]


Misschien een gekke vraag. Als je de Hewalex puur voor SWW gaat gebruiken, is een standalone warmtepompboiler geen betere keuze?
Uiteindelijk is de hewalex juist bedoeld voor bereiding van SWW...
Dat wij hem gebruiken voor de cv veranderd daar niks aan ;)

Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
andre75 schreef op zondag 25 augustus 2024 @ 22:55:
[...]


Ik heb zelf een Tado aan/uit thermostaat gebruikt en deze aangesloten op het externe contact van de Hewalex, zie elektrisch schema in de handleiding "EXT"
Welke Tado heb je dan?

S.J.


Acties:
  • +1 Henk 'm!

  • Jerra
  • Registratie: Oktober 2016
  • Laatst online: 20:36

Jerra

Beunhaas in wording

Dag @andre75 en @Tim123 ,
Ik dacht ook al dat de Hewalex PCWU primair was bedoeld voor SWW, maar ook al was die dat secundair geweest dan nog komt hij mooi uit in mijn opstelling.

Ik heb een krappe trap naar zolder dus de opdeelbaarheid van de installatie spreekt me wel aan.
Zo kan ik een passend vat uitzoeken zonder warmtepomp componenten die hem groter en zwaarder maken.

Daarbij zou ik nu ook voor een kleinere waterhoeveelheid kunnen gaan, gezien er de komende jaren nog geen badkuip en kinderen zijn, en heb ik nu minder stilstandsverliezen.
Door de losse componenten zou ik dan later alsnog een tweede vat kunnen bijplaatsen, of de dan geplaatste vervangen.

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
De standaard Tado. Via support van Tado kan deze softwarematig met een update geschikt gemaakt worden voor een warmtepomp, waardoor minder schakelingen maakt.

Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Tim123 schreef op maandag 26 augustus 2024 @ 09:01:
[...]

Uiteindelijk is de hewalex juist bedoeld voor bereiding van SWW...
Dat wij hem gebruiken voor de cv veranderd daar niks aan ;)
Dat klopt ook. Wat ik ermee aan wilde geven dat een standalone warmtepompboiler uiteindelijk misschien goedkoper is dan een Hewalex met een losse boiler.

Acties:
  • 0 Henk 'm!

  • Jerra
  • Registratie: Oktober 2016
  • Laatst online: 20:36

Jerra

Beunhaas in wording

Om nog maar even op mijzelf terug te komen, ik vind meer en meer datasheets waar er van uit wordt gegaan dat een hygiene boiler (het dode water zelf) altijd op 60 graden wordt gehouden.

Ik ben er nog niet echt over uit, zoek nog steeds naar ervaringen met hygiene boilers op een stooktemperatuur van ~45 graden...
Maar tot nu toe lijkt het me dat met zo'n hoge watertemperatuur van 60 graden benodigd is, dan kan ik natuurlijk net zo goed een normaal boilervat nemen zonder warmtewisselaars.
(En dan natuurlijk de hewalex 1 keer per week een legionella run laten doen).

@andre75 Als ik alleen al kijk naar het DHZ pakket van "de warmtepomp specialist" is de hewalex door de hoge subsidie altijd de goedkoopste oplossing voor SWW.

Acties:
  • 0 Henk 'm!

  • Surfari
  • Registratie: Mei 2021
  • Laatst online: 16:46
Jerra schreef op dinsdag 27 augustus 2024 @ 12:21:
Om nog maar even op mijzelf terug te komen, ik vind meer en meer datasheets waar er van uit wordt gegaan dat een hygiene boiler (het dode water zelf) altijd op 60 graden wordt gehouden.

Ik ben er nog niet echt over uit, zoek nog steeds naar ervaringen met hygiene boilers op een stooktemperatuur van ~45 graden...
Maar tot nu toe lijkt het me dat met zo'n hoge watertemperatuur van 60 graden benodigd is, dan kan ik natuurlijk net zo goed een normaal boilervat nemen zonder warmtewisselaars.
(En dan natuurlijk de hewalex 1 keer per week een legionella run laten doen).

@andre75 Als ik alleen al kijk naar het DHZ pakket van "de warmtepomp specialist" is de hewalex door de hoge subsidie altijd de goedkoopste oplossing voor SWW.
Een boiler met tapwater moet regelmatig verhit worden om legionella risico in de boiler te dempen. Heeft een hygiëne boiler niet. Maar hoe denk je de warmwaterleiding veilig te houden? Gaat in ieder geval niet als deze alleen lauw wordt.

Acties:
  • 0 Henk 'm!

  • Jan_De_Tuinman
  • Registratie: November 2011
  • Laatst online: 10-09 20:44
beste mede tweakers,

Hoe organiseren jullie met de hewalex de wekelijkse legionelle run?

Heb een hewalex PCWU 3kw en een 200 liter boiler. Ik heb nu in mijn agenda staan dat ik op zondag handmatig de waterpomp aanzet in het menu van de hewalex en dan vervolgens het element aanzet zodat de boiler naar 70 graden opgewarmd wordt.

Hopelijk kan dit handiger? Iemand ervaring of tips?

Acties:
  • 0 Henk 'm!

  • TTommie
  • Registratie: Juni 2004
  • Laatst online: 11-09 23:36

TTommie

Het leven is een pijpkaneel...

Jan_De_Tuinman schreef op vrijdag 13 september 2024 @ 14:47:
beste mede tweakers,

Hoe organiseren jullie met de hewalex de wekelijkse legionelle run?

Heb een hewalex PCWU 3kw en een 200 liter boiler. Ik heb nu in mijn agenda staan dat ik op zondag handmatig de waterpomp aanzet in het menu van de hewalex en dan vervolgens het element aanzet zodat de boiler naar 70 graden opgewarmd wordt.

Hopelijk kan dit handiger? Iemand ervaring of tips?
Tja dat kan op verschillende manieren. De vraag is hoe heb je je element aangesloten? Wordt door de WPB gevoed of eigen voeding?

Bij eigen voeding kan je bijvoorbeeld een Shelly tussen zetten die je een keer in de week een paar uur aan laat gaan… .

Mr. T.


Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Jan_De_Tuinman schreef op vrijdag 13 september 2024 @ 14:47:
Hopelijk kan dit handiger? Iemand ervaring of tips?
Ik doe iets soortgelijks, alleen laat ik vooraf de WP hoger gaan (55 °C i.p.v. 43 °C), zodat het element maar 5 graden hoeft te overbruggen. Het element heb ik apart aangesloten zodat ik zelf het moment van draaien kan kiezen. Maar op de agenda staat de bouw van externe aansturing, zowel van element als WP via het PV contact.
De anti-legionella run duurt wel redelijk lang omdat ik geen extra circulatiepomp heb. Het element verwarmt alleen de bovenste helft van het vat en de Wilo pomp circuleert de onderste helft. Zodra onderin de 60 °C wordt aangetikt is de temperatuur bovenin ruim boven de 70 °C. Dat kan handiger 8)7

Acties:
  • 0 Henk 'm!

  • Surfari
  • Registratie: Mei 2021
  • Laatst online: 16:46
Jan_De_Tuinman schreef op vrijdag 13 september 2024 @ 14:47:
beste mede tweakers,

Hoe organiseren jullie met de hewalex de wekelijkse legionelle run?

Heb een hewalex PCWU 3kw en een 200 liter boiler. Ik heb nu in mijn agenda staan dat ik op zondag handmatig de waterpomp aanzet in het menu van de hewalex en dan vervolgens het element aanzet zodat de boiler naar 70 graden opgewarmd wordt.

Hopelijk kan dit handiger? Iemand ervaring of tips?
Er zit een legionella programma in de Hewalex controller. Nadeel is dat het tijdstip niet in te stellen is, het is altijd op zondag maar dat doet u toch al.

Acties:
  • 0 Henk 'm!

  • Jan_De_Tuinman
  • Registratie: November 2011
  • Laatst online: 10-09 20:44
Thank voor jullie reactie.

@TTommie Heb een 3KW element die een eigen voeding heeft (eigen groep). Die kan ik met een slimme stekker wel in een schema uit en aan laten gaan. Echter mis ik dan het circuleren van de waterpomp zodat de hele boiler opwarmt. Dus vandaar nu handmatig.

@Martin7182 Das wel een goede tip. Eerst laten stoken naar 55 en dan een laatste stukje bij warmen. Dat scheelt aardig energie. Eens. Dit moet handiger kunnen :)

@Surfari Joh, dat zou gaaf zijn! dan moet ik daar even naar opzoek, ben benieuwd hoe dat dan werkt. Tijdstip op zondag is voor mij niet een issue. Wil het liefst niet afhankelijk zijn van mijn eigen agenda :)

Acties:
  • 0 Henk 'm!

  • TTommie
  • Registratie: Juni 2004
  • Laatst online: 11-09 23:36

TTommie

Het leven is een pijpkaneel...

Jan_De_Tuinman schreef op dinsdag 17 september 2024 @ 19:03:
Thank voor jullie reactie.

@TTommie Heb een 3KW element die een eigen voeding heeft (eigen groep). Die kan ik met een slimme stekker wel in een schema uit en aan laten gaan. Echter mis ik dan het circuleren van de waterpomp zodat de hele boiler opwarmt. Dus vandaar nu handmatig.
Aaaah zo, ik heb een seperaat circuit met een extra circulatiepomp. Dit omdat als straks de overheid de saldering de nek omdraait ik de boiler als een soort van accu wil gebruiken. Dus alle productie stop ik in het warm water.

Ik heb dus bewust een extra circuit aangelegd die niet door de WPB gaat. Ik dacht namelijk dat de Hewalex het niet leuk zou vinden als daar 80 graden water doorheen gaat. Dus dat probleem had ik even gemist.

Mr. T.


Acties:
  • 0 Henk 'm!

  • TTommie
  • Registratie: Juni 2004
  • Laatst online: 11-09 23:36

TTommie

Het leven is een pijpkaneel...

En om dan maar meteen het verhaal af te maken. Welkom een ieder, ik heb sinds kort ook een Hewalex draaien. Ik gebruik deze alleen voor sanitair warm water.

En ik moet zeggen tot op heden, 2 weken in gebruik bevalt het prima. Ik was al een tijdje aan het zoeken maar de locatie waar die moest komen kon geen gewone WPB (ruimte gebrek, dus toen tegen de Hewalex oplossing aangelopen) .

Omdat ik zo mijn bedenkingen had en ook niet precies wist hoe het in elkaar zat, heb ik Frank benaderd. Die naam zie je hier wel vaker langskomen. Ik heb samen met hem een plan bedacht om het weg te zetten. Dat begon vrij simpel, maar aangezien ik geen verticale boiler kwijt kan is deze horizontaal geworden en er is een extra circuit aangelegd voor als het element inspringt. Dit omdat ik mijn overtollige zonne-energie ook om wil zetten in warm water. Dus ik laat het element aangaan op het moment dat ik een overproductie heb van minimaal 1500watt en het water warmer is dan 50 graden.

Maar goed, uiteindelijk nog een paar kleine dingetjes weg gewerkt waar ik tegenaan liep samen met Frank en nu mag die aan de bak.

Tevens zal ik dit topic goed in de gaten houden want ik zie mooie dingen gebeuren in HA, en dat heeft ook zeker mijn interesse omdat dit uiteindelijk mijn centrale aanstuur systeem is in huis.

[ Voor 8% gewijzigd door TTommie op 17-09-2024 19:19 ]

Mr. T.


Acties:
  • 0 Henk 'm!

  • Tim123
  • Registratie: Mei 2022
  • Laatst online: 11-09 20:25
Waarom laat je de hewalex niet zelf 60 graden maken voor de legionella run? Is altijd beter dan COP1 lijkt mij..

Acties:
  • +1 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Dat vind ik wel wat kort door de bocht. 60 graden is een grote belasting voor de compressor, geen idee hoe lang dat goed blijft gaan. Mijn element kost €80 en de extra stroom voor een anti-legionellarun kost ~€0.10.

Acties:
  • 0 Henk 'm!

  • Hvdbnl
  • Registratie: December 2020
  • Laatst online: 11:00
Ik heb de hewalex gekoppeld aan Home Assistant (via een ew11) en een automation gemaakt die de WP op 58 zet, CP aan en element aan (via zigbee stopcontact)

En die blijft draaien totdat de sensor onderin (T2) 20m 60 graden is geweest, dan weet ik zeker dat al het water warm genoeg is.
1x per week, ben nog aan het kijken om het te doen aan de hand van de solar forecast maar dat komt wel
En moet nog een goede dimmer zoeken voor het element voor als saldering ermee stopt.

Ik denk dat als je dit wilt automatiseren je ervoor moet zorgen dat je de hewalex in Home Assistant (of soortgelijks) hebt zodat je regels kunt maken.
Ander zit je aan de hewalex regeling zelf vast en die is niet echt geweldig, of handmatig...

All electric | 6500Wp zon | 15kWh accu | 54 kWh E-2008 | 3x MP2 3000 | Hewalex & spaarpomp | Hewalex 300L Boiler | Proxmox & Home automation


Acties:
  • 0 Henk 'm!

  • TTommie
  • Registratie: Juni 2004
  • Laatst online: 11-09 23:36

TTommie

Het leven is een pijpkaneel...

Tim123 schreef op dinsdag 17 september 2024 @ 22:09:
Waarom laat je de hewalex niet zelf 60 graden maken voor de legionella run? Is altijd beter dan COP1 lijkt mij..
Dat lijkt mij inderdaad iets wat je niet wil. Als je zit hoe zwaar de compressor het al heeft boven de 50 graden.

Mr. T.


  • Jan_De_Tuinman
  • Registratie: November 2011
  • Laatst online: 10-09 20:44
@TTommie Ja, inderdaad slim om een extra circuit aan te leggen. Ga eens kijken of dat een optie is en wat handig is. Hier hetzelfde idee om zoveel mogelijk productie in de boiler te stoppen.

@Tim123 Ja, bij mij voelt 60 graden ook niet helemaal goed. Ik heb dan het idee dat de compressor het erg zwaar heeft dan.

@Hvdbnl Heb EW11 ook een poging gegeven. Krijg echter met geen mogelijkheid verbinding met de hewalex via de seriele port. Wil jij je instellingen delen? Via HW aansturen zou wel fijn zijn, ben echter nog redelijk nieuw in die wereld.

Acties:
  • +1 Henk 'm!

  • Hvdbnl
  • Registratie: December 2020
  • Laatst online: 11:00
Jan_De_Tuinman schreef op woensdag 18 september 2024 @ 13:59:


@Hvdbnl Heb EW11 ook een poging gegeven. Krijg echter met geen mogelijkheid verbinding met de hewalex via de seriele port. Wil jij je instellingen delen? Via HW aansturen zou wel fijn zijn, ben echter nog redelijk nieuw in die wereld.
Ja het is wel wat lastig.
Er zijn een aantal bestaande add-ons maar die werkte niet allemaal even lekker.
Dus ik heb een fork van een fork

https://github.com/hvdb/hewalex2mqtt-homeassistant-add-on

Dit werkt voor mij in ieder geval

All electric | 6500Wp zon | 15kWh accu | 54 kWh E-2008 | 3x MP2 3000 | Hewalex & spaarpomp | Hewalex 300L Boiler | Proxmox & Home automation


  • Jan_De_Tuinman
  • Registratie: November 2011
  • Laatst online: 10-09 20:44
Hvdbnl schreef op woensdag 18 september 2024 @ 14:33:
[...]


Ja het is wel wat lastig.
Er zijn een aantal bestaande add-ons maar die werkte niet allemaal even lekker.
Dus ik heb een fork van een fork

https://github.com/hvdb/hewalex2mqtt-homeassistant-add-on

Dit werkt voor mij in ieder geval
Kan/wil je wel de instellingen delen wel jij in EW11 hanteert voor de seriele settings? (baud, data bit, stop bit, parity en etc..)

  • Hvdbnl
  • Registratie: December 2020
  • Laatst online: 11:00
Jan_De_Tuinman schreef op woensdag 18 september 2024 @ 15:25:
[...]


Kan/wil je wel de instellingen delen wel jij in EW11 hanteert voor de seriele settings? (baud, data bit, stop bit, parity en etc..)
38400
8
1
none

Volgens mij allemaal standaard.
Baudrate is belangrijk.

Hetzelfde als hier:
strieder in "Het (grote?) hewalex warmtepomp(boiler) avontuur"

Maar vooral:
Heat Pump Controller Settings:

Navigate to the RS485 settings in the heat pump controller, labeled "Port RS485".
Modify the settings as follows:
"Transmission speed" (Baud rate) to 38400.
"Physical address" (Actual address) to 2.
"Logical address" (Logic address) to 2.
Die staat standaard niet op 2 en dan wordt het niks.

[ Voor 7% gewijzigd door Hvdbnl op 18-09-2024 21:18 ]

All electric | 6500Wp zon | 15kWh accu | 54 kWh E-2008 | 3x MP2 3000 | Hewalex & spaarpomp | Hewalex 300L Boiler | Proxmox & Home automation


  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Hvdbnl schreef op dinsdag 17 september 2024 @ 23:23:
Ik heb de hewalex gekoppeld aan Home Assistant (via een ew11) en een automation gemaakt die de WP op 58 zet, CP aan en element aan (via zigbee stopcontact)

En die blijft draaien totdat de sensor onderin (T2) 20m 60 graden is geweest, dan weet ik zeker dat al het water warm genoeg is.
1x per week, ben nog aan het kijken om het te doen aan de hand van de solar forecast maar dat komt wel
En moet nog een goede dimmer zoeken voor het element voor als saldering ermee stopt.

Ik denk dat als je dit wilt automatiseren je ervoor moet zorgen dat je de hewalex in Home Assistant (of soortgelijks) hebt zodat je regels kunt maken.
Ander zit je aan de hewalex regeling zelf vast en die is niet echt geweldig, of handmatig...
Ik heb via Jojan265 Hewalex werkend gekregen in Home Assistant via een App Deamon.

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
andre75 schreef op zaterdag 21 september 2024 @ 00:09:
[...]


Ik heb via Jojan265 Hewalex werkend gekregen in Home Assistant via een App Deamon.
Ik ook, heb de code iets aangepast ( https://github.com/HJKLMN/HomeAssistant-Hewalex2MQTT)

S.J.


  • Jan_De_Tuinman
  • Registratie: November 2011
  • Laatst online: 10-09 20:44
@Hvdbnl Thanks! dat staat dus allemaal goed bij mij.

Heb eerder het idee dat mijn EW11 geen informatie krijgt. Bij Status onder Serial Port State zie ik ook geen bytes of frames binnenkomen. data draden al een keer om gedraaid en etc... Maar weer een keer tijd in stoppen en zien hoe ik dat het beste kan troubleshooten.

Acties:
  • +1 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
Top dat je de yaml file hebt aangepast. Hier werkt het nu ook goed. Ik heb ook een template gemaakt wat het afgifte vermogen doet tijdens bedrijf en een COP berekening.

Acties:
  • 0 Henk 'm!

  • chapie
  • Registratie: Oktober 2003
  • Laatst online: 11-09 18:39
Helaas krijg ik het nog niet werkend middels AppDaemon, AppDaemon geeft bij status aan "loaded", is dat correct?

code: hewalex2mqttconfig.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[MQTT]
MQTT_ip = 192.168.0.11
MQTT_port = 1883
MQTT_authentication = True
MQTT_user = *********
MQTT_pass = **********
MQTT_GatewayDevice_Topic = HewaGate

[Pcwu]
#-----------------------------------------------------------------------------------------------
Device_Pcwu_Enabled = True
Device_Pcwu_Address = 192.168.0.51
Device_Pcwu_Port = 8899
Device_Pcwu_MqttTopic = Heatpump
#-----------------------------------------------------------------------------------------------

Ik heb een Waveshare gekoppeld op de tweede RS485 poort (A + B aangesloten, of is + en - ook nodig op de tweede poort?), deze is conform de eerder post van @Jojan265 geconfigureerd. De entiteiten zijn zichtbaar in HomeAssistant maar waarden worden helaas niet doorgegeven. Iemand enig idee wat ik over het hoofd zie?

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
chapie schreef op vrijdag 27 september 2024 @ 20:22:
Helaas krijg ik het nog niet werkend middels AppDaemon, AppDaemon geeft bij status aan "loaded", is dat correct?

code: hewalex2mqttconfig.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[MQTT]
MQTT_ip = 192.168.0.11
MQTT_port = 1883
MQTT_authentication = True
MQTT_user = *********
MQTT_pass = **********
MQTT_GatewayDevice_Topic = HewaGate

[Pcwu]
#-----------------------------------------------------------------------------------------------
Device_Pcwu_Enabled = True
Device_Pcwu_Address = 192.168.0.51
Device_Pcwu_Port = 8899
Device_Pcwu_MqttTopic = Heatpump
#-----------------------------------------------------------------------------------------------

Ik heb een Waveshare gekoppeld op de tweede RS485 poort (A + B aangesloten, of is + en - ook nodig op de tweede poort?), deze is conform de eerder post van @Jojan265 geconfigureerd. De entiteiten zijn zichtbaar in HomeAssistant maar waarden worden helaas niet doorgegeven. Iemand enig idee wat ik over het hoofd zie?
Dit zie ik in de logfile van AppDeamon na een opstart daarvan. Misschien kun je jouw logfile ook even delen, dan kunnen we in ieder geval even bekijken of alle apps goed gestart worden.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service base-addon-banner: starting

-----------------------------------------------------------
 Add-on: AppDaemon
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.16.7
 You are running the latest version of this add-on.
 System: Home Assistant OS 13.1  (amd64 / generic-x86-64)
 Home Assistant Core: 2024.9.3
 Home Assistant Supervisor: 2024.09.1
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
Log level is set to INFO
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service init-appdaemon: starting
Looking in indexes: https://pypi.org/simple, https://wheels.home-assistant.io/musllinux-index/
Collecting pyserial
  Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl.metadata (1.6 kB)
Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl (90 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 90.6/90.6 kB 5.4 MB/s eta 0:00:00
Installing collected packages: pyserial
Successfully installed pyserial-3.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
s6-rc: info: service init-appdaemon successfully started
s6-rc: info: service appdaemon: starting
s6-rc: info: service appdaemon successfully started
s6-rc: info: service legacy-services: starting
[22:53:51] INFO: Starting AppDaemon...
s6-rc: info: service legacy-services successfully started
2024-09-27 22:53:54.778913 INFO AppDaemon: Got initial state from namespace default
2024-09-27 22:53:56.706212 INFO AppDaemon: Scheduler running in realtime
2024-09-27 22:53:56.710793 INFO AppDaemon: Adding /config/apps to module import path
2024-09-27 22:53:56.711593 INFO AppDaemon: Adding /config/apps/hewalex_geco to module import path
2024-09-27 22:53:56.712263 INFO AppDaemon: Adding /config/apps/hewalex_geco/devices to module import path
2024-09-27 22:53:56.723362 INFO AppDaemon: Loading App Module: /config/apps/hewalex2mqtt.py
2024-09-27 22:53:56.905104 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/__init__.py - ignoring
2024-09-27 22:53:56.905735 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/crc.py - ignoring
2024-09-27 22:53:56.906213 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/pcwu.py - ignoring
2024-09-27 22:53:56.906660 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/zps.py - ignoring
2024-09-27 22:53:56.907106 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/__init__.py - ignoring
2024-09-27 22:53:56.907535 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/base.py - ignoring
2024-09-27 22:53:56.907927 INFO AppDaemon: Loading app hewalex2mqtt using class MyApp from module hewalex2mqtt
2024-09-27 22:53:56.908994 INFO AppDaemon: Calling initialize() for hewalex2mqtt
2024-09-27 22:53:56,909 :: hewalex2mqtt :: INFO :: Initializing Hewalex 2 Mqtt
2024-09-27 22:53:56,909 :: hewalex2mqtt :: INFO :: reading config addon_config Appdaemon
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT ip: 192.168.x.x
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT port: 1883
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT authentication: True
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT user: x
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT pass: x
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: Device_Pcwu_MqttTopic: Heatpump
2024-09-27 22:53:56,911 :: hewalex2mqtt :: DEBUG :: Sending CONNECT (u1, p1, wr0, wq0, wf0, c1, k60) client_id=b''
2024-09-27 22:53:56,911 :: hewalex2mqtt :: INFO :: Subscribed to: Heatpump/Command
2024-09-27 22:53:56,911 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m1) [(b'Heatpump/Command', 1)]
2024-09-27 22:53:56,918 :: hewalex2mqtt :: DEBUG :: Received CONNACK (0, 0)
2024-09-27 22:53:56,918 :: hewalex2mqtt :: INFO :: Connected to MQTT Broker with result code: 0
2024-09-27 22:53:56,919 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m2) [(b'Heatpump/Command/#', 0)]
2024-09-27 22:53:56,919 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-09-27 22:53:56,920 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-09-27 22:53:57,318 :: hewalex2mqtt :: INFO :: Heatpump/date 2024-09-27
2024-09-27 22:53:57,319 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m3), 'b'Heatpump/date'', ... (10 bytes)
2024-09-27 22:53:57,319 :: hewalex2mqtt :: INFO :: Heatpump/time 22:07:53
2024-09-27 22:53:57,319 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m4), 'b'Heatpump/time'', ... (8 bytes)
2024-09-27 22:53:57,320 :: hewalex2mqtt :: INFO :: Heatpump/T1 22.4
2024-09-27 22:53:57,320 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m5), 'b'Heatpump/T1'', ... (4 bytes)
2024-09-27 22:53:57,320 :: hewalex2mqtt :: INFO :: Heatpump/T2 51.5
2024-09-27 22:53:57,320 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m6), 'b'Heatpump/T2'', ... (4 bytes)
2024-09-27 22:53:57,320 :: hewalex2mqtt :: INFO :: Heatpump/T3 51.6
2024-09-27 22:53:57,320 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m7), 'b'Heatpump/T3'', ... (4 bytes)
2024-09-27 22:53:57,321 :: hewalex2mqtt :: INFO :: Heatpump/T6 27.3
2024-09-27 22:53:57,321 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m8), 'b'Heatpump/T6'', ... (4 bytes)
2024-09-27 22:53:57,321 :: hewalex2mqtt :: INFO :: Heatpump/T7 28.2
2024-09-27 22:53:57,321 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m9), 'b'Heatpump/T7'', ... (4 bytes)
2024-09-27 22:53:57,322 :: hewalex2mqtt :: INFO :: Heatpump/T8 20.0
2024-09-27 22:53:57,322 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m10), 'b'Heatpump/T8'', ... (4 bytes)
2024-09-27 22:53:57,323 :: hewalex2mqtt :: INFO :: Heatpump/T9 23.0
2024-09-27 22:53:57,324 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m11), 'b'Heatpump/T9'', ... (4 bytes)
2024-09-27 22:53:57,324 :: hewalex2mqtt :: INFO :: Heatpump/T10 25.5
2024-09-27 22:53:57,325 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m12), 'b'Heatpump/T10'', ... (4 bytes)
2024-09-27 22:53:57,325 :: hewalex2mqtt :: INFO :: Heatpump/IsManual True
2024-09-27 22:53:57,326 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m13), 'b'Heatpump/IsManual'', ... (4 bytes)
2024-09-27 22:53:57,326 :: hewalex2mqtt :: INFO :: Heatpump/FanON False
2024-09-27 22:53:57,326 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m14), 'b'Heatpump/FanON'', ... (5 bytes)
2024-09-27 22:53:57,326 :: hewalex2mqtt :: INFO :: Heatpump/CirculationPumpON False
2024-09-27 22:53:57,327 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m15), 'b'Heatpump/CirculationPumpON'', ... (5 bytes)
2024-09-27 22:53:57,327 :: hewalex2mqtt :: INFO :: Heatpump/HeatPumpON False
2024-09-27 22:53:57,327 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m16), 'b'Heatpump/HeatPumpON'', ... (5 bytes)
2024-09-27 22:53:57,328 :: hewalex2mqtt :: INFO :: Heatpump/CompressorON False
2024-09-27 22:53:57,328 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m17), 'b'Heatpump/CompressorON'', ... (5 bytes)
2024-09-27 22:53:57,328 :: hewalex2mqtt :: INFO :: Heatpump/HeaterEON False
2024-09-27 22:53:57,328 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m18), 'b'Heatpump/HeaterEON'', ... (5 bytes)
2024-09-27 22:53:57,329 :: hewalex2mqtt :: INFO :: Heatpump/EV1 187
2024-09-27 22:53:57,329 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m19), 'b'Heatpump/EV1'', ... (3 bytes)
2024-09-27 22:53:57,329 :: hewalex2mqtt :: INFO :: Heatpump/WaitingStatus 2
2024-09-27 22:53:57,329 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m20), 'b'Heatpump/WaitingStatus'', ... (1 bytes)
2024-09-27 22:53:58,036 :: hewalex2mqtt :: INFO :: Heatpump/InstallationScheme 1
2024-09-27 22:53:58,037 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m21), 'b'Heatpump/InstallationScheme'', ... (1 bytes)
2024-09-27 22:53:58,037 :: hewalex2mqtt :: INFO :: Heatpump/HeatPumpEnabled True
2024-09-27 22:53:58,038 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m22), 'b'Heatpump/HeatPumpEnabled'', ... (4 bytes)
2024-09-27 22:53:58,038 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterSensor 0
2024-09-27 22:53:58,039 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m23), 'b'Heatpump/TapWaterSensor'', ... (1 bytes)
2024-09-27 22:53:58,039 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterTemp 52.0
2024-09-27 22:53:58,039 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m24), 'b'Heatpump/TapWaterTemp'', ... (4 bytes)
2024-09-27 22:53:58,040 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterHysteresis 2.0
2024-09-27 22:53:58,041 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m25), 'b'Heatpump/TapWaterHysteresis'', ... (3 bytes)
2024-09-27 22:53:58,041 :: hewalex2mqtt :: INFO :: Heatpump/AmbientMinTemp 10.0
2024-09-27 22:53:58,042 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m26), 'b'Heatpump/AmbientMinTemp'', ... (4 bytes)
2024-09-27 22:53:58,043 :: hewalex2mqtt :: INFO :: Heatpump/TimeProgramHPM-F {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False, 9: False, 10: False, 11: False, 12: False, 13: False, 14: False, 15: False, 16: False, 17: True, 18: True, 19: True, 20: True, 21: False, 22: False, 23: False}
2024-09-27 22:53:58,044 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m27), 'b'Heatpump/TimeProgramHPM-F'', ... (250 bytes)
2024-09-27 22:53:58,045 :: hewalex2mqtt :: INFO :: Heatpump/TimeProgramHPSat {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False, 9: False, 10: False, 11: False, 12: False, 13: False, 14: False, 15: False, 16: False, 17: True, 18: True, 19: True, 20: True, 21: False, 22: False, 23: False}
2024-09-27 22:53:58,045 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m28), 'b'Heatpump/TimeProgramHPSat'', ... (250 bytes)
2024-09-27 22:53:58,045 :: hewalex2mqtt :: INFO :: Heatpump/TimeProgramHPSun {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False, 9: False, 10: False, 11: False, 12: False, 13: False, 14: False, 15: False, 16: False, 17: True, 18: True, 19: True, 20: True, 21: False, 22: False, 23: False}
2024-09-27 22:53:58,047 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m29), 'b'Heatpump/TimeProgramHPSun'', ... (250 bytes)
2024-09-27 22:53:58,047 :: hewalex2mqtt :: INFO :: Heatpump/AntiFreezingEnabled True
2024-09-27 22:53:58,048 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m30), 'b'Heatpump/AntiFreezingEnabled'', ... (4 bytes)
2024-09-27 22:53:58,048 :: hewalex2mqtt :: INFO :: Heatpump/WaterPumpOperationMode 1
2024-09-27 22:53:58,049 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m31), 'b'Heatpump/WaterPumpOperationMode'', ... (1 bytes)
2024-09-27 22:53:58,050 :: hewalex2mqtt :: INFO :: Heatpump/FanOperationMode 1
2024-09-27 22:53:58,051 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m32), 'b'Heatpump/FanOperationMode'', ... (1 bytes)
2024-09-27 22:53:58,051 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingInterval 45
2024-09-27 22:53:58,052 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m33), 'b'Heatpump/DefrostingInterval'', ... (2 bytes)
2024-09-27 22:53:58,052 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingStartTemp -7.0
2024-09-27 22:53:58,053 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m34), 'b'Heatpump/DefrostingStartTemp'', ... (4 bytes)
2024-09-27 22:53:58,053 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingStopTemp 13.0
2024-09-27 22:53:58,053 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m35), 'b'Heatpump/DefrostingStopTemp'', ... (4 bytes)
2024-09-27 22:53:58,054 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingMaxTime 8
2024-09-27 22:53:58,054 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m36), 'b'Heatpump/DefrostingMaxTime'', ... (1 bytes)
2024-09-27 22:53:58,858 :: hewalex2mqtt :: INFO :: Heatpump/ExtControllerHPOFF True
2024-09-27 22:53:58,858 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m37), 'b'Heatpump/ExtControllerHPOFF'', ... (4 bytes)
2024-09-27 22:53:59.161702 INFO AppDaemon: App initialization complete


En wat je zie je in VirCom?

Dit is mijn status:

Afbeeldingslocatie: https://tweakers.net/i/PIFBfN5BL36iAlYFxavcXkb5JpI=/800x/filters:strip_exif()/f/image/P3fzgTrMAii0FcZQa23sF6Je.png?f=fotoalbum_large

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
chapie schreef op vrijdag 27 september 2024 @ 20:22:
Helaas krijg ik het nog niet werkend middels AppDaemon, AppDaemon geeft bij status aan "loaded", is dat correct?

code: hewalex2mqttconfig.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[MQTT]
MQTT_ip = 192.168.0.11
MQTT_port = 1883
MQTT_authentication = True
MQTT_user = *********
MQTT_pass = **********
MQTT_GatewayDevice_Topic = HewaGate

[Pcwu]
#-----------------------------------------------------------------------------------------------
Device_Pcwu_Enabled = True
Device_Pcwu_Address = 192.168.0.51
Device_Pcwu_Port = 8899
Device_Pcwu_MqttTopic = Heatpump
#-----------------------------------------------------------------------------------------------

Ik heb een Waveshare gekoppeld op de tweede RS485 poort (A + B aangesloten, of is + en - ook nodig op de tweede poort?), deze is conform de eerder post van @Jojan265 geconfigureerd. De entiteiten zijn zichtbaar in HomeAssistant maar waarden worden helaas niet doorgegeven. Iemand enig idee wat ik over het hoofd zie?
Ik liep tegen hetzelfde probleem aan. Gebruik de mqtt explorer om de kijken of je de data binnen krijgt.
Een paar keer de App deamon opnieuw opstarten kan ook helpen. Ik ben er ook een tijdje mee aan het klooien geweest om het werkend te krijgen. Weet er zeker van dat MQTT user en MQTT pass correct is.
Bij mij heeft het op de Raspberry goed gewerkt en na overgang op een Nuc kreeg ik het niet meer voor elkaar om het werkend te krijgen. Uiteindelijk port 8899 aangepast naar poort 502 Poort 502 is een modbus poort.
Nu werkt het prima.

Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Vraagje over diagram no. 3, t.b.v. anti-legionellarun;
Afbeeldingslocatie: https://tweakers.net/i/uXit5pA2IcJu020Sh-Rb5kHso_s=/800x/filters:strip_exif()/f/image/zWlGMjkhYUGmzoN4bHMFy1xc.png?f=fotoalbum_large
Hoe is de extra circulatiepomp hier aangesloten; tussen boven en midden of tussen onder en midden?

Ik draai de run nu nog zonder extra circulatiepomp en laat de Wilo pomp doorlopen terwijl het element aan staat. Die pomp circuleert dus alleen de onderste helft van het vat. Zodra daar de 60 °C wordt aangetikt is de temperatuur bovenin al zo'n 75 °C. Om dat op te lossen wil ik een extra circulatiepomp aansluiten, maar dan tussen de boven- en onderkant zodat water door het hele vat circuleert. Is dat de juiste manier?

Acties:
  • 0 Henk 'm!

  • chapie
  • Registratie: Oktober 2003
  • Laatst online: 11-09 18:39
Jojan265 schreef op vrijdag 27 september 2024 @ 23:05:
[...]

Dit zie ik in de logfile van AppDeamon na een opstart daarvan. Misschien kun je jouw logfile ook even delen, dan kunnen we in ieder geval even bekijken of alle apps goed gestart worden.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service base-addon-banner: starting

-----------------------------------------------------------
 Add-on: AppDaemon
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.16.7
 You are running the latest version of this add-on.
 System: Home Assistant OS 13.1  (amd64 / generic-x86-64)
 Home Assistant Core: 2024.9.3
 Home Assistant Supervisor: 2024.09.1
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
Log level is set to INFO
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service init-appdaemon: starting
Looking in indexes: https://pypi.org/simple, https://wheels.home-assistant.io/musllinux-index/
Collecting pyserial
  Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl.metadata (1.6 kB)
Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl (90 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 90.6/90.6 kB 5.4 MB/s eta 0:00:00
Installing collected packages: pyserial
Successfully installed pyserial-3.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
s6-rc: info: service init-appdaemon successfully started
s6-rc: info: service appdaemon: starting
s6-rc: info: service appdaemon successfully started
s6-rc: info: service legacy-services: starting
[22:53:51] INFO: Starting AppDaemon...
s6-rc: info: service legacy-services successfully started
2024-09-27 22:53:54.778913 INFO AppDaemon: Got initial state from namespace default
2024-09-27 22:53:56.706212 INFO AppDaemon: Scheduler running in realtime
2024-09-27 22:53:56.710793 INFO AppDaemon: Adding /config/apps to module import path
2024-09-27 22:53:56.711593 INFO AppDaemon: Adding /config/apps/hewalex_geco to module import path
2024-09-27 22:53:56.712263 INFO AppDaemon: Adding /config/apps/hewalex_geco/devices to module import path
2024-09-27 22:53:56.723362 INFO AppDaemon: Loading App Module: /config/apps/hewalex2mqtt.py
2024-09-27 22:53:56.905104 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/__init__.py - ignoring
2024-09-27 22:53:56.905735 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/crc.py - ignoring
2024-09-27 22:53:56.906213 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/pcwu.py - ignoring
2024-09-27 22:53:56.906660 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/zps.py - ignoring
2024-09-27 22:53:56.907106 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/__init__.py - ignoring
2024-09-27 22:53:56.907535 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/base.py - ignoring
2024-09-27 22:53:56.907927 INFO AppDaemon: Loading app hewalex2mqtt using class MyApp from module hewalex2mqtt
2024-09-27 22:53:56.908994 INFO AppDaemon: Calling initialize() for hewalex2mqtt
2024-09-27 22:53:56,909 :: hewalex2mqtt :: INFO :: Initializing Hewalex 2 Mqtt
2024-09-27 22:53:56,909 :: hewalex2mqtt :: INFO :: reading config addon_config Appdaemon
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT ip: 192.168.x.x
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT port: 1883
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT authentication: True
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT user: x
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: MQTT pass: x
2024-09-27 22:53:56,910 :: hewalex2mqtt :: INFO :: Device_Pcwu_MqttTopic: Heatpump
2024-09-27 22:53:56,911 :: hewalex2mqtt :: DEBUG :: Sending CONNECT (u1, p1, wr0, wq0, wf0, c1, k60) client_id=b''
2024-09-27 22:53:56,911 :: hewalex2mqtt :: INFO :: Subscribed to: Heatpump/Command
2024-09-27 22:53:56,911 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m1) [(b'Heatpump/Command', 1)]
2024-09-27 22:53:56,918 :: hewalex2mqtt :: DEBUG :: Received CONNACK (0, 0)
2024-09-27 22:53:56,918 :: hewalex2mqtt :: INFO :: Connected to MQTT Broker with result code: 0
2024-09-27 22:53:56,919 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m2) [(b'Heatpump/Command/#', 0)]
2024-09-27 22:53:56,919 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-09-27 22:53:56,920 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-09-27 22:53:57,318 :: hewalex2mqtt :: INFO :: Heatpump/date 2024-09-27
2024-09-27 22:53:57,319 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m3), 'b'Heatpump/date'', ... (10 bytes)
2024-09-27 22:53:57,319 :: hewalex2mqtt :: INFO :: Heatpump/time 22:07:53
2024-09-27 22:53:57,319 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m4), 'b'Heatpump/time'', ... (8 bytes)
2024-09-27 22:53:57,320 :: hewalex2mqtt :: INFO :: Heatpump/T1 22.4
2024-09-27 22:53:57,320 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m5), 'b'Heatpump/T1'', ... (4 bytes)
2024-09-27 22:53:57,320 :: hewalex2mqtt :: INFO :: Heatpump/T2 51.5
2024-09-27 22:53:57,320 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m6), 'b'Heatpump/T2'', ... (4 bytes)
2024-09-27 22:53:57,320 :: hewalex2mqtt :: INFO :: Heatpump/T3 51.6
2024-09-27 22:53:57,320 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m7), 'b'Heatpump/T3'', ... (4 bytes)
2024-09-27 22:53:57,321 :: hewalex2mqtt :: INFO :: Heatpump/T6 27.3
2024-09-27 22:53:57,321 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m8), 'b'Heatpump/T6'', ... (4 bytes)
2024-09-27 22:53:57,321 :: hewalex2mqtt :: INFO :: Heatpump/T7 28.2
2024-09-27 22:53:57,321 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m9), 'b'Heatpump/T7'', ... (4 bytes)
2024-09-27 22:53:57,322 :: hewalex2mqtt :: INFO :: Heatpump/T8 20.0
2024-09-27 22:53:57,322 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m10), 'b'Heatpump/T8'', ... (4 bytes)
2024-09-27 22:53:57,323 :: hewalex2mqtt :: INFO :: Heatpump/T9 23.0
2024-09-27 22:53:57,324 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m11), 'b'Heatpump/T9'', ... (4 bytes)
2024-09-27 22:53:57,324 :: hewalex2mqtt :: INFO :: Heatpump/T10 25.5
2024-09-27 22:53:57,325 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m12), 'b'Heatpump/T10'', ... (4 bytes)
2024-09-27 22:53:57,325 :: hewalex2mqtt :: INFO :: Heatpump/IsManual True
2024-09-27 22:53:57,326 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m13), 'b'Heatpump/IsManual'', ... (4 bytes)
2024-09-27 22:53:57,326 :: hewalex2mqtt :: INFO :: Heatpump/FanON False
2024-09-27 22:53:57,326 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m14), 'b'Heatpump/FanON'', ... (5 bytes)
2024-09-27 22:53:57,326 :: hewalex2mqtt :: INFO :: Heatpump/CirculationPumpON False
2024-09-27 22:53:57,327 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m15), 'b'Heatpump/CirculationPumpON'', ... (5 bytes)
2024-09-27 22:53:57,327 :: hewalex2mqtt :: INFO :: Heatpump/HeatPumpON False
2024-09-27 22:53:57,327 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m16), 'b'Heatpump/HeatPumpON'', ... (5 bytes)
2024-09-27 22:53:57,328 :: hewalex2mqtt :: INFO :: Heatpump/CompressorON False
2024-09-27 22:53:57,328 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m17), 'b'Heatpump/CompressorON'', ... (5 bytes)
2024-09-27 22:53:57,328 :: hewalex2mqtt :: INFO :: Heatpump/HeaterEON False
2024-09-27 22:53:57,328 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m18), 'b'Heatpump/HeaterEON'', ... (5 bytes)
2024-09-27 22:53:57,329 :: hewalex2mqtt :: INFO :: Heatpump/EV1 187
2024-09-27 22:53:57,329 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m19), 'b'Heatpump/EV1'', ... (3 bytes)
2024-09-27 22:53:57,329 :: hewalex2mqtt :: INFO :: Heatpump/WaitingStatus 2
2024-09-27 22:53:57,329 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m20), 'b'Heatpump/WaitingStatus'', ... (1 bytes)
2024-09-27 22:53:58,036 :: hewalex2mqtt :: INFO :: Heatpump/InstallationScheme 1
2024-09-27 22:53:58,037 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m21), 'b'Heatpump/InstallationScheme'', ... (1 bytes)
2024-09-27 22:53:58,037 :: hewalex2mqtt :: INFO :: Heatpump/HeatPumpEnabled True
2024-09-27 22:53:58,038 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m22), 'b'Heatpump/HeatPumpEnabled'', ... (4 bytes)
2024-09-27 22:53:58,038 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterSensor 0
2024-09-27 22:53:58,039 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m23), 'b'Heatpump/TapWaterSensor'', ... (1 bytes)
2024-09-27 22:53:58,039 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterTemp 52.0
2024-09-27 22:53:58,039 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m24), 'b'Heatpump/TapWaterTemp'', ... (4 bytes)
2024-09-27 22:53:58,040 :: hewalex2mqtt :: INFO :: Heatpump/TapWaterHysteresis 2.0
2024-09-27 22:53:58,041 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m25), 'b'Heatpump/TapWaterHysteresis'', ... (3 bytes)
2024-09-27 22:53:58,041 :: hewalex2mqtt :: INFO :: Heatpump/AmbientMinTemp 10.0
2024-09-27 22:53:58,042 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m26), 'b'Heatpump/AmbientMinTemp'', ... (4 bytes)
2024-09-27 22:53:58,043 :: hewalex2mqtt :: INFO :: Heatpump/TimeProgramHPM-F {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False, 9: False, 10: False, 11: False, 12: False, 13: False, 14: False, 15: False, 16: False, 17: True, 18: True, 19: True, 20: True, 21: False, 22: False, 23: False}
2024-09-27 22:53:58,044 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m27), 'b'Heatpump/TimeProgramHPM-F'', ... (250 bytes)
2024-09-27 22:53:58,045 :: hewalex2mqtt :: INFO :: Heatpump/TimeProgramHPSat {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False, 9: False, 10: False, 11: False, 12: False, 13: False, 14: False, 15: False, 16: False, 17: True, 18: True, 19: True, 20: True, 21: False, 22: False, 23: False}
2024-09-27 22:53:58,045 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m28), 'b'Heatpump/TimeProgramHPSat'', ... (250 bytes)
2024-09-27 22:53:58,045 :: hewalex2mqtt :: INFO :: Heatpump/TimeProgramHPSun {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False, 9: False, 10: False, 11: False, 12: False, 13: False, 14: False, 15: False, 16: False, 17: True, 18: True, 19: True, 20: True, 21: False, 22: False, 23: False}
2024-09-27 22:53:58,047 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m29), 'b'Heatpump/TimeProgramHPSun'', ... (250 bytes)
2024-09-27 22:53:58,047 :: hewalex2mqtt :: INFO :: Heatpump/AntiFreezingEnabled True
2024-09-27 22:53:58,048 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m30), 'b'Heatpump/AntiFreezingEnabled'', ... (4 bytes)
2024-09-27 22:53:58,048 :: hewalex2mqtt :: INFO :: Heatpump/WaterPumpOperationMode 1
2024-09-27 22:53:58,049 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m31), 'b'Heatpump/WaterPumpOperationMode'', ... (1 bytes)
2024-09-27 22:53:58,050 :: hewalex2mqtt :: INFO :: Heatpump/FanOperationMode 1
2024-09-27 22:53:58,051 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m32), 'b'Heatpump/FanOperationMode'', ... (1 bytes)
2024-09-27 22:53:58,051 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingInterval 45
2024-09-27 22:53:58,052 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m33), 'b'Heatpump/DefrostingInterval'', ... (2 bytes)
2024-09-27 22:53:58,052 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingStartTemp -7.0
2024-09-27 22:53:58,053 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m34), 'b'Heatpump/DefrostingStartTemp'', ... (4 bytes)
2024-09-27 22:53:58,053 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingStopTemp 13.0
2024-09-27 22:53:58,053 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m35), 'b'Heatpump/DefrostingStopTemp'', ... (4 bytes)
2024-09-27 22:53:58,054 :: hewalex2mqtt :: INFO :: Heatpump/DefrostingMaxTime 8
2024-09-27 22:53:58,054 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m36), 'b'Heatpump/DefrostingMaxTime'', ... (1 bytes)
2024-09-27 22:53:58,858 :: hewalex2mqtt :: INFO :: Heatpump/ExtControllerHPOFF True
2024-09-27 22:53:58,858 :: hewalex2mqtt :: DEBUG :: Sending PUBLISH (d0, q0, r0, m37), 'b'Heatpump/ExtControllerHPOFF'', ... (4 bytes)
2024-09-27 22:53:59.161702 INFO AppDaemon: App initialization complete


En wat je zie je in VirCom?

Dit is mijn status:

[Afbeelding]
Bij deze de inhoud van de logfile:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 Add-on: AppDaemon
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.16.7
 You are running the latest version of this add-on.
 System: Home Assistant OS 13.1  (amd64 / qemux86-64)
 Home Assistant Core: 2024.9.2
 Home Assistant Supervisor: 2024.09.1
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service init-appdaemon: starting
Looking in indexes: https://pypi.org/simple, https://wheels.home-assistant.io/musllinux-index/
Collecting pyserial
  Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl.metadata (1.6 kB)
Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl (90 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 90.6/90.6 kB 6.2 MB/s eta 0:00:00
Installing collected packages: pyserial
Successfully installed pyserial-3.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
s6-rc: info: service init-appdaemon successfully started
s6-rc: info: service appdaemon: starting
s6-rc: info: service appdaemon successfully started
s6-rc: info: service legacy-services: starting
[13:39:23] INFO: Starting AppDaemon...
s6-rc: info: service legacy-services successfully started
2024-09-30 13:39:25.421800 INFO AppDaemon: AppDaemon Version 4.4.2 starting
2024-09-30 13:39:25.422200 INFO AppDaemon: Python version is 3.11.10
2024-09-30 13:39:25.422280 INFO AppDaemon: Configuration read from: /config/appdaemon.yaml
2024-09-30 13:39:25.422342 INFO AppDaemon: Added log: AppDaemon
2024-09-30 13:39:25.422430 INFO AppDaemon: Added log: Error
2024-09-30 13:39:25.422794 INFO AppDaemon: Added log: Access
2024-09-30 13:39:25.422860 INFO AppDaemon: Added log: Diag
2024-09-30 13:39:25.533898 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2024-09-30 13:39:25.646288 INFO HASS: HASS Plugin Initializing
2024-09-30 13:39:25.647361 WARNING HASS: ha_url not found in HASS configuration - module not initialized
2024-09-30 13:39:25.647447 INFO HASS: HASS Plugin initialization complete
2024-09-30 13:39:25.649415 INFO AppDaemon: Initializing HTTP
2024-09-30 13:39:25.649564 INFO AppDaemon: Using 'ws' for event stream
2024-09-30 13:39:25.651239 INFO AppDaemon: Starting API
2024-09-30 13:39:25.652280 INFO AppDaemon: Starting Admin Interface
2024-09-30 13:39:25.652419 INFO AppDaemon: Starting Dashboards
2024-09-30 13:39:25.673586 INFO HASS: Connected to Home Assistant 2024.9.2
2024-09-30 13:39:25.722420 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring
2024-09-30 13:39:25.723895 INFO AppDaemon: App 'hewalex2mqtt' added
2024-09-30 13:39:25.724383 INFO AppDaemon: Found 1 active apps
2024-09-30 13:39:25.724485 INFO AppDaemon: Found 0 inactive apps
2024-09-30 13:39:25.724565 INFO AppDaemon: Found 0 global libraries
2024-09-30 13:39:25.724651 INFO AppDaemon: Starting Apps with 1 workers and 1 pins
2024-09-30 13:39:25.727118 INFO AppDaemon: Running on port 5050
2024-09-30 13:39:25.735347 INFO HASS: Evaluating startup conditions
2024-09-30 13:39:25.742248 INFO HASS: Startup condition met: hass state=RUNNING
2024-09-30 13:39:25.742697 INFO HASS: All startup conditions met
2024-09-30 13:39:25.756136 INFO AppDaemon: Got initial state from namespace default
2024-09-30 13:39:25.956020 INFO AppDaemon: New client Admin Client connected
2024-09-30 13:39:27.754464 INFO AppDaemon: Scheduler running in realtime
2024-09-30 13:39:27.776216 INFO AppDaemon: Reading config
2024-09-30 13:39:27.819284 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring
2024-09-30 13:39:27.819903 INFO AppDaemon: /config/apps/config/packages/hewalex.yaml added or modified
2024-09-30 13:39:27.823393 INFO AppDaemon: Found 1 active apps
2024-09-30 13:39:27.823743 INFO AppDaemon: Found 0 inactive apps
2024-09-30 13:39:27.823830 INFO AppDaemon: Found 0 global libraries
2024-09-30 13:39:27.832802 INFO AppDaemon: Adding /config/apps to module import path
2024-09-30 13:39:27.833494 INFO AppDaemon: Adding /config/apps/hewalex_geco to module import path
2024-09-30 13:39:27.833719 INFO AppDaemon: Adding /config/apps/hewalex_geco/devices to module import path
2024-09-30 13:39:27.833931 INFO AppDaemon: Adding /config/apps/hewalex_geco/examples to module import path
2024-09-30 13:39:27.834898 INFO AppDaemon: Adding /config/apps/config to module import path
2024-09-30 13:39:27.835668 INFO AppDaemon: Adding /config/apps/config/packages to module import path
2024-09-30 13:39:27.856823 WARNING AppDaemon: No app description found for: /config/apps/hewalex2mqtt.py - ignoring
2024-09-30 13:39:27.858106 WARNING AppDaemon: No app description found for: /config/apps/hello.py - ignoring
2024-09-30 13:39:27.860650 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/crc.py - ignoring
2024-09-30 13:39:27.862827 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/__init__.py - ignoring
2024-09-30 13:39:27.865162 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/PCWU.py - ignoring
2024-09-30 13:39:27.867236 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/base.py - ignoring
2024-09-30 13:39:27.871985 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/__init__.py - ignoring
2024-09-30 13:39:27.874737 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/ZPS.py - ignoring
2024-09-30 13:39:27.876823 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/zps_example.py - ignoring
2024-09-30 13:39:27.878921 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/pcwu_eavesdropping.py - ignoring
2024-09-30 13:39:27.880755 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/pcwu_directcomms.py - ignoring
2024-09-30 13:39:27.882526 INFO AppDaemon: App initialization complete
2024-09-30 13:39:36.438451 INFO AppDaemon: Client disconnection from Admin Client
2024-09-30 13:39:40.020050 INFO AppDaemon: New client Admin Client connected


En vircom:
Afbeeldingslocatie: https://tweakers.net/i/XwuNrRtYCDXFZxEb7UzKYaUfzG0=/full-fit-in/4000x4000/filters:no_upscale():fill(white):strip_exif()/f/image/ij4dZhnlqmvbioaQKiOOZiXt.png?f=user_large
andre75 schreef op zaterdag 28 september 2024 @ 22:56:
[...]


Ik liep tegen hetzelfde probleem aan. Gebruik de mqtt explorer om de kijken of je de data binnen krijgt.
Een paar keer de App deamon opnieuw opstarten kan ook helpen. Ik ben er ook een tijdje mee aan het klooien geweest om het werkend te krijgen. Weet er zeker van dat MQTT user en MQTT pass correct is.
Bij mij heeft het op de Raspberry goed gewerkt en na overgang op een Nuc kreeg ik het niet meer voor elkaar om het werkend te krijgen. Uiteindelijk port 8899 aangepast naar poort 502 Poort 502 is een modbus poort.
Nu werkt het prima.
De inloggegevens voor MQTT zijn correct (net nog gecheckt), maar afgaande op het verschil in logs lijkt het erop dat de app niet gestart wordt. Echter: geen idee waarom :?

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
chapie schreef op maandag 30 september 2024 @ 14:13:
[...]


Bij deze de inhoud van de logfile:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 Add-on: AppDaemon
 Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
 Add-on version: 0.16.7
 You are running the latest version of this add-on.
 System: Home Assistant OS 13.1  (amd64 / qemux86-64)
 Home Assistant Core: 2024.9.2
 Home Assistant Supervisor: 2024.09.1
-----------------------------------------------------------
 Please, share the above information when looking for help
 or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service init-appdaemon: starting
Looking in indexes: https://pypi.org/simple, https://wheels.home-assistant.io/musllinux-index/
Collecting pyserial
  Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl.metadata (1.6 kB)
Downloading https://wheels.home-assistant.io/musllinux-index/pyserial-3.5-py2.py3-none-any.whl (90 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 90.6/90.6 kB 6.2 MB/s eta 0:00:00
Installing collected packages: pyserial
Successfully installed pyserial-3.5
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
s6-rc: info: service init-appdaemon successfully started
s6-rc: info: service appdaemon: starting
s6-rc: info: service appdaemon successfully started
s6-rc: info: service legacy-services: starting
[13:39:23] INFO: Starting AppDaemon...
s6-rc: info: service legacy-services successfully started
2024-09-30 13:39:25.421800 INFO AppDaemon: AppDaemon Version 4.4.2 starting
2024-09-30 13:39:25.422200 INFO AppDaemon: Python version is 3.11.10
2024-09-30 13:39:25.422280 INFO AppDaemon: Configuration read from: /config/appdaemon.yaml
2024-09-30 13:39:25.422342 INFO AppDaemon: Added log: AppDaemon
2024-09-30 13:39:25.422430 INFO AppDaemon: Added log: Error
2024-09-30 13:39:25.422794 INFO AppDaemon: Added log: Access
2024-09-30 13:39:25.422860 INFO AppDaemon: Added log: Diag
2024-09-30 13:39:25.533898 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2024-09-30 13:39:25.646288 INFO HASS: HASS Plugin Initializing
2024-09-30 13:39:25.647361 WARNING HASS: ha_url not found in HASS configuration - module not initialized
2024-09-30 13:39:25.647447 INFO HASS: HASS Plugin initialization complete
2024-09-30 13:39:25.649415 INFO AppDaemon: Initializing HTTP
2024-09-30 13:39:25.649564 INFO AppDaemon: Using 'ws' for event stream
2024-09-30 13:39:25.651239 INFO AppDaemon: Starting API
2024-09-30 13:39:25.652280 INFO AppDaemon: Starting Admin Interface
2024-09-30 13:39:25.652419 INFO AppDaemon: Starting Dashboards
2024-09-30 13:39:25.673586 INFO HASS: Connected to Home Assistant 2024.9.2
2024-09-30 13:39:25.722420 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring
2024-09-30 13:39:25.723895 INFO AppDaemon: App 'hewalex2mqtt' added
2024-09-30 13:39:25.724383 INFO AppDaemon: Found 1 active apps
2024-09-30 13:39:25.724485 INFO AppDaemon: Found 0 inactive apps
2024-09-30 13:39:25.724565 INFO AppDaemon: Found 0 global libraries
2024-09-30 13:39:25.724651 INFO AppDaemon: Starting Apps with 1 workers and 1 pins
2024-09-30 13:39:25.727118 INFO AppDaemon: Running on port 5050
2024-09-30 13:39:25.735347 INFO HASS: Evaluating startup conditions
2024-09-30 13:39:25.742248 INFO HASS: Startup condition met: hass state=RUNNING
2024-09-30 13:39:25.742697 INFO HASS: All startup conditions met
2024-09-30 13:39:25.756136 INFO AppDaemon: Got initial state from namespace default
2024-09-30 13:39:25.956020 INFO AppDaemon: New client Admin Client connected
2024-09-30 13:39:27.754464 INFO AppDaemon: Scheduler running in realtime
2024-09-30 13:39:27.776216 INFO AppDaemon: Reading config
2024-09-30 13:39:27.819284 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring
2024-09-30 13:39:27.819903 INFO AppDaemon: /config/apps/config/packages/hewalex.yaml added or modified
2024-09-30 13:39:27.823393 INFO AppDaemon: Found 1 active apps
2024-09-30 13:39:27.823743 INFO AppDaemon: Found 0 inactive apps
2024-09-30 13:39:27.823830 INFO AppDaemon: Found 0 global libraries
2024-09-30 13:39:27.832802 INFO AppDaemon: Adding /config/apps to module import path
2024-09-30 13:39:27.833494 INFO AppDaemon: Adding /config/apps/hewalex_geco to module import path
2024-09-30 13:39:27.833719 INFO AppDaemon: Adding /config/apps/hewalex_geco/devices to module import path
2024-09-30 13:39:27.833931 INFO AppDaemon: Adding /config/apps/hewalex_geco/examples to module import path
2024-09-30 13:39:27.834898 INFO AppDaemon: Adding /config/apps/config to module import path
2024-09-30 13:39:27.835668 INFO AppDaemon: Adding /config/apps/config/packages to module import path
2024-09-30 13:39:27.856823 WARNING AppDaemon: No app description found for: /config/apps/hewalex2mqtt.py - ignoring
2024-09-30 13:39:27.858106 WARNING AppDaemon: No app description found for: /config/apps/hello.py - ignoring
2024-09-30 13:39:27.860650 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/crc.py - ignoring
2024-09-30 13:39:27.862827 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/__init__.py - ignoring
2024-09-30 13:39:27.865162 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/PCWU.py - ignoring
2024-09-30 13:39:27.867236 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/base.py - ignoring
2024-09-30 13:39:27.871985 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/__init__.py - ignoring
2024-09-30 13:39:27.874737 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/ZPS.py - ignoring
2024-09-30 13:39:27.876823 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/zps_example.py - ignoring
2024-09-30 13:39:27.878921 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/pcwu_eavesdropping.py - ignoring
2024-09-30 13:39:27.880755 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/pcwu_directcomms.py - ignoring
2024-09-30 13:39:27.882526 INFO AppDaemon: App initialization complete
2024-09-30 13:39:36.438451 INFO AppDaemon: Client disconnection from Admin Client
2024-09-30 13:39:40.020050 INFO AppDaemon: New client Admin Client connected


En vircom:
[Afbeelding]


[...]


De inloggegevens voor MQTT zijn correct (net nog gecheckt), maar afgaande op het verschil in logs lijkt het erop dat de app niet gestart wordt. Echter: geen idee waarom :?
Het lijkt erop, dat AppDeamon geen MQTT verbinding kan maken. Wat staat er in de requirements.txt van AppDeamon?

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • Surfari
  • Registratie: Mei 2021
  • Laatst online: 16:46
Martin7182 schreef op maandag 30 september 2024 @ 12:47:
Vraagje over diagram no. 3, t.b.v. anti-legionellarun;
[Afbeelding]
Hoe is de extra circulatiepomp hier aangesloten; tussen boven en midden of tussen onder en midden?

Ik draai de run nu nog zonder extra circulatiepomp en laat de Wilo pomp doorlopen terwijl het element aan staat. Die pomp circuleert dus alleen de onderste helft van het vat. Zodra daar de 60 °C wordt aangetikt is de temperatuur bovenin al zo'n 75 °C. Om dat op te lossen wil ik een extra circulatiepomp aansluiten, maar dan tussen de boven- en onderkant zodat water door het hele vat circuleert. Is dat de juiste manier?
De extra circulatiepomp is in dit schema bedoeld als retourpomp van een circulatiesysteem. Het tapwater circuleert dan continu, na het laatste tappunt gaat het water retour naar de boiler via deze pomp. Voor normale woningen niet nodig, het is bruikbaar als je lange leidingen hebt zodat bij een tappunt direct warm water beschikbaar is. Het systeem kost energie vanwege de circulatiepomp en de continue warmteverliezen van de leidingen.

Deze opzet alleen voor de legionella run inzetten is het niet zo handig; de retourleidingen zijn buiten de legionella run lauw of niet koud maar het water staat stil dus het is juist een risico. Ook moet tijdens de run het retourwater liefst 60 graden of meer zijn en dan kom je al gauw aan een aanvoertemperatuur die 10 graden meer is(warmteverliezen van de leidingen) dus dat lost je probleem niet op.
Je kunt idd de pomp van bovenste naar middelste of onderste aansluiting laten pompen(moet evt een terugslagklep bij). Of je dan de sturing kunt gebruiken die bij dit schema hoort weet ik niet. Het zal je bedoeling zijn alleen tijdens legionella run de pomp te laten draaien?

Acties:
  • 0 Henk 'm!

  • Martin7182
  • Registratie: Juni 2020
  • Laatst online: 21:25
Bedankt @Surfari, alleen tijdens de anti-legionellarun inderdaad. Wat vreemd is, is dat je met schema no. 1 (zonder extra circulatiepomp) geen anti-legionellarun kunt programmeren. Daarom dacht ik ook dat de extra pomp hiervoor bedoeld was. Maar goed, ik ga dus tussen boven en onder aansluiten met keerklep. Het warme water kan dan misschien ook iets gaan circuleren door de stilstaande Wilo / WP circuit, maar dat maakt niet uit.

Acties:
  • +1 Henk 'm!

  • Surfari
  • Registratie: Mei 2021
  • Laatst online: 16:46
Martin7182 schreef op maandag 30 september 2024 @ 16:53:
Bedankt @Surfari, alleen tijdens de anti-legionellarun inderdaad. Wat vreemd is, is dat je met schema no. 1 (zonder extra circulatiepomp) geen anti-legionellarun kunt programmeren. Daarom dacht ik ook dat de extra pomp hiervoor bedoeld was. Maar goed, ik ga dus tussen boven en onder aansluiten met keerklep. Het warme water kan dan misschien ook iets gaan circuleren door de stilstaande Wilo / WP circuit, maar dat maakt niet uit.
Tja, het is anti-legionella-run, maar ik maak er maar legionella-run van laat die legionellen maar wegrennen😀.
Ook In de opstelling van schema 2 is het legionella programma niet beschikbaar.
Het is alleen beschikbaar met extra warmtebronnen(heater elementen, cv, kachel).
Maar je hebt een heater element dus dan zou schema 3 of 4 van toepassing zijn. Dat kun je ook instellen als er (nog) geen
circulatiepomp is.

Acties:
  • 0 Henk 'm!

  • chapie
  • Registratie: Oktober 2003
  • Laatst online: 11-09 18:39
Jojan265 schreef op maandag 30 september 2024 @ 14:57:
[...]

Het lijkt erop, dat AppDeamon geen MQTT verbinding kan maken. Wat staat er in de requirements.txt van AppDeamon?
Daar staat het volgende in:
code:
1
pyserial

Ergens kwam ik tegen dat je in de config van AppDaemon python packages kon toevoegen, daar heb ik "pyserial" en "mqtt" toegevoegd, die worden geladen. Verder heb ik nu het volgende in de logging:

code:
1
2
3
4
5
6
7
2024-10-01 11:38:24.653355 INFO HASS: Connected to Home Assistant 2024.9.2
2024-10-01 11:38:24.667007 INFO MQTT: Connected to Broker at URL 192.168.0.11:1883
2024-10-01 11:38:24.709684 INFO HASS: Evaluating startup conditions
2024-10-01 11:38:24.712208 INFO AppDaemon: Got initial state from namespace mqtt
2024-10-01 11:38:24.712571 INFO MQTT: MQTT Plugin initialization complete
2024-10-01 11:38:24.713243 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring
2024-10-01 11:38:24.715482 INFO HASS: Startup condition met: hass state=RUNNING

MQTT is dus verbonden met de broker blijkt uit bovenstaande. In het log van de MQTT broker staat het volgende:

code:
1
2
2024-10-01 14:19:09: New connection from 172.30.32.1:46174 on port 1883.
2024-10-01 14:19:09: New client connected from 172.30.32.1:46174 as appdaemon_mqtt_client (p2, c1, k60, u'*username*').

Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring

Dit suggereert dat er een app genaamd 'mqtt' is in je configuratie die niet correct is opgezet. Zorg ervoor dat elke app in je apps.yaml bestand de vereiste module en class velden heeft. Bijvoorbeeld:

mqtt:
module: mijn_mqtt_module
class: MijnMQTTClass


In mijn \addon_configs\a0d7b954_appdaemon\apps

Heb ik het bestand apps.yaml. met daarin:


code:
1
2
3
hewalex2qtt:
  module: hewalex2mqtt
  class: Hewalex2MQTT


MIjn stuk van de logile wat afwijkt van die van jouw:
code:
1

2024-10-01 20:10:21.660132 INFO HASS: Startup condition met: hass state=RUNNING
2024-10-01 20:10:21.661119 INFO HASS: All startup conditions met
2024-10-01 20:10:21.820371 INFO AppDaemon: Got initial state from namespace default
2024-10-01 20:10:23.522304 INFO AppDaemon: Scheduler running in realtime
2024-10-01 20:10:23.530149 INFO AppDaemon: Adding /config/apps to module import path
2024-10-01 20:10:23.531577 INFO AppDaemon: Adding /config/apps/hewalex_geco to module import path
2024-10-01 20:10:23.533119 INFO AppDaemon: Adding /config/apps/hewalex_geco/devices to module import path
2024-10-01 20:10:23.534959 INFO AppDaemon: Adding /config/apps/hewalex_geco/examples to module import path
2024-10-01 20:10:23.559267 INFO AppDaemon: Loading App Module: /config/apps/hewalex2mqtt.py
2024-10-01 20:10:24.167198 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/__init__.py - ignoring
2024-10-01 20:10:24.169991 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/crc.py - ignoring
2024-10-01 20:10:24.173370 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/base.py - ignoring
2024-10-01 20:10:24.176297 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/zps.py - ignoring
2024-10-01 20:10:24.179241 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/__init__.py - ignoring
2024-10-01 20:10:24.182750 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/devices/pcwu.py - ignoring
2024-10-01 20:10:24.186140 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/pcwu_eavesdropping.py - ignoring
2024-10-01 20:10:24.189271 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/zps_example.py - ignoring
2024-10-01 20:10:24.192445 WARNING AppDaemon: No app description found for: /config/apps/hewalex_geco/examples/pcwu_directcomms.py - ignoring
2024-10-01 20:10:24.195038 INFO AppDaemon: Loading app hewalex2qtt using class Hewalex2MQTT from module hewalex2mqtt
2024-10-01 20:10:24.200827 INFO AppDaemon: Calling initialize() for hewalex2qtt
2024-10-01 20:10:24,204 :: hewalex2mqtt :: INFO :: Initializing Hewalex 2 Mqtt
2024-10-01 20:10:24,204 :: hewalex2mqtt :: INFO :: reading config
2024-10-01 20:10:24,208 :: hewalex2mqtt :: INFO :: MQTT ip: 192.168.50.171
2024-10-01 20:10:24,208 :: hewalex2mqtt :: INFO :: MQTT port: 1883
2024-10-01 20:10:24,209 :: hewalex2mqtt :: INFO :: MQTT authentication: True
2024-10-01 20:10:24,209 :: hewalex2mqtt :: INFO :: MQTT user: addons
2024-10-01 20:10:24,209 :: hewalex2mqtt :: INFO :: MQTT pass:[/code]


Met name dit deel:
code:
1
2024-09-30 13:39:27.856823 WARNING AppDaemon: No app description found for: /config/apps/hewalex2mqtt.py - ignoring


Geeft al aan de AppDaemon de app hewalex2mqtt.py probeert te laden, maar geen geldige configuratie voor deze app kan vinden in je apps.yaml bestand.

[ Voor 96% gewijzigd door Sterke-Jerke op 01-10-2024 20:18 ]

S.J.


Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
chapie schreef op dinsdag 1 oktober 2024 @ 14:26:
[...]

Daar staat het volgende in:
code:
1
pyserial

Ergens kwam ik tegen dat je in de config van AppDaemon python packages kon toevoegen, daar heb ik "pyserial" en "mqtt" toegevoegd, die worden geladen. Verder heb ik nu het volgende in de logging:

code:
1
2
3
4
5
6
7
2024-10-01 11:38:24.653355 INFO HASS: Connected to Home Assistant 2024.9.2
2024-10-01 11:38:24.667007 INFO MQTT: Connected to Broker at URL 192.168.0.11:1883
2024-10-01 11:38:24.709684 INFO HASS: Evaluating startup conditions
2024-10-01 11:38:24.712208 INFO AppDaemon: Got initial state from namespace mqtt
2024-10-01 11:38:24.712571 INFO MQTT: MQTT Plugin initialization complete
2024-10-01 11:38:24.713243 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring
2024-10-01 11:38:24.715482 INFO HASS: Startup condition met: hass state=RUNNING

MQTT is dus verbonden met de broker blijkt uit bovenstaande. In het log van de MQTT broker staat het volgende:

code:
1
2
2024-10-01 14:19:09: New connection from 172.30.32.1:46174 on port 1883.
2024-10-01 14:19:09: New client connected from 172.30.32.1:46174 as appdaemon_mqtt_client (p2, c1, k60, u'*username*').
Volgens mij ontbreekt daar de mqtt app:

code:
1
2
3
paho-mqtt==1.5.0
pyserial
configparser

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • chapie
  • Registratie: Oktober 2003
  • Laatst online: 11-09 18:39
Dank voor de hulp tot zover :)
Jojan265 schreef op dinsdag 1 oktober 2024 @ 16:22:
[...]

Volgens mij ontbreekt daar de mqtt app:

code:
1
2
3
paho-mqtt==1.5.0
pyserial
configparser
Ik heb nu paho-mqtt==1.6.1 en configparser toegevoegd aan de configuratie van AppDaemon, evenals de correcte verwijzingen naar bestanden (de bestanden PCWU.py en ZPS.py in hoofdletters konden niet gevonden werden, die hernoemd ging het wel goed).

De melding over mqtt blijft komen in het log:
code:
1
2024-10-02 10:26:57.181040 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring

Maar inmiddels wel wat verder gekomen met jullie hulp, de app hewalex2mqtt laad nu.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2024-10-02 09:44:28.980996 INFO AppDaemon: Loading app hewalex2mqtt using class Hewalex2MQTT from module hewalex2mqtt
2024-10-02 09:44:28.983718 INFO AppDaemon: Calling initialize() for hewalex2mqtt
2024-10-02 09:44:28,984 :: hewalex2mqtt :: INFO :: Initializing Hewalex 2 Mqtt
2024-10-02 09:44:28,985 :: hewalex2mqtt :: INFO :: reading config
2024-10-02 09:44:28,986 :: hewalex2mqtt :: INFO :: MQTT ip: 192.168.0.11
2024-10-02 09:44:28,987 :: hewalex2mqtt :: INFO :: MQTT port: 1883
2024-10-02 09:44:28,988 :: hewalex2mqtt :: INFO :: MQTT authentication: True
2024-10-02 09:44:28,988 :: hewalex2mqtt :: INFO :: MQTT user: **********
2024-10-02 09:44:28,989 :: hewalex2mqtt :: INFO :: MQTT pass: **********
2024-10-02 09:44:28,989 :: hewalex2mqtt :: INFO :: Device_Pcwu_MqttTopic: Heatpump
2024-10-02 09:44:28,989 :: hewalex2mqtt :: DEBUG :: Sending CONNECT (u1, p1, wr0, wq0, wf0, c1, k60) client_id=b''
2024-10-02 09:44:28,990 :: hewalex2mqtt :: INFO :: Subscribed to: Heatpump/Command/#
2024-10-02 09:44:28,990 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m1) [(b'Heatpump/Command/#', 1)]
2024-10-02 09:44:28,994 :: hewalex2mqtt :: DEBUG :: Received CONNACK (0, 0)
2024-10-02 09:44:28,996 :: hewalex2mqtt :: INFO :: Verbonden to MQTT Broker with result code: 0
2024-10-02 09:44:28,997 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m2) [(b'Heatpump/#', 0)]
2024-10-02 09:44:28,998 :: hewalex2mqtt :: INFO :: ABBOSubscribed to MQTT topic: Heatpump/#
2024-10-02 09:44:28,998 :: hewalex2mqtt :: INFO :: Connecting to PCWU at 192.168.0.51:8899
2024-10-02 09:44:28,999 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-10-02 09:44:29,002 :: hewalex2mqtt :: DEBUG :: Received PUBLISH (d0, q0, r1, m0), 'Heatpump/Command/HeatPumpEnabled', ...  (5 bytes)
2024-10-02 09:44:29,002 :: hewalex2mqtt :: INFO :: Received message with topic: Heatpump/Command/HeatPumpEnabled
2024-10-02 09:44:29,003 :: hewalex2mqtt :: INFO :: Received command: False
2024-10-02 09:44:29,003 :: hewalex2mqtt :: INFO :: Received command to set HeatPumpEnabled to False
2024-10-02 09:44:29,004 :: hewalex2mqtt :: INFO :: Serial connection established.
2024-10-02 09:44:29,005 :: hewalex2mqtt :: INFO :: writePcwuConfig: Serial<id=0x7fe6c2426650, open=True>(port='socket://192.168.0.51:8899', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
2024-10-02 09:44:29,406 :: hewalex2mqtt :: INFO :: No data received from PCWU.
2024-10-02 09:44:29,714 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-10-02 09:44:29,715 :: hewalex2mqtt :: DEBUG :: Received PUBLISH (d0, q0, r1, m0), 'Heatpump/Command/HeatPumpEnabled', ...  (5 bytes)
2024-10-02 09:44:29,715 :: hewalex2mqtt :: INFO :: Received message with topic: Heatpump/Command/HeatPumpEnabled
2024-10-02 09:44:29,715 :: hewalex2mqtt :: INFO :: Received command: False
2024-10-02 09:44:29,716 :: hewalex2mqtt :: INFO :: Received command to set HeatPumpEnabled to False
2024-10-02 09:44:29,719 :: hewalex2mqtt :: INFO :: writePcwuConfig: Serial<id=0x7fe6c2426800, open=True>(port='socket://192.168.0.51:8899', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
2024-10-02 09:44:31.221066 INFO AppDaemon: App initialization complete
2024-10-02 09:44:34.053343 INFO AppDaemon: New client Admin Client connected
2024-10-02 09:44:59,008 :: hewalex2mqtt :: INFO :: Connecting to PCWU at 192.168.0.51:8899
2024-10-02 09:44:59,014 :: hewalex2mqtt :: INFO :: Serial connection established.
2024-10-02 09:44:59,433 :: hewalex2mqtt :: INFO :: No data received from PCWU.
2024-10-02 09:45:29,010 :: hewalex2mqtt :: INFO :: Connecting to PCWU at 192.168.0.51:8899
2024-10-02 09:45:29,013 :: hewalex2mqtt :: INFO :: Serial connection established.
2024-10-02 09:45:29,414 :: hewalex2mqtt :: INFO :: No data received from PCWU.
2024-10-02 09:45:29,740 :: hewalex2mqtt :: DEBUG :: Sending PINGREQ
2024-10-02 09:45:29,749 :: hewalex2mqtt :: DEBUG :: Received PINGRESP

In HA krijg ik geen data, het log van de mqttbroker geeft het volgende:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2024-10-02 10:36:18: Saving in-memory database to /data//mosquitto.db.
2024-10-02 10:36:26: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:36:31: New connection from 172.30.32.2:54672 on port 1883.
2024-10-02 10:36:31: Client <unknown> closed its connection.
2024-10-02 10:36:48: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:38:20: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:38:31: New connection from 172.30.32.2:52158 on port 1883.
2024-10-02 10:38:31: Client <unknown> closed its connection.
2024-10-02 10:38:33: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:40:08: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:40:24: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:40:31: New connection from 172.30.32.2:47044 on port 1883.
2024-10-02 10:40:31: Client <unknown> closed its connection.
2024-10-02 10:41:56: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:42:18: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:42:31: New connection from 172.30.32.2:52744 on port 1883.
2024-10-02 10:42:31: Client <unknown> closed its connection.
2024-10-02 10:43:50: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:44:01: Client appdaemon_mqtt_client disconnected.
2024-10-02 10:44:03: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:44:11: Client auto-52564E86-CE70-C3EF-ED63-497E3981375B closed its connection.
2024-10-02 10:44:24: New connection from 172.30.32.1:34372 on port 1883.
2024-10-02 10:44:24: New client connected from 172.30.32.1:34372 as appdaemon_mqtt_client (p2, c1, k60, u'*********').
2024-10-02 10:44:31: New connection from 172.30.32.2:38872 on port 1883.
2024-10-02 10:44:31: Client <unknown> closed its connection.
2024-10-02 10:45:27: Client appdaemon_mqtt_client disconnected.
2024-10-02 10:45:38: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:45:46: New connection from 172.30.32.1:38404 on port 1883.
2024-10-02 10:45:46: New client connected from 172.30.32.1:38404 as appdaemon_mqtt_client (p2, c1, k60, u'*********').
2024-10-02 10:45:47: New connection from 172.30.32.1:38416 on port 1883.
2024-10-02 10:45:47: New client connected from 172.30.32.1:38416 as auto-7B271437-8ED4-C89F-74CB-10864F661C73 (p2, c1, k60, u'**********').
2024-10-02 10:46:04: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:46:31: New connection from 172.30.32.2:40364 on port 1883.
2024-10-02 10:46:31: Client <unknown> closed its connection.

Kan het zijn dat de WaveShare geen data binnen krijgt en dus ook niets doorzet? Is het bij RS485 nodig naast de A en de B ook de + en de - aan te sluiten wanneer er op de andere pinheader (van de Geco) de + en de - aangesloten zit?

Acties:
  • 0 Henk 'm!

  • Jojan265
  • Registratie: Februari 2022
  • Laatst online: 21:12
chapie schreef op woensdag 2 oktober 2024 @ 10:54:
Dank voor de hulp tot zover :)


[...]


Ik heb nu paho-mqtt==1.6.1 en configparser toegevoegd aan de configuratie van AppDaemon, evenals de correcte verwijzingen naar bestanden (de bestanden PCWU.py en ZPS.py in hoofdletters konden niet gevonden werden, die hernoemd ging het wel goed).

De melding over mqtt blijft komen in het log:
code:
1
2024-10-02 10:26:57.181040 WARNING AppDaemon: App 'mqtt' missing 'class' or 'module' entry - ignoring

Maar inmiddels wel wat verder gekomen met jullie hulp, de app hewalex2mqtt laad nu.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2024-10-02 09:44:28.980996 INFO AppDaemon: Loading app hewalex2mqtt using class Hewalex2MQTT from module hewalex2mqtt
2024-10-02 09:44:28.983718 INFO AppDaemon: Calling initialize() for hewalex2mqtt
2024-10-02 09:44:28,984 :: hewalex2mqtt :: INFO :: Initializing Hewalex 2 Mqtt
2024-10-02 09:44:28,985 :: hewalex2mqtt :: INFO :: reading config
2024-10-02 09:44:28,986 :: hewalex2mqtt :: INFO :: MQTT ip: 192.168.0.11
2024-10-02 09:44:28,987 :: hewalex2mqtt :: INFO :: MQTT port: 1883
2024-10-02 09:44:28,988 :: hewalex2mqtt :: INFO :: MQTT authentication: True
2024-10-02 09:44:28,988 :: hewalex2mqtt :: INFO :: MQTT user: **********
2024-10-02 09:44:28,989 :: hewalex2mqtt :: INFO :: MQTT pass: **********
2024-10-02 09:44:28,989 :: hewalex2mqtt :: INFO :: Device_Pcwu_MqttTopic: Heatpump
2024-10-02 09:44:28,989 :: hewalex2mqtt :: DEBUG :: Sending CONNECT (u1, p1, wr0, wq0, wf0, c1, k60) client_id=b''
2024-10-02 09:44:28,990 :: hewalex2mqtt :: INFO :: Subscribed to: Heatpump/Command/#
2024-10-02 09:44:28,990 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m1) [(b'Heatpump/Command/#', 1)]
2024-10-02 09:44:28,994 :: hewalex2mqtt :: DEBUG :: Received CONNACK (0, 0)
2024-10-02 09:44:28,996 :: hewalex2mqtt :: INFO :: Verbonden to MQTT Broker with result code: 0
2024-10-02 09:44:28,997 :: hewalex2mqtt :: DEBUG :: Sending SUBSCRIBE (d0, m2) [(b'Heatpump/#', 0)]
2024-10-02 09:44:28,998 :: hewalex2mqtt :: INFO :: ABBOSubscribed to MQTT topic: Heatpump/#
2024-10-02 09:44:28,998 :: hewalex2mqtt :: INFO :: Connecting to PCWU at 192.168.0.51:8899
2024-10-02 09:44:28,999 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-10-02 09:44:29,002 :: hewalex2mqtt :: DEBUG :: Received PUBLISH (d0, q0, r1, m0), 'Heatpump/Command/HeatPumpEnabled', ...  (5 bytes)
2024-10-02 09:44:29,002 :: hewalex2mqtt :: INFO :: Received message with topic: Heatpump/Command/HeatPumpEnabled
2024-10-02 09:44:29,003 :: hewalex2mqtt :: INFO :: Received command: False
2024-10-02 09:44:29,003 :: hewalex2mqtt :: INFO :: Received command to set HeatPumpEnabled to False
2024-10-02 09:44:29,004 :: hewalex2mqtt :: INFO :: Serial connection established.
2024-10-02 09:44:29,005 :: hewalex2mqtt :: INFO :: writePcwuConfig: Serial<id=0x7fe6c2426650, open=True>(port='socket://192.168.0.51:8899', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
2024-10-02 09:44:29,406 :: hewalex2mqtt :: INFO :: No data received from PCWU.
2024-10-02 09:44:29,714 :: hewalex2mqtt :: DEBUG :: Received SUBACK
2024-10-02 09:44:29,715 :: hewalex2mqtt :: DEBUG :: Received PUBLISH (d0, q0, r1, m0), 'Heatpump/Command/HeatPumpEnabled', ...  (5 bytes)
2024-10-02 09:44:29,715 :: hewalex2mqtt :: INFO :: Received message with topic: Heatpump/Command/HeatPumpEnabled
2024-10-02 09:44:29,715 :: hewalex2mqtt :: INFO :: Received command: False
2024-10-02 09:44:29,716 :: hewalex2mqtt :: INFO :: Received command to set HeatPumpEnabled to False
2024-10-02 09:44:29,719 :: hewalex2mqtt :: INFO :: writePcwuConfig: Serial<id=0x7fe6c2426800, open=True>(port='socket://192.168.0.51:8899', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
2024-10-02 09:44:31.221066 INFO AppDaemon: App initialization complete
2024-10-02 09:44:34.053343 INFO AppDaemon: New client Admin Client connected
2024-10-02 09:44:59,008 :: hewalex2mqtt :: INFO :: Connecting to PCWU at 192.168.0.51:8899
2024-10-02 09:44:59,014 :: hewalex2mqtt :: INFO :: Serial connection established.
2024-10-02 09:44:59,433 :: hewalex2mqtt :: INFO :: No data received from PCWU.
2024-10-02 09:45:29,010 :: hewalex2mqtt :: INFO :: Connecting to PCWU at 192.168.0.51:8899
2024-10-02 09:45:29,013 :: hewalex2mqtt :: INFO :: Serial connection established.
2024-10-02 09:45:29,414 :: hewalex2mqtt :: INFO :: No data received from PCWU.
2024-10-02 09:45:29,740 :: hewalex2mqtt :: DEBUG :: Sending PINGREQ
2024-10-02 09:45:29,749 :: hewalex2mqtt :: DEBUG :: Received PINGRESP

In HA krijg ik geen data, het log van de mqttbroker geeft het volgende:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2024-10-02 10:36:18: Saving in-memory database to /data//mosquitto.db.
2024-10-02 10:36:26: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:36:31: New connection from 172.30.32.2:54672 on port 1883.
2024-10-02 10:36:31: Client <unknown> closed its connection.
2024-10-02 10:36:48: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:38:20: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:38:31: New connection from 172.30.32.2:52158 on port 1883.
2024-10-02 10:38:31: Client <unknown> closed its connection.
2024-10-02 10:38:33: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:40:08: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:40:24: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:40:31: New connection from 172.30.32.2:47044 on port 1883.
2024-10-02 10:40:31: Client <unknown> closed its connection.
2024-10-02 10:41:56: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:42:18: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:42:31: New connection from 172.30.32.2:52744 on port 1883.
2024-10-02 10:42:31: Client <unknown> closed its connection.
2024-10-02 10:43:50: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:44:01: Client appdaemon_mqtt_client disconnected.
2024-10-02 10:44:03: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:44:11: Client auto-52564E86-CE70-C3EF-ED63-497E3981375B closed its connection.
2024-10-02 10:44:24: New connection from 172.30.32.1:34372 on port 1883.
2024-10-02 10:44:24: New client connected from 172.30.32.1:34372 as appdaemon_mqtt_client (p2, c1, k60, u'*********').
2024-10-02 10:44:31: New connection from 172.30.32.2:38872 on port 1883.
2024-10-02 10:44:31: Client <unknown> closed its connection.
2024-10-02 10:45:27: Client appdaemon_mqtt_client disconnected.
2024-10-02 10:45:38: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:45:46: New connection from 172.30.32.1:38404 on port 1883.
2024-10-02 10:45:46: New client connected from 172.30.32.1:38404 as appdaemon_mqtt_client (p2, c1, k60, u'*********').
2024-10-02 10:45:47: New connection from 172.30.32.1:38416 on port 1883.
2024-10-02 10:45:47: New client connected from 172.30.32.1:38416 as auto-7B271437-8ED4-C89F-74CB-10864F661C73 (p2, c1, k60, u'**********').
2024-10-02 10:46:04: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:46:31: New connection from 172.30.32.2:40364 on port 1883.
2024-10-02 10:46:31: Client <unknown> closed its connection.

Kan het zijn dat de WaveShare geen data binnen krijgt en dus ook niets doorzet? Is het bij RS485 nodig naast de A en de B ook de + en de - aan te sluiten wanneer er op de andere pinheader (van de Geco) de + en de - aangesloten zit?
Dit ijkt al een heel stuk beter. Het enige dat nu nog mist lijkt de serial data te zijn. Je hoeft de + en - aansluiting niet te gebruiken van de RS 485 poort. Aks je de Hewalex op een andere manier van spanning voorziet is dat prima.

Ik zie nu dat je Waveshare als mqtt client is aangemeld op de broker. Dit hoeft niet en gaat met dezelfde user ook problemen opleveren. De Waveshare hoeft eigenlijk helemaal niet meer via mqtt aangemeld te worden, aangezien AppDeamon er nu voor zorgt, dat de seriele data omgezet wordt naar mqtt. Dit laatste lijkt nu goed te werken. Ik zou in VirCom de mqtt even uitschakelen (of user veranderen) en dan verwacht ik dat het wel werkt na en een herstart van de Waveshare en daarna herstart van AppDeamon.

LG-HM071MR-U44 / SWW Hewalex PCWU 3.0 / PV SMA + Jinko 14 kWp / Kia e-Niro


Acties:
  • 0 Henk 'm!

  • andre75
  • Registratie: Maart 2022
  • Laatst online: 21:09
@Jojan265 Ik heb in Home Assistant nog wat toevoegingen gemaakt voor de Hewalex warmtepomp. Ik heb een COP berekening gemaakt zoadat ik het rendement kan zien. Ook heb ik een counter voor de compressor gemaakt zodat ik kan zien hoe vaak de warmtepomp start. Het afgegeven vermogen wat de Hewalex levert kan ik nu ook zien.

Even terugkomend op @chapie In de Mqtt explorer zou hij de data moeten kunnen zien. Een paar keer de AppDeamon herstarten helpt ook. Het heeft mij ook wat moeite gekost om het werkend te krijgen. Maar nu het werkt met de info van @Jojan265 ben ik er erg blij mee.

[ Voor 4% gewijzigd door andre75 op 02-10-2024 17:13 ]


Acties:
  • 0 Henk 'm!

  • Sterke-Jerke
  • Registratie: Juni 2006
  • Laatst online: 18:00
Ik zie nog iets geks:

Hier gaat de connect met mqtt goed:

code:
1
2
3
4
5
6
7
2024-10-02 09:44:28,986 :: hewalex2mqtt :: INFO :: MQTT ip: 192.168.0.11
2024-10-02 09:44:28,987 :: hewalex2mqtt :: INFO :: MQTT port: 1883
2024-10-02 09:44:28,988 :: hewalex2mqtt :: INFO :: MQTT authentication: True
2024-10-02 09:44:28,988 :: hewalex2mqtt :: INFO :: MQTT user: **********
2024-10-02 09:44:28,989 :: hewalex2mqtt :: INFO :: MQTT pass: **********
2024-10-02 09:44:28,989 :: hewalex2mqtt :: INFO :: Device_Pcwu_MqttTopic: Heatpump
2024-10-02 09:44:28,989 :: hewalex2mqtt :: DEBUG :: Sending CONNECT (u1, p1, wr0



Maar in de andere logfile wordt er ook een ander IP adres geprobeerd:

code:
1
2
3
4
024-10-02 10:36:48: New connection from 192.168.0.51:8900 on port 1883.
2024-10-02 10:38:20: Client <unknown> has exceeded timeout, disconnecting.
2024-10-02 10:38:31: New connection from 172.30.32.2:52158 on port 1883.
2024-10-02 10:38:31: Client <unknown> closed its connection.


Mocht eea op dezelfde host draaien, misschien 127.0.0.1 ofzo gebruiken? Is iig niet 100% ok.


In eerste instantie is de MQTT-verbinding opgezet, en het script heeft succesvol geabonneerd op de relevante command topics (Heatpump/Command/#).
Het ontvangt berichten op deze topics, zoals zichtbaar in de logs waar commando's om de warmtepomp uit te schakelen zijn ontvangen.

Echter idd de seriële communicatie met de PCWU lijkt niet goed te werken.

Het script heeft succesvol een seriele verbinding gemaakt met de PCWU op IP 192.168.0.51 en poort 8899.

Er worden meerdere pogingen zijn gedaan om met de PCWU te communiceren, maar er wordt telkens gemeld dat er geen data is ontvangen van de PCWU. Dit kan wijzen op een issue met de PCWU zelf, de configuratie ervan, of de communicatieparameters (zoals baudrate, parity, etc.).


Wat het nog kan zijn is dat je ID's fout staan:
In in de hewalex2mqtt.py staat bij mij:

code:
1
2
3
# PCWU (Slave)
        self.devHardId = 2
        self.devSoftId = 2


Ik zal kijken of ik m;n scipt aan kan passen, zodat dit in de config file komt te staan.

S.J.

Pagina: 1 ... 19 ... 22 Laatste