Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. API-Authentifizierung

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    API-Authentifizierung

    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      smartin23 last edited by

      Hallo zusammen,

      ich habe es schon in anderen Foren probiert - aber vielleicht könnt Ihr mir hier zielgenauer helfen.

      Für meine Visualisierung möchte ich die Abfahrtszeiten der nächsten Bushaltestelle anzeigen. Dafür habe ich einen API-Zugang des Verkehrsbetriebes bekommen. Dort muss ich mich mit einer Zertifikatsdatei authentifizieren.

      Bisher habe ich dafür folgende Lösung:

      Auf der Webstation meiner Synology Diskstation läuft eine PHP-Datei, die das Zertifikat zum Server sendet und die API-Abfrage durchführt. Das Ergebnis ist eine XML-Datei. Diese speichert das PHP-Skript im Ordner der Webstation. Das Skript wird regelmäßig ausgeführt, so dass ich immer die aktuellen Abfahrtszeiten auf meiner Diskstation liegen habe.

      Nun suche ich die geschickteste Lösung, um diese Daten in meiner VIS zu verarbeiten. Aktuell habe ich die Auswertung und Aufbereitung der Daten ebenfalls auf meiner Webstation laufen und als iFrame eingebunden. Das läuft so la la. Am liebsten würde ich die Daten aber direkt in IOBroker auswerten und verarbeiten.

      Nur: Wie bekomme ich sie da rein?

      Ich habe mal probiert, die XML-Datei von der Webstation in einem Javascript mit fetch einzulesen - aber kriege da einen cors-Fehler („No 'Access-Control-Allow-Origin' header is present on the requested resource.“). Außerdem habe ich probiert, den Ordner der Webstation in Docker zu mounten, um direkt aus IOBroker darauf zugreifen zu können. Das bringt aber IOBroker zum Absturz.

      Habt Ihr einen Tipp, wie ich die abgerufenen Daten verarbeiten kann?

      Oder würdet Ihr einen ganz anderen Ansatz wählen?

      OliverIO 1 Reply Last reply Reply Quote 0
      • OliverIO
        OliverIO @smartin23 last edited by

        @smartin23

        zeige das phpskript. deine keys kannst du anonymisieren.
        aber du sprachst ja von einer zertifikatsdatei, die dürfte man dann nicht sehen

        S 1 Reply Last reply Reply Quote 0
        • S
          smartin23 @OliverIO last edited by

          @oliverio Das hier ist mein PHP-Skript:

          <?php
          	$stopID = "de:xyz:xyz"; // Haltestelle
          	$now = date(DATE_ATOM);
          	$input_xml = "<?xml version='1.0' encoding='UTF-8'?><HIER IST DIE XML-ABFRAGE DRIN>";
          	$API_url = "https://api.xyz.de/xyz/";
          
          	$header = array(
                      "Content-type: text/xml;charset=\"utf-8\""
          	);
          
          	$ch = curl_init();
          	curl_setopt($ch, CURLOPT_URL, $API_url); // URL
          	curl_setopt($ch, CURLOPT_POST, true); // Post
          	curl_setopt($ch, CURLOPT_HTTPHEADER, $header);	// Header
          	curl_setopt($ch, CURLOPT_POSTFIELDS, $input_xml); // Anfrage
                  curl_setopt($ch, CURLOPT_VERBOSE, true); // Debugging ein
          	curl_setopt($ch, CURLOPT_SSLCERTTYPE, "PEM"); // Zertifikat ist ein PEM-Zertifikat
          	curl_setopt($ch, CURLOPT_SSLCERT, getcwd() . "/cert/API.crt"); // Zertifikat für Benutzer aufrufen
          	curl_setopt($ch, CURLOPT_SSLKEY, getcwd() . "/cert/key.key"); // Passwort für Zertifikat
          	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // jedes Zertifikat zulassen (besser TRUE, aber dann läuft es nicht)
                  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // checke, ob Host existiert und Name übereinstimmt
          	curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "/cert/XYZ-CA.crt"); // Root-Zertifikat nutzen
          	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Rückgabe ermöglichen
                  
          	$data = curl_exec($ch);
          	if(curl_errno($ch))
          		print curl_error($ch);
          	else
          		curl_close($ch);
          
          	echo $data;
          	
          	$filename = "xyz.xml";
          	$handle = fopen($filename, "w");
          	fwrite($handle, $data);
          	fclose ($handle);
          ?>
          

          Die PHP authentifiziert sich halt mit crt-, key- und root-crt-Dateien und schickt eine XML-Abfrage an den Server der lokalen Verkehrsbetriebe. Die Antwort kommt auch als XML-Datei zurück. Die wird dann einfach nur abgespeichert.

          Im nächsten Schritt habe ich dann ein Javascript, was die gespeicherte XML-Datei einliest und die Daten verarbeitet und optisch aufbereitet.

          Das Javascript funktioniert halt auch ohne Probleme, wenn es direkt auf der Webstation läuft und er damit die XML-Datei "direkt vor Ort" liegen hat. Versuche ich es aber in IOBroker einzubauen, sieht er den Zugriff auf die XML-Datei halt als externen Zugriff und sperrt die Anfrage.

          Um die XML-Daten direkt in IOBroker auszuwerten und weiterzuverarbeiten, müsste ich halt entweder die ganze API-Anfrage in IOBroker "nachbauen" oder die XML-Daten da irgendwie sonst reinbekommen.

          Nur die API-Abfrage in IOBroker nachbauen kriege ich irgendwie nicht hin - habe die Authentifizierung per Datei eben nur in PHP geschafft...

          Daher war meine Idee, irgendwie die XML-Daten in IOBroker abrufbar zu machen - nur wie?

          OliverIO 1 Reply Last reply Reply Quote 0
          • OliverIO
            OliverIO @smartin23 last edited by

            @smartin23 sagte in API-Authentifizierung:

            ich hab dein php skript einfach mal nach chatgpt kopiert und gebeten, das er mir das für javascript und der axios bibliothek übersetzen soll.

            hab es nicht testen können, sieht aber erst mal gut aus.
            kleine herausforderung könnte noch sein, die crt und key dateien mit der richtigen berechtigung in ein entsprechendes verzeichnis zu legen.
            du kannst mal /opt/iobroker/iobroker-data/<dir einen verzeichnisnamen ausdenken> und verzeichnis anlegen, so das der iobroker darauf auch zugreifen kann. die dateien reinkopieren und auch die berechtigungen anpassen.
            anstatt relativer pfadangaben würde ich die dateien mit absolutem pfad eintragen.
            das selbe für die datei die geschrieben wird. wobei das ziel sein sollte ohne die auszukommen, das ergebnis direkt auszuwerten und direkt in bestimmte iobroker datenpunkte zu schreiben.

            const axios = require('axios');
            const fs = require('fs');
            
            const stopID = "de:xyz:xyz"; // Haltestelle
            const now = new Date().toISOString();
            const input_xml = "<?xml version='1.0' encoding='UTF-8'?><HIER IST DIE XML-ABFRAGE DRIN>";
            const API_url = "https://api.xyz.de/xyz/";
            
            const config = {
              headers: {
                "Content-type": "text/xml;charset=\"utf-8\""
              },
              httpsAgent: new https.Agent({
                cert: fs.readFileSync("./cert/API.crt"),
                key: fs.readFileSync("./cert/key.key"),
                ca: fs.readFileSync("./cert/XYZ-CA.crt"),
                rejectUnauthorized: true
              })
            };
            
            axios.post(API_url, input_xml, config)
              .then(response => {
                const data = response.data;
                console.log(data);
                fs.writeFileSync("xyz.xml", data);
              })
              .catch(error => {
                console.log(error);
              });
            
            S 1 Reply Last reply Reply Quote 0
            • S
              smartin23 @OliverIO last edited by

              @oliverio Danke Dir!

              Das wäre natürlich super, die Abfrage auch direkt im IOBroker zu realisieren und das Ergebnis als Datenpunkt zu schreiben.

              Ich habe das nun ausprobiert und einige Fehler der Reihe nach ausgemerzt, bis er die Anfrage nun tatsächlich verschickt. Allerdings kommt vom Server nun die Antwort "socket hang up at connResetException" - und da komme auch mit viel Googlen leider nicht weiter. Vielleicht muss ich auch mal ChatGPT dazu befragen.

              Da die PHP-Abfrage ja sehr stabil läuft: Gibt es wirklich keine Möglichkeit, die dort erzeugte XML-Datei irgendwie in den IOBroker zu bekommen? Ich stelle mir die Lösung am einfachsten vor, weil die benötigten Daten ja nunmal schon lokal auf der Diskstation liegen. Nur leider eben in der Webstation und nicht im Docker-Container.

              OliverIO 2 Replies Last reply Reply Quote 0
              • OliverIO
                OliverIO @smartin23 last edited by

                @smartin23

                ja,
                du installierst den simple api adapter
                und sendest aus dem php skript heraus selbst einen request an den iobroker.
                damit kann man datenpunkte schreiben, aber auch lesen

                S 1 Reply Last reply Reply Quote 0
                • OliverIO
                  OliverIO @smartin23 last edited by OliverIO

                  @smartin23 said in API-Authentifizierung:

                  socket hang up at connResetException

                  ist eine Fehlermeldung des Clients. Das socket wurde geschlossen, obwohl noch daten zu senden waren.

                  Füge mal denm httpagent noch die Option keepalive true hinzu und prüfe
                  ob die Informationen aus den Dateien auch rechtzeitig bereit stehen.
                  Wenn bei Start des requests erst noch die NAS anlaufen muss, dann kann der timeout für den request und für die socket schnell da sein.

                  httpsAgent: new https.Agent({
                      cert: fs.readFileSync("./cert/API.crt"),
                      key: fs.readFileSync("./cert/key.key"),
                      ca: fs.readFileSync("./cert/XYZ-CA.crt"),
                      rejectUnauthorized: true,
                      keepAlive: true
                    })
                  
                  1 Reply Last reply Reply Quote 0
                  • S
                    smartin23 @OliverIO last edited by

                    @oliverio Danke! Die Simple-API ist genau das, was mir weiterhilft!!! 🙂

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post

                    Support us

                    ioBroker
                    Community Adapters
                    Donate

                    877
                    Online

                    31.7k
                    Users

                    79.8k
                    Topics

                    1.3m
                    Posts

                    2
                    8
                    447
                    Loading More Posts
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes
                    Reply
                    • Reply as topic
                    Log in to reply
                    Community
                    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                    The ioBroker Community 2014-2023
                    logo