Home Assistant im Wohnmobil

Hallo Community,

darf ich das Thema HA im Wohnmobil nochmals ansprechen.
Ich finde es schade, dass die Projekte von smarthome_more nicht weiterverfolgt werden.
Ich würde gerne Schritt für Schritt meinen Ausbau dokumentieren.
Hierfür bräuchte ich aber bei diversen Themen den fachlichen Rat aus der Community.

Zur Zeit bastele ich an einer GPS-Maus, die mir die aktuellen Koordinaten übermitteln soll.
Ziel ist das Tracking einer Strecke (MariaDB), Alarmanlagenanbindung mit Tracking und Fernstilllegung des WoMos.
Die NMEA-Daten kann ich bereits auslesen, jedoch liefert mir das YAML Script keine Werte außer GPS Höhe.
Könnte mir einer sagen, was ich hier falsch mache?

sensor:
  - platform: serial
    name: GPS Raw Data
    serial_port: /dev/ttyACM0
    baudrate: 4800
    
sensor:
  - platform: template
    sensors:
      gpgga:
        friendly_name: "GPGGA"
        value_template: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {{ raw.split('$GPGGA')[1].split(',')[0] | default('') }}
          {% else %}
            unknown
          {% endif %}

LG
Muskel

EDIT by Jay: Code bitte immer über die Codefunktion „</>“ im Editor hinzufügen.

2 x Sensor geht nicht, für das Splitting hatte ich noch ein Beispiel liegen!

Versuch mal:

sensor:
  - platform: serial
    name: "GPS Raw Data"
    serial_port: /dev/ttyACM0
    baudrate: 4800

  - platform: template
    sensors:
      gps_latitude:
        friendly_name: "GPS Latitude"
        value_template: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA')[1].split(',') %}
            {{ parts[2] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}

      gps_longitude:
        friendly_name: "GPS Longitude"
        value_template: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA')[1].split(',') %}
            {{ parts[4] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}


Kann es leider aktuell nicht testen (kein GPS!), eventuell funktioniert das ja so!

1 „Gefällt mir“

@Dr.Big das sollte so funktionieren.

Das NMEA Protokoll hat immer eine feste Reihenfolge im Protokoll von 1-14. Hinter der jeweiligen Nummer liegen dann die Werte z.B. Anzahl der Satelliten, Breitengrad, Längengrad, UTC-Zeit, Höhe usw… Das kenne ich noch sehr gut aus den Modellbauzeiten. Die Nummer 8 oder 9 sollte den Wert für die Höhe über dem Meeresspiegel liefern.

Wichtig ist daher im Template die Auswertung der Rohdaten vom Sensor und über part kann die gewünschte Nummer abgegriffen werden. Ich denke mal du möchtest nachher einen Standort haben, also brauchst du Breiten- und Längengrad mit Ausrichtung (N-S oder W-O) Anzahl der Satelliten ist immer interessant zu wissen und zum Schluss noch die gewünschte Höhe.

 {% set parts = raw.split('$GPGGA,')[1].split(',') %}
 {{ parts[8] | float | default(0) }}
sensor:
  - platform: serial
    name: "GPS Raw Data"
    serial_port: /dev/ttyACM0
    baudrate: 4800

template:
  - sensor:
      - name: GPS Breitengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[1] ~ ' ' ~ parts[2] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Längengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[3] ~ ' ' ~ parts[4] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Satelliten
        icon: mdi:satellite-uplink
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[6] | int | default(0) }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Höhe
        unit_of_measurement: "m"
        device_class: distance
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[8] | float | default(0) }}
          {% else %}
            unknown
          {% endif %}
1 „Gefällt mir“

Jetzt kapier ich garnichts mehr.
Hab das Script in die configuration.yaml 1:1 hineinkopiert.
Jetzt zeigt der RAW Stream nur noch $GPGLL an.

Du müsstest schon etwas genauer werden. Welches Script, dass hier sind Sensoren die etwas auslesen und wie schaut deine configuration.yaml jetzt aus, kommt es dort zu Fehlern? Hast du einen Neustart von HA durchgeführt, nachdem du das hineinkopiert hast. Was sagt die Konfigurationsprüfung beim Neustart von HA?. Bei der Einrückung in der configuration.yaml kommt es immer schnell zu Fehlern, daher meine Fragen.

Erst einmal Danke, dass Du so schnell antwortest.
Ich habe hier einen Testaufbau und deshalb ist die configuration.yaml noch sehr jungfräulich.
Habe das vorher gepostet Script hineinkopiert.


# Loads default set of integrations. Do not remove.
default_config:

# Load frontend themes from the themes folder
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

sensor:
  - platform: serial
    name: "GPS Raw Data"
    serial_port: /dev/ttyACM0
    baudrate: 4800

template:
  - sensor:
      - name: GPS Breitengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[1] ~ ' ' ~ parts[2] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Längengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[3] ~ ' ' ~ parts[4] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Satelliten
        icon: mdi:satellite-uplink
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[6] | int | default(0) }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Höhe
        unit_of_measurement: "m"
        device_class: distance
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[8] | float | default(0) }}
          {% else %}
            unknown
          {% endif %}

Prüfung OK, Neustart durchgeführt.

Ok, die Einrückung in der config.yaml sieht gut aus. Die ist ja wirklich noch leer, da sollten also keine Problem auftreten.

Das eigentliche Problem ist, dass dein NMEA-Satz anscheinend in GPGLL geparst ist. In den beiden gezeigten Bespielen wird allerdings GPGGA verwendet und nicht GPGLL. GPGGA hattest du auch ganz oben in deinem ersten Beispiel.

Die Sensoren müssen daher umgeschrieben werden und eventuell kannst du nachdem das GPS ein Fix hat, auch über GPGGA die Höhe auslesen. Versuche es mal so.

sensor:
  - platform: serial
    name: "GPS Raw Data"
    serial_port: /dev/ttyACM0
    baudrate: 4800

template:
  - sensor:
      - name: GPS Breitengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGLL' in raw %}
            {% set parts = raw.split('$GPGLL,')[1].split(',') %}
            {{ parts[0] ~ ' ' ~ parts[1] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Längengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGLL' in raw %}
            {% set parts = raw.split('$GPGLL,')[1].split(',') %}
            {{ parts[2] ~ ' ' ~ parts[3] | default('unknown') }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Höhe
        unit_of_measurement: "m"
        device_class: distance
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGLL' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[8] | float | default(0) }}
          {% else %}
            unknown
          {% endif %}
      - name: GPS Satelliten
        icon: mdi:satellite-uplink
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[6] | int | default(0) }}
          {% else %}
            unknown
          {% endif %}

Ich geb so langsam auf.
Hab nochmal die ganze Konfiguration zurück gesetzt und die GPS-Maus auf einen anderen USB-Port gesteckt.
Danach in die configuration.yaml Ein einfaches Script geschrieben.

sensor:
  - platform: serial
    name: "GPS Raw Data"
    serial_port: /dev/ttyACM0
    baudrate: 4800

template:
  - sensor:
      - name: GPS Höhe
        unit_of_measurement: "m"
        device_class: distance
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[8] | float | default(0) }}
          {% else %}
            unknown
          {% endif %}

Entität GPS Höhe wird angelegt und enthält den Wert 61,2 m.
Danach Längengrad identisch abgefragt, es kommen aber keine Werte.
In den Aktionen kann ich auch sehen, das GPGGA die richtigen Werte enthält, aber sie werden nicht in parts[2] und parts [8] geschrieben.

Probier mal:

template:
  - sensor:
      - name: "GPS Breite"
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {% set lat = parts[1] | float(0) %}
            {% set ns = parts[2] %}
            {% set lat_deg = (lat // 100) + (lat % 100) / 60 %}
            {{ lat_deg if ns == 'N' else -lat_deg }}
          {% else %}
            0
          {% endif %}
        availability: >
          {{ '$GPGGA' in states('sensor.gps_raw_data') }}

      - name: "GPS Länge"
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {% set lon = parts[3] | float(0) %}
            {% set ew = parts[4] %}
            {% set lon_deg = (lon // 100) + (lon % 100) / 60 %}
            {{ lon_deg if ew == 'E' else -lon_deg }}
          {% else %}
            0
          {% endif %}
        availability: >
          {{ '$GPGGA' in states('sensor.gps_raw_data') }}

      - name: "GPS Höhe"
        unit_of_measurement: "m"
        device_class: distance
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[8] | default(0) | float }}
          {% else %}
            0
          {% endif %}
        availability: >
          {{ '$GPGGA' in states('sensor.gps_raw_data') }}

Ich glaube, das sind immer die falschen parts.
Dieses Script liefert zum ersten Mal einen Koordinaten-Wert:

template:
  - sensor:
      - name: GPS Breitengrad
        unit_of_measurement: "°"
        state: >
          {% set raw = states('sensor.gps_raw_data') %}
          {% if '$GPGGA' in raw %}
            {% set parts = raw.split('$GPGGA,')[1].split(',') %}
            {{ parts[1] | float | default(0) }}
          {% else %}
            unknown
          {% endif %}

Wenn ich von deinem

$GPGGA,132040.00,5058.53856,N,00702.52315,E,1,10,0.86,53.9,M,46.6,M,,*6C

ausgehe sollte das mit meinem Beispiel eigentlich passen? Muss ich mir später noch mal in Ruhe anschauen!
Hast du denn mein Beispiel oben mal direkt probiert?

Bis auf die Umwandlung durch | float hat sich im Codebeispiel zu unseren oben gezeigten Beispielen doch nichts geändert?

Mit den Parts musst dann ein wenig testen. Hier nochmal eine Liste der Aufteilung. Der erste Part beginnt dann mit der UTC-Zeit. Also von dort aus zählen. Da HA aber bei 0 anfängt zu zählen ist die UTC zeit nicht Part1 sondern Part0. Part 1 wäre damit Breitengrad, Part 5 der Längengrad und Part 8 die Höhe.

Der Code von @Dr.Big sollte daher die passenden Parts ausgewählt haben. Hast du den schon getestet, wie er fragte?

1 „Gefällt mir“

Ja, hab ich getestet.
Ich mach jetzt trial and error, aber so richtig verstehe ich den NMEA-Datensatz nicht.
Werden da nicht nacheinander die Datensätze GPGLL, GPRMC, GPGGA, usw. nacheinander geschickt?
Ich muss doch nur so lange abfragen, bis der String mit GPGGA kommt.
Danach werte ich die Felder aus.
Ich frage aber GPGLL ab und werte dann GPGGA aus, der aber nur die Datensätze von GPGLL enthält. Wenn ich „if ‚$GPGGA‘ in raw“ abfrage kommt nämlich kein Ergebnis.:thinking:

So, wollte noch ein kurzes Feedback zu meinem Problem geben.

Die Aufgabenstellung war ja ein Geotracking mittels GPS-Maus für mein Wohnmobil.
Ziel war die Darstellung auf einer Karte (falls mal geklaut) und das Loggen der gefahrenen Strecke.

Mann muss sagen, wer billig kauft, kauft doppelt.
Die günstige GPS-Maus (VK-162 von Arceli) hat irgendwie nicht funktioniert. Schlechter Empfang und die NMEA-Strings - die ich brauchte - haben irgendwie nur sporadisch funktioniert.
Abhilfe hat die qualitativ höherwertige GPS-Maus BU-353N5 (ca. 50 €) geschaffen.

Anbei die gps.yaml mit der ich den NMEA GNGGA String auswerte.
Danach noch schnell einen device_tracker erstellt und an eine Karte als Entität übergeben.
So, ich hoffe hiermit dem ein oder anderen eine kleine Hilfestellung gegeben zu haben und ich werde mich jetzt den anderen Gadgets im Wohnmobil widmen.

template:
  - trigger:
      - platform: state
        entity_id: sensor.gps_raw_data
      - platform: state
        entity_id: sensor.gps_breitengrad
      - platform: state
        entity_id: sensor.gps_laengengrad
    sensor:
      - name: "GPS Uhrzeit"
        state: >
          {% set data = trigger.to_state.state.split(',') %}
          {% if data[0] == '$GNGGA' %}
          {% set raw = data[1] %}
          {{ raw[0:2] ~ ':' ~ raw[2:4] ~ ':' ~ raw[4:6] }}
          {% else %}
            {{ this.state }}
          {% endif %}
      - name: "GPS Breitengrad"
        unit_of_measurement: "°"
        state: >
          {% set data = trigger.to_state.state.split(',') %}
          {% if data[0] == '$GNGGA' %}
          {% set lat = data[2] | float(0) %}
          {% set ns = data[3] %}
          {% set lat_deg = (lat // 100) + (lat % 100) / 60 %}
          {{ (lat_deg if ns == 'N' else -lat_deg) | round(4) }}
          {% else %}
            {{ this.state }}
          {% endif %}
      - name: "GPS Laengengrad"
        unit_of_measurement: "°"
        state: >
          {% set data = trigger.to_state.state.split(',') %}
          {% if data[0] == '$GNGGA' %}
          {% set lat = data[4] | float(0) %}
          {% set ns = data[5] %}
          {% set lat_deg = (lat // 100) + (lat % 100) / 60 %}
          {{ (lat_deg if ns == 'E' else -lat_deg) | round(4) }}
          {% else %}
            {{ this.state }}
          {% endif %}
      - name: "GPS Satelliten"
        unit_of_measurement: "Stueck"
        state: >
          {% set data = trigger.to_state.state.split(',') %}
          {% if data[0] == '$GNGGA' %}
          {% set nr = data[7] %}
          {{ nr }}
          {% else %}
            {{ this.state }}
          {% endif %}
      - name: "GPS Hoehe"
        unit_of_measurement: "mtr"
        state: >
          {% set data = trigger.to_state.state.split(',') %}
          {% if data[0] == '$GNGGA' %}
          {% set mtr = data[9] %}
          {{ mtr | float }}
          {% else %}
            {{ this.state }}
          {% endif %}
      - name: "GPS Wohnmobil"
        state: "ok"
        attributes:
          latitude: "{{states('sensor.gps_breitengrad') | float }}"
          longitude: "{{states('sensor.gps_laengengrad') | float }}"
2 „Gefällt mir“