Daten über Sensor Template importieren in HA configuration.yaml oder json Datei? Fehler / Frage

Hallo zusammen,

erstmal hoffe ich das ich hier jemanden finden kann der mir eventuell bei meinem Problem helfen kann.
Kurz zu mir: Blutiger Anfänger mit HomeAssistant sowie im Programmieren von Python oder anderen Sprachen. Also seid bitte nicht Böse zu mir wenn es vielleicht klar sein müsste :smiley:

Wie oben beschrieben möchte ich etwa 20 verschiedene Datenpunkte welche sich dauerhaft verändern einlesen und später in die influxdb laden und daraus eine Grafana Visualisierung gestalten.

In diesem Thread geht es erstmal um das Daten einsammeln den hier scheitert es schon.

Es handelt sich um etwa 20 Sensoren die ich auslesen möchte. Es gibt leider keine css Datei sondern ich nutze wie zu sehen eine “Info Seite in der die Werte wie folgt aufgeführt sind”

{
	"power":	11.090000152587891,
	"voltage":	5062.5,
	"current":	2188.75,
	"fanSpeed":	2712,
	"temp":	54,
#usw. ...... (Das ihr die Auflistungsart seht)
}

Weg 1 - auslesen über configuration.yaml über Sensor Platform Rest

sensor:
  - platform: rest
    name: Power
    resource: http://192.168.178.6/api/system/info
    value_template: "{{ value_json.power }}"
    unit_of_measurement: 'W'
    scan_interval: 60

  - platform: rest
    name: Voltage
    resource: http://192.168.178.6/api/system/info
    value_template: "{{ value_json.voltage }}"
    unit_of_measurement: 'V'
    scan_interval: 60

Ich habe hier mal 2 Sensoren als Beispiel aufgelistet. Diese Strategie funktioniert tatsächlich. Allerdings nur bei 4 von 20 Sensoren. Die anderen sind genau gleich geschrieben und passen. Und manchmal verabschiedet sich die Webseite wenn ich das richtig sehe.

Folgende Beispiel Fehler hatte ich schon bei den Versuchen:

2024-01-22 16:31:58.874 WARNING (MainThread) [homeassistant.components.sensor] Platform rest not ready yet: Server disconnected without sending a response.; Retrying in background in 30 seconds

2024-01-21 22:03:58.762 WARNING (MainThread) [homeassistant.components.sensor] Setup of sensor platform rest is taking over 10 seconds.


Kann ich das überhaupt über Weg 1 sinnvoll machen?

Weg 2 - Python Script erstellt und eine json Datei angelegt in der er die Werte 1 zu 1 aus der Webseite übernimmt

Python Skript:

import requests
import json
import time
import logging

# Konfigurieren Sie das Logging
logging.basicConfig(filename='daten1.log', level=logging.DEBUG)

# Fügen Sie Protokollmeldungen hinzu, um den Ablauf des Skripts zu verfolgen
logging.info('Skript gestartet.')

try:
    def daten_aus_website_auslesen(url):
        while True:
            try:
                # Anfrage an die Website senden
                response = requests.get(url)

                # Überprüfen, ob die Anfrage erfolgreich war (Status-Code 200)
                if response.status_code == 200:
                    # JSON-Daten extrahieren
                    daten = response.json()

                    # Daten in eine Datei schreiben
                    with open('ausgelesene_daten.json', 'w', encoding='utf-8') as datei:
                        json.dump(daten, datei, indent=2)

                    print('Daten wurden erfolgreich in "ausgelesene_daten.json" gespeichert.')
                else:
                    print(f'Fehler bei der Anfrage. Status-Code: {response.status_code}')

            except Exception as e:
                print(f'Ein Fehler ist aufgetreten: {e}')

            # Wartezeit bis zur nächsten Ausführung (maximal alle 60 Sekunden)
            time.sleep(60)

    # Hier die URL deiner Website einfügen
    website_url = 'http://192.168.178.6/api/system/info'
    daten_aus_website_auslesen(website_url)

    logging.info('Skript erfolgreich beendet.')
except Exception as e:
    # Erfassen Sie Ausnahmen und Fehler
    logging.error(f'Fehler aufgetreten: {str(e)}')
    raise

configuration.yaml

# 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
scene: !include scenes.yaml
    
    
shell_command:
  daten_auslesen: python3 scripts/daten1.py


    
influxdb:
  host: 192.168.178.8
  port: 8086
  database: home_assistant
  username: xxxxxxxx
  password: xxxxxxxxx
  max_retries: 30
  default_measurement: verzeichnis1

logger:
  default: warning
  logs:
    homeassistant.components.sensor.rest: debug
    homeassistant.components.shell_command: debug```

automations.yaml

- alias: "Daten aus Website auslesen beim Start"
  trigger:
    platform: homeassistant
    event: start
  action:
    - service: shell_command.daten_auslesen

Das funktioniert aufjedenfall bis der Timeout nach 60s kommt.
Er erstellt somit die ausgelesene Datei in der alle daten wie auf der Webseite drin stehen.

Allerdings bringt er dann folgende Fehler:

2024-01-22 18:12:28.015 ERROR (MainThread) [homeassistant.components.shell_command] Timed out running command: `python3 -c 'import os; os.chdir("/config/scripts/"); exec(open("daten1.py").read())'`, after: 60s
2024-01-22 18:12:28.018 ERROR (MainThread) [homeassistant.components.automation.daten_aus_website_auslesen_beim_start] Daten aus Website auslesen beim Start: Error executing script. Unexpected error for call_service at pos 1:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 92, in async_service_handler
stdout_data, stderr_data = await process.communicate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/subprocess.py", line 200, in communicate
stdin, stdout, stderr = await tasks.gather(stdin, stdout, stderr)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/subprocess.py", line 180, in _read_stream
output = await stream.read()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/streams.py", line 686, in read
block = await self.read(self._limit)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/streams.py", line 693, in read
await self._wait_for_data('read')
File "/usr/local/lib/python3.11/asyncio/streams.py", line 525, in _wait_for_data
await self._waiter
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 476, in _async_step
await getattr(self, handler)()
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 713, in _async_call_service_step
response_data = await self._async_run_long_action(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 675, in _async_run_long_action
return long_task.result()
^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/core.py", line 2149, in async_call
response_data = await coro
^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/core.py", line 2186, in _execute_service
return await target(service_call)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 91, in async_service_handler
async with asyncio.timeout(COMMAND_TIMEOUT):
File "/usr/local/lib/python3.11/asyncio/timeouts.py", line 111, in __aexit__
raise TimeoutError from exc_val
TimeoutError
2024-01-22 18:12:28.029 ERROR (MainThread) [homeassistant.components.automation.daten_aus_website_auslesen_beim_start] While executing automation automation.daten_aus_website_auslesen_beim_start
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 92, in async_service_handler
stdout_data, stderr_data = await process.communicate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/subprocess.py", line 200, in communicate
stdin, stdout, stderr = await tasks.gather(stdin, stdout, stderr)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/subprocess.py", line 180, in _read_stream
output = await stream.read()
^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/streams.py", line 686, in read
block = await self.read(self._limit)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/asyncio/streams.py", line 693, in read
await self._wait_for_data('read')
File "/usr/local/lib/python3.11/asyncio/streams.py", line 525, in _wait_for_data
await self._waiter
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/automation/__init__.py", line 669, in async_trigger
await self.action_script.async_run(
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1587, in async_run
return await asyncio.shield(run.async_run())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 426, in async_run
await self._async_step(log_exceptions=False)
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 479, in _async_step
self._handle_exception(
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 502, in _handle_exception
raise exception
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 476, in _async_step
await getattr(self, handler)()
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 713, in _async_call_service_step
response_data = await self._async_run_long_action(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 675, in _async_run_long_action
return long_task.result()
^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/core.py", line 2149, in async_call
response_data = await coro
^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/core.py", line 2186, in _execute_service
return await target(service_call)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 91, in async_service_handler
async with asyncio.timeout(COMMAND_TIMEOUT):
File "/usr/local/lib/python3.11/asyncio/timeouts.py", line 111, in __aexit__
raise TimeoutError from exc_val
TimeoutError```

Ich komme an der Stelle nicht mehr weiter. :smiley:

Macht es den überhaupt Sinn die Daten so auszulesen :slight_smile:
Bekomme ich die daten aus einer json Liste sortiert in eine Datenbank?

Grüße Chris

Ich bin etwas weiter gekommen.

Ich habe es geschafft den Code so zu ändern das er alle 5 Sekunden die Daten der Webseite abruft und genau in diesem Format in einer .json-Datei abspeichert.

Jetzt brauche ich nur noch eine Möglichkeit die .json Datei abzurufen und in der influxdb abzuspeichern kann mir hier jemand helfen?

Folgenden Code habe ich verwendet um die Daten welche auf einer infoseite liegen abzurufen und in einer .json Datei abzuspeichern.
Funktioniert aufjedenfall mal.

Automations.yaml

- alias: "Daten aus Website auslesen alle 10 Sekunden"
  trigger:
    platform: time_pattern
    seconds: "/5"
  action:
    - service: shell_command.daten_auslesen```

Configuration.yaml

# 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
scene: !include scenes.yaml


shell_command:
  daten_auslesen: python3 python_script/daten1.py

Python Programm - daten1.py

import requests
import json
import time
import logging
import sys  # Importiere das sys-Modul für die Systemfunktionen

# Konfigurieren Sie das Logging
logging.basicConfig(filename='daten1.log', level=logging.DEBUG)

# Fügen Sie Protokollmeldungen hinzu, um den Ablauf des Skripts zu verfolgen
logging.info('Skript gestartet.')

try:
    def daten_aus_website_auslesen(url):
        while True:
            try:
                # Anfrage an die Website senden
                response = requests.get(url)

                # Überprüfen, ob die Anfrage erfolgreich war (Status-Code 200)
                if response.status_code == 200:
                    # JSON-Daten extrahieren
                    daten = response.json()

                    # Daten in eine Datei schreiben
                    with open('ausgelesene_daten.json', 'w', encoding='utf-8') as datei:
                        json.dump(daten, datei, indent=2)

                    print('Daten wurden erfolgreich in "ausgelesene_daten.json" gespeichert.')
                else:
                    print(f'Fehler bei der Anfrage. Status-Code: {response.status_code}')

            except Exception as e:
                print(f'Ein Fehler ist aufgetreten: {e}')

            # Füge eine Wartezeit von 2 Sekunden hinzu, bevor das Skript beendet wird
            time.sleep(2)

            # Beende das Skript ordnungsgemäß
            sys.exit(0)

    # Hier die URL deiner Website einfügen
    website_url = 'http://192.168.178.6/api/system/info'
    daten_aus_website_auslesen(website_url)

    logging.info('Skript erfolgreich beendet.')
except Exception as e:
    # Erfassen Sie Ausnahmen und Fehler
    logging.error(f'Fehler aufgetreten: {str(e)}')
    raise```

Das funktioniert soweit einwandfrei und liest alle 5 Sekunden aus. Allerdings wird hier über den Shell Command der Skript gestartet und nacher wieder beendet. Wie sinnvoll das ganze so ist kann ich nicht ganz sagen. Ob es einen effektiveren Weg gibt? Ich bin offen für andere Ideen. Mit Hilfe von Simon, Chatgpt und google habe ich es jetzt mal geschafft so weit zu kommen :smiley:

Okay weitere Stunden und ich habe eine Lösung gefunden um die Einbindung richtig zu machen :smiley:

rest:
  - resource: http://192.168.178.6/api/system/info
    scan_interval: 10
    sensor:
      - name: "Leistung"
        value_template: "{{ value_json['power'] }}"
        unit_of_measurement: "W"
      - name: "Spannung"
        value_template: "{{ value_json['voltage'] }}"
        unit_of_measurement: "V"
      - name: "Lüfter RPM"
        value_template: "{{ value_json['RPM'] }}"
        unit_of_measurement: "RPM"
      ....
.....#usw. alle weiteren Werte

Bedeutet das obere ging deshalb nicht weil ich eben 20 Instanzen von Rest Abfragen auf die Webseite gestartet habe, also jeden Wert mit einem eigenen Rest Befehl versucht habe zu holen. :smiley:
Damit war die Webseite wohl überfordert.

Jetzt ein Rest Befehl und der holt alle Werte raus. :smiley:

Damit hat sich das vorläufig mal erledigt.

Danke trotzdem den Lesern :smiley:

Und ich könnte Wetten irgendjemand googlet mal und findet hier die Lösung. Alleine dafür hat es sich gelohnt einen Thread zu erstellen :slight_smile: