Klimaanlage Panasonic Etherea ins HA einbinden

Danke für den Tipp, ich werde mich da nochmal in Ruhedran setzen wenn ich im neuen Jahr ein bischen Zeit und Nerven für hab.

Mal eine andere Frage, ich habe jetzt irgendwo gelesen dass über die ESP Lösung keine inside-temperature übertragen wird, stimmt das?

Also ich habe eine Temperatur, würde sagen, ausprobieren.

Also hab nun mal Zeit gehabt zu löten. Funktioniert genauso wie mit den 5v aber fühle mich ehrlich gesagt sicherer so… heishamon spricht ja auch davon, dass die 5v Leitung nicht für Nutzung gedacht ist. Dachte nur wenn schon dann richtig machen :nerd_face:

Leider ist das Kabel 2cm zu kurz…

Temperatur wird bei mir natürlich auch ausgegeben. Sowohl innen als auch außen.

Vielen Dank auch für den thread, ich hab vorher auch nichts mit esp am Hut gehabt aber dass es so einfach geht hätte ich nicht gedacht. Hab jetzt Lust auf mehr esp :grin:

2 „Gefällt mir“

Ich würde das gerne so nachbauen wie du es realisiert hast. Hast du dafür möglicherweise ein Verdrahtungsschema, dem man folgen kann und eine Übersicht welche Komponenten du verwendest hast?

Aussentemperatur habe ich keine. Wo wird die denn ermittelt und angezeigt?
Ah, habs gefunden. Ist ein eigener Sensor und wird nicht im Klima-Regler selbst angezeigt.

Im Endeffekt hab ich mich an @phettsack Anleitung gehalten.

Außer dass ich die 12V Leitung der AC genommen habe. Vorsicht, ich habe die Pins des Steckers umgesteckt! (Damit die Farben halbwegs passen. Eben rot = +, schwarz =- etc- Sicherheitshalber bei sich durchmessen! Ich hab die CS-Z35ZKEW)

12V DC (rot) auf 5V DC/DC (hab einen MP1584EN von Ali genommen. Ca 1,50€ für 5 Stück). Dann die 5V auf den HV des 5V/3,3V Level shifter(kosten 10 Stück bei ali um 1€) UND an den ESP32 5V. An den Level shifter bei HV1/ HV2 die Datenleitungen der AC (weiß/ gelb).

Vom Level shifter dann die LV Leitung an 3,3V ESP32, LV1 (weiß) an 8 vom ESP32 und LV2 (gelb) an 9 vom ESP32.

GND (schwarz) alle durchschleifen (also an den MP1584EN, den Levelshifter und den ESP)

Am ESP32 brauchst du sowohl den 3,3 V als auch den 5V Anschluss (der ESP nimmt den 5V für seine Stromversorgung und den 3,3V nimmt er zur Berechnung der Datenleitungen)

Edit: unten noch nen Schaltplan erstellt. Keine Garantie auf Vollständigkeit, ruhig nochmal drüber schauen.

 esphome:
  name: panasonic-ac2

esp32:
  board: esp32-c3-devkitm-1
  framework:
     type: esp-idf

wifi:
  networks:
    ssid: ""
    password: ""
  ap: {}
  
logger:
  level: DEBUG
#  baud_rate: 0 # ESP8266 only

api:

ota:
  platform: esphome

# Requires ESPHome 1.15.0+ for the even parity option
uart:
  tx_pin: GPIO8
  rx_pin: GPIO9
  baud_rate: 9600
  parity: EVEN

external_components:
  source: github://DomiStyle/esphome-panasonic-ac
  components: [panasonic_ac]


climate:
  - platform: panasonic_ac
    # For CZ-TACG1
    type: cnt

    # For DNSK-P11
    # type: wlan

    name: Panasonic AC
    horizontal_swing_select:
      name: Panasonic AC Horizontal Swing Mode
    vertical_swing_select:
      name: Panasonic AC Vertical Swing Mode
    outside_temperature:
      name: Panasonic AC Outside Temperature

    # Enable as needed
    eco_switch:
      name: Panasonic AC Eco Switch
    econavi_switch:
      name: Panasonic AC Econavi Switch
    nanoex_switch:
      name: Panasonic AC NanoeX Switch
    # mild_dry_switch:
    #   name: Panasonic AC Mild Dry Switch
    current_power_consumption:
      name: Panasonic AC Power Consumption

    # Useful when the ac does not report a current temperature (CZ-TACG1 only)
    # current_temperature_sensor: temperature_sensor_id

2 „Gefällt mir“

Top. Vielen Dank.

Da werde ich mich bei Gelegenheit mal dransetzen.

Hey zusammen!
schön dass in die Sache wieder Leben kommt.
Ich habe auch eine Aquarea und zwei Ethereas lokal im HA laufen - perfekt!
Leider meine ich ein Fehlverhalten gefunden zu haben:

Ich habe eine Art Nachtabsenkung gebaut, die auch funktioniert, aber:
Das mit den Swingmodes klappt nicht bzw. toggelt bei jedem Aufruf der Szene zwischen center und dem, was ich angegeben habe (Horiz.right beim Wandgerät bzw. up bei der Truhe).
Habt Ihr das auch?

Ansonsten bin ich wirklich sehr zufrieden damit und kann das nur empfehlen.
Viele Grüße!

Gerade mal ausprobiert. Der Swingmode swingt tatsächlich nicht wie erwartet.
Ich habe den bisher nicht aktiv verwendet.
Vermutlich hat Panasonic da irgendwann was am Protokoll verbessert.

Hallo zusammen,

auch wenn die Frage nur bedingt etwas direkt mit der Einbindung der Panasonic Klima in HA zu tun hat und eher ein ESP32 Thema ist:

Kann es sein, dass die Boards eine MAC-Randomisierung haben?

Meine 5 Innengeräte laufen super mit der Lösung hier. Ich wollte nur meine Fritzbox auf bekannte Geräte beschränken und sobald das aktiv ist, sind die Klimaanlagen nicht mehr auffindbar. Das Protokoll der Fritzbox spricht meiner Meinung nach stark für wechselnde MAC-Adressen.

Da ich im ESP Thema nicht wirklich drin bin, lässt sich das unkompliziert abstellen, falls es zutreffend ist?

Danke!

@Orti72 Vielen dank für dein tolles Script und deine Anleitung!

Ich baue gerade alle Komponenten zusammen um nach der Installation meiner 3 Klimageräte direkt starten zu können. Leider suche ich mir gerade einen “Wolf” um eine RGB-LED (5mm, WS2811) mit 3 PINs zu finden. Von Alie*** über Conrad bis Reichelt find ich kein entsprechend passendes Bauteil :expressionless_face:

Hast du ein Tip wo ich eine entsprechende RGB LED mit Data Pin finden kann?

Dank Dir!

@Ralftopas Ich glaube, das hab ich falsch formuliert. WS2811 ist der Chip, wenn der in einer LED verbaut ist wird es WS2812. Da findet man reichlich 5mm LED auf den bekannten Plattformen. Ich hab den Dout-Pin abgeknipst, muss ja nicht in Reihe geschaltet werden.

Hier noch mein aktueller Code, läuft so auf meinen beiden Anlagen bislang stabil ohne Ausfälle. Ich hab feste IP vergeben, geht bestimmt auch anders. Ich hab diesen Code in einer “ac-controller-main-config.yaml”. Das konkrete Gerät dann wie in der zweiten Code-Section.

# Lokale Steuerung der Panasonic Klimaanlage
#
# basiert auf github://DomiStyle/esphome-panasonic-ac
#
# Mein Modell: CS-Z20XKEW mit 5-pol. Anschluss (PAP-05V-S) an Modul CZ-TACG1
# Board Waveshare ESP32-C6-Mini
# zusätzlich Status LED onboard und extern 
# zusätzlich Fern-Restart per HA
# zusätzlich einige Diagnosedaten (IP, BSSID, WiFi-Qualität und Info bzgl. der Kommunikation mit der Klimaanlage)

# In der Geräte-Konfigurations-YAML benötigte substitutions:
#   device_name: wasauchimmer
#   friendly_name: wasauchimmer
#   const_ac_timeout: '20000'  # Timout in ms bis Verbindungsverlust zur AC signalisiert wird

esphome:
  name: ${device_name}
  friendly_name: ${friendly_name}
  project:
    name: "Michael.AC-Controller"
    version: "4.0.8"
  on_boot:
    then:
      - text_sensor.template.publish:
          id: ac_link_seit
          state: "Niemals"
      - wait_until:
          condition:
            time.has_time:
          timeout: 15s
      - if:
          condition:
            time.has_time: 
          then:
            - lambda: |-
                char buffer[25];
                auto now = id(systemtime).now();
                now.strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S");
                ESP_LOGI("Klimaanlage", "Boot-time: %s", buffer);
                id(systemstart).publish_state(buffer);
          else:
            - lambda: |-
                ESP_LOGE("Klimaanlage", "No valid time, setting boot-timestamp to unkown.");
                id(systemstart).publish_state("Unbekannt");

esp32:
  board: esp32-c6-devkitc-1
  framework:
    type: esp-idf

# Logging ein
logger:

# Home Assistant API ein
api:
  encryption:
    key: !secret api_key

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: ${wifi_ip}
    gateway: 192.168.30.1
    subnet: 255.255.255.0
  enable_btm: True
  enable_rrm: True
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${device_name} Fallback Hotspot"
    password: !secret fallback_password

captive_portal:

#
# Konfiguration externe Komponente Panasonic-AC und ADC für Lichtsensor ###########################
#

# Requires ESPHome 1.15.0+ for the even parity option
uart:
  tx_pin: GPIO4 # weiß, HV2
  rx_pin: GPIO5 # gelb, HV1
  baud_rate: 9600
  parity: EVEN

external_components:
  - source: github://DomiStyle/esphome-panasonic-ac
    components: [panasonic_ac]

climate:
  # Klima-Komponente für HA
  - platform: panasonic_ac
    id: my_panasonic_ac
    # For CZ-TACG1
    type: cnt

    name: Panasonic AC
    horizontal_swing_select:
      name: Panasonic AC Horizontal Swing Mode
    vertical_swing_select:
      name: Panasonic AC Vertical Swing Mode
    outside_temperature:
      name: Panasonic AC Outside Temperature

    # Enable as needed
    # eco_switch:
    #   name: Panasonic AC Eco Switch
    # econavi_switch:
    #  name: Panasonic AC Econavi Switch
    nanoex_switch:
      name: Panasonic AC NanoeX Switch
    mild_dry_switch:
      name: Panasonic AC Mild Dry Switch
    current_power_consumption:
      name: Panasonic AC Power Consumption

    # Useful when the ac does not report a current temperature (CZ-TACG1 only)
    # current_temperature_sensor: temperature_sensor_id

#
# Konfiguration eigene funktionale Erweiterungen ################################################
#
    # Schnittstelle überwachen und Zeit updaten, wenn sich Werte ändern
    on_state:
      then:
        - lambda: |-
            id(ac_last_seen) = millis();

globals:
  - id: ha_connected
    type: bool
    restore_value: no
    initial_value: 'false'

  - id: bad_wifi_signal_count
    type: int
    restore_value: no
    initial_value: '0'

  - id: led_last_red
    type: float
    restore_value: no
    initial_value: '0'
  - id: led_last_green
    type: float
    restore_value: no
    initial_value: '0'
  - id: led_last_blue
    type: float
    restore_value: no
    initial_value: '0'
  - id: led_last_brightness
    type: float
    restore_value: no
    initial_value: '0'
  - id: led_last_state
    type: std::string
    restore_value: no
    initial_value: ''
  - id: brightness_sensor_last_value
    type: float
    restore_value: no
    initial_value: '0'

  - id: ac_timeout
    type: uint32_t
    restore_value: no
    initial_value: ${const_ac_timeout}
  - id: ac_last_seen
    type: uint32_t
    restore_value: no
    initial_value: '0'
  - id: ac_connected
    type: bool
    restore_value: no
    initial_value: 'false'

time:
  - platform: homeassistant
    id: systemtime

switch:
  # Remote Restart-Button in HA
  - platform: restart
    name: "ESP Neustart"

sensor:
  # WiFi Signalstärke RSSI in dBm
  - platform: wifi_signal
    name: "WiFi Signal dBm"
    id: wifi_signal_dbm
    update_interval: never
    entity_category: "diagnostic"
    device_class: signal_strength
    filters:
      - lambda: |-
          static float last_sent = NAN;  // letzter gesendeter Wert
          // Wenn Wert < -80 -> sofort senden
          if (x < -80.0) {
            last_sent = x;
            return x;
          }
          // Wenn Wert >= -80 und Unterschied >= 3 -> senden
          if (isnan(last_sent) || fabs(x - last_sent) >= 3.0) {
            last_sent = x;
            return x;
          }
          // sonst nicht senden
          return {};
    on_value: 
      then:
        - component.update: wifi_signal_prozent
        - if:
            # prüfen, ob RSSI eine zeitlang unter -85 dBm, dann Roaming/Reconnect versuchen.
            condition:
              - lambda: 'return x < -85;'
            then:
              - lambda: 'id(bad_wifi_signal_count)++;'
            else:
              - lambda: 'id(bad_wifi_signal_count) = 0;'
        - if:
            condition:
              - lambda: 'return id(bad_wifi_signal_count) > 10;'
            then:
              - lambda: |-
                  ESP_LOGI("Klimaanlage", "Bad WiFi-connected, starting new scan for better AP");
                  id(bad_wifi_signal_count) = 0;
                  wifi::global_wifi_component->start_scanning();
  # WiFi Signalstärke RSSI in %
  - platform: template
    name: "WiFi Signal Prozent"
    id: wifi_signal_prozent
    icon: mdi:wifi
    entity_category: "diagnostic"
    unit_of_measurement: "%"
    update_interval: never
    # übliche Funktion zur Umrechnung von RSSI in Prozent
    accuracy_decimals: 0
    lambda: |-
      float rssi = id(wifi_signal_dbm).state;
      return round(min(max(2 * (rssi + 100.0), 0.0), 100.0));

  - platform: uptime
    name: Laufzeit

  # Helligkeitssensor Rohwert [V], LDR mit Spannungsteiler 10k
  - platform: adc
    pin: GPIO1
    id: sensor_helligkeit_raw
    attenuation: 12db
    update_interval: 500ms
    internal: true
    samples: 5
    filters:
      # Gätten der Messwerte und Ausreißer entfernen
      - quantile:
          window_size: 7
          send_every: 4
          send_first_at: 3
          quantile: .25
      - delta: 0.033
    on_value: 
      then:
        lambda: |-
          ESP_LOGI("Klimaanlage", "Helligkeit Sensor brightness raw value = %.3fV", x);
          if (id(brightness_sensor_last_value) != x) {
            id(brightness_sensor_last_value) = x;
            id(sensor_helligkeit).update();
          }
  # Für Anzeige in HA, wird per Intervall upgedatet
  - platform: template
    name: "Sensor Helligkeit"
    id: sensor_helligkeit
    icon: mdi:lightbulb-question-outline
    entity_category: "diagnostic"
    unit_of_measurement: "%"
    accuracy_decimals: 0 # Keine Nachkommastellen
    state_class: measurement
    # Die Umrechnung von Volt (0-3.3V) in Prozent (0-100%)
    lambda: |-
      return (id(sensor_helligkeit_raw).state / 3.3) * 100;

  - platform: template
    name: "LED Helligkeit"
    id: led_helligkeit
    icon: mdi:lightbulb-on-outline
    entity_category: "diagnostic"
    unit_of_measurement: "%"
    accuracy_decimals: 0 # Keine Nachkommastellen
    state_class: measurement

text_sensor:
  # Infos für HA-Anzeige
  - platform: wifi_info
    ip_address:
      name: "IP Addresse"
      entity_category: "diagnostic"
    bssid:
      name: "BSSID"
      entity_category: "diagnostic"
  - platform: template
    name: "AC-Link seit"
    id: ac_link_seit
    entity_category: "diagnostic"
    icon: mdi:clock-check-outline
    update_interval: never
  - platform: template
    name: "Systemstart"
    id: systemstart
    entity_category: "diagnostic"
    icon: mdi:clock-check
    update_interval: never
  - platform: template
    name: "LED Mode"
    id: led_mode
    entity_category: "diagnostic"
    icon: mdi:led-variant-outline
    update_interval: never

binary_sensor:
  # Überwachung der Schnittstelle zur AC
  - platform: template
    name: "AC-Link"
    id: ac_verbindung
    entity_category: "diagnostic"
    device_class: connectivity
    lambda: |-
      if (id(ac_last_seen) == 0) return false; // noch nie aktualisiert → nicht verbunden
      // sonst auswerten, wenn innerhalb der timeout-Zeit in ms eine Antwort kam
      id(ac_connected) = (millis() - id(ac_last_seen)) < id(ac_timeout);
      return id(ac_connected);
    # Textsensor mit Zeitstempel befüllen
    on_press:
      then:
        - script.execute: set_ac_connection_on_time
    on_release:
      then:
        - text_sensor.template.publish:
            id: ac_link_seit
            state: "Getrennt"

number:
  # erzeugt Controls, über den die LED Brightness in Abhängigkeit des Helligkeitssensors angepasst werden kann
  - platform: template
    name: "LED max"
    id: led_brightness_max_slider_value
    icon: mdi:lightbulb-on-outline
    min_value: 0
    max_value: 100
    step: 1
    initial_value: 100
    restore_value: true
    optimistic: true
    set_action:
      - lambda: |-
          if (x < id(led_brightness_min_slider_value).state) {
            id(led_brightness_min_slider_value).publish_state(x);
          }
          id(led_brightness_max_slider_value).publish_state(x);
  - platform: template
    name: "LED min"
    id: led_brightness_min_slider_value
    icon: mdi:lightbulb-night-outline
    min_value: 0
    max_value: 100
    step: 1
    initial_value: 20
    restore_value: true
    optimistic: true
    set_action:
      - lambda: |-
          if (x > id(led_brightness_max_slider_value).state) {
            id(led_brightness_max_slider_value).publish_state(x);
          }
          id(led_brightness_min_slider_value).publish_state(x);
  - platform: template
    name: "LED Gain"
    id: led_brightness_gain_slider_value
    icon: mdi:trending-up
    min_value: 0
    max_value: 1
    step: 0.1
    initial_value: 0
    restore_value: true
    optimistic: true

light:
  # Konfiguration ESP32 C6 Onboard-LED
  - platform: esp32_rmt_led_strip
    id: status_led
    chipset: WS2811
    pin: GPIO0
    num_leds: 1
    rmt_symbols: 48
    rgb_order: RGB
    default_transition_length: 700ms
    internal: true
    effects:
      - pulse:
          name: led_pulse
          transition_length:
            on_length: 500ms
            off_length: 200ms
          update_interval: 500ms
          min_brightness: 0%
          max_brightness: 100%

  # Konfiguration ESP32 C6 extrene WS2812 LED
  - platform: esp32_rmt_led_strip
    id: onboard_led
    chipset: WS2812
    pin: GPIO8
    num_leds: 1
    rmt_symbols: 48
    rgb_order: RGB
    default_transition_length: 700ms
    internal: true
    effects:
      - pulse:
          name: led_pulse
          transition_length:
            on_length: 500ms
            off_length: 200ms
          update_interval: 500ms
          min_brightness: 0%
          max_brightness: 100%

script:
  # WiFi-Signalstärke linear in RGB-Farben abbilden
  - id: set_wifi_quality_led
    mode: single
    then:
      - if:
          condition:
            - api.connected: 
          then:  
            # Farbverlauf bei RSSI von -80 bis -55 dBm:
            #   -80 dBm = HSV(355°, 100%, 100%) ≈ RGB(255, 0, 42)    — Reines Rot (sehr schlechte Verbindung)
            #   -55 dBm = HSV(140°, 100%, 100%) ≈ RGB(0, 255, 150)   — Türkisgrün (sehr gute Verbindung)
            - lambda: |-
                int dbm = (int) id(wifi_signal_dbm).state;
                if (dbm > -55) dbm = -55;
                if (dbm < -85) dbm = -85;

                float hue;
                if (dbm <= -85) {
                    hue = 355.0; // festes Rot
                } else {
                    // Interpolationswert: -85 dBm = 0.0 → -55 dBm = 1.0
                    float t = (dbm + 85.0) / 30.0;
                    hue = 355.0 - t * (355.0 - 140.0);
                }

                // HSV zu RGB konvertieren
                float s = 1.0;
                float v = 1.0;
                float c = v * s;
                float h_prime = hue / 60.0;
                float x = c * (1.0 - fabs(fmod(h_prime, 2.0) - 1.0));
                float m = v - c;
                float r = 0, g = 0, b = 0, brightness = 0;

                if (0 <= h_prime && h_prime < 1) { r = c; g = x; b = 0; }
                else if (1 <= h_prime && h_prime < 2) { r = x; g = c; b = 0; }
                else if (2 <= h_prime && h_prime < 3) { r = 0; g = c; b = x; }
                else if (3 <= h_prime && h_prime < 4) { r = 0; g = x; b = c; }
                else if (4 <= h_prime && h_prime < 5) { r = x; g = 0; b = c; }
                else if (5 <= h_prime && h_prime <= 6) { r = c; g = 0; b = x; }

                // Addiere m zur Normalisierung auf [0–1]
                r += m;
                g += m;
                b += m;

                // Brightness bestimmen in Abhängigkeit Umgebungslicht       
                float slider_value_max = id(led_brightness_max_slider_value).state;  // Slider in HA von 0 - 100
                float slider_value_min = id(led_brightness_min_slider_value).state;  // Slider in HA von 0 - 100
                
                // Sensor auslesen, Vertsärkungsfaktor anwenden und auf 3.3 = Maximalspannung begrenzen
                float adc_value = id(sensor_helligkeit_raw).state;
                adc_value = std::min(adc_value + adc_value * id(led_brightness_gain_slider_value).state, 3.3f);
                adc_value += adc_value * (id(led_brightness_gain_slider_value).state);

                // 1. Lineare Interpolation (als Basis) von 22% bis Slider-Wert
                float slope = (slider_value_max - slider_value_min) / 3.3;
                float linear_brightness_percent = slider_value_min + (adc_value * slope);

                // 2. Wert für logarithmische Kurve normalisieren (0.0 bis 1.0)
                float normalized = (linear_brightness_percent - slider_value_min) / (slider_value_max - slider_value_min);

                // 3. Logarithmische Kurve erzeugen
                // Der normalisierte Wert wird mit dem Exponenten x versehen.
                // Ein kleinerer Exponent (z. B. 0.2) macht die Kurve "aggressiver", d.h. kleine Helligkeitsveränderungen haben eine stärkere Auswirkung.
                // Ein größerer Exponent (z. B. 0.6) macht die Kurve sanfter.
                float nonlinear_value = pow(normalized, 0.6);

                // 4. Wert zurück auf den gewünschten Bereich skalieren
                float final_brightness_percent = slider_value_min + nonlinear_value * (slider_value_max - slider_value_min);

                // Farbhelligkeit korrigieren: dunkle Töne wie Blau/Türkis etwas anheben
                // Bereich: Hue 180°–260° (Blau/Blaugrün)
                float correction_factor = 1.0f;
                if (hue >= 180.0f && hue <= 260.0f) {
                    correction_factor = 1.15f; // +15% Helligkeit
                }

                // Korrektur anwenden und auf Maximalwert 1.0 begrenzen
                final_brightness_percent = final_brightness_percent * correction_factor;

                // 5. Clamping und auf den gültigen Bereich skalieren
                brightness = std::max((slider_value_min / 100.0), std::min(1.0, final_brightness_percent / 100.0));
                // und nach HA schicken
                id(led_helligkeit).publish_state(brightness * 100.0f);

                ESP_LOGI("Klimaanlage",
                  "WiFi-RSSI %ddBm, RGB(%.0f%%, %.0f%%, %.0f%%), Brightness %.0f%%; ", dbm, r * 100.0f, g * 100.0f, b * 100.0f, brightness * 100.0f);
                id(led_set_color).execute(r, g, b, brightness);
                id(led_mode).publish_state("WiFi-Status");

  # Pulsierende LED in rot (WiFi-loss), immer Brightness = 100%
  - id: led_pulse_red
    then:
      - lambda: |-
          // RGB-Werte in den globalen Variablen für die WiFi-Qualität zurücksetzen
          id(led_last_red) = 0;
          id(led_last_green) = 0;
          id(led_last_blue) = 0;
          // Wenn Pulse hat LED immer 100% Helligkeit
          id(led_helligkeit).publish_state(100.0f);
          id(led_mode).publish_state("WiFi-loss");
      - light.turn_on:
          id: status_led
          red: 100%
          green: 0%
          blue: 0%
          effect: led_pulse
      - light.turn_on:
          id: onboard_led
          red: 100%
          green: 0%
          blue: 0%
          effect: led_pulse

  # Pulsierende LED in gelb (HA API-loss), immer Brightness = 100%
  - id: led_pulse_yellow
    then:
      - lambda: |-
          // RGB-Werte in den globalen Variablen für die WiFi-Qualität zurücksetzen
          id(led_last_red) = 0;
          id(led_last_green) = 0;
          id(led_last_blue) = 0;
          // Wenn Pulse hat LED immer 100% Helligkeit
          id(led_helligkeit).publish_state(100.0f);
          id(led_mode).publish_state("API-loss");
      - light.turn_on:
          id: status_led
          red: 95%
          green: 100%
          blue: 0%
          effect: led_pulse
      - light.turn_on:
          id: onboard_led
          red: 95%
          green: 100%
          blue: 0%
          effect: led_pulse

  # Pulsierende LED in magenta (AC communication loss), immer Brightness = 100%
  - id: led_pulse_magenta
    then:
      - lambda: |-
          // RGB-Werte in den globalen Variablen für die WiFi-Qualität zurücksetzen
          id(led_last_red) = 0;
          id(led_last_green) = 0;
          id(led_last_blue) = 0;
          // Wenn Pulse hat LED immer 100% Helligkeit
          id(led_helligkeit).publish_state(100.0f);
          id(led_mode).publish_state("AC-loss");
      - light.turn_on:
          id: status_led
          red: 83%
          green: 0%
          blue: 100%
          effect: led_pulse
      - light.turn_on:
          id: onboard_led
          red: 83%
          green: 0%
          blue: 100%
          effect: led_pulse

  # LED bei Farbänderung ansteuern, Parameter = RGB in %
  - id: led_set_color
    parameters:
      red: float
      green: float
      blue: float
      brightness: float
    then:
      - if:
          condition:
            - lambda: 'return id(led_last_red) != red || id(led_last_green) != green || id(led_last_blue) != blue || id(led_last_brightness) != brightness;'
          then:
            - lambda: |-
                // Speichere die neuen Werte in den globalen Variablen
                id(led_last_red) = red;
                id(led_last_green) = green;
                id(led_last_blue) = blue;
                id(led_last_brightness) = brightness;
            - light.turn_on:
                id: status_led
                red: !lambda 'return red;'
                green: !lambda 'return green;'
                blue: !lambda 'return blue;'
                brightness: !lambda 'return brightness;'
                effect: none
            - light.turn_on:
                id: onboard_led
                red: !lambda 'return red;'
                green: !lambda 'return green;'
                blue: !lambda 'return blue;'
                brightness: !lambda 'return brightness;'
                effect: none

  # Zeit speichern, wann AC online ging seit letzter Unterbrechung
  - id: set_ac_connection_on_time
    then:
      - wait_until:
          condition:
            time.has_time:
          timeout: 15s
      - if:
          condition:
            time.has_time: 
          then:
            - lambda: |-
                char buffer[25];
                auto now = id(systemtime).now();
                now.strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S");
                ESP_LOGI("Klimaanlage", "AC connected since: %s", buffer);
                id(ac_link_seit).publish_state(buffer);
          else:
            - lambda: |-
                ESP_LOGI("Klimaanlage", "No valid time, setting ac-connection-timestamp to unkown.");
                id(ac_link_seit).publish_state("Unbekannt");

interval:
  # Steuerung der LED:
  # wenn kein WiFi: rot blinken
  # wenn WiFi aber Timeout zur AC: magenta blinken
  # wenn WiFi und Verbindung zur AC aber keine Verbindung zur API: gelb blinken
  # wenn WiFi und Verbindung zur AC und API: RSSI als RGB-Farbe
  - interval: 2s
    then:
      - if:
          condition:
            wifi.connected: {}
          then:
            - component.update: wifi_signal_dbm
            - if:
                condition:
                  not:
                    - lambda: 'return id(ac_connected);'
                then:
                  - if:
                      condition: 
                        - lambda: 'return id(led_last_state) != "led_pulse_magenta";'
                      then:
                        - lambda: 'id(led_last_state) = "led_pulse_magenta";'   
                        - script.execute: led_pulse_magenta
                else:
                  - if:
                      condition:
                        not:
                          api.connected:
                      then:
                        - if:
                            condition: 
                              - lambda: 'return id(led_last_state) != "led_pulse_yellow";'
                            then:
                              - lambda: 'id(led_last_state) = "led_pulse_yellow";'
                              - script.execute: led_pulse_yellow
                      else:
                        - lambda: 'id(led_last_state) = "";'
                        - delay: 200ms
                        - script.execute: set_wifi_quality_led
          else:
            - script.execute: led_pulse_red

Hier dann das konkrete Gerät, da wird der obige Block eingebunden. Wie gesagt, geht bestimmt auch anders, ich mach es so…

# Lokale Steuerung der Panasonic Klimaanlage
#
# basiert auf github://DomiStyle/esphome-panasonic-ac
#
# Mein Modell: CS-Z20XKEW mit 5-pol. Anschluss (PAP-05V-S) an Modul CZ-TACG1
# Board Waveshare ESP32-C6-Mini
# zusätzlich Status LED onboard und extern 
# zusätzlich Fern-Restart per HA
# zusätzlich einige Diagnosedaten (IP, BSSID, WiFi-Qualität und Info bzgl. der Kommunikation mit der Klimaanlage)

substitutions:
  # Gerätespezifische Namen
  device_name: ac-schlafzimmer
  friendly_name: AC-Schlafzimmer

  # IP
  wifi_ip: 192.168.30.133

  # Timout in ms bis Verbindungsverlust zur AC signalisiert wird
  const_ac_timeout: '20000'  

# Hauptkonfiguration wird hier eingebunden
<<: !include ac-controller-main-config.yaml

@Orti72 Ah jetzt wird ein Schuh draus.

Den WS2811 hab ich gefunden als einzelne Treiberplatine mit Din und Dout.
Auch LEDs mit integriertem Chip. Auf deinem Bild waren nur 3 Pins angeschlossen :wink:
Das hat mich dann etwas aus dem Konzept gebracht…
Aber wenn du Dout nur abgeknipst hast, erklärt sich das natürlich.
Vielen Dank auch nochmal für deine aktualisierte YAML!
Dann bastel ich mal weiter und passe es an meine Geräte an.
Merci!!

@Orti72 & @Spliffsta

Ich habe eure Schaltungen einmal kombiniert und etwas geändert.
Statt eines ESP32-C6 Mini habe ich (weil hier noch rumgeflogen) einen ESP32-C3 Mini (weniger Eingänge) genutzt.
Ergänzend zu @Orti72 habe ich den MP1584 für 12V implementiert, so wie ihn @Spliffsta nutzt.

Der optionale Elko ist rausgeflogen um es etwas zu verschlanken.

Mein Schaltplan sieht folgendermaßen aus:

Da ich E-Technik so bewandert bin: Evtl. könnt ihr einmal drüberschauen ob das so passt? :wink:

Da ich die Pins identisch zu @Orti72 genommen habe, sollte seine YAML unverändert bleiben können, oder?

Vielen Dank!!

PS:
@Orti72 in deiner YAML steht:

uart:
  tx_pin: GPIO4 # weiß, HV2
  rx_pin: GPIO5 # gelb, HV1

Sollte es nicht LV2 und LV1 heißen? Ändert zwar nichts am Programm, aber die LVs kommen doch an den ESP und nicht die HVs?

Hallo zusammen,

Ich wollte die Schaltung mit 12V, DCDC Converter und Levelshifter nun auch bei mir realisieren, jedoch scheint der 2. Pin (neben GND) an der Klimaanlage keine 12V zur Verfügung zu stellen, sondern nur um die 5V zu schwanken (evtl. floating? Hatte dazu was im GitHub gesehen). Hat jemand Ideen oder ähnliche Erfahrungen gemacht?

@Quickstep1453 Ich habe auch auf der neuesten Modellreihe die gestern installiert wurde nur um die 5VDC, genauso wie am untersten Pin.

@Orti72 Ich hab dein Script inkl Aufbau nun an meiner Panasonic getestet. LEider habe ich ein MAgenta-Blinken der LED. Einen Tip wieso es zum Timeout kommt bzw. was ich zum debuggen machen kann?

Dank Dir!

VG Ralf

Habe das Problem gefunden: Das PAP Kabel mit Stecker von Ali passte nicht zu 100%. Mit einem neuen Kabel geht es jetzt!

@Quickstep1453 Prima… wollte schon schreiben, dass das vermutlich ein Kontakt/Kabelproblem ist.

(Beitrag vom Verfasser gelöscht)

1 „Gefällt mir“

Hat jemand Erfahrung mit JLPCB? Vielleicht kann man da für kleines Geld mal ein paar Dutzend von den Platinen erstellen lassen. Meine theoretische Erfahrung aus Berichten anderer ist gut, bin aber kein Platinen-Praktiker.
Mein fliegender Aufbau ohne Levelshifter, Stepdown etc läuft zwar auch seit ziemlich längerer Zeit, aber das muss ja kein gutes Beispiel sein :slight_smile: