Installation stundenplan24 / Vertretungsplan von Indiware als integration (api?)

Sorry, es dauert noch etwas mit dem Code. Durch Prüfung des Netzwerkverkehrs habe ich entdeckt, dass es noch eine andere Möglichkeit gibt, die Zahl der Veränderungen und gleichzeitig den aktuellen Stundenplan inkl. Veränderungen anzuzeigen.

Ich nutze dazu die URL

https://www.stundenplan24.de/schulnummer//wplan/wdatenk/WPlanKl_20240905.xml

Ausgeben lasse ich mir das dann so:

image

Ich teste das jetzt noch ein paar Tage und kann dann gern den Code teilen, wenn alles funktioniert.

3 „Gefällt mir“

Da ich jetzt für mich zufrieden bin mit dem Ergebnis und auch die Familie mit den Angaben und der Darstellung fein ist, teile ich meine Herangehensweise gern mal mit euch. Vielleicht kann ja jemand darauf aufbauen.

Mein Ziel war folgendes:

Ich möchte für beide Kinder den Vertretungsplan für den nächsten Tag darstellen. Darin sollen die Änderungen, die ein Fach betreffen vermerkt und gekennzeichnet sein. Ursprünglich dachte ich daran, die gesamte Woche darzustellen, aber das ist nicht nötig. Das ganze sieht dann so aus:

image

Der angezeigte Tag ändert sich immer morgens um 8 Uhr, damit man ggf. früh vor der Schule nochmal schauen kann.

Unter der Tabelle ist noch vermerkt, dass es allgemeine Informationen (.z.B. Kurzplan wegen Hitze u.ä.) gibt. Ursprünglich hatte ich die auch angezeigt. Allerdings ist das tw. soviel, dass es mir das Layout sprengte. Deshalb nur der Hinweis auf die App.

Am Ende wird noch der Stand des Plans angezeigt.

Den Abruf der Daten habe ich über NodeRed gelöst. Hier der Flow zum importieren und anpassen: flows-abruf-vertretungsplan1.txt (10,3 KB)

Hinweise zum Flow:

  • In der funktion-Node “Variablen … festlegen” gibt man die gewünschte Klasse und die Schulnummer ein.

  • in der function-Node “URLs … zusamenfügen” werden die URLs für den Abruf der Daten zusammengesetzt. Da ich ursprünglich mehr Tage als heute und morgen abgefragt habe, ist dies noch im Script enthalten. Vielleicht braucht es jemand. Am Ende übergebe ich nur “urlTag0” (heute) und “urlTag1” morgen als payload.

  • Die Node “Time Range” entscheidet nach der aktuellen Uhrzeit, welcher Plan abgerufen wird. Das könnte man auch in der vorhergegenden function-Node machen, hab ich aber nicht.

  • In den http-Request-Nodes “Plan heute” & “Plan morgen” müsst ihr eure Zugangsdaten eintragen. Benutzername ist meist “schueler”, Kennwort solltet ihr von der Schule erhalten haben.

  • Die xml-Node macht aus den Daten ein json.

  • Die function-Node “Zusammenstellen Plan …” macht dann aus allem die gewünschte Darstellung. Ich habe mich dafür entschieden, gleich fertiges HTML zu übergeben, da ich dann freier in der Darstellung bin.

  • Die Sensor-Node müsst ihr auch bearbeiten. Also einen Sensor anlegen, den rictigen HA-Server auswählen usw. Ich übergebe dann die Anzahl der Änderungen als State, den Rest als Attribute.

  • Bei der inject-Node am Anfang müsst ihr noch einstellen, wie sie auslösen soll. Ich habe 1 Sekunde nach Start des Flows, dann alle 10 Minuten.

Zur Darstellung auf dem Dashboard nutze ich die “Lovelace HTML Jinja2 Template card”:

type: custom:html-template-card
title: null
ignore_line_breaks: true
content: >-
  {{ state_attr('sensor.plan_kind1', 'kopf') }} {% if
  is_state('sensor.plan_kind1', '0') %} <span style="font-weight:900;
  color: lime;">Keine Änderungen.</span>
            {% else %} <span style="font-size: 1.5em; font-weight:900; color: red;">{{ states('sensor.plan_kind1') }} Veränderung(en).</br></br></span>
            {% endif %}
  {{ state_attr('sensor.plan_kind1', 'tabelle') }} {{
  state_attr('sensor.plan_kind1', 'stand') }}  <style>
    ha-card {
      background: none;
      color: #fff;
      margin: -10px;
    }
  </style>

Natürlich müsst ihr den richtigen Sensor eintragen, damit etwas angezeigt wird.

Hinweis zur Karte: Card-mod funktioniert auch, allerdings bei mir nicht ganz sauber. Deshalb habe ich meine Formatierungen in den -Bereich eingetragen.

Alles in allem ist es eine recht fummelige Arbeit gewesen, die richtigen Daten zu filtern. Für mich habe ich die passende Lösung mit etwas Hilfe von ChatGPT gefunden.

3 „Gefällt mir“

Hi, das sieht richtig gut aus, ich werde die nächsten Tage versuchen, dass auf den Plan meiner Tochter anzupassen. Viele Grüße Heiko

1 „Gefällt mir“

Ist gelungen :slight_smile:
image
Danke.
Wie könnte man jetzt noch auswerten, ob der Unterricht an dem Tag zur 1. oder 3. Stunde beginnt (Helfer) um davon abhängig eine Routine zu starten?

2 „Gefällt mir“

Hallo @heiko2112 , hallo @ttarzan ,

an die XML Datei komme ich ran. Gibt es evtl. eine Möglichkeit die XML Website ohne Node Red auszulesen und in eine Tabelle zu wandeln? Hat jemand noch die Stundenplan24 App in Home Assistant mittels der XML aber ohne Node Red zum Laufen gebracht?

Danke für eure Hilfe.

Wahrscheinlich kann man das auch per Rest-Sensor machen. War mir persönlich allerdings zu unübersichtlich, ein Template zu basteln.

Dennoch vielen Dank für deine Mühe für die Rückinfo. Ich probiere es mal über ChatGPT + Gemini mit dem Restsensor. Ein paar Codezeilen hat ChatGPT schon “rausgehauen”. Ich möchte sie noch verstehen und dann detailliert umsetzen. Mal sehen, ob es mir gelingt… :wink:

Bin gespannt, was dabei raus kommt :+1:

Ich möchte die Übersicht über aktuellen Stundenplan nicht mehr missen, da sich doch immer wieder am Morgen etwas ändert.

2 „Gefällt mir“

Genau, dass ist das Ziel. Jeden Morgen soll der aktuelle Plan für beide Jungs angezeigt werden. Morgens reicht auch, weil das oft erst früh eingepflegt wird. Ich halte dich auf dem Laufenden. :wink:

2 „Gefällt mir“

Hallo Zusammen,

ich möchte ich mal auf den aktuellen Stand bringen, was ich so zusammen mit ChatGPT und Gemini probiert habe. Für alle die mitlesen: Ja, ich weiß, dass es mit NodeRed geht, aber darauf möchte ich verzichten.

Also den Rest Sensor habe ich angelegt und der gibt auch ein “ok” zurück. Also scheint die Verbindung zu Stundenplan24.de schon einmal zu gehen.

# Stundeplan24.de
  - platform: rest
    authentication: basic
    username: !secret rest_username
    password: !secret rest_password
    scan_interval: 3600
    resource: "https://www.stundenplan24.de/schulnummer//wplan/wdatenk/WPlanKl_{{ now().strftime('%Y%m%d') }}.xml"
    method: GET
    headers:
      Accept: "application/xml"
    value_template: "ok"
    name: "Plan 9o"
    json_attributes_path: "$.WplanVp.Klassen.Kl"
    json_attributes:
      - St
      - Fa
      - Le
      - Ra

Was auch funktioniert ist der/die XPath expression (getestet und XPath Tester). Mit //Kl[Kurz="9o"]/Pl/Std/Ra/text() werden mir aus XML die Räume für die 9o angezeigt. Hier wollten sowohl ChatGPT wie auch Gemini ein “@” vor “Kurz” stellen. Damit war die Treffrate “No Match”.

Was mir aber im Moment noch Schwierigkeiten bereit, ist das aufbereiten der Daten mittels “value_template”. Sowohl ChatGPT wie auch Gemini konnten hier nicht helfen. Sobald ich eine der vorgeschlagen Templates eingebe, geht der Sensor auf “unknown”.

Beispiele sind:

{% set stunden = value.xpath('//Kl[Kurz="9o"]/Pl/Std') %}
  [
    {% for stunde in stunden %}
    {
      "stunde": "{{ stunde.xpath('St/text()')[0] }}",
      "fach": "{{ stunde.xpath('Fa/text()')[0] }}",
      "lehrer": "{{ stunde.xpath('Le/text()')[0] }}",
      "raum": "{{ stunde.xpath('Ra/text()')[0] }}"
    }{% if not loop.last %},{% endif %}
    {% endfor %}
  ]
    value_template: >
      {% set stunden = value.xpath('//Kl[Kurz="9o"]/Pl/Std') %}
      {
        "stunde": "{{ stunden[0].xpath('St/text()')[0] }}",
        "fach": "{{ stunden[0].xpath('Fa/text()')[0] }}",
        "lehrer": "{{ stunden[0].xpath('Le/text()')[0] }}",
        "raum": "{{ stunden[0].xpath('Ra/text()')[0] }}"
      }
    name: "stundenplan_9o"
    json_attributes:
      - stunde
      - fach
      - lehrer
      - raum

Ich bekomme leider die Sensoren oder Attribute nicht wirklich in den Sensor rein. Die Attribute würden ja reichen. Auch der Vorschlag mit RAW Daten zu arbeiten und einen template_sensor anzulegen, hat leider im Moment nicht nicht funktioniert.

    value_template: "{{ value }}"
    name: "stundenplan_raw"

und dann

template:
  - sensor:
      - name: "Plan 9o Raum Stunde 1"
        state: >
          {% set xml = states('sensor.stundenplan_raw') %}
          {% if '<Kl>' in xml %}
            {% set klassen = xml.split('<Kl>') %}
            {% for klasse in klassen %}
              {% if '<Kurz>9o</Kurz>' in klasse %}
                {% set stunden = klasse.split('<Std>') %}
                {% if stunden[1] %}
                  {{ stunden[1].split('<Ra>')[1].split('</Ra>')[0] }}
                {% else %}
                  "Keine Stunden gefunden"
                {% endif %}
              {% endif %}
            {% endfor %}
          {% else %}
            "Keine Daten gefunden"
          {% endif %}


oder so ähnlich. Die Daten aus der XML lassen sich im Moment nicht wirklich extrahieren. Wenn jemand noch eine Idee hat, wäre ich dankbar. Ich bin leider kein Profil im Code schreiben. endif, else und if ist okay, aber dann hört es auf :wink: . Bei “value_xpath” denke, dass funktionieren könnte, aber ChatGPT und Gemini sind (stellenweise - nicht immer) der Meinung das die XPATH Anweisung in REST und HA nicht funktioniert.

Das erst einmal zum Zwischenstand. Euch ein wunderschönes Wochenende.

1 „Gefällt mir“