Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Off Topic
  4. Microcontroller
  5. [Gelöst] EspHome: Zeit seit letztem State Wechsel

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    16
    1
    1.9k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    901

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.2k

[Gelöst] EspHome: Zeit seit letztem State Wechsel

Geplant Angeheftet Gesperrt Verschoben Microcontroller
5 Beiträge 3 Kommentatoren 1.1k Aufrufe 3 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • W Offline
    W Offline
    WolfgangFB
    schrieb am zuletzt editiert von WolfgangFB
    #1

    Wie könnte man das realisieren? Ich hätte gerne einen Datenpunkt (State) in dem z.B. alle Minute aktualisiert wird, wann der Zustand von BinarySensor X zuletzt geändert worden ist.

    SBorgS 1 Antwort Letzte Antwort
    0
    • W WolfgangFB

      Wie könnte man das realisieren? Ich hätte gerne einen Datenpunkt (State) in dem z.B. alle Minute aktualisiert wird, wann der Zustand von BinarySensor X zuletzt geändert worden ist.

      SBorgS Offline
      SBorgS Offline
      SBorg
      Forum Testing Most Active
      schrieb am zuletzt editiert von
      #2

      @wolfgangfb Kommt darauf an was du genau mit dem Datenpunkt/Daten anstellen willst?
      Die letzte Änderung steht dir im entsprechenden Datenpunkt jederzeit zur Verfügung:
      Bild 001.png

      Da kommst du per "LC" (=last change) dran, zB. Javascript

      console.log (getState("esphome.0.xxxxxx.Sensor.xxxxx.state").lc);
      

      Du kannst jetzt natürlich auch ein Blockly nutzen welches auf "Änderung" triggert und dann den "LC" wieder in einen weiteren Datenpunkt schreibt.

      LG SBorg ( SBorg auf GitHub)
      Projekte: Lebensmittelwarnung.de | WLAN-Wetterstation | PimpMyStation

      W 1 Antwort Letzte Antwort
      0
      • SBorgS SBorg

        @wolfgangfb Kommt darauf an was du genau mit dem Datenpunkt/Daten anstellen willst?
        Die letzte Änderung steht dir im entsprechenden Datenpunkt jederzeit zur Verfügung:
        Bild 001.png

        Da kommst du per "LC" (=last change) dran, zB. Javascript

        console.log (getState("esphome.0.xxxxxx.Sensor.xxxxx.state").lc);
        

        Du kannst jetzt natürlich auch ein Blockly nutzen welches auf "Änderung" triggert und dann den "LC" wieder in einen weiteren Datenpunkt schreibt.

        W Offline
        W Offline
        WolfgangFB
        schrieb am zuletzt editiert von
        #3

        @sborg
        Hi

        Ich möchte eigentlich gerade vermeiden, mit JS darauf reagieren zu müssen. Deshalb hätte ich gerne direkt aus dem ESP heraus die Info, wann z.B. ein Bewegungsmelder zuletzt ausgelöst hat (am besten in Sekunden).
        Im Moment scheiter ich aber gerade an der Syntax von Time_component und lambdas :-(

        1 Antwort Letzte Antwort
        0
        • W Offline
          W Offline
          WolfgangFB
          schrieb am zuletzt editiert von
          #4

          @wolfgangfb
          So, ich habe es geschafft, vielleicht interessiert es ja auch andere, deshalb hier meine ausführliche Lösung.

          Mein Ziel war es, in der Vis auf einen Blick zu erkennen, wann z.B. eine Bewegungsmelder oder ein Türkontakt zuletzt ausgelöst hat.

          vis_movement.jpg

          Das ganze hatte ich ursprünglich in Javaskript realisiert, immerhin soll ja in de Regel auch irgendwas passieren, wenn der Bewegungsmelder auslöst :-) Aber mein Ehrgeiz war es, das ganze zu vereinfachen so dass der Sensor direkt die gewünschte Zeit ausgibt.
          Meine Sensoren sind in der Regel ESP8266 besiert, das ganze wird in ESPHome gemacht. Als Hardware verwende ich für den Bewegungmelder AM312 Sensor, der kostet bei Ali 40 Cent und ist meiner Meinung nach zuverlässiger als der HC-SR501

          Ein "nromaler" Bewegungsmelder sieht dort ja wie folgt aus:

          binary_sensor:
            - platform: gpio
              name: "Bewegung"
              pin: 
                number: D5
          

          Damit wird ein Datenpunkt angelegt, der immer dann für ein paar Sekunden true wird, wenn der Bewegugsmelder auslöst. Damit kann man dann ein Licht steuern oder was auch immer.

          Jetzt zur Zeiterfassung und da habe ich eben gemerkt, dass C++ nicht meine (Programmier) Muttersprache ist. Hat mich einiges an Kopfzerbrechen gekostet bis ich da immer am Ende auf die richtige Syntax und die richtigen Typumwandlungen gekommen bin. C++ Experten dürfen mir hier auch gerne Vorschläge machen, wie der Code besser oder suaberer wird.

          Zunächst definiere ich mir eine Variale, in der die Sekunden seit dem letzten Auslösen gespeichert werden:

          globals:  
            - id: D5Last
              type: int
              restore_value: yes
              initial_value: '0'
          

          (id ist der Name der Variable, der Type eben, was darin gespeichert werden soll, restore_value sorgt dafür, dass der Wert bei einem Neustart erhalten bleibt und initial_value ist der Ausgangswert).

          Jetzt zur Zeit, hierfür wird die Time Komponente benötig:

          time:
            - platform: sntp
              timezone: Etc/GMT+1
              id: MySntp
              on_time:
                - seconds: /5
                  then:
                    - lambda: |-
                        id(D5Last) += 5;
          

          Was macht dieser Teil: Es wird eine Echtzeituhr gestartet (die eigentliche Zeit werte ich hier garnicht aus) und alle 5 Sekunden wird ein Trigger ausgelöst, der auf die bisherige Zeit seit dem letzten Auslösen 5 (Sekunden) draufaddiert. Man könnte das ganze natürlich auch Sekündlich machen, bringt aber meiner Meinung nach nichts.
          Als nächstes muss die Zeit wieder auf 0 zurückgesetzt werden, wenn der Bewegungsmelder auslöst: Also den den Bewegungsmelder erweitern.

          binary_sensor:
            - platform: gpio
              name: "Bewegung"
              pin: 
                number: D5
              on_state:
                then:
                - lambda: id(D5Last) = 0;
          

          Jetzt zum scvhwierigsten Teil, das ganze als fertig lesbaren Text mit Einheit "Sek" zu liefern so dass es dirket in die VIS eingebunden werden kann.

          Das ganze wird realisiert über einen sogenannten Textsensor. Die habe ich bisher dafür verwendet um beispielsweise die IP eines ESP anzuzeigen.

          text_sensor:
            - platform: template
              name: "IP"
              lambda: 'return {WiFi.localIP().toString().c_str()};'
          

          Jetzt musste ich ertmal kapieren, wie das mit den Lambdas und dem c_str etc. funktioniert.

          aber zunächst mal einen Datenpunkt anlegen:

            - platform: template
              name: "D5MotionLast"
              id: D5MotionLastID
              update_interval: never
          

          Das ist dann der Datenpunkt, der in Vis als "Text" eingebunden wird.
          (normalerweise wird so ein Textsensor alle 60 Seekunden aktualisiert, hier wird mit "never aber dafür gesorgt, dass er selbständig nie aktualisier, das will ich ja selbst steuern.)

          Also die Zeitkomponente erweitert:

          time:
            - platform: sntp
              timezone: Etc/GMT+1
              id: MySntp
              on_time:
                - seconds: /5
                  then:
                    - lambda: |-
                        id(D5Last) += 5;
                    - text_sensor.template.publish:
                        id: D5LastId
                        state: !lambda return MyTime(id(D5Last));
          
          

          Mit text_sensor.template.publish kann man den Textsensor von außen mit einem neuen Wert versehen. Die Aufgabe war jetzt noch aus der nakten Zehl (int) eine schöne Ausgabe zu machen.
          Gehen würde das z.B. mit

          return str_sprintf("%02.0f sec",float(D5Last));
          

          aber ich wollte es schöner haben und 13565 Sekunden finde ich nicht sonderlich aussagekräftig.
          Also in der ersten Minute die Sekunden anzeigen, inder ersten Stunde die Minuten und am ersten Tag die Stunden, dann nur noch die Tage (wer will darf das ganze gerne auf Wochen, Monate etc. erweitern).
          Da ich das ganze nicht nur für einen Sensor mahen wollte habe ich mir überlegt, wie ich diese Funktion nicht bei jedem Sensor neu reinkopieren muss.
          Also die Funktion ausgelagert.
          Im gleichen Verzeichnis in dem die yaml Dateien sind eine Date "MyTime.h" angelgt und diese am Anfan in das yaml Projekt eingebunden:

          esphome:
            name: Testraum
            platform: ESP8266
            board: nodemcuv2
            includes:
               - MyTime.h 
          

          die Datei "MyTime.h" sieht wie folgt aus:

          std::string MyTime(int secs){
            char Plural = ' ';
            if (secs > 60 * 60 * 24 *2 ) 
              {
              Plural = 'e';
              }
            if (secs < 60){
              return str_sprintf("%02.0f Sek", float(secs));
              } else
              {
              if (secs < 60 * 60){
                return str_sprintf("%2.0f Min", abs(float(secs/60)));
                } else
                {
                if (secs < 60 * 60 * 24){
                	return str_sprintf("%2.0f Std", abs(float(secs/(60 * 60))));
                	} else
                	{
                	return str_sprintf("%2.0f Tag%c", abs(float(secs/(60 * 60 * 24))), Plural);
                	}
                }
              }
            }
          

          (Das geht mit Sicherheit eleganter, Verbesserungsvorschläge nehme ich aber gerne an).

          Auf jeden Fall funktioniert das ganze und es wird sogar bei einem Tag nur "Tag" und ab dem zweiten Tag "Tage" ausgegeben :-)

          Hier das ganze nochmal als komplettes yaml File das sich so auch übersetzen lassen sollte (wenn ich beim Copy&Paste keinen Fehler gemacht habe :-)

          esphome:
            name: Testraum
            platform: ESP8266
            board: nodemcuv2
            includes:
               - MyTime.h 
          
          # Enable logging
          logger:
          
          # Enable Home Assistant API
          api:
          
          ota:
            password: "xxxx"
          
          wifi:
            ssid: xxxx"
            password: "xxxx"
          
            # Enable fallback hotspot (captive portal) in case wifi connection fails
            ap:
              ssid: "xxxx"
              password: "xxxx"
          
          captive_portal:
          
          web_server:
            port: 80 
          
          globals:  
            - id: D5Last
              type: int
              restore_value: yes
              initial_value: '0'
          
          text_sensor:
            - platform: template
              name: D5Last
              id: D5LastId
              update_interval: never
          
          binary_sensor:
            - platform: gpio
              pin: 
                number: D5
              on_state:
                then:
                - lambda: id(D5Last) = 0;
          
          time:
            - platform: sntp
              timezone: Etc/GMT+1
              id: MySntp
              on_time:
                - seconds: /5
                  then:
                    - lambda: |-
                        id(D5Last) += 5;
                    - text_sensor.template.publish:
                        id: D5LastId
                        state: !lambda return MyTime(id(D5Last));
          
          
          1 Antwort Letzte Antwort
          0
          • K Offline
            K Offline
            Kopterframe
            schrieb am zuletzt editiert von
            #5

            @wolfgangfb Servus, kann man auch z.B. bei

            time:
              - platform: sntp
                timezone: Etc/GMT+1
                id: MySntp
                on_time:
                  - seconds: /5 # Wert aus einer Variable nehmen????
                    then:
            
            1 Antwort Letzte Antwort
            0
            Antworten
            • In einem neuen Thema antworten
            Anmelden zum Antworten
            • Älteste zuerst
            • Neuste zuerst
            • Meiste Stimmen


            Support us

            ioBroker
            Community Adapters
            Donate

            570

            Online

            32.6k

            Benutzer

            82.2k

            Themen

            1.3m

            Beiträge
            Community
            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
            ioBroker Community 2014-2025
            logo
            • Anmelden

            • Du hast noch kein Konto? Registrieren

            • Anmelden oder registrieren, um zu suchen
            • Erster Beitrag
              Letzter Beitrag
            0
            • Home
            • Aktuell
            • Tags
            • Ungelesen 0
            • Kategorien
            • Unreplied
            • Beliebt
            • GitHub
            • Docu
            • Hilfe