Kategoria: HomeAssistant

Posty o rozbudowie smartdom w oparciu o Home Assistant

  • Konfiguracja HomeAssistant

    System

    HA działa jako kontener na dockerze. Nie jest to najprostsza konfiguracja, ale jedna z najbardziej elastycznych. Z jednej strony mamy możliwość aktualizacji HA, a z drugiej możliwość uruchomienia dodatkowego oprogramowania – w moim przypadku: Ebusd oraz Samba.

    Dodatki

    DodatekCel
    DuckDNS + NgnixKonfiguracja SSL plus wystawienie HA do internetu
    ESPHome Device BuilderESPHome – oprogramowanie dla chipów i czujników
    File editorEdycja plików
    Frigate HailoRTPodgląd kamer, analiza ruchu, serwer NVR
    Home Assistant Google Drive BackupAutomatyczne backupy w chmurze
    Mosquitto brokerSerwer MQTT
    SQLite WebKlient SQL dla SQLLite
    TasmoAdminZarządzanie urządzeniami Tasmota
    TasmoBackupBackup urządzeń Tasmota
    Uptime KumaMonitoring urządzeń
    Zigbee2MQTTObsługa urządzeń Zigbee

    HACS

    Niestandardowe integracje

    IntegracjaCel
    HACSModuł do pobierania dodatkowych komponentów i integracji
    AntistormPrognoza burz i opadów
    Disk SpaceSensor wielkości dysku
    FrigateIntegracja z frigate
    Media player templateDedykowany player dla niestandardowych urządzeń multimedialnych
    Uptime KumaIntegracja z Uptime Kuma
    ViomiseIntegracja dla odkurzacza Viomi SE and Xiaomi STY02YM, STYJ02YM
    Waste Collection SchedulePobranie danych
    Weather CardAnimowana „stara” karta pogody

    Niestandardowe komponenty

    KomponentyCel
    Advanced Camera CardKomponent kamer z frigate z historią
    Atomic Calendar ReviveKalendarz
    Bar CardPasek Bar
    Button CardKlawisze na GUI
    Mini Media PlayerMniejszy komponent dla Media Player
    Xiaomi Vacuum Map Card Komponent odkurzacza Xiaomi
  • Monitorowanie otoczenia

    Monitorowanie otoczenia

    Do monitorowania obrazu z kamera do niedawna używałem addona motionEye, jednak ostatnio przesiadłem się na addon Frigate. Oferuje znacznie większe możliwości, takie jak rozpoznawanie określonych obiektów oraz dzięków. W tym rozwiązaniu jest używany akcelerator NPU Hailo8L, odciża procesor RP5 z operacji analizy obrazu. Hailo ma bardzo dobry współczynnik ilości obliczeń do zużywanej mocy. Całość jest zasilana ze standardowego zasilacza RPI5.

    Hardware

    • „tania” chińska kamera P05-7
    • ESP32 + kamera OV2460
    • Raspberry Pi AI Kit (M.2 HAT+ i akcelerator Hailo-8L) – link
    • (opcjonalnie) TV z GoogleTV
    • (opcjonalnie) Telefon z Androidem wraz ze skonfigurowaną aplikacją HA

    Software

    • Addon: Frigate HailoRT
    • Integracja HACS: Frigate Home Assistant Integration
    • Komponent HACS: Advanced Camera Card
    • (opcjonalnie) TvOverlay – aplikacja umożliwiająca wyświetlanie powiadomień na Google TV
    • uruchomiony serwer Samba

    Konfiguracja HA

    Używam podłączonego dysku USB do przechowywania nagrań. Dysk jest skonfigurowany jako dysk sieciowy przy użyciu Samby.

    W HA: Ustawienia -> System -> Pamięć masowa

    Instalacja Hailo

    Podłączenie Hailo do RPi5 – link

    Konfiguracja systemu pod Hailo – link

    Niestety paczka hailo-all zawiera firmware i sterownik w wersji 4.20, a wersja Frigate HailoRT 0.15 zwiera oprogramowanie do Hailo w wersji 4.19. Konieczne jest przygotowanie własnej wersji sterownika i frimware do obsługi Hailo. Szczegóły rozwiązania w artykule link.

    Konfiguracja Frigate

    mqtt:
      host: 192.168.1.2
      user: MQTT_USER
      password: MQTT_PASSWORD
    
    ffmpeg:
      hwaccel_args: preset-rpi-64-h264
    
    record:
      enabled: true
      retain:
        days: 3
        mode: motion
      alerts:
        retain:
          days: 10
          mode: motion
      detections:
        retain:
          days: 10
          mode: motion
    timestamp_style:
      position: bl
      format: '%Y.%m.%d %H:%M:%S'
    
    detectors:
      hailo8l:
        type: hailo8l
        device: PCIe
    #    model:
    #      # from https://github.com/hailo-ai/hailo_model_zoo/blob/master/docs/public_models/HAILO8L/HAILO8L_object_detection.rst
    
    model:
      width: 640
      height: 640
      input_tensor: nhwc
      input_pixel_format: bgr
      model_type: yolox
      path: /config/model_cache/h8l_cache/yolov8s.hef
      labelmap:
        0: person
        1: bicycle
        2: car
        3: motorcycle
        4: airplane
        5: bus
        6: train
        7: truck
        8: boat
        9: traffic light
        10: fire hydrant
        11: stop sign
        12: parking meter
        13: bench
        14: bird
        15: cat
        16: dog
        17: horse
        18: sheep
        19: cow
        20: elephant
        21: bear
        22: zebra
        23: giraffe
        24: backpack
        25: umbrella
        26: handbag
        27: tie
        28: suitcase
        29: frisbee
        30: skis
        31: snowboard
        32: sports ball
        33: kite
        34: baseball bat
        35: baseball glove
        36: skateboard
        37: surfboard
        38: tennis racket
        39: bottle
        40: wine glass
        41: cup
        42: fork
        43: knife
        44: spoon
        45: bowl
        46: banana
        47: apple
        48: sandwich
        49: orange
        50: broccoli
        51: carrot
        52: hot dog
        53: pizza
        54: donut
        55: cake
        56: chair
        57: couch
        58: potted plant
        59: bed
        60: dining table
        61: toilet
        62: TV
        63: laptop
        64: mouse
        65: remote
        66: keyboard
        67: cell phone
        68: microwave
        69: oven
        70: toaster
        71: sink
        72: refrigerator
        73: book
        74: clock
        75: vase
        76: scissors
        77: teddy bear
        78: hair drier
        79: toothbrush
    
    #detectors:
    #  hailo8l:
    #    type: hailo8l
    #    device: PCIe
    
    #model:
    #  width: 300
    #  height: 300
    #  input_tensor: nhwc
    #  input_pixel_format: bgr
    #  model_type: ssd
    #  path: /config/model_cache/h8l_cache/ssd_mobilenet_v1.hef
    
    #objects:
    #  track:
    #    - person
    #    - car
    #    - face
    #    - license_plate
    #    - dog
    #    - cat
    #    - package
    #  filters:
    #    person:
    #      threshold: 0.40
    #    car:
    #      threshold: 0.40
    #    face:
    #      threshold: 0.40
    #    license_plate:
    #      threshold: 0.40
    #    dog:
    #      threshold: 0.40
    #    cat:
    #      threshold: 0.40
    #    package:
    #      threshold: 0.40
    
    snapshots:
      enabled: true
      timestamp: true
      bounding_box: true
      retain:
        default: 14
    
    go2rtc:
      streams:
        Wejscie2: # <- for RTSP streams
          - rtsp://192.168.1.137:8001/ # <- stream which supports video & aac audio
    
    cameras:
      Wejscie2: # <------ Name the camera
        enabled: true
        ffmpeg:
          inputs:
            - path: rtsp://127.0.0.1:8554/Wejscie2 # <----- The stream you want to use for detection
              roles:
                - detect
                - record
        record:
          enabled: true
        detect:
          enabled: true # <---- disable detection until you have a working camera feed
    #      width: 1280
    #      height: 720
    #      fps: 15
        mqtt:
          enabled: true
          timestamp: true
          bounding_box: true
          crop: true
          quality: 90
          required_zones:
            - Chodnik
        motion:
          threshold: 30
          mask: 0,0.058,0.254,0.057,0.255,0.012,0.003,0.01
          contour_area: 20
          improve_contrast: true
    #    onvif:
    #      host: 192.168.4.137
    #      port: 8000
    #      user: admin
    #      ignore_time_mismatch: true
    
        zones:
          Ulica:
            coordinates: 0.532,0.276,0.658,0.321,0.909,0.462,1,0.509,0.999,0.003,0.531,0.004
            loitering_time: 0
            inertia: 3
          Chodnik:
            coordinates: 0.325,1,0.842,0.428,0.65,0.324,0.534,0.284,0.532,0.134,0.003,0.262,0,1
            loitering_time: 0
            inertia: 3
          Parking:
            coordinates: 0.847,0.433,1,0.51,0.998,0.998,0.332,1
            loitering_time: 0
        review:
          alerts:
            required_zones:
              - Ulica
              - Chodnik
          detections:
            required_zones:
              - Ulica
              - Chodnik
      Garaz2:
        enabled: true
        ffmpeg:
          inputs:
            - path: http://192.168.1.138:8080/
              roles:
                - detect
                - record
          input_args: -avoid_negative_ts make_zero -fflags nobuffer -flags low_delay -strict
            experimental -fflags +genpts+discardcorrupt -use_wallclock_as_timestamps 1
            -c:v mjpeg
          output_args:
            detect: -f rawvideo -pix_fmt yuv420p -an
    #        record: -f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v libx264 -preset ultrafast -an
            record: -f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps
              1 -strftime 1 -preset ultrafast -an
    #        rtmp: -f flv -pix_fmt yuv420p -c:v libx264 -preset ultrafast -an
        record:
          enabled: true
        detect:
          enabled: true
          width: 800
          height: 600
          fps: 5
    #    objects:
    #      track:
    #        - person
    #        - face
    #        - package
    #        - cup
        mqtt:
          enabled: true
          timestamp: true
          bounding_box: true
          crop: false
          quality: 100
          height: 600
        motion:
          threshold: 35
          contour_area: 10
          improve_contrast: false
      Podjazd:
        enabled: false
        ffmpeg:
          inputs:
            - path: http://192.168.1.139:8080/
              roles:
                - detect
                - record
          input_args: -avoid_negative_ts make_zero -fflags nobuffer -flags low_delay -strict
            experimental -fflags +genpts+discardcorrupt -use_wallclock_as_timestamps 1
            -c:v mjpeg
          output_args:
            detect: -f rawvideo -pix_fmt yuv420p -an
    #        record: -f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v libx264 -preset ultrafast -an
            record: -f segment -pix_fmt yuv420p -segment_time 10 -segment_format mp4 -reset_timestamps
              1 -strftime 1 -preset ultrafast -an
    #        rtmp: -f flv -pix_fmt yuv420p -c:v libx264 -preset ultrafast -an
        record:
          enabled: true
        detect:
          enabled: true
          fps: 5
    #    objects:
    #      track:
    #        - person
    #        - face
    #        - package
    #        - cup
        mqtt:
          enabled: true
          timestamp: true
          bounding_box: true
          crop: false
          quality: 100
          height: 600
        motion:
          threshold: 35
          contour_area: 10
          improve_contrast: false
    version: 0.15-1

    Ja korzystam z modelu yolov8s, który należy wcześniej wgrać do katalogu homeassistant/model_cache/h8l_cache

    Powiadomienia na telewizorze GoogleTV (opcjonalnie)

    Telewizor z GoogleTV z aplikacją TVOverlay oraz uruchomiony serwer MQTT na instancji HA.

    Konfiguracja TvOverlay

    Uruchamiamy aplikację na TV i ustawiamy:

    • Background Visibility na 0%
    • Clock Visibility na 0%
    • MQTT – IP, login i hasło serwera MQTT
    • More settings -> Battery Optimalization

    Konfigurację można zweryfikować pobierając XMLa z linku http://IP_TV:5001

    Konfiguracja TvOverlay w HA

    Należy dodać w configuration.yaml w sekcji notify poniższy kod (ustawiając IP_TV i port – domyślnie 5001)

    notify:
      - name: TvOverlayNotify
        platform: rest
        method: POST_JSON
        resource: http://[ip]:[port]/notify 
        verify_ssl: false
        title_param_name: title
        data:
          id: "{{ data.id | default(null) }}"
          appTitle: "{{ data.appTitle  | default('Home Assistant') }}"
          appIcon: "{{ data.appIcon | default('mdi:home-assistant') }}"
          color: "{{ data.color | default('#049cdb') }}"
          image: "{{ data.image | default(null) }}"
          smallIcon: "{{ data.smallIcon | default(null) }}"
          largeIcon: "{{ data.largeIcon | default(null) }}"
          corner: "{{ data.corner  | default(null) }}"
          seconds: "{{ data.seconds | default(null) }}"
          
      - name: TvOverlayNotifyFixed
        platform: rest
        method: POST_JSON
        resource: http://[ip]:[port]/notify_fixed
        verify_ssl: false
        title_param_name: title
        data:
          id: "{{ data.id | default(null) }}"
          text: "{{ data.text  | default(null) }}"
          icon: "{{ data.icon | default(null) }}"
          textColor: "{{ data.textColor | default(null) }}"
          iconColor: "{{ data.iconColor | default(null) }}"
          borderColor: "{{ data.borderColor | default(null) }}"
          backgroundColor: "{{ data.backgroundColor | default(null) }}"
          shape: "{{ data.shape | default(null) }}"
          visible: "{{ data.visible | default(true) }}"
          expiration: "{{ data.expiration | default(null) }}"
    
          
    rest_command:
      tvoverlay:
        url: http://[ip]:[port]/set/overlay
        method: POST
        verify_ssl: false
        headers:
          accept: 'application/json'
        content_type:  'application/json; charset=utf-8'
        payload: '{{ payload }}'

    Następnie można przetestować powiadomienie wywołując usługę w HA z menu Narzędzia deweloperskie -> Akcje

    action: notify.tvoverlaynotify
    data:
      message: The garage door has been open for 10 minutes.
      title: Your Garage Door Friend
      data:
        id: notification_sample
        appTitle: AppTitle
        appIcon: mdi:unicorn
        color: "#FFF000"
        smallIcon: mdi:speaker-multiple
        largeIcon: mdi:camera
        corner: bottom_end
        seconds: 20
        image: https://picsum.photos/300

    Wysłanie powiadomienia z Frigate na telefon i TV

    Jeżeli wysyłanie następuje tylko na telefon to można skorzystać z gotowego blueprinta (link).

    Poniżej moja automatyzacja

    - id: '1663062012156'
      alias: Frigate Notifications
      trigger:
        - platform: mqtt
          topic: frigate/events
          id: frigate-event
          payload: NAZWA_KAMERY
          value_template: "{{ value_json['after']['camera'] }}"
          variables:
            after_zones: "{{ trigger.payload_json['after']['entered_zones'] }}"
            before_zones: "{{ trigger.payload_json['before']['entered_zones'] }}"
            camera: "{{ trigger.payload_json['after']['camera'] }}"
            id: "{{ trigger.payload_json['after']['id'] }}"
            label: "{{ trigger.payload_json['after']['label'] }}"
            score: "{{ trigger.payload_json['after']['score'] }}"
            time_clip_start: "{{ trigger.payload_json['after']['start_time'] - 10.0 }}"
      # Conditions must be used to filter out objects / detections that are not of interest
      condition:
        # This condition is used to ensure that I am only notified of objects that are new or only just entered a zone. This is to avoid getting loads of updated notifications for the same dog in my backyard (as an example).
        - condition: or
          conditions:
            - condition: template
              value_template: "{{ trigger.payload_json['type'] == 'new' }}"
            - condition: template
              value_template: "{{ before_zones | length == 0 }}"
        - condition: template
          value_template: >-
                {{ 'Chodnik' in (after_zones + before_zones) }}
    #    - condition: template
    #      value_template: >-
    #        {{
    #         (as_timestamp(now())-as_timestamp(state_attr('automation.frigate_notifications_with_details2',
    #            'last_triggered') | default(0)) | int > 5) }}
        - condition: state
          entity_id: input_boolean.tv_notify_motion
          state: 'on'
    
      action:
        - service: notify.mobile_phone_app
          data:
            message: >-
               {{ label }}({{ int(score | round(2) * 100) }}%) na {{ after_zones }} wykryty przez {{ camera }}, {{ id }}
            data:
              image: >-
                    /api/frigate/notifications/{{ id }}/thumbnail.jpg
              url: >-
                https://HAOS_EXTERNAL_LINK/api/frigate/notifications/{{ id }}/{{camera}}/clip.mp4
              actions:
                - action: URI
                  title: Video
                  uri: >-
                    https://HAOS_EXTERNAL_LINK/api/frigate/notifications/{{id}}/{{camera}}/clip.mp4
                - action: URI
                  title: Snapshot
                  uri: >-
                    https://HAOS_EXTERNAL_LINK/api/frigate/notifications/{{ id }}/snapshot.jpg
                - action: URI
                  title: Thumbnail
                  uri: >-
                    https://HAOS_EXTERNAL_LINK/api/frigate/notifications/{{ id }}/thumbnail.jpg
        - service: notify.tvoverlaynotify
          data:
            data:
              appTitle: Frigate
              largeIcon: mdi:camera
              color: "#000800"
              seconds: 30
              image: >-
                 https://HAOS_EXTERNAL_LINK/api/frigate/notifications/{{id}}/thumbnail.jpg
            title: >-
              {{ label }} wykryto na {{ camera }}
            message: >-
              {{ label }}({{ int(score | round(2) * 100) }}%) na {{ after_zones }} wykryty przez {{ camera }}
      mode: parallel
      max: 10
    #  trace:
    #    stored_traces: 20

    Linki

    https://frigate.video

    https://docs.frigate.video

    https://github.com/gugutab/TvOverlay

    https://github.com/SgtBatten/HA_blueprints

    https://community.home-assistant.io/t/frigate-mobile-app-notifications-2-0/559732/2618

  • Ambientlight TV za pomocą HyperBian, RPi3 i kamery USB

    Ambientlight TV za pomocą HyperBian, RPi3 i kamery USB

    Fajny projekt, gdzie niewielkim kosztem jest wyświetlane podświetlenie LED za telewizorem na podstawie wyświetlanego obrazu. W moim rozwiązaniu użyta jest kamera umieszczona naprzeciwko TV oraz „stare” Rasberry PI3, które wcześniej sterowało moim domem i po upgrade do RPI5 leżało w szufladzie.

    Została użyta kamera ponieważ na TV wyświetlane są tylko programy z aplikacji streaminowych, nie ma możliwości użycia grabbera sygnału i odczytu obrazu z we/wy HDMI.

    Instalacja jest podzielona na dwie części:

    • RPI3 wraz kamerą USB (kamera umieszczona prawie naprzeciw telewizora),
    • sterowalna listwa LED z ESP32.

    Instalacja

    Schemat blokowy instalacji LED za TV

    Sprzęt

    • Zasilacz 5V/20A (koszt ok 50 PLN) – pewnie można użyć trochę mniejszy,
    • Listwa RGB 2805 (koszt ok 80 PLN) – długość ok 4m (72LED na poziomych listwach i 40 na pionowych),
    • ESP32-DevKitC-32U z anteną (koszt ok 10$),
    • bezpieczniki samochodowe 2x10A,
    • kostka połączeniowa,
    • rezystor 300om (tłumienie zakłóceń na linii DATA),
    • kabel zasilający 2×1.5mm2 – połączenie od zasilacza do kostki.

    Uwagi

    Niestety listwa dolna jest mocniej zasłonięta przez obudowę TV – co powoduje słabsze świecenie diód w dolnej części.

    Konfiguracja

    ESP32

    Zainstalowane oprogramowanie WLED (z przeglądarki Chrome) – link.
    WLED działa przez WIFI, na routerze ustawiony jest stały adres IP. Dodatkowo w WLED ustawiono ilość diód (Length), maksymalną wydajność prądową zasilacza (Maximum PSU Current ) oraz pin z linią danych (Data GPIO).

    RPI3

    Zainstalowane oprogramowanie HyperBian.

    Aby zmniejszyć opóźnienie na linii kamera a listwa LED rejestruje obraz z rozdzielczością 320×240 przy 30FTPs. Relatywnie po kadrowaniu w moim przypadku zostaje ok 100×55 co i tak przewyższa ilość diód LED.

    Integracja z HA

    Standardowa integracja

    Automatyzacje

    Automatyczne włączenie/wyłączenie nagrywania i przetwarzania obrazu przy włączeniu telewizora.

    - id: '1739489846028'
      alias: Turn_off_WLED_salon_on_TV
      description: ''
      triggers:
      - platform: state
        entity_id: media_player.tv
        from: 'on'
        to: 'off'
      conditions: []
      actions:
      - action: light.turn_on
        target:
          entity_id: light.wled210_3
        data:
          brightness_pct: 1    
      - action: switch.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: switch.tv_salon_component_all
      - delay: '00:00:03'
      - action: light.turn_on
        target:
          entity_id: light.wled210_3
        data:
          brightness_pct: 1    
      - action: light.turn_off
        target:
          entity_id: light.wled210_3
      mode: single
    - id: '1739489846029'
      alias: Turn_on_WLED_salon_on_TV
      description: ''
      triggers:
      - platform: state
        entity_id: media_player.tv
        from: 'off'
        to: 'on'
      actions:
      - action: light.turn_on
        target:
          entity_id: light.wled210_3
        data:
          brightness_pct: 1
      - action: switch.turn_on
        target:
          entity_id: switch.tv_salon_component_all
      - action: switch.turn_on
        target:
          entity_id: switch.tv_salon_component_led_device
      - action: light.turn_on
        target:
          entity_id: light.wled210_3
        data:
          brightness_pct: 1    
      mode: single

    Linki

    https://docs.hyperion-project.org

    https://install.wled.me

    https://kno.wled.ge/basics/getting-started

    https://wled-calculator.github.io

    https://www.thegeekpub.com/274631/wled-how-to-setup-and-configure-wled

  • Monitoring urządzeń w domu

    Duża ilość urządzeń w domowej sieci wifi powoduje zawsze problemy z dostępnością wszystkich urządzeń. Do monitoringu działania urządzeń wykorzystuje oprogramowanie „Uptime Kuma” jak dodatek zainstalowany w HA

    Konfiguracja

    Ustawienia pojedynczego monitora dla urządzenia

    Powiadomienia wysyłam bezpośrednio poprzez HA na komórkę. Większość urządzeń monitoruje na odpowiednim temacie MQTT – przykład powyżej.

    Aby pominąć błędne powiadomienia:

    • dla MQTT – heartbeat: 60 sek oraz ilość prób: 5,
    • dla ping – heartbeat: 300 sek oraz ilość prób: 5,

    Konfiguracja HA

    Za pomocą dodatkowej integracji HACS: „Uptime Kuma HACS integration: dodane są sensory do HA, dodatkowo wykorzystany Dashboard HACS: button-card.

    Konfiguracja karty:

    type: vertical-stack
    cards:
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_watermeter1_mqtt
            icon: mdi:water
            name: mbus
            show_state: false
            color: rgb(255, 0, 0)
            font-size: 6px
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_watermeter2
            icon: mdi:water
            name: cam
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_kamera_wejscie
            icon: mdi:camera
            name: Wejście
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_kamera_garaz
            icon: mdi:camera
            name: Garaz
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_alarm_mqtt
            icon: mdi:motion-sensor
            name: Alarm
            show_state: false
            color: rgb(255, 0, 0)
            font-size: 6px
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_kotlownia_mqtt
            icon: mdi:motion-sensor
            name: Kotłownia
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_wemos1_mqtt
            icon: mdi:remote
            name: Wemos1
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_wemos2_mqtt
            icon: mdi:garage-open
            name: Wemos2
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_pompa_wody_mqtt
            icon: mdi:pump
            name: Pompa
            show_state: false
            color: rgb(255, 0, 0)
            font-size: 6px
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_ebusd_signal_mqtt
            icon: mdi:gas-burner
            name: ebusd
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_lampa_sypialnia_lewa_mqtt
            icon: mdi:lamp
            name: Sypialnia lewa
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_lampa_sypialnia_prawa_mqtt
            icon: mdi:lamp
            name: Sypialnia prawa
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_solaredge
            icon: mdi:solar-power-variant
            name: Panele
            show_state: false
            color: rgb(255, 0, 0)
            font-size: 6px
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_odkurzacz
            icon: mdi:robot-vacuum
            name: ebusd
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_nam
            icon: mdi:air-filter
            name: NAM
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_drukarka_hp5070
            icon: mdi:printer
            name: Drukarka
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
      - type: horizontal-stack
        cards:
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_frigate
            icon: mdi:cctv
            name: Frigate
            show_state: false
            color: rgb(255, 0, 0)
            font-size: 6px
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_hyperion
            icon: mdi:led-strip-variant
            name: Hyperion
            show_state: false
            color: rgb(255, 0, 0)
            state:
              - value: up
                color: rgb(0, 255, 0)
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_wled_tv
            icon: mdi:led-off
            name: WLED TV
            show_state: false
            color: gray
            state:
              - value: pending
                color: orange
              - value: up
                color: rgb(0,255,0)
              - value: down
                color: red
          - type: custom:button-card
            styles:
              name:
                - color: gray
                - font-size: 12px
            entity: sensor.uptimekuma_wled_sypialnia
            icon: mdi:led-off
            name: WLED Sypialnia
            show_state: false
            color: gray
            state:
              - value: pending
                color: orange
              - value: up
                color: rgb(0,255,0)
              - value: down
                color: red
    
  • 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

  • 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

  • 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

  • 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
  • Szczegółowa lista sprzętu

    UrządzeniaCelKonfiguracja
    Shelly 1, Shelly 1PM, Shelly 2Sterowanie oświetleniemMQTT
    Shelly Door/Window 2Otwarcie/zamknięcie drzwiMQTT
    Sonoff Basic, Sonoff THLampy stojące, choinkaMQTT
    Sonoff BasicPompa wodyMQTT
    Satel Integra 64Wykrywanie ruchu, UPS dla RPIlink
    Raspberry PI5 8GB z wentylatorem,
    Raspberry AI Kit (Hailo-8L)
    HomeAssistant, Ebusd, Serwer NAS (Samba), analiza obrazu z kamer
    Nettigo Air Monitor 0.3Pomiar jakości powietrza
    Wodomierz Multical 21Pomiar zużycia wodylink
    Viomi Pro 2Sterowanie odkurzaniemlink
    Vaillant VC ecoTEC Pro 186/5, Sterownik VC400 plus Ebus 3Sterowanie ogrzewaniemlink
    Google miniSterowanie głosem (ang.)
    AmplitunerSterowanie nagłośnieniemlink
    Falownik SolarEdgeProdukcja prądu
    Drukarka atramentowa HPOdczyt poziomu tuszów
    RPi3 + kameraAmbient Light TVlink
    Taśmy LED Podświetlenie TV i sypialni

    Urządzenia ZigBee

    UrządzenieCel
    Bramka SONOFF Zigbee 3.0 USB Dongle Plus (ZBDongle-P)Bramka ZigBee
    Głowice TUYA HY368 ZigBee
    Głowice GTZ08 ZigBee 3.0 TUYA
    Termostaty kaloryferów
    Gniazdka zigbee:
    – BlitzWolf BW-SHP13
    – Forta IGZ-K
    Włączenie/wyłączenie + pomiar mocy
    Żarówki zigbee:
    – OSRAM LIGHTIFY LED Classic A60 clear
    Sterowanie jasnością
    Silnik rolety MOES AM43Sterowanie roletą
    Agara CubeSterowanie oświetleniem
    Lampki ogrodowe OSRAM Smart+Sterowanie oświetleniem zewnętrznym
    Sonoff BASICZBR3Przełącznik

    Czujniki

    Czujnik/ChipCelKonfiguracja
    SI7021Pomiar temperatury i wilgotnościlink
    BME-280Pomiar temperatury, wilgotności i ciśnienialink
    Moduł radiowy CC1101 RF 868MHZ Pomiar zużycia wodylink
    HC-SR04Pomiar odległościlink
    HC-SR501Czujnik PIR (regulowany)
    NodeMCU2Sterowniki
    Wemos D1 miniSterowniki
    Wemos PIR ShieldCzujnik PIR
    ESP32 + CamKamery
    ESP32 + CamOdczyt analogowego licznikalink
    ESP32Sterowanie taśmami LED
  • 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