Tag: integracja

  • Pozycjonowanie obiektów na mapie HA

    Dzięki modułowi map w HA można wyświetlać bieżące pozycje osób, samochodów oraz zwierzaków (psa).

    Lokalizacja na mapie w HA

    HA mapa

    Pozycjonowanie osób

    Weryfikacja pozycji GPS

    Konfiguracja w aplikacji Home Assistant na telefon:

    1. Ustawienia>Aplikacja towarzysząca
    2. ustawić:
      • nazwę urządzenia
      • Działanie w tle
      • Zarządzaj sensorami
        • Jednorazowa dokładna lokalizacja: Włączony
        • Lokalizacja w tle: Włączony
        • Strefa lokalizacji: Włączony
        • (Opcjonalnie) Lokalizacja geokodowana: Włączony
    3. Zezwolić na lokalizację aplikacji
    4. (opcjonalnie) wyłączyć powiadomienia z aplikacji – jeżeli tylko do weryfikacji lokalizacji.

    Weryfikacja obecności w domu

    Dla tych osób, które nie mają włączonej lokalizacji w aplikacji lub nie używają aplikacji wykrycie obecności w domu odbywa się na podstawie integracji PING. Poszczególne telefony mają przypisane na routerze statyczne adresy IP (na podstawie adresów MAC).
    W ustawieniach osoby w HA jest przypisana odpowiednia integracja PING dla telefonu danej osoby.

    Pozycjonowanie samochodów

    Pozycjonowanie samochodów na mapie odbywa się na podstawie lokalizatorów GPS umieszczonych w samochodach. Domyślnie dane z lokalizatora GPS wysyłane są do serwera i widoczne w na mapie HA oraz w aplikacji Traccar.

    Z powodu bezpieczeństwa zależało mi aby wszelkie informacje nie były przechowywane na „obcych” serwerach lokalizacji – stąd konfiguracja własnego serwera do śledzenia samochodów.

    Lokalizacja samochodów w Traccar

    Hardware

    • Lokalizator GPS MKING MK08 wersja OBD2 – koszt ok 110PLN (listopad 2025), link
    • Karta SIM VigrinMobile – koszt ok 5PLN, plus 30PLN/rok

    Software

    • Aplikacja: Traccar
    • Aplikacja na telefon GPS.MIKING (tylko na potrzeby wstępnej konfiguracji i weryfikacji)

    Konfiguracja

    Wymagania: HA wystawione na zewnątrz z poprawnie skonfigurowanym HTTPS i DNS.

    Instalacja aplikacji traccar w HA.

    Przekierowanie portu na routerze dla aplikacji traccar na wewnętrzny IP serwera HA.

    Konfiguracja lokalizatora GPS MKING MK08

    1. Włożenie aktywnej karty SIM do lokalizatora
    2. Instalacja w samochodzie oraz opcjonalne włączenie silnika, poczekanie kilka minut na pierwszy odczyt lokalizacji
    3. Weryfikacja lokalizacji na mapie w aplikacji na telefon: GPS.MIKING
    4. Zmiana hasła lokalizatora w aplikacji GPS.MIKING
    5. Odczyt ustawień lokalizatora – wysłanie SMSa na numer telefonu lokalizatora: CXZT
      W odpowiedzi można zweryfikować: oryginalny adres serwera lokalizacji oraz ID urządzenia
    6. Ustawienie nowego serwera lokalizacji: IP <adres_IP_serwera_Traccar> <port_serwera>
      przykładowo: IP moj_dom.duckdns.org 1234
      odpowiedź SMS: SET IP OK
    7. weryfikacja lokalizacji przez wysłanie SMS: G1234
      odpowiedź SMS: link do lokalizacji na google

    Konfiguracja w Traccar

    1. Konfiguracja protokołu urządzeń
      Należy w addonie Traccar zmodyfikować plik traccar.xml, aby ustawić właściwy protokół komunikacyjny dla lokalizatorów GPS – w moim przypadku protokół to H02

      <!-- Enter you custom configuration below this line -->
      <entry key='h02.port'>5013</entry>

    2. (opcjonalnie) Dodajemy przekierowanie portu skonfigurowanego powyżej na routerze na wewnętrzny IP serwer HA – tylko dla przypadku, gdy HA jest wystawione do internetu i ma zewnętrzny adres IP.
    3. Dodajemy urządzenie w ustawieniach podając ID urządzenia

    Konfiguracja w HA

    Integracja w HA przy użyciu integracji Traccar Server.

    Przykładowe atrybuty

      Dla wygody prezentacji na mapie dla każdego z samochodu dodanie osoby:

      • nazwa
      • zdjęcie
      • nazwa encji z lokalizacją (encja z integracji)

        Pozycjonowanie zwierzaków

        Analogicznie jak pozycjonowanie ludzi czy samochodów na mapie w HA można prezentować lokalizację zwierzaków.

        Hardware

        Tractive – wymagane dedykowane urządzenie oraz opłacanie abonamentu.

        Software

        Intergracja w HA: Tractive – wymagane aktywne konto w aplikacji na telefon Tractive

        Aby ikona na mapie w HA pokazywała zdjęcie należy zrobić kroki analogicznie jak dla samochodu.

        Linki:
        https://www.traccar.org/configuration-file/

        https://tractive.com/pl/pd/gps-dla-psa

      1. Pobranie danych z analogowego licznika wody

        Prosty projekt odczytujący z analogowego licznika dane i przekazujący informację do HomeAssistant przez MQTT. Projekt wykorzystuje bibliotekę uczenia maszynowego Tensorflow Lite do analizy obrazu.

        Hardware

        • ESP32 + OV2640 2.0MP camera module + antena (koszt ok 10$)
        • karton i trochę srebrnej taśmy

        Software

        AI on the Edge Device

        Konfiguracja

        Link

        https://github.com/jomjol/AI-on-the-edge-device

      2. Sterownie odkurzaczem Viomi Pro 2

        Prosta integracja sterowania odkurzaczem Viomi Pro 2.

        Korzysta z „custom” komponentów (instalowane przez HACS):

        Konfiguracja

        Viomise

        Instalujemy „custom” komponent przez HACS.

        Do konfiguracji będzie potrzebny IP oraz token urządzenia, który można pobrać za pomocą instrukcji.

        Dodajemy integrację z poziomu HA

        Xiaomi Cloud Map Extractor

        W pliku configuration.yaml

        camera:
        - platform: xiaomi_cloud_map_extractor
          host: !secret vacuum_host
          token: !secret vacuum_token
          username: !secret xiaomi_cloud_username
          password: !secret xiaomi_cloud_password
          draw: ['all']
          attributes:
            - calibration_points
        #    - goto
        #    - room_numbers
        #    - rooms
        #    - vacuum_room
        #    - vacuum_room_name
          map_transformation:
            scale: 5
            trim:
              top: 44
              bottom: 35
              left: 48
              right: 25
          sizes:
            charger_radius: 15
            vacuum_radius: 20
            path_width: 5
          colors:
            color_map_outside: [255, 255, 255]

        Home Assistant

        Wygląd karty

        Konfiguracja

        Linki

        https://hacs.xyz

        https://github.com/DominikWrobel/viomise

        https://github.com/PiotrMachowski/Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor

        https://github.com/PiotrMachowski/Home-Assistant-custom-components-Xiaomi-Cloud-Map-Extractor

      3. Integracja kotła Valliant z ebusd

        Integracja z kotłem Valliant VC 186 oraz sterownikiem pogodowym VC400 korzysta z protokołu eBUS. Jako adapter eBUS wykorzystywana jest płytka w wersji 2.2 zbudowana na podstawie strony eBus Adapter 3. Od czasu jego zlutowania (2020) pojawiło się kilka nowszych wersji adaptera, ale nie zamierzam zmieniać, bo działa bardzo skutecznie. Komunikacja z HA jest za pomocą serwera MQTT.

        Schemat blokowy

        Wygląd płytki adaptera eBus z UART

        Oprogramowanie

        Korzystam z ebusd uruchomionego na Linuxie (Debian) jako serwis.

        Instalacja

        Instalacja pakietu ebusd wg instrukcji: link.

        Konfiguracja

        Konfiguracja w pliku /etc/default/ebusd

        #tryb standardowy
        #EBUSD_OPTS="--scanconfig -l/var/log/ebusd.log --device=/dev/ttyUSB0 --mqtthost=192.168.0.2 --mqttport=1883 --mqttjson --mqttuser=user_mqtt --mqttpass=pass_mqtt --mqttint=/etc/ebusd/mqtt-hassio.cfg"
        
        #tryb instalatora wi
        EBUSD_OPTS="--scanconfig -l/var/log/ebusd.log --device=/dev/ttyUSB0 --mqtthost=192.168.0.2 --mqttport=1883 --mqttjson --mqttuser=user_mqtt --mqttpass=pass_mqtt --mqttint=/etc/ebusd/mqtt-hassio.cfg --accesslevel=install"

        Oczywiście wartości mqtthost, mqttport, mqttuser, mqttpass należy ustawić na poprawne.

        Aby zmieniać niektóre wartości (krzywa grzewcza, stany liczników gazu) ebusd musi działać w trybie instalatora. Weryfikację, czy dany parametr jest modyfikowalny można sprawdzić w projekcie GIT https://github.com/john30/ebusd-configuration wyszukując odpowieni plik dla instalacji.

        Weryfikacja działania ebusd

        ebusctl info

        dla mojej instalacji komenda zwraca

        version: ebusd 24.1.24.1
        update check: OK
        device: /dev/ttyUSB0, serial
        access: install
        signal: acquired
        symbol rate: 22
        max symbol rate: 1441
        min arbitration micros: 0
        max arbitration micros: 3168
        min symbol latency: 0
        max symbol latency: 15
        scan: finished
        reconnects: 0
        masters: 3
        messages: 432
        conditional: 7
        poll: 110
        update: 16
        address 03: master #11
        address 08: slave #11, scanned "MF=Vaillant;ID=BAI00;SW=0516;HW=7401", loaded "vaillant/bai.308523.inc" ([id_hw=7401]), "vaillant/08.bai.csv"
        address 10: master #2
        address 15: slave #2, scanned "MF=Vaillant;ID=40000;SW=0139;HW=7301", loaded "vaillant/15.400.csv"
        address 31: master #8, ebusd
        address 36: slave #8, ebusd

        Problemy

        Ponieważ rozwiązanie działało już przez kilka lat nastąpiło przepełnienie liczników (ebusd/bai/PrEnergyXXX) odpowiedzialnych za zliczanie zużycia gazu.

        Poniżej komendy do zresetowania odpowiednich liczników:

        #odczyt
        ebusctl read -V -c bai PrEnergyCountHwc1
        
        #zapis
        ebusctl write -c bai PrEnergySumHc1 0
        ebusctl write -c bai PrEnergySumHwc1 0
        ebusctl write -c bai PrEnergyCountHc1 0
        ebusctl write -c bai PrEnergyCountHwc1 0

        Jeżeli przy zapisie są błędy „ERR: element not found” powyższe komendy należy wykonać w trybie instalatora (parametr „–accesslevel=install”).

        Home Assistant

        Karta ogrzewania w HA

        Rozwiązanie bazuje na cyklicznym odczycie danych przez MQTT. Aby oczytać jakąś wartość należy najpierw wysłać wiadomość odpowiedni topic MQTT. Do testowania najlepiej użyć klienta umożliwiającego podłączenie się bezpośrednio do serwera MQTT, np. MQTT Explorer

        Skrypty wymuszające pobieranie danych:

        script:
          ebus_refresh_2m:
            alias: "Pobierz dane ebus"
            sequence:
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/RoomTemp/get'
                  payload: ''   
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/WaterPressure/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/CirPump/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/IsInHoliday/get'
                  payload: ''  
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/IsInParty/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/IsInSingleHwcLoadingMode/get'
                  payload: ''           
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/ActualRoomTempDesired/get'
                  payload: ''         
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/HwcTempDesired/get'
                  payload: ''        
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergySumHwc1/get'
                  payload: ''           
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergySumHc1/get'
                  payload: ''           
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergyCountHwc1/get'
                  payload: ''            
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergyCountHc1/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/StorageTemp/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/OperatingMode/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/OperatingModeHwc/get'
                  payload: ''
          ebus_refresh_30m:
            alias: "Pobierz dane ebus"
            sequence:
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/HcHours/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/HwcHours/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/FlowSetPotmeter/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/HwcSetPotmeter/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/HeatingCurve/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergySumHwc2/get'
                  payload: ''           
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergySumHwc3/get'
                  payload: ''           
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergySumHc2/get'
                  payload: ''           
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/bai/PrEnergySumHc3/get'
                  payload: ''
              - service: mqtt.publish
                data_template:
                  topic: 'ebusd/400/ReducedNightTemp/get'
                  payload: ''

        i odpowiednie automatyzacje, dodatkowo automatyzacja powiadamiająca o zbyt niskim ciśnieniu w instalacji

        automation:
          - alias: "Ebusd - update after start"
            trigger:
              platform: homeassistant
              event: start
            action:
            - delay: 00:01:00
            - service: script.ebus_refresh_2m 
            - service: script.ebus_refresh_30m    
              
          - id: 'update_ebusd_1'
            alias: Ebusd - update 5min
            trigger:
              platform: time_pattern
              minutes: '/2'
            condition:
            - condition: state
              entity_id: sensor.ebusd_running
              state: 'true'
            action:
              - service: script.ebus_refresh_2m
          - id: 'update_ebusd_2'
            alias: Ebusd - update 30min
            trigger:
              platform: time_pattern
              minutes: /30
            condition:
            - condition: state
              entity_id: sensor.ebusd_running
              state: 'true'
            action:
              - service: script.ebus_refresh_30m     
              
          - id: waterpressure_low_notification
            alias: "Ebusd - Waterpressure Low Notification"
            initial_state: 'on'
            
            trigger:
              platform: numeric_state
              entity_id: sensor.cisnienie_wody
              below: 0.75    
            action:
            - service: notify.gmail_notifier
              data:
                message: "Ciśnienie wody za niskie:  {{ states('sensor.cisnienie_wody') }}"
                title: "[HA] Ciśnienie wody"
            - service: persistent_notification.create
              data:
                title: "Ciśnienie wody"
                message: >
                  Ciśnienie wody za niskie:  {{ states('sensor.cisnienie_wody') }}
                notification_id: "waterpressure_error"  

        Poniżej ustawienia mqtt (ustawienie w pliku configuration.yaml oraz mqtt.yaml)

        configuration.yaml

        ...
        mqtt: !include mqtt.yaml
        ...

        mqtt.yaml

        sensor:
        #########
        # EBUSD #
        #########
          - state_topic: "ebusd/global/running"
            name: "ebusd_running"
                
          - state_topic: "ebusd/global/signal"
            name: "ebusd_signal"
            
          - state_topic: "ebusd/global/uptime"
            name: "ebusd_uptime"
            
          - state_topic: "ebusd/global/version"
            name: "ebusd_version"
        
        
          - state_topic: "ebusd/bai/Status01"
            name: "ebus_FlowTemp"
            value_template: "{{ value_json['temp']['value'] }}"
            unit_of_measurement: '°C'
            device_class: temperature
        
          - state_topic: "ebusd/bai/Status01"
            name: "ebus_ReturnTemp"
            value_template: "{{ value_json['temp_1']['value'] | round(1)}}"
            unit_of_measurement: '°C'
            device_class: temperature
        
          - state_topic: "ebusd/bai/Status01"
            name: "Temperatura zewnętrzna"
            value_template: "{{ value_json['temp_2']['value'] | round(1)}}"
            unit_of_measurement: '°C'
            device_class: temperature
        
          - state_topic: "ebusd/bai/Status01"
            name: "Temperatura c.w."
            value_template: "{{ value_json['temp_4']['value'] }}"
            unit_of_measurement: '°C'
            device_class: temperature
            
          - state_topic: "ebusd/bai/Status01"
            name: "Płomień"
            value_template: "{{ value_json['pumpstate']['value'] }}"
        
        ##z automatyzacji
          - state_topic: "ebusd/400/RoomTemp"
            name: "Temperatura Jadalnia"
            value_template: "{{ ((value_json['temp']['value']|float)-1) | round(1)}}"
            unit_of_measurement: '°C'
            device_class: temperature
            
          - state_topic: "ebusd/400/ActualRoomTempDesired"
            name: "Temperatura zadana"
            value_template: "{{ value_json['value']['value'] | round(1)}}"
            unit_of_measurement: '°C'
            device_class: temperature
            
          - state_topic: "ebusd/bai/HcHours"
            name: "Liczba godzin pracy ogrzewania"
            value_template: "{{ value_json['value']['value'] }}"
            unit_of_measurement: 'h'
        
          - state_topic: "ebusd/bai/HwcHours"
            name: "Liczba godzin pracy c.w.u."
            value_template: "{{ value_json['value']['value'] }}"
            unit_of_measurement: 'h'
        
          - state_topic: "ebusd/bai/FlowSetPotmeter"
            name: "Ustawienie ogrzewania"
            value_template: "{{ value_json['value']['value'] | round(1)}}"
            unit_of_measurement: '°C'
            device_class: temperature
        
          - state_topic: "ebusd/bai/HwcSetPotmeter"
            name: "Ustawienie c.w.u"
            value_template: "{{ value_json['value']['value'] | round(1)}}"
            unit_of_measurement: '°C'
            device_class: temperature
            
          - state_topic: "ebusd/bai/WaterPressure"
            name: "Ciśnienie wody"
            value_template: "{{ value_json['press']['value'] }}"
            unit_of_measurement: 'Pa'
            device_class: pressure
            
          - state_topic: "ebusd/bai/CirPump"
            name: "Pompa cyrkulacyjna"
            value_template: "{{ value_json['value']['value'] }}"
            
          - state_topic: "ebusd/400/HeatingCurve"
            name: "Krzywa grzewcza"
            value_template: "{{ value_json['value']['value'] }}"
            
          - state_topic: "ebusd/400/IsInHoliday"
            name: "Tryb wakacyjny"
            value_template: "{{ value_json['value']['value'] }}"
            
          - state_topic: "ebusd/400/IsInParty"
            name: "Tryb impreza"
            value_template: "{{ value_json['value']['value'] }}"
            
          - state_topic: "ebusd/400/IsInSingleHwcLoadingMode"
            name: "Tryb ładowania zasobnika"
            value_template: "{{ value_json['value']['value'] }}"
        
          - state_topic: "ebusd/bai/Status02"
            name: "ebusd_hwcmode"
            value_template: "{{ value_json['hwcmode']['value'] }}"
        
          - state_topic: "ebusd/bai/Status02"
            name: "ebusd_st2_1"
            value_template: "{{ value_json['temp_1']['value'] }}"
        
          - state_topic: "ebusd/bai/Status02"
            name: "ebusd_st2_2"
            value_template: "{{ value_json['temp_2']['value'] }}"
            unit_of_measurement: '°C'
            device_class: temperature    
        
          - state_topic: "ebusd/bai/Status02"
            name: "ebusd_st2_3"
            value_template: "{{ value_json['temp_3']['value'] }}"    
        
          - state_topic: "ebusd/bai/Status02"
            name: "ebusd_st2_4"
            value_template: "{{ value_json['temp_4']['value'] }}"    
            unit_of_measurement: '°C'
            device_class: temperature    
            
          - state_topic: "ebusd/bai/PrEnergySumHwc1"
            name: "ebusd_PrEnergySumHwc1"
            value_template: "{{ value_json['value']['value'] }}"    
            unit_of_measurement: 'W'
            device_class: power
            
          - state_topic: "ebusd/bai/PrEnergySumHwc2"
            name: "ebusd_PrEnergySumHwc2"
            value_template: "{{ value_json['value']['value'] }}"    
            unit_of_measurement: 'W'
            device_class: power
        
          - state_topic: "ebusd/bai/PrEnergySumHwc3"
            name: "ebusd_PrEnergySumHwc3"
            value_template: "{{ value_json['value']['value'] }}"   
            unit_of_measurement: 'W'
            device_class: power
        
          - state_topic: "ebusd/bai/PrEnergySumHc1"
            name: "ebusd_PrEnergySumHc1"
            value_template: "{{ value_json['value']['value'] }}"   
            unit_of_measurement: 'W'
            device_class: power
        
          - state_topic: "ebusd/bai/PrEnergySumHc2"
            name: "ebusd_PrEnergySumHc2"
            value_template: "{{ value_json['value']['value'] }}"   
            unit_of_measurement: 'W'
            device_class: power
        
          - state_topic: "ebusd/bai/PrEnergySumHc3"
            name: "ebusd_PrEnergySumHc3"
            value_template: "{{ value_json['value']['value'] }}"   
            unit_of_measurement: 'W'
            device_class: power
        
          - state_topic: "ebusd/bai/PrEnergyCountHwc1"
            name: "ebusd_PrEnergyCountHwc1"
            value_template: "{{ value_json['value']['value'] }}"    
            unit_of_measurement: 'W'
            device_class: power
        
          - state_topic: "ebusd/400/OperatingModeHwc"
            name: "ebusd_OperatingModeHwc"
            value_template: "{{ value_json.value.value }}"
        
          - state_topic: "ebusd/400/OperatingMode"
            name: "ebusd_OperatingMode"
            value_template: "{{ value_json.value.value }}"

        Konfiguracja dodatkowych obiektów w pliku mqtt.yaml

        climate:
          - name: "Ogrzewanie"
            max_temp: 25
            min_temp: 15
            precision: 0.1
            temp_step: 0.5
            modes:
              - "heat"
              - "off"
            mode_state_template: >-
              {% set values = { 'auto':'auto', 'on':'heat',  'hwc':'cool', 'off':'off'} %}
              {% set state = value_json['pumpstate']['value'] %}
              {{ values[state] if state in values.keys() else 'off' }}
            mode_state_topic: "ebusd/bai/Status01"
            current_temperature_topic: "ebusd/400/RoomTemp"
            current_temperature_template: '{{value_json["temp"].value|float -1.25 }}'
            temperature_state_topic: "ebusd/400/ActualRoomTempDesired"
            temperature_state_template: '{{value_json.value.value}}'
          - name: "Ciepła woda"
            max_temp: 65
            min_temp: 40
            precision: 1
            temp_step: 1
            modes:
              - "heat"
              - "off"
            mode_state_template: >-
              {% set values = { 'hwc':'heat', 'off':'off'} %}
              {% set state = value_json['pumpstate']['value'] %}
              {{ values[state] if state in values.keys() else 'off' }}
              
            mode_state_topic:  "ebusd/bai/Status01"
            temperature_state_topic: "ebusd/400/HwcTempDesired"
            temperature_state_template: '{{value_json.value.value}}'
            temperature_command_topic: "ebusd/400/HwcTempDesired/set"
            current_temperature_topic: "ebusd/bai/StorageTemp"
            current_temperature_template: '{{value_json["temp"].value}}'
        
        number:
          - name: mqtt_tryb_wakacyjny
            icon: mdi:caravan
            min: 0 
            max: 20
            step: 1
            mode: slider
            command_topic: ebusd/400/IsInHoliday/set
            state_topic: "ebusd/400/IsInHoliday"
            value_template: '{{value_json.value.value | int}}'
          - name: mqtt_krzywa_grzewcza
            icon: mdi:chart-bell-curve-cumulative
            min: 0.2
            max: 4
            step: 0.1
            mode: slider
            command_topic: ebusd/400/HeatingCurve/set
            state_topic: ebusd/400/HeatingCurve
            value_template: '{{value_json.value.value | float}}'
        
        switch:
          - name: mqtt_tryb_impreza
            icon: mdi:glass-cocktail
            command_topic: "ebusd/400/IsInParty/set"
            state_topic: "ebusd/400/IsInParty"
            value_template: '{{value_json.value.value }}'
            payload_on: "on"
            payload_off: "off"
          - name: mqtt_tryb_ladowania_zasobnika
            icon: mdi:heat-pump
            command_topic: "ebusd/400/IsInSingleHwcLoadingMode/set"
            state_topic: "ebusd/400/IsInSingleHwcLoadingMode"
            value_template: '{{value_json.value.value }}'
            payload_on: "on"
            payload_off: "off"    

        Zużycie gazu

        Zużycie gazu można wyliczyć na podstawie liczników PrEnergySumHwc1 oraz PrEnergySumHw1. Na podstawie pomiarów należy wyliczyć stosunek zużycia gazu do sumy PrEnergySumHwc1 i PrEnergySumHw1.

        Komponent do wprowadzenia poprzednich wartości odczytanych

        type: entities
        entities:
          - entity: input_number.gas_last_measure
          - entity: input_number.gas_prenergysumhc1
          - entity: input_number.gas_prenergysumhwc1
          - entity: input_number.wspolczynnik_gazu
          - entity: sensor.licznik_gazu
        title: Zużycie gazu
        show_header_toggle: false

        Wyliczenie bieżącej wartości zużycia gazu (plik sensors.yaml)

              licznik_gazu:
                friendly_name: "Licznik gazu"
                unit_of_measurement: "m³"
                device_class: gas
                icon_template:
                    mdi:gas-burner
                value_template: '{{ ((states.input_number.gas_last_measure.state | float) +
                   ((states.sensor.ebusd_prenergysumhc1.state | int +  states.sensor.ebusd_prenergysumhwc1.state | int) -
                   (states.input_number.gas_prenergysumhc1.state | int + states.input_number.gas_prenergysumhwc1.state | int)) /
                   (states.input_number.wspolczynnik_gazu.state | float)
                   ) |round(3) 
                  }}

        Linki

        https://ebusd.eu

        https://adapter.ebusd.eu/v2/index.en.html

        https://github.com/john30/ebusd-configuration/issues/117

      4. Pomiar odległości, temperatury oraz wilgotności

        Kiedyś wymyśliłem, że przydałaby się informacja, czy w garażu jest zaparkowany samochód. Wyszło całkiem proste urządzenie, które poza identyfikacją samochodu, jednocześnie weryfikuje – czy jest otwarta, czy zamknięta brama garażowa oraz mierzy temperaturę i wilgotność w garażu. Koszt ok 40 PLN (bez obudowy i zasilacza na microUSB).

        Czujnik temperatury jest opcjonalny.

        Ważne jest umiejscowienie całego urządzenia – na suficie, czujnik odległości skierowany w dół, nad końcem otwartej bramy garażowej, dzięki temu można wyłapać stany (otwarty garaż, auto/zamknięty garaż, brak auta/zamknięty garaż) dodatkowo czujnik musi być umieszczony nad zaparkowanym autem.

        Wykorzystane komponenty:

        • Czujnik odległości HC-SR04
        • Czujnik SI7021 (ja wykorzystałem wolny czujnik od Sonoff TH10, TH16, itd.)
        • Wemos D1 mini

        Poniżej schemat:

        plus podłączenie SI7021 na D5 (pin 12). Na schemacie nie zaznaczono masy i podłączenie zasilania do Wemos D1 mini.

        Oprogramowanie

        Należy wcześniej zainstalować dodatek ESPHome w HomeAssistant.

        Poniżej konfiguracja Wemos D1 mini w ESPHome. Należy dodatkowo utworzyć plik secrets.yaml w EspHome.

        esphome:
          name: wemos1
          platform: ESP8266
          board: d1_mini
        
        wifi:
          networks:
          - ssid: !secret ssid
            password: !secret password
        
          # Enable fallback hotspot (captive portal) in case wifi connection fails
          ap:
            ssid: "Wemos1 Fallback Hotspot"
            password: !secret password_fallback
        
        captive_portal:
        
        # Enable logging
        logger:
        
        # Enable Home Assistant API
        api:
        
        ota:
          - platform: esphome
          
        web_server:
        
        sensor:
          - platform: dht
            model: SI7021 
            pin: D5
            temperature:
              name: "garaz_temperature"
            humidity:
              name: "garaz_humidity"
            update_interval: 60s
            
          - platform: ultrasonic
            trigger_pin: D7
            echo_pin: D6
            timeout: 3 m
            update_interval: 3s
            name: "garaz_distance"    
            filters:
            - lambda: |-
                 float MAX_DIFFERENCE = .3;  // adjust this!
                 static float last_value_t = NAN;
                 static int count_missed_t = 0;
                 if (count_missed_t == 3) last_value_t = x;
                 if (isnan(last_value_t) || std::abs(x - last_value_t) < MAX_DIFFERENCE) {
                    if (count_missed_t)
                       ESP_LOGI("sensor", "New echo value %.3f", x);
                    count_missed_t = 0;
                    return last_value_t = x;
                 } else {
                    count_missed_t += 1;
                    ESP_LOGW("sensor", "Missed echo value %.3f => %.3f, %d", last_value_t, x, count_missed_t);
                    return last_value_t;
                 }
            - sliding_window_moving_average:
                 window_size: 256
                 send_every: 1  
        mqtt:
          broker:  !secret mqtt_broker_ip
          username: !secret mqtt_username
          password: !secret mqtt_password

        Plik secrets.yaml

        #mqtt
        mqtt_broker_ip: 192.168.1.1
        mqtt_username: uzytkownik_mqtt
        mqtt_password: haslo_mqtt
        
        # Your Wi-Fi SSID and password
        ssid: 'nazwa_wifi'
        password: 'haslo_wifi'
        
        #Wifi Fallback Hotspot
        password_fallback: 'magiczne_haslo'

        Konfiguracja

        Home Assistant

        Czujnik jest wykrywany automatycznie przez Home Assistanta.

        Kod sensora

          - platform: template
            sensors:
              garaz:
                friendly_name: "Garaż"
                value_template: >-           
                    {% if float(states("sensor.garaz_distance"))<float(0.30) -%}
                       Otwarty
                    {% elif (float(states("sensor.garaz_distance"))>float(0.80)) and (float(states("sensor.garaz_distance"))<=float(1.10))  -%}
                       Auto 1
                    {% elif (float(states("sensor.garaz_distance"))>float(1.10)) and (float(states("sensor.garaz_distance"))<=float(1.18))  -%}
                       Auto 2
                    {% elif (float(states("sensor.garaz_distance"))>float(1.18)) and (float(states("sensor.garaz_distance"))<=float(1.30))  -%}
                       Auto 3
                    {% elif (float(states("sensor.garaz_distance"))>float(1.30)) -%}
                       Pusty
                    {% else -%}
                       ???
                    {% endif -%}
                icon_template:
                    mdi:car

        Należy dobrać odpowiednio wysokości, aby poprawnie wykrywać otwarcie garażu oraz poszczególne samochody (muszą się różnić wysokością dachu).

        Automatyzacje

        - id: 'auto_garaz_swiatla_on_gate'
          alias: 'Garaż - włącz światło (brama)'
          trigger:
            platform: state
            entity_id: sensor.garaz
            to: 'Otwarty'
          condition:
            - condition: state
              entity_id: light.garaz
              state: 'off'
              for:
                seconds: 10
          action:
            service: light.turn_on
            entity_id: light.garaz
        
        - id: 'openGarageNotification10m'
          alias: openGarageNotification10m
          description: 'Garaz - powiadomienie o otwarciu przez 10m'
          trigger:
          - platform: state
            entity_id:
            - sensor.garaz
            to: Otwarty
            for:
              hours: 0
              minutes: 10
              seconds: 0
          condition: []
          action:
          - service: script.notify_opengarage_10m
            data: {}
          mode: single

        i przykładowy skrypt z powiadomieniem o otwartym garażu (plik script.yaml)

          notify_opengarage_10m:
            alias: "Powiadomienie - Otwarty garaz przez 10min"
            sequence:
              - service: camera.snapshot
                target:
                  entity_id: camera.esp32camgaraz_esp_cam
                data:
                  filename: ../media/snapshot10m.jpg
              - service: notify.gmail_notifier
                data:
                  title: "[HA] Garaż otwarty"
                  message: "Garaż otwarty"
                  data:
                    images:
                    - ../media/snapshot10m.jpg
      5. Integracja z alarmem Satel Integra 64

        Istnieje oczywiście możliwość integracji przez moduł eth, ale ponieważ jest on kosztowny zaprojektowałem proste rozwiązanie wykorzystując wolne wyjścia w domowej centrali Satel Integra. Nie jest to dwukierunkowa integracja, a jedynie przekazywanie informacji od alarmu do HomeAssistant. Dzięki temu można stworzyć fajne automatyzacje na podstawie wykrytego ruchu. Koszt integracji ok 50 PLN

        W tym rozwiązaniu akumulator w centrali alarmowej jest wykorzystywany jako UPS dla RaspberryPI, co oczywiście skraca czas działania alarmu przy długich wyłączeniach prądu.

        Hardware

        • Konwerter poziomów logicznych dwukierunkowy, 4-kanałowy – Pololu – 2 szt.
        • Przetwornica Step-Down – 9-38V – na 5V – USB – 5A
        • NodeMCU (alternatywnie Wemos D1 mini – tańsze rozwiązanie, ja miałem pod ręką akurat wolny chipset NodeMCU)

        Schemat blokowy

        Zastosowałem 25W przetwornicę napięcia, aby z alarmu zasilić od razu RaspberryPI na którym jest uruchomiony HomeAssistant. Dzięki temu w przypadku braku zasilania RPi działa aż do wyczerpania baterii w alarmie.

        Ważne jest użycie i skonfigurowanie odpowiednich wyjść w na płycie Integra – nie wszystkie wyjścia są wyjściami wysokoprądowymi.

        Uwaga na schemacie nie zaznaczono masy.

        Widok płytki od strony elementów

        Software

        Alarm

        Konfiguracja w systemie alarmowym jest wykonana w oprogramowaniu DLOADX.

        Wyjścia typu Out są wysterowane przez 3 sekundy przez wejścia z czujek PIR

        Wyjście OUT Integra64OpisNodeMcu
        4Zasilanie 12V/3A: – Raspberry 5V/2,5A – NodeMCU 5V/300mA –
        5Załączony alarm w strefach: 1, 3D3/GPIO0
        6PIR1D1/GPIO5
        7PIR2D4/GPIO2
        9PIR3D2/GPIO4
        10PIR4D5/GPIO14
        12PIR5D0/GPIO16
        13PIR6D6/GPIO12
        14PIR7D7/GPIO13

        HomeAssistant

        ESPHome

        Należy wcześniej zainstalować addon ESPHome w HomeAssistant

        Konfiguracja NodeMCU w ESPHome. Należy dodatkowo utworzyć plik secrets.yaml

        esphome:
          name: alarm
          platform: ESP8266
          board: nodemcuv2
        
        wifi:
          networks:
          - ssid: !secret ssid
            password: !secret password
        
          # Enable fallback hotspot (captive portal) in case wifi connection fails
          ap:
            ssid: "Alarm Fallback Hotspot"
            password: !secret password_fallback
        
        captive_portal:
        
        # Enable logging
        logger:
          level: INFO
        
        # Enable Home Assistant API
        api:
          port: 6053
        
        ota:
          - platform: esphome
          
        #web_server:
        
        mqtt:
          broker:  !secret mqtt_broker_ip
          username: !secret mqtt_username
          password: !secret mqtt_password
        
        binary_sensor:
          - platform: gpio
            pin: 
              number: GPIO0
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "alarm_1_3"
            
          - platform: gpio
            pin: 
              number: GPIO5
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir1"
            device_class: motion
        
          - platform: gpio
            pin: 
              number: GPIO2
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir2"
            device_class: motion
            
          - platform: gpio
            pin: 
              number: GPIO4
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir3"
            device_class: motion
        
          - platform: gpio
            pin: 
              number: GPIO14
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir4"
            device_class: motion
            
          - platform: gpio
            pin: 
              number: GPIO16
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir5"   
            device_class: motion
            
          - platform: gpio
            pin: 
              number: GPIO12
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir6"
            device_class: motion
            
          - platform: gpio
            pin:  
              number: GPIO13
            filters:
              - invert:
              - delayed_on: 250ms
              - delayed_off: 250ms
            name: "ruch_pir7"
            device_class: motion

        Plik secrets.yaml

        #mqtt
        mqtt_broker_ip: 192.168.1.1
        mqtt_username: uzytkownik_mqtt
        mqtt_password: haslo_mqtt
        
        # Your Wi-Fi SSID and password
        ssid: 'nazwa_wifi'
        password: 'haslo_wifi'
        
        #Wifi Fallback Hotspot
        password_fallback: 'magiczne_haslo'

        Przykładowe automatyzacje

        Włączenie/wyłączenie światła

        - id: 'auto_kuchnia_swiatla_on'
          alias: 'Kuchnia - Włącz światło'
          trigger:
            platform: state
            entity_id: binary_sensor.ruch_pir1
            from: 'off'
            to: 'on'
          condition:
            condition: and
            conditions:
            - condition: state
              entity_id: light.kuchnia
              state: 'off'
              for:
                seconds: 5
            - condition: template
              value_template: "{{ states.sun.sun.attributes.elevation  | int < 3 }}"
          action:
            service: light.turn_on
            entity_id: light.kuchnia
        
        - id: 'auto_kuchnia_swiatla_off'
          alias: 'Kuchnia - wyłącz po 3 min'
          trigger:
            platform: state
            entity_id: binary_sensor.ruch_pir1
            to: 'off'
            for: 
              minutes: 3
          condition:
            - condition: state
              entity_id: light.kuchnia
              state: 'on'
          action:
            service: light.turn_off
            entity_id: light.kuchnia

        Wyłączenie urządzeń przy załączeniu strefy w alarmie

        - id: 'auto_alarm_swiatla_off'
          alias: 'Alarm - Wyłącz światła przy załączonym alarmie'
          trigger:
            platform: state
            entity_id: binary_sensor.alarm_1_3
            from: 'off'
            to: 'on'
            for: 
              seconds: 15
          condition:
            - condition: state
              entity_id: group.swiatla_dol
              state: 'on'
          action:
            - service: light.turn_off
              entity_id: group.swiatla_dol
            - service: switch.turn_off
              entity_id: switch.pompa_wody
            - service: light.turn_off
              entity_id: light.lampki_choinkowe
            - service: media_player.turn_off
              entity_id: media_player.amplituner
            - service: media_player.turn_off
              entity_id: media_player.tv

        Linki

        https://esphome.io

        https://www.satel.pl/instrukcje

      6. Sterowanie przez podczerwień i pomiar temperatury, wilgotności i ciśnienia

        Jedno z moich pierwszych urządzeń to pilot na podczerwień (odbiornik i nadajnik) oraz pomiar temperatury, wilgotności i ciśnienia (szacunkowy koszt ok 40 PLN, bez zasilacza). Jest też gotowy shield IR do Wemos D1 mini – co jest prostszym rozwiązaniem niż lutowanie całości.

        Wykorzystane komponenty:

        • Wemos D1 mini
        • BME280
        • nadajnik i odbiornik podczerwieni

        Poniżej schemat logiczny:

        Układ połączeń

        Uwaga – należy jak najdalej odsunąć czujnik BME280 od Wemos D1

        Oprogramowanie

        Do układu Wemos D1 mini zostało wgrane oprogramowanie Tasmota Sensor. Wcześniej używałem ESPHome, ale w tym przypadku trudniej obsługiwać sterowanie różnymi pilotami na podczerwień. Tasmota Sensor rozpoznaje kody pilotów różnych dostawców., dzięki czemu skrypty w HomeAssistant są prostsze. Opcjonalnie można by też użyć wersji tasmota-ir, aby obsłużyć więcej różnych dostawców urządzeń IR.

        Konfiguracja

        Tasmota Sensor

        Dodatkowo w Tasmocie jest ustawiona konfiguracja połączenia do serwera MQTT.

        Odczyt kodów IR z pilota najlepiej przeprowadzić z poziomu konsoli Tasmota.

        HomeAssistant

        Czujnik BME280 wykrywany jest automatycznie przez HA.

        Przykładowy skrypt wysyłający kod IR do urządzenia:

         script:
          amplituner_volume_up:
            alias: Głośniej
            sequence:
              - service: mqtt.publish
                data_template:
                  payload: "{\"Protocol\":\"NEC\",\"Bits\":32,\"Data\":0x5EA158A7}"
                  topic: cmnd/wemos2/IRSend
                  retain: true

        Linki

        https://tasmota.github.io/docs

      7. Pobranie danych z licznika wody Multical 21

        Poniżej tania integracja (ok. 50PLN) odczytu bieżącego zużycia wody z licznika Multical 21. Aby uruchomić tą integracja trzeba:

        • spore umiejętności przy lutowaniu oraz
        • kontakt z firmą, która obsługuje rozliczenie wody i trochę cierpliwości, aby otrzymać kod deszyfrujący AES dla licznika

        Licznik Multial 21 może wysyłać dane bezprzewodowo przy użyciu protokołu Wireless M-Bus. Multical21 zapewnia następujące dane:

        • licznik całkowity – całkowite zużycie wody w m³
        • licznik docelowy – zużycie wody do 1. dnia bieżącego miesiąca
        • temperatura średnia – w °C
        • temperatura otoczenia – w °C
        • kody informacyjne – BURST, LEAK, DRY, REVERSE, TAMPER, RADIO OFF
        Kod informacyjny
        wyświetlany na
        wyświetlaczu
        Znaczenie
        LEAK W ciągu ostatniej doby nie zanotowano zatrzymania przepływu przez wodomierz przez minimum jedną godzinę.
        Może to świadczyć o nieszczelności kranu lub zbiornika toalety.
        BURST Stałe wysokie zużycie wody w ciągu pół godziny, co oznacza pęknięcie rury.
        TAMPER Próba oszustwa. Wodomierz nie nadaje się do celów rozliczeniowych.
        DRY Brak wody w wodomierzu. Pomiar nie jest prowadzony.
        REVERSE Woda przepływa przez wodomierz w nieprawidłowym kierunku.
        RADIO OFFRADIO OFF wyświetlany ciągle. Nadajnik radiowy jest permanentnie wyłączony.

        Hardware

        • Wemos D1 mini (lub ESP32) – koszt ok 12 PLN
        • moduł radiowy CC1101 868 MHz z anteną (ja zamówiłem tu) – koszt ok 30 PLN
        • 7 przewodów

        Software

        Połączenie

        Trzeba sporo wprawy, aby zlutować połączenia do CC1101 – raster jest mniejszy niż standardowy goldpin.

        CC1101ESP8266
        VCC3V3
        GNDGND
        CSND8
        MOSID7
        MISOD6
        SCKD5
        GDO0D2

        Poniżej jak mi to wyszło:

        Uruchomienie

        Polecam najpierw złożyć, uruchomić bez kodu deszyfrującego – zweryfikować, czy działa komunikacja . A następnie ponowne programowanie Wemos D1 mini już z kluczem AES. W moim przypadku odczyt następuje z ok 10 metrów przez kilka ścian.

        Aby uzyskać klucz deszyfrujący AES należy skontaktować się ze spółką rozliczającą wodę. W moim przypadku wystarczyło pismo ogólne zgłoszone przez platformę EPUAP (w tym wypadku nie musiałem poświadczać swojej tożsamości) i plik z kluczem oraz hasłem dostałem bezpośrednio na emaila. (podziękowania dla pana Piotra ze Spółki Komunalnej Żukowo).

        Przykładowe pismo znajduje się tu.

        Plik ZIP z plikiem KEM zawiera kluczem AES, Aby odczytać klucz AES konieczne jest hasło i należy użyć dodatkowego programu w python.

        Programowanie

        Na PlatformIO zaimportuj projekt esp-multical21.

        Zmiany w kodzie

        Należy zmienić nazwę pliku config_template.h na config.h oraz w pliku wprowadzić zmiany

        Ustawić numer licznika

        //numer seryjny licznika
        #define SERIAL_NUMBER       0x65, 0x00, 0x05, 0x43

        Ustawić sieć WiFi, adres serwera MQTT

        std::vector<CREDENTIAL> const credentials = {
             { "sid_sieci_wifi", "haslo_sieci_wifi", "", "", ""}   // no MQTT
           , { "sid_sieci_wifi", "haslo_sieci_wifi", "adres_IP_serwera_mqtt", "login_serwera_mqtt", "haslo_serwera_mqtt"}  // MQTT with auth
        };

        Ustawić klucz AES (najlepiej po sprawdzeniu, czy odbiera się ramki z licznika

        #define ENCRYPTION_KEY      0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x10, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
        

        Weryfikacja logów na porcie COM z prędkością 115200. Podczas wyszukiwania sieci mruga dioda na chipie Wemos D1.

        Dekodowanie pliku KEM

        Aby odczytać klucz AES należy uruchomić program kem-decryptor.py w pythonie ze strony:

        https://gist.github.com/mbursa/caa654a01b9e804ad44d1f00208a2490

        kem-decryptor.py nazwa_pliku_ZIP_lub_KEM hasło

        Na ekranie oraz w pliku etc\wmbusmeters.d\<numer_Licznika> będzie klucz który przepisujemy do pliku config.h, ponownie kompilujemy i wgrywamy oprogramowanie do Wemos D1 mini.

        Konfiguracja HA

        W moim przypadku Wemos przesyła informacje do serwera MQTT uruchomionego jako dodatek w HA.

        Konfiguracja dla sekcji mqtt:

        Plik configuration,xml

        mqtt: !include mqtt.yaml

        Plik mqtt.xml

          - state_topic: "watermeter/0/total"
            name: "watermeter_total"  
            unit_of_measurement: "m³"
            device_class: water
            state_class: total_increasing
            icon: mdi:water
        
          - state_topic: "watermeter/0/target"
            name: "watermeter_target"  
            unit_of_measurement: "m³"
            device_class: water
            state_class: total_increasing
            icon: mdi:water
        
          - state_topic: "watermeter/0/infocode"
            name: "watermeter_infocode"  
            
          - state_topic: "watermeter/0/flowtemp"
            name: "watermeter_flowtemp"  
            unit_of_measurement: '°C'
            device_class: temperature   
        
          - state_topic: "watermeter/0/ambienttemp"
            name: "watermeter_ambienttemp"  
            unit_of_measurement: '°C'
            device_class: temperature   

        A tak to wygląda w HomeAssistant:

        Linki

        Karta katalogowa Multical 21

        https://github.com/chester4444/esp-multical21

        https://github.com/wmbusmeters