blackscreener

Holtop ERV esphome logger

Jul 23rd, 2025
464
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
YAML 64.28 KB | Source Code | 0 0
  1. esphome:
  2.   name: $devicename
  3.   #on_boot:
  4.   #  then:
  5.     #  - pzemac.reset_energy: pzemac_1
  6.  
  7. esp32:
  8.   board: nodemcu-32s
  9.   #board_flash_mode: dout
  10.   framework:
  11.     type: esp-idf
  12.    
  13.     version: recommended
  14. debug:
  15.   update_interval: 60s
  16.  
  17.  
  18. substitutions:
  19.   devicename: reku-logger
  20.   friendly_name: Rekuperator
  21.  
  22. wifi:
  23.   ssid: !secret wifi_ssid
  24.   password: !secret wifi_pass
  25.  
  26.   # Enable fallback hotspot (captive portal) in case wifi connection fails
  27.   ap:
  28.     ssid: "sweet-fallback-${devicename}"
  29.     password: cvbcbcbcvbdfbgte4
  30.  
  31. captive_portal:
  32. logger:
  33.   baud_rate: 0
  34.   level: DEBUG
  35.  
  36. # Enable Home Assistant API
  37. api:
  38.  #password: !secret api-password
  39.  
  40. ota:
  41.   - platform: esphome
  42.  
  43. # Enable Web server
  44. #web_server:
  45. # port: 80
  46. i2c:
  47.   - id: bus_a
  48.     sda: 21
  49.     scl: 22
  50.     scan: false
  51.    # frequency: 50kHz
  52.   - id: bus_b
  53.     sda: 18
  54.     scl: 19
  55.     scan: false
  56.   #  frequency: 50kHz
  57.  
  58.  
  59. uart:
  60.   - id: mod_bus #reku
  61.     tx_pin: 16
  62.     rx_pin: 17
  63.     baud_rate: 9600
  64.     stop_bits: 1
  65.  
  66.   - id: mod_bus2 #pzem
  67.     tx_pin: 1
  68.     rx_pin: 3
  69.     baud_rate: 9600
  70.     stop_bits: 2  #1 dla esp8266
  71.  
  72.  
  73. time:
  74.   - platform: sntp
  75.     id: czas_systemowy
  76.  
  77. # Example configuration entry
  78. button:
  79.   - platform: restart
  80.     name: "ESP Reku Restart"
  81.  
  82. globals:
  83.   - id: przewietrzanie_timer_koniec_timestamp # <--- DODAJ TĘ LINIĘ
  84.     type: int
  85.     restore_value: yes
  86.     initial_value: '0'
  87.  
  88.   - id: okap_timer_koniec_timestamp
  89.     type: int
  90.     restore_value: yes # Zachowaj stan po restarcie
  91.     initial_value: '0' # 0 oznacza, ze timer nie jest aktywny
  92.  
  93.   - id: impreza_timer_koniec_timestamp
  94.     type: int
  95.     restore_value: yes
  96.     initial_value: '0' # 0 oznacza, ze timer nie jest aktywny
  97.  
  98.  
  99.   - id: licznik_korekt
  100.     type: int
  101.     restore_value: no
  102.     initial_value: '0'
  103.  
  104.   - id: ostatni_timestamp_korekty # Nowa zmienna globalna
  105.     type: int
  106.     restore_value: yes # Ważne: przywróć wartość po restarcie, aby opóźnienie działało poprawnie
  107.     initial_value: '0' # Domyślnie 0, co oznacza, że pierwsza korekta może nastąpić od razu po uruchomieniu
  108.  
  109.   - id: limit_korekt_na_godzine
  110.     type: int
  111.     restore_value: no
  112.     initial_value: '10'
  113.  
  114.   - id: stary_nawiew
  115.     type: int
  116.     restore_value: no
  117.     initial_value: '0'
  118.   - id: stary_wywiew
  119.     type: int
  120.     restore_value: no
  121.     initial_value: '0'
  122.  
  123.   # Aktualny tryb z podtypem dla trybu auto
  124.   - id: tryb_auto_status
  125.     type: std::string
  126.     initial_value: '"normal"'
  127.  
  128.   # Aktualny aktywny tryb
  129.   - id: aktywny_tryb
  130.     type: std::string
  131.     initial_value: '"auto"'
  132.  
  133.   - id: ostatnie_obroty
  134.     type: int
  135.     restore_value: no
  136.     initial_value: '0'
  137.  
  138.   - id: czy_przewietrzanie
  139.     type: bool
  140.     restore_value: no
  141.     initial_value: 'false'
  142.  
  143. modbus:
  144.   - id: mod_bus_reventon
  145.     uart_id: mod_bus
  146.     send_wait_time: 200ms
  147.  #   flow_control_pin: GPIO4
  148.   - id: mod_bus_pzem
  149.  #   send_wait_time: 200ms
  150.     uart_id: mod_bus2
  151.  
  152. modbus_controller:
  153.   - id: reventon_reku
  154.     address: 0x01
  155.     modbus_id: mod_bus_reventon
  156.     update_interval: 15s
  157.  
  158.   - id: pzem1
  159.     modbus_id: mod_bus_pzem
  160.     address: 0x1
  161.     #command_throttle: 0ms
  162.     setup_priority: -10
  163.     update_interval: 5s
  164.  
  165. text_sensor:
  166.   - platform: debug
  167.     device:
  168.       name: "Device Info"
  169.     reset_reason:
  170.       name: "Reset Reason"
  171.  
  172.  
  173.   - platform: template
  174.     name: "Aktywny tryb rekuperatora"
  175.     lambda: |-
  176.       std::string tryb = id(aktywny_tryb);
  177.       if (tryb == "auto") {
  178.         std::string status = id(tryb_auto_status);
  179.         //return std::string("Tryb auto - ") + status;
  180.         return std::string(status);
  181.       }
  182.       return tryb;
  183.     update_interval: 30s
  184.  
  185.  
  186.   - platform: template
  187.     name: "Ostatni reset korekt"
  188.     id: ostatni_reset_korekt
  189.     lambda: |-
  190.       char str[20];
  191.       time_t curr_time = id(czas_systemowy).now().timestamp;
  192.       strftime(str, sizeof(str), "%H:%M", localtime(&curr_time));
  193.       return std::string(str);
  194.     update_interval: 1h
  195.  
  196.   - platform: template
  197.     name: $friendly_name Uptime
  198.     id: uptime_human
  199.     icon: mdi:clock-start
  200.  
  201.  
  202.  
  203.   - platform: modbus_controller
  204.     modbus_controller_id: reventon_reku
  205.     name: ${friendly_name} Status
  206.     id: reku_status
  207.     register_type: holding
  208.     address: 0x0012 #18
  209.     response_size: 2
  210.     raw_encode: HEXBYTES
  211.     #bitmask: 0
  212.     lambda: |-
  213.        std::string z = "";
  214.        int idx = item->offset+1;
  215.        if ((data[idx] & 0x0001) != 0) z += "Alarm pożarowy ON, ";
  216.        if ((data[idx] & 0x0002) != 0) z += "Bypass ON, ";
  217.        if ((data[idx] & 0x0004) != 0) z += "Bypass OFF, ";
  218.        if ((data[idx] & 0x0008) != 0) z += "Odladzanie, ";
  219.        if(z.length() > 0){
  220.          z.pop_back();
  221.        }
  222.        return {z};
  223.  
  224.   - platform: modbus_controller
  225.     modbus_controller_id: reventon_reku
  226.     name: ${friendly_name} Status2
  227.     id: reku_status2
  228.     register_type: holding
  229.     address: 0x0012 #18
  230.     response_size: 2
  231.     raw_encode: HEXBYTES
  232.  
  233.   - platform: modbus_controller
  234.     modbus_controller_id: reventon_reku
  235.     name: ${friendly_name} Fault Message
  236.     id: reku_fault_message
  237.     register_type: holding
  238.     address: 0x0014 #20
  239.     response_size: 2
  240.     raw_encode: HEXBYTES
  241.  
  242.   - platform: modbus_controller
  243.     modbus_controller_id: reventon_reku
  244.     name: ${friendly_name} Fault Message2
  245.     id: reku_fault_message2
  246.     register_type: holding
  247.     address: 0x0014 #20
  248.     response_size: 2
  249.     #raw_encode: HEXBYTES
  250.     lambda: |-
  251.        std::string z = "";
  252.        int idx = item->offset+1;
  253.        if ((data[idx] & 0x0001) != 0) z += "Błąd czujnika temperatury powietrza zewnętrznego (OA), ";
  254.        if ((data[idx] & 0x0002) != 0) z += "Błąd pamięci EEPROM, ";
  255.        if ((data[idx] & 0x0004) != 0) z += "Błąd czujnika temperatury powietrza wywiewanego (RA) lub SW4-3 jest w pozycji ON, ale bez podłączenia do czujnika wilgotności, ";
  256.        if ((data[idx] & 0x0008) != 0) z += "Błąd czujnika temperatury powietrza usuwanego (EA), ";
  257.        if ((data[idx] & 0x0010) != 0) z += "Błąd komunikacji, ";
  258.        if ((data[idx] & 0x0020) != 0) z += "Błąd czujnika temperatury powietrza nawiewanego (SA), ";
  259.        if ((data[idx] & 0x0040) != 0) z += "Błąd wentylatora wywiewnego, ";
  260.        if ((data[idx] & 0x0080) != 0) z += "Błąd wentylatora nawiewnego, ";
  261.    
  262.        if(z.length() > 0){
  263.          z.pop_back();
  264.        }
  265.        return {z};
  266.  
  267. script:
  268.   - id: sprawdz_ograniczenie_korekt
  269.     mode: single
  270.     parameters:
  271.       korekta_id: int
  272.     then:
  273.       - if:
  274.           condition:
  275.             lambda: return id(licznik_korekt) < id(limit_korekt_na_godzine);
  276.           then:
  277.             - lambda: 'id(licznik_korekt) += 1;'
  278.             - logger.log:
  279.                 format: "Wykonano korektę. Licznik: %d / %d"
  280.                 args:
  281.                  - id(licznik_korekt)
  282.                   - id(limit_korekt_na_godzine)
  283.             - if:
  284.                 condition:
  285.                   lambda: return korekta_id == 1;
  286.                 then:
  287.                   - script.execute: korekta_do_nadcisnienia
  288.             - if:
  289.                 condition:
  290.                   lambda: return korekta_id == 2;
  291.                 then:
  292.                   - script.execute: korekta_do_podcisnienia
  293.  
  294.             # --- DODAJ AKTUALIZACJĘ TIMESTAMPU PO WYKONANIU KOREKTY ---
  295.             - lambda: 'id(ostatni_timestamp_korekty) = id(czas_systemowy).now().timestamp;'
  296.             - logger.log: "Zaktualizowano timestamp ostatniej korekty."
  297.          
  298.           else:
  299.             - logger.log: "Limit korekt na godzinę osiągnięty – korekta zablokowana."
  300.  
  301.   - id: korekta_do_nadcisnienia # Zwiększa wywiew, aby zredukować nadciśnienie (nawiew > wywiew)
  302.     mode: restart
  303.     then:
  304.       - lambda: |-
  305.           const int max_fan_difference = 3;
  306.           int current_nawiew = id(wentylator_nawiewny).state; // Nawiew jest referencją (stała wartość)
  307.           int current_wywiew = id(wentylator_wywiewny).state;
  308.           int new_wywiew = current_wywiew + 1; // Próbujemy zwiększyć wywiew
  309.  
  310.           // Warunki:
  311.          // 1. New_wywiew nie może przekroczyć 10.
  312.           // 2. Różnica (nawiew - new_wywiew) musi być <= max_fan_difference.
  313.           //    (Czyli wywiew może być max o 3 biegi mniejszy od nawiewu)
  314.           if (new_wywiew <= 10 && (current_nawiew - new_wywiew) <= max_fan_difference) {
  315.             id(wentylator_wywiewny).make_call().set_value(new_wywiew).perform();
  316.             ESP_LOGI("Korekta_Nadcisnienia", "Zwiekszono wywiew: wywiew = %d (nawiew = %d). Roznica: %d",
  317.                      new_wywiew, current_nawiew, current_nawiew - new_wywiew);
  318.           } else {
  319.             ESP_LOGI("Korekta_Nadcisnienia", "Korekta nadcisnienia zablokowana: wywiew=%d, nawiew=%d. Roznica %d, limit %d. (Wywiew min/max lub poza roznica)",
  320.                      current_wywiew, current_nawiew, current_nawiew - current_wywiew, max_fan_difference);
  321.           }
  322.  
  323.  
  324.   - id: korekta_do_podcisnienia # Zmniejsza wywiew, aby zredukować podciśnienie (nawiew < wywiew)
  325.     mode: restart
  326.     then:
  327.       - lambda: |-
  328.           const int max_fan_difference = 3;
  329.           int current_nawiew = id(wentylator_nawiewny).state; // Nawiew jest referencją (stała wartość)
  330.           int current_wywiew = id(wentylator_wywiewny).state;
  331.           int new_wywiew = current_wywiew - 1; // Próbujemy zmniejszyć wywiew
  332.  
  333.           // Warunki:
  334.          // 1. New_wywiew nie może schodzić poniżej 0.
  335.           // 2. Różnica (new_wywiew - nawiew) musi być <= max_fan_difference.
  336.           //    (Czyli wywiew może być max o 3 biegi większy od nawiewu)
  337.           if (new_wywiew >= 0 && (new_wywiew - current_nawiew) <= max_fan_difference) {
  338.             id(wentylator_wywiewny).make_call().set_value(new_wywiew).perform();
  339.             ESP_LOGI("Korekta_Podcisnienia", "Zmniejszono wywiew: wywiew = %d (nawiew = %d). Roznica: %d",
  340.                      new_wywiew, current_nawiew, new_wywiew - current_nawiew);
  341.           } else {
  342.             ESP_LOGI("Korekta_Podcisnienia", "Korekta podcisnienia zablokowana: wywiew=%d, nawiew=%d. Roznica %d, limit %d. (Wywiew min/max lub poza roznica)",
  343.                      current_wywiew, current_nawiew, current_wywiew - current_nawiew, max_fan_difference);
  344.           }
  345.  
  346.   - id: wlacz_przewietrzanie
  347.     mode: single
  348.     then:
  349.       - logger.log: "TRYB PRZEWIETRZANIA: aktywacja"
  350.       - switch.turn_off: balans_przeplywu_switch
  351.       - lambda: |-
  352.           id(czy_przewietrzanie) = true;
  353.           id(stary_nawiew) = (int)id(wentylator_nawiewny).state;
  354.           id(stary_wywiew) = (int)id(wentylator_wywiewny).state;
  355.           id(przewietrzanie_timer_koniec_timestamp) = id(czas_systemowy).now().timestamp + (int)id(czas_przewietrzania_minuty).state * 60;
  356.       - number.set:
  357.           id: wentylator_nawiewny
  358.           value: 10
  359.       - number.set:
  360.           id: wentylator_wywiewny
  361.           value: 10
  362.       - lambda: |-
  363.           int czas = (int)id(czas_przewietrzania_minuty).state;
  364.           ESP_LOGI("przewietrzanie", "Czas przewietrzania: %d min", czas);
  365.       - delay: !lambda 'return id(czas_przewietrzania_minuty).state * 60 * 1000;'
  366.       - switch.turn_off: tryb_przewietrzania_switch
  367.  
  368.   - id: zakoncz_przewietrzanie
  369.     mode: single
  370.     then:
  371.       - logger.log: "TRYB PRZEWIETRZANIA: zakończenie – przywracanie poprzednich ustawień"
  372.       - lambda: |-
  373.           id(czy_przewietrzanie) = false;
  374.           id(przewietrzanie_timer_koniec_timestamp) = 0; // Wyzeruj timer
  375.       - number.set:
  376.           id: wentylator_nawiewny
  377.           value: !lambda 'return id(stary_nawiew);'
  378.       - number.set:
  379.           id: wentylator_wywiewny
  380.           value: !lambda 'return id(stary_wywiew);'
  381.       - switch.turn_on: balans_przeplywu_switch
  382.       - homeassistant.event:
  383.           event: esphome.przewietrzanie_zakonczone
  384.           data:
  385.             message: "Tryb przewietrzania zakończony"
  386.             nawiew: !lambda 'return id(wentylator_nawiewny).state;'
  387.             wywiew: !lambda 'return id(wentylator_wywiewny).state;'
  388.  
  389. #   - id: set_mode
  390. #     mode: single
  391. #     parameters:
  392. #       tryb: std::string
  393. #     then:
  394. #       - lambda: |-
  395. #           id(aktywny_tryb) = tryb;
  396. #           id(tryb_select_esp).publish_state(tryb);
  397. #           ESP_LOGI("tryb", "Ustawiono tryb: %s", tryb.c_str());
  398.  
  399. #       - switch.turn_on: balans_przeplywu_switch
  400.  
  401. #       - if:
  402. #           condition:
  403. #             lambda: return tryb == "nocny";
  404. #           then:
  405. #             - switch.turn_off: balans_przeplywu_switch
  406. #             - number.set:
  407. #                 id: wentylator_nawiewny
  408. #                 value: 2
  409. #             - number.set:
  410. #                 id: wentylator_wywiewny
  411. #                 value: 2
  412.  
  413. #       - if:
  414. #           condition:
  415. #             lambda: return tryb == "intensywny";
  416. #           then:
  417. #             - number.set:
  418. #                 id: wentylator_nawiewny
  419. #                 value: 10
  420. #             - number.set:
  421. #                 id: wentylator_wywiewny
  422. #                 value: 10
  423. #             - delay: 2h
  424. #             - script.execute:
  425. #                 id: set_mode
  426. #                 tryb: "normalny"
  427.  
  428. #       - if:
  429. #           condition:
  430. #             lambda: return tryb == "gosc";
  431. #           then:
  432. #             - number.set:
  433. #                 id: wentylator_nawiewny
  434. #                 value: 10
  435. #             - number.set:
  436. #                 id: wentylator_wywiewny
  437. #                 value: 10
  438. #             - switch.turn_off: balans_przeplywu_switch
  439. #             - delay: 4h
  440. #             - homeassistant.event:
  441. #                 event: esphome.tryb_goscia
  442. #                 data:
  443. #                   message: "Tryb gość zakończony. Powrót do normalnego trybu."
  444. #             - script.execute:
  445. #                 id: set_mode
  446. #                 tryb: "normalny"
  447.  
  448. #       - if:
  449. #           condition:
  450. #             lambda: return tryb == "urlopowy";
  451. #           then:
  452. #             - switch.turn_off: balans_przeplywu_switch
  453. #             - number.set:
  454. #                 id: wentylator_nawiewny
  455. #                 value: 1
  456. #             - number.set:
  457. #                 id: wentylator_wywiewny
  458. #                 value: 1
  459.  
  460. #       - if:
  461. #           condition:
  462. #             lambda: return tryb == "serwisowy";
  463. #           then:
  464. #             - switch.turn_off: balans_przeplywu_switch
  465. #             - switch.turn_off: tryb_przewietrzania_switch
  466.  
  467. #       - if:
  468. #           condition:
  469. #             lambda: return tryb == "auto";
  470. #           then:
  471. #             - switch.turn_on: balans_przeplywu_switch
  472.  
  473. #       - if:
  474. #           condition:
  475. #             lambda: return tryb == "normalny";
  476. #           then:
  477. #             - switch.turn_on: balans_przeplywu_switch
  478.  
  479.  
  480. #       - if:
  481. #           condition:
  482. #             lambda: return tryb == "okno";
  483. #           then:
  484. #             - switch.turn_off: balans_przeplywu_switch
  485. #             - number.set:
  486. #                 id: wentylator_nawiewny
  487. #                 value: 1
  488. #             - number.set:
  489. #                 id: wentylator_wywiewny
  490. #                 value: 3
  491. #             - lambda: id(ostatnie_obroty) = 3;
  492.  
  493.   - id: set_mode
  494.     mode: single
  495.     parameters:
  496.       mode: std::string
  497.       target_reku_speed: int
  498.     then:
  499.       - lambda: |-
  500.           std::string new_mode = mode;
  501.           int obroty_nawiew = 0;
  502.           int obroty_wywiew = 0;
  503.  
  504.           if (new_mode == "auto") {
  505.             obroty_nawiew = 3;
  506.             obroty_wywiew = 3;
  507.             ESP_LOGI("set_mode", "Tryb AUTO: Poczatkowe obroty: Nawiew=%d, Wywiew=%d. Dalsza regulacja w interval.", obroty_nawiew, obroty_wywiew);            
  508.             id(reku_on_off_switch).make_call().set_value(true).perform(); // Upewnij sie, ze glowny przelacznik jest ON
  509.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  510.             // W trybie auto dalsze obroty sa dynamicznie ustalane przez interval: 1min
  511.          
  512.           } else if (new_mode == "nocny") {
  513.             obroty_nawiew = 2;
  514.             obroty_wywiew = 2;
  515.             ESP_LOGI("set_mode", "Tryb NOCNY: Poczatkowe obroty: Nawiew=%d, Wywiew=%d. Dalsza regulacja w interval.", obroty_nawiew, obroty_wywiew);            
  516.             id(reku_on_off_switch).make_call().set_value(true).perform();
  517.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy          
  518.  
  519.           } else if (new_mode == "okno") {
  520.             obroty_nawiew = 1;
  521.             obroty_wywiew = 4;
  522.             ESP_LOGI("set_mode", "Tryb OKNO: Nawiew=%d, Wywiew=%d.", obroty_nawiew, obroty_wywiew);            
  523.             id(reku_on_off_switch).make_call().set_value(true).perform();
  524.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  525.  
  526.  
  527.           } else if (new_mode == "normalny") {
  528.             obroty_nawiew = 2;
  529.             obroty_wywiew = 2;
  530.             ESP_LOGI("set_mode", "Tryb NORMALNY Nawiew=%d, Wywiew=%d.", obroty_nawiew, obroty_wywiew);            
  531.             id(reku_on_off_switch).make_call().set_value(true).perform();
  532.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  533.  
  534.  
  535.           } else if (new_mode == "serwisowy") {
  536.             id(reku_on_off_switch).make_call().set_value(false).perform();
  537.             id(tryb_przewietrzania_switch).turn_off();
  538.             id(balans_przeplywu_switch).turn_off();
  539.             ESP_LOGI("set_mode", "Tryb SERWISOWY: Wylaczam rekuperator. Wentylatory: Nawiew=%d, Wywiew=%d.", obroty_nawiew, obroty_wywiew);
  540.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  541.  
  542.           } else if (new_mode == "urlopowy") {
  543.             obroty_nawiew = 1;
  544.             obroty_wywiew = 1;
  545.             ESP_LOGI("set_mode", "Tryb URLOPOWY: Wentylatory wylaczone (Nawiew=%d, Wywiew=%d).", obroty_nawiew, obroty_wywiew);
  546.             id(reku_on_off_switch).make_call().set_value(true).perform();        
  547.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  548.  
  549.           } else if (new_mode == "okap_auto") {
  550.             obroty_nawiew = target_reku_speed;
  551.             obroty_wywiew = target_reku_speed;
  552.             ESP_LOGI("set_mode", "Tryb OKAP_AUTO: Nawiew=%d, Wywiew=%d (zalezne od predkosci okapu).", obroty_nawiew, obroty_wywiew);            
  553.             id(reku_on_off_switch).make_call().set_value(true).perform();
  554.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  555.          
  556.           } else if (new_mode == "wylaczony") {
  557.             ESP_LOGI("set_mode", "Tryb WYLACZONY: Rekuperator wylaczony (Nawiew=%d, Wywiew=%d).", obroty_nawiew, obroty_wywiew);
  558.             id(reku_on_off_switch).make_call().set_value(false).perform();
  559.             id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer imprezy
  560.             id(tryb_przewietrzania_switch).turn_off();
  561.             id(balans_przeplywu_switch).turn_off();
  562.  
  563.           } else if (new_mode == "impreza") {
  564.             obroty_nawiew = 7;
  565.             obroty_wywiew = 7;
  566.             ESP_LOGI("set_mode", "Tryb IMPREZA: Nawiew=%d, Wywiew=%d. Aktywny na %d godzin.", obroty_nawiew, obroty_wywiew, (int)id(impreza_czas_trwania_godz).state);
  567.             id(reku_on_off_switch).make_call().set_value(true).perform();
  568.             // Ustaw timer zakonczenia trybu Impreza (teraz + zdefiniowany czas w minutach)
  569.             id(impreza_timer_koniec_timestamp) = id(czas_systemowy).now().timestamp + (int)id(impreza_czas_trwania_godz).state * 3600;
  570.  
  571.           }
  572.           else {
  573.             ESP_LOGW("set_mode", "Nieznany tryb: %s", new_mode.c_str());
  574.             return;
  575.           }
  576.  
  577.           // Wykonaj zmiany obrotow tylko jesli tryb sie zmienil LUB
  578.           // jesli to tryb 'okap_auto' i jego obroty sie zmienily (bo sa dynamiczne)
  579.           // UWAGA: Jesli reku_on_off_switch zostal wylaczony wczesniej, wentylatory i tak zostana ustawione na 0.
  580.           if (id(aktywny_tryb) != new_mode ||
  581.              (new_mode == "okap_auto" && (id(wentylator_nawiewny).state != obroty_nawiew || id(wentylator_wywiewny).state != obroty_wywiew))) {
  582.  
  583.             id(aktywny_tryb) = new_mode;
  584.             id(ostatnie_obroty) = obroty_nawiew; // Aktualizuj dla spójności
  585.  
  586.             // Aktualizacja select.tryb_select_esp ---
  587.             id(tryb_select_esp).publish_state(new_mode);
  588.  
  589.             // Logika ustawiania obrotow wentylatorow (wykonuje sie nawet jesli sa na 0)
  590.             ESP_LOGI("set_mode", "Przelaczono na tryb: '%s'. Ustawiam obroty: Nawiew=%d, Wywiew=%d.", new_mode.c_str(), obroty_nawiew, obroty_wywiew);
  591.             id(wentylator_nawiewny).make_call().set_value(obroty_nawiew).perform();
  592.             id(wentylator_wywiewny).make_call().set_value(obroty_wywiew).perform();
  593.           } else {
  594.             ESP_LOGD("set_mode", "Tryb '%s' juz jest aktywny z obrotami Nawiew=%d. Brak zmian.", new_mode.c_str(), obroty_nawiew);
  595.           }
  596.  
  597. interval:
  598.   - interval: 1h
  599.     then:
  600.       - lambda: 'id(licznik_korekt) = 0;'
  601.       - component.update: licznik_korekt_sensor
  602.       - component.update: licznik_korekt_pozostale
  603.       - component.update: ostatni_reset_korekt
  604.  
  605.   - interval: 1min
  606.     then:
  607.       - lambda: |-
  608.           // Sprawdz glowny przelacznik rekuperatora. Jesli jest wylaczony, przerwij logike sterowania.
  609.           // Tryby "serwisowy", "urlopowy", "wylaczony" obsluguja to poprzez wylaczenie reku_on_off_switch.
  610.           if (!id(reku_on_off_switch).state) {
  611.             ESP_LOGD("interval", "Rekuperator wylaczony glownym przelacznikiem. Pomijam logike sterowania.");
  612.             id(tryb_auto_status) = "reku wylaczony (switch OFF)"; // Uaktualnij status
  613.             return; // Przerwij dalsze wykonywanie lambdy
  614.           }
  615.  
  616.           // --- LOGIKA DLA TRYBU OKAPU (z wykorzystaniem sensora predkosci z Home Assistant) ---
  617.           float hood_fan_speed_percent = 0.0;
  618.           if (id(okap_predkosc_ha).has_state()) { // Sprawdz, czy sensor ma juz stan
  619.               hood_fan_speed_percent = id(okap_predkosc_ha).state;
  620.           } else {
  621.               // W przypadku braku stanu sensora, traktujemy okap jako wylaczony
  622.               ESP_LOGW("okap_logic", "Sensor okap_predkosc_ha nie ma stanu! Traktuje okap jako wylaczony.");
  623.           }
  624.  
  625.           bool okap_is_on = hood_fan_speed_percent > 0.0; // Okap jest wlaczony, jesli predkosc > 0
  626.  
  627.           int reku_speed_for_okap = 0;
  628.           std::string okap_status_text = "";
  629.  
  630.           if (okap_is_on) {
  631.             // Dostosuj progi i obroty rekuperatora do swoich biezacych potrzeb
  632.             // Przyjmujemy 3 biegi okapu: niski, sredni, wysoki
  633.             if (hood_fan_speed_percent > 66.0) { // Np. powyzej 66% to Bieg 3 okapu
  634.               reku_speed_for_okap = 9; // Najwyzsze obroty rekuperatora
  635.               okap_status_text = "Okap: Bieg 3 (Wysoki)";
  636.            } else if (hood_fan_speed_percent > 33.0) { // Np. powyzej 33% to Bieg 2 okapu
  637.              reku_speed_for_okap = 7; // Srednie obroty rekuperatora
  638.              okap_status_text = "Okap: Bieg 2 (Sredni)";
  639.            } else { // Pomiedzy 0% a 33% to Bieg 1 okapu
  640.              reku_speed_for_okap = 5; // Nizsze obroty rekuperatora
  641.              okap_status_text = "Okap: Bieg 1 (Niski)";
  642.            }
  643.  
  644.            // Aktywuj tryb okap_auto i ustaw odpowiednie obroty
  645.            if (id(aktywny_tryb) != "okap_auto" ||
  646.                id(wentylator_nawiewny).state != reku_speed_for_okap) {
  647.              ESP_LOGI("tryb", "Wykryto aktywny Okap (%s) - przelaczam w tryb OKAP_AUTO. Obroty reku: %d.", okap_status_text.c_str(), reku_speed_for_okap);
  648.               id(set_mode)->execute("okap_auto", reku_speed_for_okap);
  649.             }
  650.             id(tryb_auto_status) = okap_status_text;
  651.  
  652.             // Ustaw "timer" okapu: oblicz czas zakonczenia na teraz + czas trwania z number.okap_czas_trwania_min
  653.             id(okap_timer_koniec_timestamp) = id(czas_systemowy).now().timestamp + (int)id(okap_czas_trwania_min).state * 60;
  654.             ESP_LOGI("tryb", "Timer OKAP_AUTO zresetowany na %d minut. Koniec o: %s", (int)id(okap_czas_trwania_min).state, id(czas_systemowy).now().strftime("%Y-%m-%d %H:%M:%S").c_str());
  655.  
  656.             return; // Zakoncz, bo tryb okap ma priorytet
  657.           } else { // Okap jest wylaczony (hood_fan_speed_percent jest 0)
  658.             if (id(aktywny_tryb) == "okap_auto") {
  659.                 // Jesli bylismy w trybie okap_auto, ale okap sie wylaczyl, sprawdzamy "timer"
  660.                 if (id(czas_systemowy).now().timestamp >= id(okap_timer_koniec_timestamp)) {
  661.                     ESP_LOGI("tryb", "Okap wylaczony, timer OKAP_AUTO minal - powracam do trybu AUTO.");
  662.                     id(set_mode)->execute("auto", 0);
  663.                     id(okap_timer_koniec_timestamp) = 0; // Wyzeruj timer po zakonczeniu
  664.                 } else {
  665.                     int remaining_seconds = id(okap_timer_koniec_timestamp) - id(czas_systemowy).now().timestamp;
  666.                     id(tryb_auto_status) = "Okap wylaczony (timer aktywny)";
  667.                     ESP_LOGD("tryb", "Okap wylaczony, timer OKAP_AUTO nadal aktywny. Pozostalo: %d s", remaining_seconds);
  668.                 }
  669.                 return;
  670.             }
  671.           }
  672.           // --- KONIEC LOGIKI TRYBU OKAPU ---
  673.  
  674.  
  675.           // --- LOGIKA TRYBU IMPREZA (NAJWYŻSZY PRIORYTET PO OKAPIE) ---
  676.           if (id(aktywny_tryb) == "impreza") {
  677.             if (id(czas_systemowy).now().timestamp >= id(impreza_timer_koniec_timestamp)) {
  678.                 ESP_LOGI("tryb", "Timer trybu IMPREZA minal - powracam do trybu AUTO.");
  679.                 id(set_mode)->execute("auto", 0);
  680.                 id(impreza_timer_koniec_timestamp) = 0; // Wyzeruj timer po zakonczeniu
  681.                 return; // Zakoncz, bo tryb zmieniony
  682.             } else {
  683.                 int remaining_minutes = (id(impreza_timer_koniec_timestamp) - id(czas_systemowy).now().timestamp) / 60;
  684.                 id(tryb_auto_status) = "Impreza (" + std::to_string(remaining_minutes) + " min do konca)";
  685.                 ESP_LOGD("tryb", "Tryb IMPREZA nadal aktywny. Pozostalo: %d min", remaining_minutes);
  686.                 return; // Zakoncz, bo tryb impreza ma priorytet nad auto/nocny
  687.             }
  688.           }
  689.           // --- KONIEC LOGIKI TRYBU IMPREZA ---
  690.  
  691.           // Pobierz aktualny czas
  692.           auto t = id(czas_systemowy).now();
  693.           int hour = t.hour;
  694.  
  695.           // --- NOWA LOGIKA: Wyjście z trybu nocnego ---
  696.           // Jeśli jesteśmy w trybie nocnym, a godzina nie jest już nocna (np. >= 6 rano i < 23)
  697.           if (id(aktywny_tryb) == "nocny" && (hour >= 6 && hour < 23)) {
  698.               ESP_LOGI("tryb", "Koniec trybu nocnego - przechodzę w tryb AUTO.");
  699.               id(set_mode)->execute("auto", 0);
  700.               return; // Zakończ, by w tej minucie już być w trybie auto
  701.           }
  702.           // --- KONIEC NOWEJ LOGIKI ---
  703.  
  704.  
  705.           // 1. Logika otwartego okna
  706.           if (id(czy_jakies_okno_otwarte).state) {
  707.             // Jeśli okno jest otwarte i system jest włączony, ale nie jest w trybie "okno"
  708.             if (id(reku_on_off_switch).state && id(aktywny_tryb) != "okno") {
  709.               ESP_LOGI("tryb", "Okno otwarte — przełączam w tryb OKNO");
  710.               id(set_mode)->execute("okno", 0);
  711.             }
  712.             // Zawsze kończ działanie, jeśli jakiekolwiek okno jest otwarte
  713.             return;
  714.           }
  715.  
  716.           // Jeśli doszliśmy tutaj, to znaczy, że wszystkie okna są ZAMKNIĘTE.
  717.           // Sprawdź, czy trzeba wyjść z trybu "okno"
  718.           if (id(aktywny_tryb) == "okno") {
  719.             ESP_LOGI("tryb", "Wszystkie okna zamknięte — przywracam tryb AUTO");
  720.             id(set_mode)->execute("auto", 0);
  721.             return; // Zakończ, aby w następnej minucie już działać w trybie auto
  722.           }
  723.  
  724.  
  725.  
  726.           // Sprawdź warunki do wejścia w tryb nocny
  727.           if ((hour >= 23 || hour < 6) &&
  728.               id(reku_on_off_switch).state == 1 &&
  729.               !id(czy_przewietrzanie) &&
  730.               id(aktywny_tryb) != "serwisowy" &&
  731.               id(aktywny_tryb) != "urlopowy" &&
  732.               id(aktywny_tryb) != "nocny" &&
  733.               id(aktywny_tryb) != "okno" &&
  734.               !id(dom_pusty).state) { // <--- TUTAJ USUNIĘTO DODATKOWY NAWIAS ZAMYKAJĄCY
  735.             ESP_LOGI("tryb", "Automatyczne przełączenie na tryb nocny");
  736.             id(set_mode)->execute("nocny", 0);
  737.             return;  // pomiń dalej logikę w tej minucie
  738.           }
  739.  
  740.           if (id(reku_on_off_switch).state != 1) {
  741.             id(tryb_auto_status) = "reku wyłączony";
  742.             return;
  743.           }
  744.           if (id(czy_przewietrzanie)) {
  745.             id(tryb_auto_status) = "przewietrzanie aktywne";
  746.             return;
  747.           }
  748.  
  749.           std::string tryb = id(aktywny_tryb);
  750.  
  751.           // Deklaracje zmiennych na tym poziomie
  752.           float hum = 0.0;
  753.           int co2 = 0;
  754.           bool pusty = id(dom_pusty).state; // Pobranie stanu 'dom_pusty' raz
  755.  
  756.           // Pobranie wartości z globalnych sensorów
  757.           if (id(max_humidity_all_sensors).has_state()) {
  758.               hum = id(max_humidity_all_sensors).state;
  759.           } else {
  760.               // Wartość domyślna, jeśli sensor max_humidity_all_sensors nie ma jeszcze stanu
  761.               // To jest tylko na wypadek braku odczytu na samym starcie
  762.               hum = 0.0;
  763.               ESP_LOGW("Wilgotnosc", "Maksymalna wilgotność nie jest dostępna!");
  764.           }
  765.  
  766.           if (id(co2_value).has_state()) {
  767.               co2 = (int)id(co2_value).state;
  768.           }
  769.  
  770.           if (tryb == "nocny") {
  771.             // Logika CO2 i wilgotności dla trybu nocnego
  772.             int obroty = id(ostatnie_obroty);
  773.             std::string status;
  774.  
  775.             if (co2 > id(co2_nocny_high).state) {
  776.               obroty = 5;
  777.               status = "nocny - wysoki CO2";
  778.             } else if (co2 < id(co2_nocny_low).state) {
  779.               obroty = 2;
  780.               status = "nocny - niski CO2";
  781.             }
  782.  
  783.             // Dodatkowa logika wilgotności nocnej
  784.             if (hum > id(wilgotnosc_nocna_high).state && obroty < 4) {
  785.               obroty = 4;
  786.               status = "nocny - wysoka wilgotność";
  787.             } else if (hum < id(wilgotnosc_nocna_low).state && obroty > 2) {
  788.               obroty = 2;
  789.               status = "nocny - niska wilgotność";
  790.             }
  791.  
  792.             // Wykonaj tylko jeśli się zmieniło
  793.             if (obroty != id(ostatnie_obroty)) {
  794.               id(wentylator_nawiewny).make_call().set_value(obroty).perform();
  795.               id(wentylator_wywiewny).make_call().set_value(obroty).perform();
  796.               id(ostatnie_obroty) = obroty;
  797.             }
  798.  
  799.             // Zawsze ustaw status, nawet gdy obroty się nie zmieniają
  800.             if (status.empty()) {
  801.               status = "nocny - bez zmian";
  802.             }
  803.             id(tryb_auto_status) = status;
  804.             return;
  805.           }
  806.  
  807.           if (tryb == "auto") {
  808.             // **NOWA LOGIKA: Sprawdź najpierw, czy dom jest pusty**
  809.             if (pusty) { // Używamy zmiennej 'pusty' zdeklarowanej i ustawionej wcześniej
  810.               // Jeśli dom jest pusty, wymuś obroty na 1 i zakończ logikę dla trybu auto
  811.               int obroty = 1; // Minimalne obroty dla trybu "dom pusty"
  812.               if (obroty != id(ostatnie_obroty)) {
  813.                 id(wentylator_nawiewny).make_call().set_value(obroty).perform();
  814.                 id(wentylator_wywiewny).make_call().set_value(obroty).perform();
  815.                 id(ostatnie_obroty) = obroty;
  816.               }
  817.               id(tryb_auto_status) = "dom pusty";
  818.  
  819.             } else {
  820.               // **ISTNIEJĄCA LOGIKA: Uruchamiana tylko, gdy dom NIE jest pusty**
  821.               // Używamy już zdeklarowanych i ustawionych zmiennych hum i co2
  822.               // Usuwamy podwójne deklaracje hum i co2 tutaj!
  823.  
  824.               // Obroty z logiki CO2
  825.               int obroty_co2 = 3;
  826.               std::string status_co2 = "normalny";
  827.               if (co2 > id(co2_auto_high).state) {
  828.                 obroty_co2 = 9;
  829.                 status_co2 = "wysoki CO2";
  830.               } else if (co2 > id(co2_auto_medium).state) {
  831.                 obroty_co2 = 6;
  832.                 status_co2 = "średni CO2";
  833.               } else if (co2 > id(co2_auto_low).state) {
  834.                 obroty_co2 = 4;
  835.                 status_co2 = "niski CO2";
  836.               }
  837.  
  838.               // Obroty z logiki wilgotności
  839.               int obroty_hum = 3;
  840.               std::string status_hum = "";
  841.               if (hum > id(wilgotnosc_wysoka).state) {
  842.                 obroty_hum = 9;
  843.                 status_hum = "wilgotność";
  844.               } else if (hum < id(wilgotnosc_niska).state) {
  845.                 obroty_hum = 3;
  846.               }
  847.  
  848.               // Wybór wyższych obrotów
  849.               int obroty = std::max(obroty_co2, obroty_hum);
  850.  
  851.               if (obroty != id(ostatnie_obroty)) {
  852.                 id(wentylator_nawiewny).make_call().set_value(obroty).perform();
  853.                 id(wentylator_wywiewny).make_call().set_value(obroty).perform();
  854.                 id(ostatnie_obroty) = obroty;
  855.               }
  856.  
  857.               // Ustawienie statusu
  858.               if (obroty == obroty_hum && status_hum != "") {
  859.                 id(tryb_auto_status) = "Tryb auto - " + status_hum;
  860.               } else {
  861.                 id(tryb_auto_status) = "Tryb auto - " + status_co2;
  862.               }
  863.             }
  864.           }
  865.  
  866. # Example configuration entry
  867. psram:
  868.   mode: quad
  869.   speed: 40MHZ
  870.  
  871.  
  872. sensor:
  873.   - platform: template
  874.     name: "Okap - czas do końca"
  875.     id: okap_czas_do_konca
  876.     unit_of_measurement: "min"
  877.     icon: "mdi:stove-fan"
  878.     update_interval: 10s # Odświeżaj co 10 sekund dla płynniejszego liczenia
  879.     lambda: |-
  880.       int now_timestamp = id(czas_systemowy).now().timestamp;
  881.       int end_timestamp = id(okap_timer_koniec_timestamp);
  882.  
  883.       if (end_timestamp > now_timestamp) {
  884.         // Oblicz pozostały czas w sekundach, a następnie w minutach
  885.         int remaining_seconds = end_timestamp - now_timestamp;
  886.         return (float)std::ceil(remaining_seconds / 60.0); // Zaokrągl w górę do najbliższej minuty
  887.       } else {
  888.         return 0; // Jeśli tryb się zakończył lub nieaktywny
  889.       }
  890.  
  891.  
  892.   - platform: template
  893.     name: "Impreza - czas do końca"
  894.     id: impreza_czas_do_konca
  895.     unit_of_measurement: "min"
  896.     icon: "mdi:party-popper"
  897.     update_interval: 60s
  898.     lambda: |-
  899.       int now_timestamp = id(czas_systemowy).now().timestamp;
  900.       int end_timestamp = id(impreza_timer_koniec_timestamp);
  901.  
  902.       if (end_timestamp > now_timestamp) {
  903.         // Oblicz pozostały czas w sekundach, a następnie w minutach
  904.         int remaining_seconds = end_timestamp - now_timestamp;
  905.         return (float)std::ceil(remaining_seconds / 60.0); // Zaokrągl w górę do najbliższej minuty
  906.       } else {
  907.         return 0; // Jeśli tryb się zakończył lub nieaktywny
  908.       }
  909.  
  910.   - platform: template
  911.     name: "Przewietrzanie - czas do końca"
  912.     id: przewietrzanie_czas_do_konca
  913.     unit_of_measurement: "min"
  914.     icon: "mdi:timer-sand"
  915.     update_interval: 60s # Odświeżaj co 10 sekund dla płynniejszego liczenia
  916.     lambda: |-
  917.       int now_timestamp = id(czas_systemowy).now().timestamp;
  918.       int end_timestamp = id(przewietrzanie_timer_koniec_timestamp);
  919.  
  920.       if (end_timestamp > now_timestamp) {
  921.         // Oblicz pozostały czas w sekundach, a następnie w minutach
  922.         int remaining_seconds = end_timestamp - now_timestamp;
  923.         return (float)std::ceil(remaining_seconds / 60.0); // Zaokrągl w górę do najbliższej minuty
  924.       } else {
  925.         return 0; // Jeśli przewietrzanie się zakończyło lub nieaktywne
  926.       }
  927.  
  928.   # Nowy sensor do odczytu predkosci okapu z Home Assistant
  929.   - platform: homeassistant
  930.     name: "Predkosc Okapu z HA"
  931.     id: okap_predkosc_ha
  932.     entity_id: fan.fan_hood # <--- ZMIEŃ TO NA PRAWIDŁOWE entity_id TWOJEGO OKAPU W HA!
  933.     attribute: percentage # Odczytujemy atrybut 'percentage' z encji typu fan w HA
  934.     unit_of_measurement: "%"
  935.     accuracy_decimals: 0
  936.     internal: true # Ten sensor jest uzywany tylko wewnetrznie przez ESPHome
  937.  
  938.  
  939.   - platform: template
  940.     name: "Maksymalna Wilgotność w Domu"
  941.     id: max_humidity_all_sensors # Nowy ID dla sensora maksymalnej wilgotności
  942.     unit_of_measurement: "%"
  943.     accuracy_decimals: 1
  944.     update_interval: 60s # Ustaw interwał aktualizacji np. na 10 sekund
  945.     lambda: |-
  946.       float max_h = 0.0;
  947.  
  948.       if (id(wilgotnosc_lazienka).has_state()) {
  949.           max_h = std::max(max_h, id(wilgotnosc_lazienka).state);
  950.       }
  951.       if (id(wilgotnosc_kuchnia).has_state()) {
  952.           max_h = std::max(max_h, id(wilgotnosc_kuchnia).state);
  953.       }
  954.       if (id(wilgotnosc_kotlownia).has_state()) {
  955.           max_h = std::max(max_h, id(wilgotnosc_kotlownia).state);
  956.       }
  957.  
  958.       //Jeśli masz więcej sensorów, dodaj kolejne bloki if i std::max()
  959.  
  960.       return max_h;
  961.  
  962.  
  963.   - platform: debug
  964.     free:
  965.       name: "Heap Free"
  966.     block:
  967.       name: "Heap Max Block"
  968.     loop_time:
  969.       name: "Loop Time"
  970.     psram:
  971.       name: "Free PSRAM"
  972.     cpu_frequency:
  973.       name: "CPU Frequency"
  974.  
  975.  
  976.   - platform: internal_temperature
  977.     name: "Internal Temperature"
  978.  
  979.   - platform: uptime
  980.     id: uptime_sensor
  981.     internal: True
  982.     update_interval: 60s
  983.     on_raw_value:
  984.       then:
  985.         - text_sensor.template.publish:
  986.             id: uptime_human
  987.             state: !lambda |-
  988.               int seconds = round(id(uptime_sensor).raw_state);
  989.               int days = seconds / (24 * 3600);
  990.               seconds = seconds % (24 * 3600);
  991.               int hours = seconds / 3600;
  992.               seconds = seconds % 3600;
  993.               int minutes = seconds /  60;
  994.               seconds = seconds % 60;
  995.               return (
  996.                 (days ? to_string(days) + "d " : "") +
  997.                 (hours ? to_string(hours) + "h " : "") +
  998.                 (minutes ? to_string(minutes) + "m " : "") +
  999.                 (to_string(seconds) + "s")
  1000.               ).c_str();
  1001.  
  1002.   - platform: homeassistant
  1003.     id: co2_value
  1004.     entity_id: sensor.co2_salon
  1005.     internal: true
  1006.  
  1007.   - platform: homeassistant
  1008.     id: wilgotnosc_lazienka
  1009.     entity_id: sensor.atc_lazienka_parter_humidity
  1010.     internal: true
  1011.  
  1012.   - platform: homeassistant
  1013.     entity_id: sensor.ble_kuchnia_humidity
  1014.     id: wilgotnosc_kuchnia
  1015.     internal: true
  1016.  
  1017.   - platform: homeassistant
  1018.     entity_id: sensor.atc_04e8_humidity
  1019.     id: wilgotnosc_kotlownia
  1020.     internal: true
  1021.  
  1022.  
  1023.   - platform: template
  1024.     name: "Wykonane korekty (w tej godzinie)"
  1025.     id: licznik_korekt_sensor
  1026.     unit_of_measurement: "x"
  1027.     lambda: 'return id(licznik_korekt);'
  1028.     update_interval: 60s
  1029.  
  1030.   - platform: template
  1031.     name: "Pozostale korekty"
  1032.     id: licznik_korekt_pozostale
  1033.     unit_of_measurement: "x"
  1034.     lambda: 'return id(limit_korekt_na_godzine) - id(licznik_korekt);'
  1035.     update_interval: 60s
  1036.  
  1037.  
  1038.  
  1039.   #####################################################################
  1040.   #                  KANAL NAWIEWU (POWIETRZE WCHODZACE)             #
  1041.   #####################################################################
  1042.  
  1043.   # 1. Czujnik SDP810 dla nawiewu - surowe ciśnienie
  1044.   - platform: sdp3x
  1045.     name: "Cisnienie Roznicowe Nawiew"
  1046.     id: nawiew_raw_pressure
  1047.     address: 0x25
  1048.     i2c_id: bus_a # Zmień na ID Twojej magistrali dla nawiewu
  1049.     update_interval: 5s
  1050.     filters:
  1051.      # Pierwszy filtr w liście
  1052.       - exponential_moving_average:
  1053.           alpha: 0.7 # Wcięcie 2 spacje pod 'exponential_moving_average'
  1054.       # Drugi filtr w liście. Wcięcie jak pierwszy filtr (myślnik w tej samej kolumnie).
  1055.     #  - lambda: 'return x > 0 ? x : 0;'
  1056.      
  1057.     # 2. Sensor szablonowy - oblicza przepływ dla nawiewu w m3/h
  1058.   - platform: template
  1059.     name: "Przeplyw Nawiew m3/h"
  1060.     id: nawiew_airflow_m3_h
  1061.     update_interval: 5s
  1062.     icon: "mdi:air-filter"
  1063.     unit_of_measurement: "m³/h"
  1064.     lambda: |-
  1065.       // Stałe fizyczne
  1066.       const float p_atm = 101325.0;    // Ciśnienie atmosferyczne w Pa
  1067.       const float R = 287.05;          // Stała gazowa dla powietrza J/(kg·K)
  1068.  
  1069.       // Pobierz temperaturę (°C) i przelicz na Kelwiny
  1070.       float temp_c = id(nawiew_temp).state;
  1071.       float temp_k = temp_c + 273.15;
  1072.  
  1073.       // Oblicz gęstość powietrza (rho)
  1074.       float rho = p_atm / (R * temp_k);
  1075.  
  1076.       // Średnica i pole przekroju kanału (0.2 m)
  1077.       float duct_diameter = 0.2;
  1078.       float duct_radius = duct_diameter / 2.0;
  1079.       float duct_area = M_PI * pow(duct_radius, 2.0);
  1080.  
  1081.       // Odczytaj ciśnienie w hPa i przelicz na Pa
  1082.       float pressure_hpa = id(nawiew_raw_pressure).state;
  1083.       float pressure_pa = pressure_hpa * 100.0;
  1084.  
  1085.       // Sprawdź, czy ciśnienie dodatnie
  1086.       if (pressure_pa <= 0) {
  1087.         return 0;
  1088.       }
  1089.  
  1090.       // Oblicz prędkość i przepływ
  1091.       float velocity_mps = sqrt((2.0 * pressure_pa) / rho);
  1092.       float flow_m3_s = velocity_mps * duct_area;
  1093.  
  1094.       // Przelicz na m³/h
  1095.       return flow_m3_s * 3600.0;
  1096.  
  1097.   #####################################################################
  1098.   #                  KANAL WYWIEWU (POWIETRZE WYCHODZACE)             #
  1099.   #####################################################################
  1100.  
  1101.   # 3. Czujnik SDP810 dla wywiewu - surowe ciśnienie
  1102.   - platform: sdp3x
  1103.     name: "Cisnienie Roznicowe Wywiew"
  1104.     id: wywiew_raw_pressure
  1105.     address: 0x25
  1106.     i2c_id: bus_b # Zmień na ID Twojej magistrali dla wywiewu
  1107.     update_interval: 5s
  1108.     filters:
  1109.       - exponential_moving_average:
  1110.           alpha: 0.7
  1111.       #- lambda: 'return x > 0 ? x : 0;'
  1112.      
  1113.   # 4. Sensor szablonowy - oblicza przepływ dla wywiewu w m3/h
  1114.   - platform: template
  1115.     name: "Przeplyw Wywiew m3/h"
  1116.     id: wywiew_airflow_m3_h
  1117.     icon: "mdi:air-filter"
  1118.     unit_of_measurement: "m³/h"
  1119.     update_interval: 5s
  1120.     lambda: |-
  1121.       // Stałe fizyczne
  1122.       const float p_atm = 101325.0;    // Ciśnienie atmosferyczne w Pa
  1123.       const float R = 287.05;          // Stała gazowa dla powietrza J/(kg·K)
  1124.  
  1125.       // Pobierz temperaturę wywiewu i przelicz na Kelwiny
  1126.       float temp_c = id(wywiew_temp).state;
  1127.       float temp_k = temp_c + 273.15;
  1128.  
  1129.       // Oblicz gęstość powietrza (kg/m³) z równania gazu doskonałego
  1130.       float rho = p_atm / (R * temp_k);
  1131.  
  1132.       // Parametry kanału
  1133.       float duct_diameter = 0.2; // Średnica kanału (m)
  1134.       float duct_radius = duct_diameter / 2.0;
  1135.       float duct_area = M_PI * pow(duct_radius, 2.0);  // Pole przekroju ()
  1136.  
  1137.       // Ciśnienie dynamiczne w hPa → Pa
  1138.       float pressure_hpa = id(wywiew_raw_pressure).state;
  1139.       float pressure_pa = pressure_hpa * 100.0;
  1140.  
  1141.       // Jeśli ciśnienie ≤ 0, zwróć 0
  1142.       if (pressure_pa <= 0) {
  1143.         return 0.0;
  1144.       }
  1145.  
  1146.       // Oblicz prędkość przepływu (m/s)
  1147.       float velocity_mps = sqrt((2.0 * pressure_pa) / rho);
  1148.  
  1149.       // Oblicz przepływ objętościowy (m³/s) → przelicz na m³/h
  1150.       float flow_m3_s = velocity_mps * duct_area;
  1151.  
  1152.       return flow_m3_s * 3600.0;
  1153.  
  1154.  
  1155. # 5. Sensor szablonowy - oblicza różnicę przepływu (Nawiew - Wywiew)
  1156.   - platform: template
  1157.     name: "Roznica Przeplywu"
  1158.     id: flow_difference_m3_h
  1159.     icon: "mdi:compare-arrows"
  1160.     unit_of_measurement: "m³/h"
  1161.     update_interval: 10s
  1162.     lambda: |-
  1163.       if (isnan(id(nawiew_airflow_m3_h).state) || isnan(id(wywiew_airflow_m3_h).state)) {
  1164.         return 0.0;
  1165.       }
  1166.       return id(nawiew_airflow_m3_h).state - id(wywiew_airflow_m3_h).state;
  1167.     on_value:
  1168.       - if:
  1169.           condition:
  1170.            # 1. Sprawdź, czy balans przepływu jest włączony
  1171.             - switch.is_on: balans_przeplywu_switch
  1172.             # 2. Sprawdź, czy minął wystarczający czas od ostatniej korekty
  1173.             - lambda: |-
  1174.                 // Czas opóźnienia w minutach (np. 5 minut)
  1175.                 const int delay_minutes = 5; // <--- TUTAJ ZMIENIASZ CZAS OPÓŹNIENIA W MINUTACH
  1176.                 const int delay_seconds = delay_minutes * 60; // Przeliczenie na sekundy
  1177.  
  1178.                 time_t current_time = id(czas_systemowy).now().timestamp;
  1179.                 int last_correction_time = id(ostatni_timestamp_korekty);
  1180.                 return (current_time - last_correction_time) >= delay_seconds;
  1181.           then:
  1182.             - logger.log:
  1183.                 format: "Różnica przepływu: %.1f m³/h"
  1184.                 args: ["id(flow_difference_m3_h).state"]
  1185.  
  1186.             - if:
  1187.                 condition:
  1188.                   lambda: return id(flow_difference_m3_h).state > 30; # Nadciśnienie - nawiew o 25 m³/h większy od wywiewu
  1189.                 then:
  1190.                   - script.execute:
  1191.                       id: sprawdz_ograniczenie_korekt
  1192.                       korekta_id: 1 # Wywołuje korekta_do_nadcisnienia (zwiększa wywiew)
  1193.  
  1194.             - if:
  1195.                 condition:
  1196.                   lambda: return id(flow_difference_m3_h).state < -30; # Podciśnienie - wywiew o 25 m³/h większy od nawiewu
  1197.                 then:
  1198.                   - script.execute:
  1199.                       id: sprawdz_ograniczenie_korekt
  1200.                       korekta_id: 2 # Wywołuje korekta_do_podcisnienia (zmniejsza wywiew)
  1201.  
  1202.  
  1203.  
  1204.  ############   PZEM-004T V3 Reku
  1205.   - platform: pzemac
  1206.     modbus_id: mod_bus_pzem
  1207.     address: 1
  1208.     id: pzemac_1
  1209.     current:
  1210.       name: "Rekuperator prąd"
  1211.       accuracy_decimals: 2
  1212.       id: reku_prad
  1213.     voltage:
  1214.       name: "Rekuperator napięcie"
  1215.       unit_of_measurement: V
  1216.       accuracy_decimals: 2
  1217.       id: reku_napiecie
  1218.     energy:
  1219.       name: "Rekuperator zużycie energii"
  1220.       filters:
  1221.        # Wh to kWh is 0.001
  1222.         - multiply: 0.001
  1223.       unit_of_measurement: kWh
  1224.       accuracy_decimals: 3
  1225.       id: pg_energia
  1226.     power:
  1227.       name: "Rekuperator moc"
  1228.       unit_of_measurement: W
  1229.       accuracy_decimals: 2
  1230.       id: reku_moc
  1231.     frequency:
  1232.       name: "Rekuperator częstotliwość"
  1233.       unit_of_measurement: Hz
  1234.       accuracy_decimals: 2
  1235.     power_factor:
  1236.       name: "Rekuperator współczynnik mocy"
  1237.       accuracy_decimals: 2
  1238.       id: reku_power_factor
  1239.     update_interval: 5s
  1240.  
  1241.   - platform: total_daily_energy
  1242.     name: "Rekuperator dzienne zużycie energii"
  1243.     power_id: pg_energia
  1244.     unit_of_measurement: "kWh"
  1245.     accuracy_decimals: 3
  1246.     id: pg_daily_kwh
  1247.     icon: mdi:counter
  1248.     device_class: energy
  1249.     filters:
  1250.      # Multiplication factor from W to kW is 0.001
  1251.       - multiply: 0.001
  1252.  
  1253.   - platform: template
  1254.     name: ${friendly_name} sprawność
  1255.     unit_of_measurement: "%"
  1256.     lambda: |-
  1257.       float dzielnik = id(wywiew_temp).state - id(czerpnia_temp).state;
  1258.       if (dzielnik != 0) {
  1259.         float dzielna = id(nawiew_temp).state - id(czerpnia_temp).state;
  1260.         return (dzielna / dzielnik) * 100.0;
  1261.       } else {
  1262.         // Zwróć 0 lub inną domyślną wartość, gdy nie można wykonać obliczeń
  1263.         return 0;
  1264.       }
  1265.     accuracy_decimals: 1
  1266.     update_interval: 15s
  1267.  
  1268.    # sprawność temperaturowa = (T2-T1)/(T3-T1)
  1269.    # T1 – temperatura powietrza zewnętrznego (nawiewanego przed wymiennikiem) [°C]
  1270.    # T2 – temperatura powietrza nawiewanego za wymiennikiem [°C]
  1271.    # T3– temperatura powietrza wywiewanego z pomieszczeń przed wymiennikiem [°C]
  1272.  
  1273.   - platform: wifi_signal
  1274.     name: ${friendly_name} RSSI
  1275.     update_interval: 60s
  1276.  
  1277.   - platform: modbus_controller
  1278.     modbus_controller_id: reventon_reku
  1279.     name: ${friendly_name} Temperatura wywiew
  1280.     id: wywiew_temp
  1281.     register_type: holding
  1282.     address: 0x000c #12
  1283.     unit_of_measurement: "°C"
  1284.     device_class: "temperature"
  1285.     value_type: U_WORD
  1286.     filters:
  1287.       - lambda: return x - 40.0;
  1288.     #accuracy_decimals: 1
  1289.  
  1290.   - platform: modbus_controller
  1291.     modbus_controller_id: reventon_reku
  1292.     name: ${friendly_name} Temperatura czerpnia
  1293.     id: czerpnia_temp
  1294.     register_type: holding
  1295.     address: 0x000d #13
  1296.     unit_of_measurement: "°C"
  1297.     device_class: "temperature"
  1298.     value_type: U_WORD
  1299.     filters:
  1300.       - lambda: return x - 40.0;
  1301.     #accuracy_decimals: 1
  1302.    
  1303.   - platform: modbus_controller
  1304.     modbus_controller_id: reventon_reku
  1305.     name: ${friendly_name} Temperatura wyrzutnia
  1306.     id: wyrzutnia_temp
  1307.     register_type: holding
  1308.     address: 0x000f #15
  1309.     unit_of_measurement: "°C"
  1310.     device_class: "temperature"
  1311.     value_type: U_WORD
  1312.     filters:
  1313.       - lambda: return x - 40.0;
  1314.     #accuracy_decimals: 1
  1315.      
  1316.   - platform: modbus_controller
  1317.     modbus_controller_id: reventon_reku
  1318.     name: ${friendly_name} Temperatura nawiew
  1319.     id: nawiew_temp
  1320.     register_type: holding
  1321.     address: 0x000e #14
  1322.     unit_of_measurement: "°C"
  1323.     device_class: "temperature"
  1324.     value_type: U_WORD
  1325.     filters:
  1326.       - lambda: return x - 40.0;
  1327.     #accuracy_decimals: 1
  1328.    
  1329.   - platform: modbus_controller
  1330.     modbus_controller_id: reventon_reku
  1331.     name: ${friendly_name} CO2
  1332.     id: co2_reku
  1333.     register_type: holding
  1334.     address: 0x0300 #768
  1335.     unit_of_measurement: "ppm"
  1336.     device_class: "carbon_dioxide"
  1337.     value_type: U_WORD
  1338.     skip_updates: 100    
  1339.     #accuracy_decimals: 1
  1340.      
  1341.   - platform: modbus_controller
  1342.     modbus_controller_id: reventon_reku
  1343.     name: ${friendly_name} Fan running time
  1344.     id: fan_running_time
  1345.     register_type: holding
  1346.     address: 0x0301 #769
  1347.     unit_of_measurement: "min"
  1348.     value_type: U_WORD
  1349.     filters:
  1350.       - lambda: return x * 6.0;
  1351.     skip_updates: 12  
  1352.     #accuracy_decimals: 1
  1353.      
  1354.   - platform: modbus_controller
  1355.     modbus_controller_id: reventon_reku
  1356.     name: ${friendly_name} Wilgotność
  1357.     id: wilgotnosc_reku
  1358.     register_type: holding
  1359.     address: 0x0302 #770
  1360.     unit_of_measurement: "%"
  1361.     device_class: "humidity"
  1362.     value_type: U_WORD
  1363.     skip_updates: 10      
  1364.     #accuracy_decimals: 1
  1365.      
  1366. binary_sensor:
  1367.     - platform: homeassistant
  1368.       id: okno_salon
  1369.       entity_id: binary_sensor.shelly_blu_door_window_ce04_window
  1370.  
  1371.     - platform: homeassistant
  1372.       id: okno_salon2
  1373.       entity_id: binary_sensor.shelly_blu_door_window_24b7_window
  1374.  
  1375.     - platform: homeassistant
  1376.       id: okno_gabinet_l
  1377.       entity_id: binary_sensor.shelly_blu_door_window_cc52_window
  1378.  
  1379.     - platform: homeassistant
  1380.       id: okno_gabinet_p
  1381.       entity_id: binary_sensor.shelly_blu_door_window_882d_window
  1382.  
  1383.     - platform: homeassistant
  1384.       id: okno_lazienka
  1385.       entity_id: binary_sensor.shelly_blu_door_window_06b3_window
  1386.  
  1387.     - platform: homeassistant
  1388.       id: dom_pusty
  1389.       entity_id: input_boolean.dom_pusty
  1390.       internal: False
  1391.       name: Dom pusty
  1392.  
  1393.     - platform: template
  1394.       id: czy_jakies_okno_otwarte
  1395.       name: "Czy jakiekolwiek okno otwarte"
  1396.       lambda: |-
  1397.         return id(okno_salon).state || id(okno_salon2).state || id(okno_gabinet_l).state
  1398.         || id(okno_gabinet_p).state || id(okno_lazienka).state;
  1399.       #on_press:
  1400.        # then:
  1401.         #  - if:
  1402.          #     condition:
  1403.           #      lambda: return id(aktywny_tryb) != "okno";
  1404.            #   then:
  1405.             #    - logger.log: "Wykryto otwarte okno — przełączam na tryb OKNO"
  1406.              #   - script.execute:
  1407.               #      id: set_mode
  1408.                #     tryb: "okno"
  1409.  
  1410.  
  1411.       #on_release:
  1412.        # then:
  1413.         #  - if:
  1414.          #     condition:
  1415.           #      lambda: return id(aktywny_tryb) == "okno";
  1416.            #   then:
  1417.             #    - logger.log: "Wszystkie okna zamknięte — przywracam tryb AUTO"
  1418.              #   - script.execute:
  1419.               #      id: set_mode
  1420.                #     tryb: "auto"
  1421.  
  1422.     - platform: status
  1423.       name: ${friendly_name} Logger Status
  1424.  
  1425.     - platform: modbus_controller
  1426.       modbus_controller_id: reventon_reku
  1427.       name: ${friendly_name} On/Off status
  1428.       #device_class: running
  1429.       register_type: holding
  1430.       #entity_category: diagnostic
  1431.       address: 0x0009 #9
  1432.       #bitmask: 0x1
  1433.      
  1434.     - platform: modbus_controller
  1435.       modbus_controller_id: reventon_reku
  1436.       name: ${friendly_name} Auto restart status
  1437.       #device_class: running
  1438.       register_type: holding
  1439.       #entity_category: diagnostic
  1440.       address: 0x0000 #0
  1441.       #bitmask: 0x1
  1442.      
  1443.     - platform: modbus_controller
  1444.       modbus_controller_id: reventon_reku
  1445.       name: ${friendly_name} Nagrzewnica status
  1446.       #device_class: running
  1447.       register_type: holding
  1448.       #entity_category: diagnostic
  1449.       address: 0x0001 #1
  1450.       #bitmask: 0x1
  1451.      
  1452.     - platform: modbus_controller
  1453.       modbus_controller_id: reventon_reku
  1454.       name: ${friendly_name} Zewnętrzny sygnał ON/OFF
  1455.       #device_class: running
  1456.       register_type: holding
  1457.       #entity_category: diagnostic
  1458.       address: 0x0010 #16
  1459.       #bitmask: 0x1
  1460.      
  1461.     - platform: modbus_controller
  1462.       modbus_controller_id: reventon_reku
  1463.       name: ${friendly_name} Sygnał ON/OFF czujnika CO2
  1464.       #device_class: running
  1465.       register_type: holding
  1466.       #entity_category: diagnostic
  1467.       address: 0x0011 #17
  1468.       #bitmask: 0x1
  1469.  
  1470. switch:
  1471.   - platform: template
  1472.     name: "Tryb przewietrzania"
  1473.     id: tryb_przewietrzania_switch
  1474.     optimistic: true
  1475.     restore_mode: RESTORE_DEFAULT_OFF
  1476.     on_turn_on:
  1477.       - script.execute: wlacz_przewietrzanie
  1478.     on_turn_off:
  1479.       - script.execute: zakoncz_przewietrzanie
  1480.  
  1481.   - platform: template
  1482.     name: "Automatyczny Balans Przeplywu"
  1483.     id: balans_przeplywu_switch
  1484.     icon: "mdi:light-switch"
  1485.     # Ustawia przełącznik na wyłączony po restarcie ESP
  1486.     restore_mode: RESTORE_DEFAULT_OFF
  1487.     optimistic: true
  1488.  
  1489.   - platform: template
  1490.     name: ${friendly_name} switch
  1491.     id: reku_switch
  1492.     restore_mode: RESTORE_DEFAULT_OFF
  1493.     lambda: |-
  1494.       if (id(reku_on_off_switch).state==1) {
  1495.         return true;
  1496.       } else {
  1497.         return false;
  1498.       }
  1499.     turn_on_action:
  1500.       - number.set:
  1501.           id: reku_on_off_switch
  1502.           value: 1
  1503.     turn_off_action:
  1504.       - number.set:
  1505.           id: reku_on_off_switch
  1506.           value: 0
  1507.  
  1508. number:
  1509.     - platform: template
  1510.       name: "Czas trwania trybu Impreza"
  1511.       id: impreza_czas_trwania_godz
  1512.       min_value: 1
  1513.       max_value: 8
  1514.       step: 1
  1515.       unit_of_measurement: "h"
  1516.       mode: BOX
  1517.       restore_value: yes
  1518.       initial_value: 5 # Domyslny czas trwania 5 godzin
  1519.       optimistic: true
  1520.  
  1521.  
  1522.     - platform: template
  1523.       name: "Czas trwania trybu Okap"
  1524.       id: okap_czas_trwania_min
  1525.       min_value: 5
  1526.       max_value: 60
  1527.       step: 5
  1528.       unit_of_measurement: "min"
  1529.       mode: BOX
  1530.       restore_value: yes
  1531.       initial_value: 15 # Domyslny czas trwania 15 minut
  1532.       optimistic: true
  1533.  
  1534.     - id: co2_auto_high
  1535.       name: "CO2 Auto High"
  1536.       min_value: 400
  1537.       max_value: 2000
  1538.       step: 10
  1539.       unit_of_measurement: "ppm"
  1540.       optimistic: true
  1541.       initial_value: 1200
  1542.       platform: template
  1543.       mode: box
  1544.  
  1545.     - id: co2_auto_medium
  1546.       name: "CO2 Auto Medium"
  1547.       min_value: 400
  1548.       max_value: 2000
  1549.       step: 10
  1550.       unit_of_measurement: "ppm"
  1551.       optimistic: true
  1552.       initial_value: 1000
  1553.       platform: template
  1554.       mode: box
  1555.  
  1556.     - id: co2_auto_low
  1557.       name: "CO2 Auto Low"
  1558.       min_value: 400
  1559.       max_value: 2000
  1560.       step: 10
  1561.       unit_of_measurement: "ppm"
  1562.       optimistic: true
  1563.       initial_value: 800
  1564.       platform: template
  1565.       mode: box
  1566.  
  1567.     - id: co2_nocny_high
  1568.       name: "CO2 Nocny High"
  1569.       min_value: 400
  1570.       max_value: 2000
  1571.       step: 10
  1572.       unit_of_measurement: "ppm"
  1573.       optimistic: true
  1574.       initial_value: 800
  1575.       platform: template
  1576.       mode: box
  1577.  
  1578.     - id: co2_nocny_low
  1579.       name: "CO2 Nocny Low"
  1580.       min_value: 400
  1581.       max_value: 2000
  1582.       step: 10
  1583.       unit_of_measurement: "ppm"
  1584.       optimistic: true
  1585.       initial_value: 700
  1586.       platform: template
  1587.       mode: box
  1588.  
  1589.     - id: wilgotnosc_wysoka
  1590.       name: "Wilgotność Wysoka"
  1591.       min_value: 40
  1592.       max_value: 100
  1593.       step: 1
  1594.       unit_of_measurement: "%"
  1595.       optimistic: true
  1596.       initial_value: 70
  1597.       platform: template
  1598.       mode: box
  1599.  
  1600.     - id: wilgotnosc_niska
  1601.       name: "Wilgotność Niska"
  1602.       min_value: 30
  1603.       max_value: 100
  1604.       step: 1
  1605.       unit_of_measurement: "%"
  1606.       optimistic: true
  1607.       initial_value: 55
  1608.       platform: template
  1609.       mode: box
  1610.  
  1611.     - id: wilgotnosc_nocna_high
  1612.       name: "Wilgotność nocna wysoka"
  1613.       min_value: 60
  1614.       max_value: 100
  1615.       step: 1
  1616.       unit_of_measurement: "%"
  1617.       optimistic: true
  1618.       initial_value: 80
  1619.       platform: template
  1620.       mode: box
  1621.  
  1622.     - id: wilgotnosc_nocna_low
  1623.       name: "Wilgotność nocna niska"
  1624.       min_value: 30
  1625.       max_value: 100
  1626.       step: 1
  1627.       unit_of_measurement: "%"
  1628.       optimistic: true
  1629.       initial_value: 65
  1630.       platform: template
  1631.       mode: box
  1632.  
  1633.     - platform: template
  1634.       name: "Czas przewietrzania"
  1635.       id: czas_przewietrzania_minuty
  1636.       min_value: 1
  1637.       max_value: 30
  1638.       step: 1
  1639.       unit_of_measurement: "min"
  1640.       optimistic: true
  1641.       restore_value: true
  1642.       initial_value: 10
  1643.       mode: box
  1644.  
  1645.  
  1646.     - platform: modbus_controller
  1647.       modbus_controller_id: reventon_reku
  1648.       id: reku_on_off_switch
  1649.       address: 0x0009 #9
  1650.       value_type: U_WORD
  1651.       min_value: 0
  1652.       max_value: 1
  1653.       step: 1
  1654.       mode: box
  1655.       internal: true
  1656.  
  1657.     - platform: modbus_controller
  1658.       modbus_controller_id: reventon_reku
  1659.       name: ${friendly_name} Temperatura X otwarcia bypass’u
  1660.       address: 0x0002 #2
  1661.       unit_of_measurement: "°C"
  1662.       id: temp_x_bypass
  1663.       value_type: U_WORD
  1664.       min_value: 5
  1665.       max_value: 30
  1666.       step: 1
  1667.       mode: box
  1668.       entity_category: config
  1669.  
  1670.      
  1671.     - platform: modbus_controller
  1672.       modbus_controller_id: reventon_reku
  1673.       name: ${friendly_name} Temperatura Y otwarcia bypass’u
  1674.       address: 0x0003 #3
  1675.       unit_of_measurement: "°C"
  1676.       id: temp_y_bypass
  1677.       value_type: U_WORD
  1678.       min_value: 2
  1679.       max_value: 15
  1680.       step: 1
  1681.       mode: box
  1682.       entity_category: config      
  1683.      
  1684.     - platform: modbus_controller
  1685.       modbus_controller_id: reventon_reku
  1686.       name: ${friendly_name} Interwał odszraniania
  1687.       address: 0x0004 #4
  1688.       unit_of_measurement: "min"
  1689.       #device_class: "temperature"
  1690.       id: defrosting_interval
  1691.       value_type: U_WORD
  1692.       min_value: 15
  1693.       max_value: 99
  1694.       step: 1
  1695.       mode: box
  1696.       entity_category: config      
  1697.      
  1698.     - platform: modbus_controller
  1699.       modbus_controller_id: reventon_reku
  1700.       name: ${friendly_name} Temperatura odszraniania
  1701.       address: 0x0005 #5
  1702.       unit_of_measurement: "°C"
  1703.       id: defrosting_enter_temperature
  1704.       value_type: U_WORD
  1705.       min_value: -9
  1706.       max_value: 5
  1707.       lambda: "return x - 40.0;"
  1708.       write_lambda: "return x + 40.0;"
  1709.       step: 1
  1710.       mode: box
  1711.       entity_category: config      
  1712.      
  1713.     - platform: modbus_controller
  1714.       modbus_controller_id: reventon_reku
  1715.       name: ${friendly_name} Czas odszraniania
  1716.       address: 0x0006 #6
  1717.       unit_of_measurement: "min"
  1718.       #device_class: "temperature"
  1719.       id: defrost_duration_time
  1720.       value_type: U_WORD
  1721.       min_value: 2
  1722.       max_value: 20
  1723.       step: 1
  1724.       mode: box
  1725.       entity_category: config      
  1726.      
  1727.     - platform: modbus_controller
  1728.       modbus_controller_id: reventon_reku
  1729.       name: ${friendly_name} Czujnik CO2
  1730.       address: 0x0007 #7
  1731.       unit_of_measurement: "ppm"
  1732.       id: co2_set
  1733.       value_type: U_WORD
  1734.       min_value: 00
  1735.       max_value: 2500
  1736.       lambda: "return x * 10.0;"
  1737.       write_lambda: "return x / 10.0;"
  1738.       step: 1
  1739.       mode: box
  1740.       entity_category: config  
  1741.       skip_updates: 20      
  1742.      
  1743.     - platform: modbus_controller
  1744.       modbus_controller_id: reventon_reku
  1745.       name: ${friendly_name} Wentylator nawiewny
  1746.       icon: "mdi:fan-speed-1"
  1747.       address: 0x000a #10
  1748.       lambda: |-
  1749.          if (x == 2) {
  1750.          return 1;
  1751.          }
  1752.          if (x == 3) {
  1753.          return 2;
  1754.          }
  1755.          if (x == 5) {
  1756.          return 3;          
  1757.          }
  1758.          if (x == 8) {
  1759.          return 4;          
  1760.          }        
  1761.          if (x == 9) {
  1762.          return 5;          
  1763.          }          
  1764.          if (x == 10) {
  1765.          return 6;          
  1766.          }            
  1767.          if (x == 11) {
  1768.          return 7;          
  1769.          }            
  1770.          if (x == 12) {
  1771.          return 8;          
  1772.          }
  1773.          if (x == 13) {
  1774.          return 9;          
  1775.          }
  1776.          if (x == 14) {
  1777.          return 10;          
  1778.          } else {
  1779.           return NAN;
  1780.          }
  1781.       write_lambda: |-
  1782.          if (x == 1) {
  1783.          return 2;
  1784.          }
  1785.          if (x == 2) {
  1786.          return 3;
  1787.          }
  1788.          if (x == 3) {
  1789.          return 5;          
  1790.          }
  1791.          if (x == 4) {
  1792.          return 8;          
  1793.          }        
  1794.          if (x == 5) {
  1795.          return 9;          
  1796.          }          
  1797.          if (x == 6) {
  1798.          return 10;          
  1799.          }            
  1800.          if (x == 7) {
  1801.          return 11;          
  1802.          }            
  1803.          if (x == 8) {
  1804.          return 12;          
  1805.          }
  1806.          if (x == 9) {
  1807.          return 13;          
  1808.          }
  1809.          if (x == 10) {
  1810.          return 14;          
  1811.          } else {
  1812.           return NAN;
  1813.          }  
  1814.       #unit_of_measurement: "%"
  1815.       id: wentylator_nawiewny
  1816.       value_type: U_WORD
  1817.       entity_category: ""
  1818.       min_value: 1
  1819.       max_value: 10
  1820.       step: 1
  1821.       mode: slider
  1822.  
  1823.     - platform: modbus_controller
  1824.       modbus_controller_id: reventon_reku
  1825.       name: ${friendly_name} Wentylator wywiewny
  1826.       icon: "mdi:fan-speed-1"
  1827.       address: 0x000b #11
  1828.       lambda: |-
  1829.          if (x == 2) {
  1830.          return 1;
  1831.          }
  1832.          if (x == 3) {
  1833.          return 2;
  1834.          }
  1835.          if (x == 5) {
  1836.          return 3;          
  1837.          }
  1838.          if (x == 8) {
  1839.          return 4;          
  1840.          }        
  1841.          if (x == 9) {
  1842.          return 5;          
  1843.          }          
  1844.          if (x == 10) {
  1845.          return 6;          
  1846.          }            
  1847.          if (x == 11) {
  1848.          return 7;          
  1849.          }            
  1850.          if (x == 12) {
  1851.          return 8;          
  1852.          }
  1853.          if (x == 13) {
  1854.          return 9;          
  1855.          }
  1856.          if (x == 14) {
  1857.          return 10;          
  1858.          } else {
  1859.           return NAN;
  1860.          }
  1861.       write_lambda: |-
  1862.          if (x == 1) {
  1863.          return 2;
  1864.          }
  1865.          if (x == 2) {
  1866.          return 3;
  1867.          }
  1868.          if (x == 3) {
  1869.          return 5;          
  1870.          }
  1871.          if (x == 4) {
  1872.          return 8;          
  1873.          }        
  1874.          if (x == 5) {
  1875.          return 9;          
  1876.          }          
  1877.          if (x == 6) {
  1878.          return 10;          
  1879.          }            
  1880.          if (x == 7) {
  1881.          return 11;          
  1882.          }            
  1883.          if (x == 8) {
  1884.          return 12;          
  1885.          }
  1886.          if (x == 9) {
  1887.          return 13;          
  1888.          }
  1889.          if (x == 10) {
  1890.          return 14;          
  1891.          } else {
  1892.           return NAN;
  1893.          }  
  1894.       #unit_of_measurement: "%"
  1895.       id: wentylator_wywiewny
  1896.       value_type: U_WORD
  1897.       entity_category: ""
  1898.       min_value: 1
  1899.       max_value: 10
  1900.       step: 1
  1901.       mode: slider    
  1902.      
  1903. select:
  1904.   - platform: template
  1905.     name: "Tryb rekuperatora (ESP)"
  1906.     id: tryb_select_esp
  1907.     optimistic: true
  1908.     options:
  1909.      - auto
  1910.       - normalny
  1911.       - nocny
  1912.       - impreza
  1913.       - urlopowy
  1914.       - serwisowy
  1915.       - okno
  1916.       - okap_auto
  1917.     initial_option: auto
  1918.     restore_value: yes
  1919.     on_value:
  1920.       then:
  1921.         - script.execute:
  1922.             id: set_mode
  1923.             mode: !lambda 'return x;'
  1924.             target_reku_speed: 0
  1925.  
  1926.   - platform: modbus_controller
  1927.     modbus_controller_id: reventon_reku
  1928.     name: ${friendly_name} Ustawienia wielofunkcyjne
  1929.     icon: "mdi:fan"
  1930.     id: multi_sel
  1931.     address: 0x0018 #24
  1932.     entity_category: config
  1933.     value_type: U_WORD
  1934.     optimistic: false
  1935.     optionsmap:
  1936.       "Kasuj": 0
  1937.       "Usunięcie alarmu filtra": 1
  1938.       "Usunięcie harmonogramu tygodniowego": 2
  1939.      
  1940.   - platform: modbus_controller
  1941.     modbus_controller_id: reventon_reku
  1942.     name: ${friendly_name} Ustawienia alarmu filtra
  1943.     icon: "mdi:fan"
  1944.     id: filter_sel
  1945.     address: 0x0019 #25
  1946.     entity_category: config
  1947.     value_type: U_WORD
  1948.     optimistic: false
  1949.     optionsmap:
  1950.       "45 dni": 0
  1951.       "60 dni": 1
  1952.       "90 dni": 2
  1953.       "180 dni": 3
  1954.  
  1955.  
Advertisement
Add Comment
Please, Sign In to add comment