the78mole / esphome_components

ESPhome Components from the little digger
Other
24 stars 11 forks source link

Expand writer queue #7

Closed jensgraef closed 1 year ago

jensgraef commented 1 year ago

Currently the writer class only supports one telegram at a time. This should be changed to allow multiple pending write commands.

See https://github.com/the78mole/esphome_components/issues/4#issuecomment-1336187716 for the original suggestion.

jensgraef commented 1 year ago

I just pushed the first attempt at implementing a writer queue to https://github.com/the78mole/esphome_components/tree/larger-write-queue It compiles but I have not yet tested it it.

Cases to test:

Bascht74 commented 1 year ago

I testet the new tree with my config and it works at least in normal environments.

I am using this configuration right now:

select:
  - platform: template
    name: "Warmwasser Betriebsart"
    id: warmwasser_betriebsart
    entity_category: config
    optimistic: true
    options:
      - Dauerhaft aus (0)
      - Dauerhaft ein (1)
      - Automatik (2)
    initial_option: Automatik (2)
    set_action: 
      - lambda:
          auto index = id(warmwasser_betriebsart).index_of(x);
          if (index.has_value()) {
            uint8_t command[] = {0x0C, 0x0E, (uint8_t)index.value(), 0x65, 0x65, 0x65, 0x65, 0x65};
            budoil->writer.enqueueTelegram(command, 8);
          }
  - platform: template
    name: "Heizung Betriebsart"
    id: heizung_betriebsart
    entity_category: config
    optimistic: true
    options:
      - manuell Nacht (0)
      - manuell Tag (1)
      - Automatik (2)
    initial_option: Automatik (2)
    set_action: 
      - lambda:
          auto index = id(heizung_betriebsart).index_of(x);
          if (index.has_value()) {
            uint8_t command[] = {0x07, 0x00, 0x65, 0x65, 0x65, 0x65, (uint8_t)index.value(), 0x65};
            budoil->writer.enqueueTelegram(command, 8);
          }
  - platform: template
    name: "Warmwasser Zirkulation"
    id: warmwasser_zirkulation
    entity_category: config
    optimistic: true
    options:
      - dauerhaft aus
      - 1x pro Stunde
      - 2x pro Stunde
      - 3x pro Stunde
      - 4x pro Stunde
      - 5x pro Stunde
      - 6x pro Stunde
      - dauerhaft an
    initial_option: 1x pro Stunde
    set_action: 
      - lambda:
          auto index = id(warmwasser_zirkulation).index_of(x);
          if (index.has_value()) {
            uint8_t command[] = {0x0C, 0x0E, 0x65, 0x65, 0x65, 0x65, 0x65, (uint8_t)index.value()};
            budoil->writer.enqueueTelegram(command, 8);
          }
  - platform: template
    name: "Sommer ab"
    id: sommer_ab
    entity_category: config
    optimistic: true
    options:
      - Sommer
      - 10 °C
      - 11 °C
      - 12 °C
      - 13 °C
      - 14 °C
      - 15 °C
      - 16 °C
      - 17 °C
      - 18 °C
      - 19 °C
      - 20 °C
      - 21 °C
      - 22 °C
      - 23 °C
      - 24 °C
      - 25 °C
      - 26 °C
      - 27 °C
      - 28 °C
      - 29 °C
      - 30 °C
      - Winter
    initial_option: 18 °C
    set_action: 
      - lambda:
          auto index = id(sommer_ab).index_of(x);
          if (index.has_value()) {
            uint8_t command[] = {0x07, 0x00, 0x65, (uint8_t)index.value(), 0x65, 0x65, 0x65, 0x65};
            budoil->writer.enqueueTelegram(command, 8);
          }
jensgraef commented 1 year ago

Merged and solved with #10

Bascht74 commented 1 year ago

Cases to test:

  • Adding a single telegram to the writer (no usage of the queue)
  • adding two telegrams to the writer (single usage of the queue)
  • adding three telegrams to the writer (dual usage of the queue - offset calculation check)
  • filling the queue

Can i help with that?

  • Adding a single telegram to the writer (no usage of the queue) --> Works, as I am using this right now.

  • adding two telegrams to the writer (single usage of the queue) --> I could easily add to commands to my select, e.g.

  • lambda: auto index = id(warmwasser_betriebsart).index_of(x); if (index.has_value()) { uint8_t command[] = {0x07, 0x00, 0x65, 0, 0x65, 0x65, 0x65, 0x65}; budoil->writer.enqueueTelegram(command, 8); uint8_t command[] = {0x07, 0x00, 0x65, (uint8_t)index.value(), 0x65, 0x65, 0x65, 0x65}; budoil->writer.enqueueTelegram(command, 8);

  • adding three telegrams to the writer (dual usage of the queue - offset calculation check) --> I could easily add to commands to my select, e.g.

  • lambda: auto index = id(warmwasser_betriebsart).index_of(x); if (index.has_value()) { uint8_t command[] = {0x07, 0x00, 0x65, 0, 0x65, 0x65, 0x65, 0x65}; budoil->writer.enqueueTelegram(command, 8); uint8_t command[] = {0x07, 0x00, 0x65, 1, 0x65, 0x65, 0x65, 0x65}; budoil->writer.enqueueTelegram(command, 8); uint8_t command[] = {0x07, 0x00, 0x65, (uint8_t)index.value(), 0x65, 0x65, 0x65, 0x65}; budoil->writer.enqueueTelegram(command, 8);

  • filling the queue --> What does this mean? e.g. add ten, twenty entries to the queue?

... how to check that the result is OK? Just check the the queue is sent to buderus and we get an ACK?

Bascht74 commented 1 year ago

Merged and solved with #10

Ups, I wrote while you merged :-)

jensgraef commented 1 year ago

Yeah, we wrote at the same time. I've added some tests for it, @the78mole tested it on his setup and if it doesn't cause any problems at your installation, I'm happy :)

Bascht74 commented 1 year ago

No problems,

I found a little copy paste error within my lambda, but that was my fault. Works as expected, but I didn't try to add lot's of entries to the queue. Just "normal" chances of values...

the78mole commented 1 year ago

I didn't test all options, but at least it still compiles and works with my config. You both are crazy 🤣 I love it 🥰

But I'll extend my config during the upcoming days. Just need some time for that.

Bascht74 commented 1 year ago

Yes, baby. Genau das, was ich wollte 👍 exactly what I wanted to achieve ... :-)

time:
  - platform: sntp
    id: sntp_time
    on_time:
      # Immer morgens um 08:00 Uhr 15 Minuten Wasser Zirkulation laufen lassen...
      - seconds: 0
        minutes: 0
        hours: 8
        days_of_week: MON-SUN
        then:
          - text_sensor.template.publish:
              id: logging
              state: "Schalte Warmwasserzirkulation für 15 Minuten ein"
          - select.set_index:
              id: warmwasser_zirkulation
              index: 7 # Dauerhaft an
          - delay: 15min # 15 Minuten warten
          - select.set_index:
              id: warmwasser_zirkulation
              index: 0 # wieder Dauerhaft aus
      # Immer Mittwochs um 14:00 Uhr Wasser aufheizen auf 65 Grad für 2 Stunden ...
      - seconds: 0
        minutes: 0
        hours: 14
        days_of_week: WED
        then:
          - text_sensor.template.publish:
              id: logging
              state: "Thermische Desinfektion. Warmwasser für 2 Stunden auf 65 Grad stellen und Warmwasserbetrieb einschalten"
          - select.set_index:
              id: warmwasser_betriebsart
              index: 2 # WW Automatik (Berücksichtigt Heizung Sommer, Urlaub usw.
          - number.set: 
              id: warmwasser_Temperatur
              value: 65 # Grad
          - delay: 90min # 90 Minuten warten
          - text_sensor.template.publish:
              id: logging
              state: "Schalte Warmwasserzirkulation für 30 Minuten zur Spülung / Desinfektion ein"
          - select.set_index:
              id: warmwasser_zirkulation
              index: 7 # Dauerhaft an
          - delay: 30min # 15 Minuten warten
          - text_sensor.template.publish:
              id: logging
              state: "Thermische Desinfektion beendet. Warmwasser wieder auf 50 Grad stellen, Warmwasserbetrieb & Zirkulation wieder ausschalten"
          - select.set_index:
              id: warmwasser_zirkulation
              index: 0 # wieder Dauerhaft aus
          - number.set: 
              id: warmwasser_Temperatur
              value: 50 # Grad
          - select.set_index:
              id: warmwasser_betriebsart
              index: 0 # WW Nachtmodus / Dauerhaft aus
      # Immer jeden Tag außer Mittwochs um 14:00 Uhr Wasser aufheizen auf 50 Grad für 1 Stunde ...
      - seconds: 0
        minutes: 0
        hours: 14
        days_of_week: MON,TUE,THU,FRI,SAT,SUN
        then:
          - text_sensor.template.publish:
              id: logging
              state: "Warmwasserbetrieb für 1 Stunde einschalten"
          - select.set_index:
              id: warmwasser_betriebsart
              index: 2 # WW Automatik (Berücksichtigt Heizung Sommer, Urlaub usw.
          - delay: 1h # 1 Stunden warten
          - text_sensor.template.publish:
              id: logging
              state: "Warmwasserbetrieb wieder ausschalten"
          - select.set_index:
              id: warmwasser_betriebsart
              index: 0 # WW Nachtmodus / Dauerhaft aus

Kleine Nebenstory:

Ich habe übrigens das mit dem defekten Sensor herausbekommen, was da los ist. Der Heizungsbauer hat den einfach nur "lose" in den Warmwasser-Tank reingeschoben. D.h. der lag überhaupt nicht an der wand an und hat daher nur eine "Vermutung" über die Warmwassertemperatur gehabt. Dadurch hat er immer eine zu niedrige Temperatur angezeigt.

Somit hat die Heizung bei zuvor eingestellten 60 Grad immer schön 80° Heizungswasser reingeschoben, bis dann im Messbereich auf 60 Grad "Lufttemperatur" vorhanden waren. Das läuft jetzt schon seit 8 Jahren so, seitdem der WW-Speicher ausgetauscht wurde. Die Verrohrung zwischen Heizung und WW-Speicher waren zudem nur unzureichend gedämmt. Im Kellerraum waren es 22 Grad bei offenem Fenster. Keine Ahnung, was das an Gas über die 8 Jahre gekostet haben dürfte.... Heute kam der Heizungsbauer und hat sich das angesehen und Buderus die "Schuld" gegeben. Er hatte es aber m.E. nicht so eingebaut, wie es in der Anleitung vorhanden war und das Ergebnis "kann so nicht gut funktionieren" einfach "ignoriert". Jetzt wird er ausgetauscht und das ganze ordentlich gemacht... Zusätzlich machen wir jetzt nur 1x pro Tag WW (50°) (14 Uhr, wenn die Heizkörper am wenigsten brauchen) und 1x am Tag Zirkulation zum Spülen (08:00 Uhr, dann ist da schön warmes Wasser) und 1x pro Woche Desinfektion (dafür jetzt 65 Grad) am Mittwoch um 14:00 + 30 Minuten Zirkulation. Bin gespannt, wie sich das Auswirkt. Habe Thermometer im Keller (in HA integriert) und ESPHome am Gaszähler laufen :-).

Will jetzt noch einen Wärmemengenzähler installieren lassen, damit man sehen kann, wie effizient die Heizung noch läuft und ob eine WP (ggf. als Zusatz) geht. In einem anderen Haus habe ich das schon so laufen. Das ist noch ein Konstanttemperaturkessel installiert. Der braucht immer zwischen 60-70 Grad und hatte < 45% Effizienz Den haben wir jetzt schön mit 10cm Dämmung hinten, 6cm vorne und rundum auch nochmal 3cm eingepackt und schon ist die Effizient auf 75% hochgegangen (Raumtemperatur auch von 20,5 Grad auf 16 Grad gesunken im Keller). Viel Heizung und Heizrohre im Keller dämmen hilft scheinbar schon eine Menge. Flir sei Dank, kann man den Erfolg sogar sehen und wo noch Handlungsbedarf ist...

the78mole commented 1 year ago

@Bascht74 ein kleiner Off-Topic-Einschub meinerseits... Das mit der Desinfektion ist mittlerweile sehr umstritten.

Einfach nur den Warmwasserspeicher auf 65 oder 70°C aufheizen bringt langfristig nichts. Es muss mindestens eine Zikulation stattfinden, die zeitgleich den gesamten Warmwasserstrang bis zu den Entnahmestellen auf mindestens 60°C bringt. Allerdings ist mittlerweile auch sehr umstritten, ob es nicht zur Züchtung hitzeresistenten Keime beiträgt, jede Woche einmal Evolution zu spielen.

In Mehrfamilienhäusern ist das keine Frage, da geht es fast nicht anders, aber dort gibt es auch regelmäßige Kontrollen. In Einfamilienhäusern ist es viel wichtiger, dass die Dimensionierung des WW-Speichers passt und der Durchsatz entsprechend gegeben ist. Außerdem macht es auch noch sehr viel aus, welche Rohre nach dem Boiler verlegt sind und wie anfällig diese somit bzgl. Biofilm sind. Macht man jetzt jede Woche eine Desinfektion, erzeugt man ggf. viel tote Biomasse (wenn man Keime im System hat), die sich in "geeigneten Rohren" anlagern und als ideale Nahrungsgrundlage für weitere Keine dienen und man verschiebt das Problem zeitlich nur etwas. Die hohe Temperatur (>60°C) sorgt zudem für Kalkausfällung und man befördert den Ackerboden in den Rohren weiter.

Also insgesamt stehe ich der Bevorratung von Warmwasser und der Legionellenschaltung mittlerweile sehr, sehr kritisch gegenüber und tendiere stark zum Hygienespeicher oder zur Frischwasserstation. Letztere hat den Nachteil, dass es eine weitere Pumpe mit Regelung braucht, ersteres hat aber auch nicht nur Vorteile...

Ich habe momentan auch noch einen WW-Speicher an der Buderus, den ich derzeit auf 50°C Dauerhaft eingestellt habe (das hat aber andere Gründe, das Thermostat in meiner Dursche ist kaputt und das ist die Noch-nicht-autsch-Temperatur). Bei Abwesenheit sollte man dann aber den Speicher runterkühlen und anschließend eben hochheizen und die Leitungen spülen.

Sobald ich die Wärmpumpe in Betrieb hab, wird aber alles auf Hygiene-Pufferspeicher umgestellt und dann bin ich die Sorgen endlich komplett los, muss aber dann schauen, dass Puffer und Brühschutz sauber abgestimmt sind, weil jedes Grad mehr einfach ordentlich Effizienz der WP kostet.

Bascht74 commented 1 year ago

@the78mole Danke für die Info! Werde mal überlegen. Bei mir läuft das WW auch grundsätzlich auf 50 Grad (wenn die Sonne scheint wird es auch wärmer gemacht)

@jensgraef Evtl. gibt es hier noch ein Problem, wenn der Befehl nicht erfolgreich geschickt werden kann, wie hier bei einem Test, wo ich wohl einen Fehler noch mache, zu sehen ist. Scheinbar wird hier weder 10 noch 15 geschickt, sondern es gibt einen Timeout. Der scheint die Anzahl der Retries nicht richtig runterzusetzen... Vielleicht interpretiere ich "retrying" auch falsch.

[01:04:26][D][uart_debug:114]: <<< 04 00 07 01 81 02 C0 CA 10 03 98
[01:04:26][D][uart_debug:114]: >>> 10
[01:04:27][D][uart_debug:114]: <<< 02
[01:04:27][D][uart_debug:114]: >>> 10
[01:04:27][D][uart_debug:114]: <<< 04 00 07 01 81 02 C0 CA 10 03 98
[01:04:27][D][number:054]: 'Max_Kesseltemperatur' - Setting number value
[01:04:27][D][number:113]:   New number value: 80.000000
[01:04:27][D][number:012]: 'Max_Kesseltemperatur': Sending state 80.000000
[01:04:27][D][uart_debug:114]: >>> 10
[01:04:27][D][uart_debug:114]: <<< 02
[01:04:27][D][km271:138]: stx sent, waiting for dle
[01:04:27][D][uart_debug:114]: >>> 02
[01:04:27][D][uart_debug:114]: <<< 10
[01:04:27][D][uart_debug:114]: >>> 00 9A 65 65 65 50 65 65 10 03 BC
[01:04:28][W][km271:119]: ack for writer was invalid, retrying: 2
[01:04:28][D][uart_debug:114]: <<< 02
[01:04:38][D][uart_debug:114]: <<< 02
[01:04:38][D][km271:138]: stx sent, waiting for dle
[01:04:38][D][uart_debug:114]: >>> 02
[01:04:38][D][uart_debug:114]: <<< 10
[01:04:38][D][uart_debug:114]: >>> 00 9A 65 65 65 50 65 65 10 03 BC
[01:04:39][W][km271:119]: ack for writer was invalid, retrying: 2
[01:04:39][D][uart_debug:114]: <<< 02
[01:04:45][D][esp32.preferences:113]: Saving 1 preferences to flash...
[01:04:45][D][esp32.preferences:142]: Saving 1 preferences to flash: 1 cached, 0 written, 0 failed
[01:04:48][D][sensor:127]: 'KM217 WiFi Signal Sensor': Sending state -60.00000 dBm with 0 decimals of accuracy
[01:04:49][D][uart_debug:114]: <<< 02
[01:04:49][D][km271:138]: stx sent, waiting for dle
[01:04:49][D][uart_debug:114]: >>> 02
[01:04:49][D][uart_debug:114]: <<< 10
[01:04:49][D][uart_debug:114]: >>> 00 9A 65 65 65 50 65 65 10 03 BC
[01:04:50][W][km271:119]: ack for writer was invalid, retrying: 2
[01:04:50][D][uart_debug:114]: <<< 02
[01:05:00][D][uart_debug:114]: <<< 02
[01:05:00][D][km271:138]: stx sent, waiting for dle
[01:05:00][D][uart_debug:114]: >>> 02
[01:05:00][D][uart_debug:114]: <<< 10
[01:05:00][D][uart_debug:114]: >>> 00 9A 65 65 65 50 65 65 10 03 BC
[01:05:01][W][km271:119]: ack for writer was invalid, retrying: 2
[01:05:01][D][uart_debug:114]: <<< 02
[01:05:11][D][uart_debug:114]: <<< 02
[01:05:11][D][km271:138]: stx sent, waiting for dle
[01:05:11][D][uart_debug:114]: >>> 02
[01:05:11][D][uart_debug:114]: <<< 10
[01:05:11][D][uart_debug:114]: >>> 00 9A 65 65 65 50 65 65 10 03 BC
[01:05:12][W][km271:119]: ack for writer was invalid, retrying: 2
[01:05:12][D][uart_debug:114]: <<< 02
[01:05:22][D][uart_debug:114]: <<< 02
[01:05:22][D][km271:138]: stx sent, waiting for dle
[01:05:22][D][uart_debug:114]: >>> 02
[01:05:22][D][uart_debug:114]: <<< 10
[01:05:22][D][uart_debug:114]: >>> 00 9A 65 65 65 50 65 65 10 03 BC
[01:05:23][E][km271:122]: ack for writer was invalid and retry count exhausted, aborting: 2
[01:05:23][D][uart_debug:114]: <<< 02
[01:05:33][D][uart_debug:114]: <<< 02
[01:05:33][D][uart_debug:114]: >>> 10
[01:05:33][D][uart_debug:114]: <<< 04 00 07 01 81 02 C0 CA 10 03 98
[01:05:33][D][uart_debug:114]: >>> 10
[01:05:34][D][uart_debug:114]: <<< 02
[01:05:34][D][uart_debug:114]: >>> 10
[01:05:34][D][uart_debug:114]: <<< 04 00 07 01 81 02 C0 CA 10 03 98