JSON-APIs auswerten

User stellen ihre Haussteuerung vor

Moderator: Co-Administratoren

MichaelN
Beiträge: 9561
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

JSON-APIs auswerten

Beitrag von MichaelN » 20.07.2021, 12:45

JSON-Ausgabe von Web-APIs auswerten

Jetzt habe ich mal den ganz großen Wurf gemacht und mein JSON-Skript soweit erweitert, das es auch beliebige, komplexere, valide JSON-Ausgaben von Web-Seiten / APIs auswerten kann. Und zwar vollautomatisch ohne Anpassungen im Code, mit auszählen von Textstellen oder ähnlichem. Der einzige Nachteil ist, das dadurch die anzulegenden Systemvariablen durch den im JSON vorgegebenen Namen bestimmt sind.
Da die Probleme mit system.exec und intensiver String-Verarbeitung und begrenzten Variablennamen mit einer aktuellen Firmware längst Geschichte sind, ist es nun möglich sowas ohne Sonderlösungen in der Skriptsprache der CCU abzubilden.

Eine alternative Idee JSON Daten zu erlangen: siehe Beitrag von Henke

Was macht das Skript?
API eines externen Servers abfragen, den JSON-Output decodieren und in vorhandene Systemvariablen schreiben

benötigte Fähigkeiten:
Grundkenntnisse in der WebUI-Programmierung (Anlegen und Ändern von Programmen, Einfügen und Anpassen von Skripten)
Anlegen von Systemvariablen
Skripte unter "Skript testen" laufen lassen und die Ausgaben verstehen und intepretieren
grundlegendes Logik-Verständnis / Abstraktionsvermögen um die beschriebenen Lösungen ggf. auf eigene Bedürfnisse anzupassen

Systemgrenzen: Arrays funktionieren, Unter-Objekte funktionieren, Objekte geschachtelt in Arrays funktionieren, ebenso Arrays in Gruppen. Allerdings funktioniert nur eine Verschachtelungsebene sicher. Mehrfach geschachtelte Objekte werden u. U. nicht vollständig gelesen.
Wenn die in JSON genutzten Zeichen zur Strukturierung ":,[]{}" in den Nutzdaten vorkommen werden sie durch Leerzeichen ersetzt (einstellbar durch anpassen der Variable "durch"). Unterstriche '_' werden durch Bindestriche '-' ersetzt. Um Arrays getrennt von Objekten zu behandeln ersetze ich in Arrays das Komma ',' durch Backslash '\'. Die ggf in den Nutzdaten vorhandenen \ werden zu / umgeschrieben. Das kann ggf. durch Änderung der Variablen TrennerArray und TrennerArrayErsatz angepasst werden, wenn man unbedingt das \ in den Daten benötigt.


Damit es keine Kollision mit vorhandenen Systemvariablen (SV) gibt, wird dem SV-Namen ein Präfix vorangestellt. Der Präfix kann nach eigenen Wünschen und Bedürfnissen angepasst werden. Nur dieses Präfix und die URL der abzurufenden Web-Adresse sind im Skript zu ändern. Das sind diese Stellen:

Code: Alles auswählen

string url = "http://IP/";
string prefix = "JSON_";
V1.9: will man statt der System-Funktion ein CUxD-Device nutzen, dann ist dieses Gerät entsprechend in die Variable einzutragen:

Code: Alles auswählen

string CUXD_Device = "CUxD.CUX2801001:1";
V1.11: Falls die Ausgabe des URL-Aufrufs vor oder nach dem dem eigentlichen JSON noch unnötige Daten enthält, kann man diese entfernen lassen. Dazu in diesen Zeilen den Text eingeben, mit dem der JSON-Code beginnen soll (Start_JSON) und/oder bis zu dem das JSON gehen soll (Ende_JSON). Dies kann die Ausführung bei sehr umfangreichen JSON-Daten stark beschleunigen.

Code: Alles auswählen

! optional kann man Texte am Anfang und Ende abschneiden
string Start_JSON =''; ! 'Hier den Start des eigentlichen JSON-Codes eingeben'
string Ende_JSON =''; ! 'Hier den Ende des eigentlichen JSON-Codes eingeben'  
Beispiel siehe viewtopic.php?f=18&t=68762&start=60#p705892


Das Skript enthält Testdaten. D.h. wenn man das Skript unverändert in "Skript testen" laufen lässt, erhält man auf jeden Fall eine Ausgabe. Die Testdaten (Bereich zwischen !Testdaten und ! Ende Testdaten) sollte man nach dem ersten Testlauf rauslöschen, damit das Skript bei Fehlern in der Datenübermittlung richtig reagieren kann.

Für die Werte, die man aus dem JSON benötigt, muss man eine Systemvariable mit dem passenden Namen anlegen: bestehend aus Präfix+JSON-Schlüsselname. Bei komplexeren JSON-Daten mit Unter-Objekten und Arrays setzen sich die SV-Namen dann aus Objektname+JSON-Schlüssel+Arrayname+fortlaufender Nummer zusammen.

Am besten Testen unter Programme / Zentralenverknüpfungen / Skript testen.
Dann erhält man eine Ausgabe, an der man sehen kann, wie die Systemvariablen heißen müssen und welche Werte da abgelegt werden. Wenn die SV existiert, dann wird im Erfolgsfall === SV xxx written === ausgegeben.

Wenn es da läuft in ein Programm einbinden.

Hier der Skript-Code:

Code: Alles auswählen

!JSON universell auslesen
!V1.11 MichaelN https://homematic-forum.de/forum/viewtopic.php?f=18&t=68762
!GPL-3.0-or-later
string url = "http://IP/";
url = "wget --no-check-certificate --timeout=2 -O - '"#url#"'";
string prefix = "JSON_";
string CUXD_Device = ""; ! falls man CUxD  nutzt, Device eintragen z.B. "CUxD.CUX2801001:1"
! optional kann man Texte am Anfang und Ende abschneiden
string Start_JSON =''; ! 'Hier den Start des eigentlichen JSON-Codes eingeben'
string Ende_JSON =''; ! 'Hier den Ende des eigentlichen JSON-Codes eingeben'
! Trenner kann notfalls angepasst werden, wenn es mit den Nutzdaten kollidiert
string TrennerArray = " \ ";  TrennerArray = TrennerArray.Trim();
string TrennerArrayErsatz = "/";
! festlegen welche Zeichen in den Nutzdaten durch welches Zeichen ersetzt werden
string ersetzen = ":,[]{}";
string durch = " ";

string rueck;
string error;
object SV;
string SVName;
var Wert;

!Testdaten rauslöschen für produktiven Betrieb
rueck = '{
  "Vorname": "Ronald",
  "Nachname": "Reagan",
  "Geburtsdatum": "1911-02-06",
  "Nationalitaet": "US-amerikanisch",
  "Partei":
  {
    "Name": "Republican Party",
    "Synonyme": ["Republikaner","Grand Old Party", "GOP"],
    "Hauptsitz": "Washington/D.C.",
    "Gründungsdatum": "1854-03-20",
    "Gründungsort": "Ripon"
  },
  "Amt": "US-Präsident",
  "Hobbys": ["Reiten", "Golfen", "Lesen"],
  "verheiratet": true,
  "Kinder": [
    {
      "Vorname": "Michael",
      "Nachname": "Reagan"    },
   {
      "Vorname": "Patti",
      "Nachname": "Davis"    },
   {
      "Vorname": "Ron",
      "Nachname": "Reagan"    }]
}
';
! Ende Testdaten


!- Abruf der Daten
if ( !CUXD_Device ) {
! system.exec
system.Exec(url , &rueck, &error);
} else {
! CUxD
dom.GetObject(CUXD_Device#".CMD_SETS").State(url);
dom.GetObject(CUXD_Device#".CMD_QUERY_RET").State(1);
rueck = dom.GetObject(CUXD_Device#".CMD_RETS").State();
}



if (!rueck== "")
{
   WriteLine("=== HTTP-Request OK === "#rueck);
   if ( Start_JSON.Length() > 0 ) {
       ! JSON am Anfang kürzen
	   rueck = rueck.Substr(rueck.Find(Start_JSON));
   }
   if ( Ende_JSON.Length() > 0 ) {
       ! JSON am Ende kürzen
	   rueck = rueck.Substr(0,rueck.Find(Ende_JSON));
   }
   rueck = rueck.ToLatin(); ! wegen deutschen Umlauten
   rueck = rueck.Trim(" {}[]");
   rueck = rueck.Replace('\n','');
   rueck = rueck.Replace('\r','');
   rueck = rueck.Replace('_','-');
   rueck = rueck.Replace(TrennerArray,TrennerArrayErsatz);
   if (rueck.Substr(0,1) == "[" ) { rueck = "data:"#rueck; }
   WriteLine("=== nach Replace === '"#rueck#"'");


! Array und Payload aufbereiten
   integer pos1 = 0; integer posG = 0;
   integer pos2 = rueck.Length();
   string temp = ""; string temp2;
   string teil;
   boolean Array = false; boolean Payload = false;
   while ( pos1 < pos2 )
	 {
         teil = rueck.Substr(pos1,1);
         if ( teil == "[")
            {! Array gefunden
            Array = true;
            }
         if ( (teil == "," ) && Array )
           {! Komma gegen Schraegstrich tauschen
            teil = TrennerArray;
            }
         if ( teil == "]")
            {! Array Ende
            Array = false;
            }
         if (  teil == '"' ) {
            if ( Payload )
            {! Payload Ende
            Payload = false;
            } else {
            ! Payload Start
            Payload = true;
            }
            }
         if ( ( ersetzen.Contains(teil) )  && Payload )
           {! verbotene Zeichen austauschen
            teil = durch;
            }
         temp = temp#teil;
         pos1 = pos1 + 1;
		 }
   rueck = temp;
   rueck = rueck.Replace('"','');
   WriteLine("=== nach Aufbereitung === '"#rueck#"'");
   WriteLine("=== Output V1.11 ===");

   string Part; string SVNameArray;
   string Gruppe = ""; string GruppeNeu;
   integer G1; integer G2;
   integer ArrayZaehler = 0;
   boolean ArrayMitGruppe = false;

   foreach (Part, rueck.Split(",") ){
          if (Part.Contains(":"))
          {
           if (Part.Contains("{"))
           { ! Unter-Objekt gefunden
             !WriteLine("Z96 Part='"#Part#"'"); ! *** DEBUG

             if (Part.Contains("[")) {
               ! enthält Arrray
               GruppeNeu = Part.StrValueByIndex(":", 0);
               GruppeNeu = GruppeNeu.Trim() #"_";
               Part = Part.Substr(GruppeNeu.Length()+2).Trim("{ ");
               Gruppe = Gruppe # GruppeNeu; Gruppe = Gruppe.Replace("__","_");
               !WriteLine("Gruppe alt:"#Gruppe); ! DEBUG ***
               !WriteLine("Inhalt alt:"#Part); ! DEBUG ***
             } else {
               ! enthält kein Array, aber möglicherweise geschachtelte Objekte
               temp = Part.Replace("{",";");
               G2 = web.webGetValueListCount(temp);
               G1=0;
               while (G1 < (G2-1)) {
               GruppeNeu = web.webGetValueFromList(temp,(G1)).Trim(" :");
               if ( (GruppeNeu == "_") || (GruppeNeu == "") ) {
               	    ArrayZaehler = ArrayZaehler + 1;
                    GruppeNeu = ArrayZaehler.ToString(0).Trim() # "_";
                    }
               Gruppe = Gruppe # GruppeNeu # "_";
               G1 = G1 + 1;
               }
               if ( Gruppe == "_" ) {
               	    ArrayZaehler = ArrayZaehler + 1;
                    Gruppe = ArrayZaehler.ToString(0).Trim() # "_";
                    }
               Gruppe = Gruppe.Replace("__","_");
               Part = web.webGetValueFromList(temp,(G2-1));
               !WriteLine("Gruppe neu:"#Gruppe); ! *** DEBUG
               !WriteLine("Inhalt neu:"#Part); ! **** DEBUG
             }

             !WriteLine("=== GRUPPE-START: "#Gruppe);
           }
           if (Part.Contains(TrennerArray)) {
              ! Array gefunden
              !WriteLine("=== ARRAY auflösen:"#Part);
              ArrayMitGruppe = false;
              Part = Part.Replace("[","");
              Part = Part.Replace("]","");
              pos1 = 0;  posG = 0;
              SVName = Gruppe;
              if (Part.Contains(":"))
                  {
                  SVName = Part.StrValueByIndex(":", 0);
                  Part = Part.Substr(SVName.Length()+1).Trim();
                  SVName = SVName.Trim("[{ ");
		  !WriteLine("*** Z365 ARRAY aufgelöst in:"#SVName#"==="#Part#"===");  ! DEBUG ***
                  }
              foreach (temp,Part.Split(TrennerArray))
              	{
                !WriteLine("Z352 temp="#temp); ! DEBUG ***

                if ( temp.Contains(":")) {
                ! Array enthält eine Gruppe

                  SVName = temp.StrValueByIndex(":", 0).Trim("{ ");
                  temp2 = temp;
                  temp = temp.StrValueByIndex(":", 1).Trim(" []");
                  SVNameArray = SVName#posG.ToString(0).Trim();
                      if ( temp.Contains("{")) {
                      ! weitere Gruppe gefunden
                      ArrayMitGruppe = true;
                      Gruppe = Gruppe # SVName # "_";
                      temp = temp.Trim(" {"); ! temp.StrValueByIndex("{", 1).Trim();
                      SVName = temp;
                      temp = temp2.StrValueByIndex(":", 2).Trim(" []");
                      SVNameArray = SVName#posG.ToString(0).Trim();
                      !WriteLine("Z363 Gruppe="#Gruppe#" SVNameAray="#SVNameArray#" temp="#temp); ! DEBUG ***
                      }

                  if ( temp.Contains("}")) { posG = posG + 1; }
                  !WriteLine("Z367 Gruppe="#Gruppe#" SVNameAray="#SVNameArray#" temp="#temp); ! DEBUG ***
                  WriteLine (prefix # Gruppe # SVNameArray #" = '"# temp.Trim(" {[]}") #"'");
	              SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get((prefix # Gruppe # SVNameArray));
     	          if (SV) {
                   SV.State(temp.Trim(" {[]}"));
                   WriteLine("=== SV "#prefix # Gruppe # SVNameArray #" written ===");
                   }
                } else {
                ! keine Gruppe
                  SVNameArray = SVName#pos1.ToString(0).Trim();
                  WriteLine (prefix # Gruppe # SVNameArray #" = '"# temp.Trim(" {[]}") #"'");
	              SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get((prefix # Gruppe # SVNameArray));
     	          if (SV) {
                   SV.State(temp.Trim(" {[]}"));
                   WriteLine("=== SV "#prefix # Gruppe # SVNameArray #" written ===");
                   }
                  pos1 = pos1 + 1;
                  }
           		if ( (temp.Contains("}")) && (ArrayMitGruppe)  )
           		{ ! Unter-Objekt zu Ende
               		  ! Gruppe um letzten Eintrag kürzen
               		  temp2 = Gruppe.Replace("_",";");
               		  G2 = web.webGetValueListCount(temp2);
                      !WriteLine("Z365 GRUPPE: "#Gruppe#" ==="); ! DEBUG ***
               		  Gruppe = ""; G1=0;
               				while (G1 < (G2-2)) {
               				Gruppe = Gruppe # web.webGetValueFromList(temp2,(G1)) # "_";
                			!WriteLine("Z368 "#G1#"/"#G2#":"#Gruppe); ! *** DEBUG
               				G1 = G1 + 1;
               				}
             		!WriteLine("=== Z374 GRUPPE-ENDE: "#Gruppe#" ===");
                    ArrayMitGruppe = false;
           		}


                }
                if ( posG > 0 ) {
                	!WriteLine("Z413 Part="#Part); ! *** DEBUG

              		! Gruppe um letzten Eintrag kürzen
               		temp2 = Gruppe.Replace("_",";");
               		G2 = web.webGetValueListCount(temp2);
                    !WriteLine("=== GRUPPE-ENDE (array): "#Gruppe#"***");
               		Gruppe = ""; G1=0;
               		while (G1 < (G2-2)) {
               				Gruppe = Gruppe # web.webGetValueFromList(temp2,(G1)) # "_";
                			!WriteLine("Z422 "#G1#"/"#G2#":"#Gruppe); ! *** DEBUG
               				G1 = G1 + 1;
               				}

                        }
			! ARRAY ENDE


           } else {
           ! ohne Array
           ! WriteLine("Z154 Part='"#Part#"'"); ! *** DEBUG
           Part = Part.Replace(":",";");
           SVName = Gruppe#web.webGetValueFromList(Part,0).Trim();
           Wert = web.webGetValueFromList(Part,1).RTrim("}").Trim(" {[]}");
           WriteLine (prefix # SVName #" = '"# Wert #"'");
	       SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get((prefix # SVName));
     	   if (SV) {
                   SV.State(Wert);
                   WriteLine("=== SV "#prefix # SVName #" written ===");
                   }
           if (Part.Contains("}"))
             { ! Unter-Objekt zu Ende
             ! *** Gruppe muss um so viele Einträge gekürzt werden, wie } vorhanden sind in Part ***
             Part = Part.Replace(" ","");
             ! WriteLine("Z199 Part='"#Part#"'"); ! *** DEBUG
             while ( Part.EndsWith("}") ) {
               ! Gruppe um letzten Eintrag kürzen
               temp = Gruppe.Replace("_",";");
               G2 = web.webGetValueListCount(temp);
               Gruppe = ""; G1=0;
               while (G1 < (G2-2)) {
               		Gruppe = Gruppe # web.webGetValueFromList(temp,(G1)) # "_";
               		! WriteLine("=== "#G1#":"#Gruppe); *** DEBUG
               		G1 = G1 + 1;
               		}
               Part = Part.Substr(0,(Part.Length()-1)) ;
               ! WriteLine("Z212 Part="#Part); ! *** DEBUG
             } ! Ende while
             !WriteLine("=== GRUPPE-ENDE: "#Gruppe#" ===");
            }
           }
         }
   }
} else {
  WriteLine("Error at HTTP Request");
}
Beispiel:
Aus diesen Testdaten (Quelle Wikipedia)

Code: Alles auswählen

{
  "Vorname": "Ronald",
  "Nachname": "Reagan",
  "Geburtsdatum": "1911-02-06",
  "Nationalitaet": "US-amerikanisch",
  "Partei":
  {
    "Name": "Republican Party",
    "Synonyme": ["Republikaner", "Grand Old Party", "GOP"],
    "Hauptsitz": "Washington/D.C.",
    "Gründungsdatum": "1854-03-20",
    "Gründungsort": "Ripon"
  },
  "Amt": "US-Präsident",
  "Hobbys": ["Reiten", "Golfen", "Lesen"],
  "verheiratet": true,
  "Kinder": [
    {
      "Vorname": "Michael",
      "Nachname": "Reagan"    },
   {
      "Vorname": "Patti",
      "Nachname": "Davis"    },
   {
      "Vorname": "Ron",
      "Nachname": "Reagon"    }]
}
wird folgende Ausgabe generiert:

Code: Alles auswählen

nach Replace: '  Vorname: Ronald,  Nachname: Reagan,  Geburtsdatum: 1911-02-06,  Nationalitaet: US-amerikanisch,  Partei:  {    Name: Republican Party,    Synonyme: [Republikaner, Grand Old Party, GOP],    Hauptsitz: Washington/D.C.,    Gründungsdatum: 1854-03-20,    Gründungsort: Ripon  },  Amt: US-Präsident,  Hobbys: [Reiten, Golfen, Lesen],  verheiratet: true,  Kinder: [    {      Vorname: Michael,      Nachname: Reagan    },   {      Vorname: Patti,      Nachname: Davis    },   {      Vorname: Ron,      Nachname: Reagon    }]}'
nach Array-Aufbereitung: '  Vorname: Ronald,  Nachname: Reagan,  Geburtsdatum: 1911-02-06,  Nationalitaet: US-amerikanisch,  Partei:  {    Name: Republican Party,    Synonyme: [Republikaner\ Grand Old Party\ GOP],    Hauptsitz: Washington/D.C.,    Gründungsdatum: 1854-03-20,    Gründungsort: Ripon  },  Amt: US-Präsident,  Hobbys: [Reiten\ Golfen\ Lesen],  verheiratet: true,  Kinder: [    {      Vorname: Michael\      Nachname: Reagan    }\   {      Vorname: Patti\      Nachname: Davis    }\   {      Vorname: Ron\      Nachname: Reagon    }]}'
=== Output ===
JSON_Vorname = 'Ronald'
JSON_Nachname = 'Reagan'
JSON_Geburtsdatum = '1911-02-06'
JSON_Nationalitaet = 'US-amerikanisch'
=== GRUPPE-START: Partei_
JSON_Partei_Name = 'Republican Party'
=== ARRAY auflösen:    Synonyme: [Republikaner\ Grand Old Party\ GOP]
JSON_Partei_Synonyme0 = 'Republikaner'
JSON_Partei_Synonyme1 = 'Grand Old Party'
JSON_Partei_Synonyme2 = 'GOP'
JSON_Partei_Hauptsitz = 'Washington/D.C.'
JSON_Partei_Gründungsdatum = '1854-03-20'
JSON_Partei_Gründungsort = 'Ripon'
=== GRUPPE-ENDE: Partei_***
JSON_Amt = 'US-Präsident'
=== ARRAY auflösen:  Hobbys: [Reiten\ Golfen\ Lesen]
JSON_Hobbys0 = 'Reiten'
JSON_Hobbys1 = 'Golfen'
JSON_Hobbys2 = 'Lesen'
JSON_verheiratet = 'true'
=== GRUPPE-START: Kinder_
=== ARRAY auflösen:[    {      Vorname: Michael\      Nachname: Reagan    }\   {      Vorname: Patti\      Nachname: Davis    }\   {      Vorname: Ron\      Nachname: Reagon    }]}
JSON_Kinder_Vorname0 = 'Michael'
JSON_Kinder_Nachname0 = 'Reagan'
JSON_Kinder_Vorname1 = 'Patti'
JSON_Kinder_Nachname1 = 'Davis'
JSON_Kinder_Vorname2 = 'Ron'
JSON_Kinder_Nachname2 = 'Reagon'
=== GRUPPE-ENDE: Kinder_***
Will man den Vornamen in eine Systemvariable schreiben lassen, dann legt man eine SV JSON_Vorname an.
Braucht man den zweiten Wert des Array Hobbys, dann legt man eine SV JSON_Hobbys1 an. Achtung: Arrays werde bei 0 startend nummeriert.
Benötigt man den Wert Name aus dem Partei-Objekt, dann lautet der SV-Name JSON_Partei_Name.
Zuletzt geändert von MichaelN am 24.06.2023, 11:11, insgesamt 25-mal geändert.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

MichaelN
Beiträge: 9561
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: JSON-APIs auswerten

Beitrag von MichaelN » 03.08.2021, 19:04

Version 1.5 veröffentlicht. Nun sind auch Gruppen in Arrays möglich.
Wenn jemand auf ein JSON stößt, das sich nicht auswerten lässt (sehr komplexe stoßen immer noch an Grenzen) kann es hier ja mal in Code Tags posten. Dann kann ich es mir ansehen.
Zuletzt geändert von MichaelN am 20.08.2021, 21:58, insgesamt 1-mal geändert.
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Benutzeravatar
Black
Beiträge: 5463
Registriert: 12.09.2015, 22:31
System: Alternative CCU (auf Basis OCCU)
Wohnort: Wegberg
Hat sich bedankt: 418 Mal
Danksagung erhalten: 1069 Mal
Kontaktdaten:

Re: JSON-APIs auswerten

Beitrag von Black » 03.08.2021, 19:58

ich hab grad mal probeweise dein Script mit Backup ausgaben des SDV gequält, programmBackup und complete-Device-Backup.
es lief durch und die Ausgaben waren auf den erstblick erstmal stimmig.

gute Arbeit

Black
Wenn das Fernsehprogramm immer mehr durch nervende Werbung unterbrochen wird und der Radiomoderator nur noch Müll erzählt, ist es besser, die Zeit für sinnvolle Dinge zu nutzen -
mal aufs Klo zu gehen, ein Bier zu holen oder einfach mal den roten AUS-Knopf zu drücken. Klick - und weg

Script Time Scheduler V1.3
AstroSteuerung über Zeitmodul flexibel mit Offset / spätestens, frühestens
SDV 5.03.01 Das umfassende Entwicklungs und Diagnosetool für Homematik
Selektive Backups - Nützliche Dinge, die die WebUI nicht kann

Intel NUC6 Celeron 16GB mit 512GB SSD unter Proxxmox mit insgesamt 5 VM: 2 x bloatwarebefreiter Raspberrymatik, 2 x IOBroker als Middleware und einer MariaDB zur Archivierung. Verbrauch: 6W

technical contribution against annoying advertising

MichaelN
Beiträge: 9561
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: JSON-APIs auswerten

Beitrag von MichaelN » 04.08.2021, 14:26

Dummerweise führt

Code: Alles auswählen

rueck = rueck.Replace(^\^,'/');
Und die sonstigen Vorkommen von ^ zur nicht Nutzbarkeit Speicherbarkeit des Skript auf einer Standard CCU

Meine schlaue Idee war eigentlich das \ als Trennzeichen zu nutzen, da es eher nicht in einem JSON vorkommen sollte.
Leider schlägt dann der Quoting-Teufel zu, dem ich bisher elegant ausgewichen bin.

Lt. Doku müsste ich "\\" schreiben um das \ zu Quoten. Das geht ja bekanntlich nciht. "\\\" führt auch zum RunTimeError.
Wie bekomme ich denn nun \ in einen String, ohne ^ zu benutzen? Und wäre das dann überhaupt CCU und RM kompatibel?

Ich glaube, ich weiche auf einen anderen Trenner aus. * z. B. Sollte auch nicht so häufig in Messdaten o. Ä. Vorkommen?!
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Tyfys
Beiträge: 531
Registriert: 17.04.2021, 17:12
System: CCU
Hat sich bedankt: 26 Mal
Danksagung erhalten: 121 Mal

Re: JSON-APIs auswerten

Beitrag von Tyfys » 04.08.2021, 14:41

Also du willst den Backslash in einen Schrägstrich wandeln.

und dir macht das Accent circonflexe ^ die Speicherung zu nichte

Das sollte doch so gehen :

Code: Alles auswählen

rueck = rueck.Replace("\",'/');
Oder hab ich das Problem nicht erkannt ?

Gruß
Harry
Gruß
Harry

MichaelN
Beiträge: 9561
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

Re: JSON-APIs auswerten

Beitrag von MichaelN » 04.08.2021, 14:45

Sollte oder hast Du es ausprobiert?
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Tyfys
Beiträge: 531
Registriert: 17.04.2021, 17:12
System: CCU
Hat sich bedankt: 26 Mal
Danksagung erhalten: 121 Mal

Re: JSON-APIs auswerten

Beitrag von Tyfys » 04.08.2021, 15:09

leider hab ich das nicht ausprobiert, weil ich dachte es geht nur um ^.

Ein Skript mit diesem Zeichen ^ wird auf meiner CCU2 nicht gespeichert.

Nun hab ich meine Idee ausprobiert.
Der Backslash wirft dann bei der Fehlerprüfung einen Fehler aus.
Im Skrip testen tut sich auch nix.

ist ja tricky


Gruß
Harry
Gruß
Harry

Tyfys
Beiträge: 531
Registriert: 17.04.2021, 17:12
System: CCU
Hat sich bedankt: 26 Mal
Danksagung erhalten: 121 Mal

Re: JSON-APIs auswerten

Beitrag von Tyfys » 04.08.2021, 18:06

Hallo Michael

Hab auch mal ein wenig rum experimentiert.
Einige Commands haben mit dem "\" keine Probleme, wenn solo definiert ist.


Mit Trick 17 kann man dann aus einem \ ein / machen
bzw. auch aus / ein \

Code: Alles auswählen

string x="Hallo\die\Welt!";
WriteLine(x);
string bs=" \ ";
WriteLine(bs.Trim());
x=x.Replace(bs.Trim(),"/");
WriteLine(x);
x=x.Replace("/",bs.Trim());
WriteLine(x);

x="Hallo\die\Welt!";
x=x.Replace(" \ ".Trim(),"/");
WriteLine(x);

Code: Alles auswählen

Hallo\die\Welt!
\
Hallo/die/Welt!
Hallo\die\Welt!
Hallo/die/Welt!

Abspeichern lässt sich das auch.

Vielleicht hilft es dir weiter, wenn du zu dem selben Ergebnis kommst.

Gruß
Harry
Gruß
Harry

Benutzeravatar
Black
Beiträge: 5463
Registriert: 12.09.2015, 22:31
System: Alternative CCU (auf Basis OCCU)
Wohnort: Wegberg
Hat sich bedankt: 418 Mal
Danksagung erhalten: 1069 Mal
Kontaktdaten:

Re: JSON-APIs auswerten

Beitrag von Black » 04.08.2021, 18:27

Das escaping, gerade wenn es compatible mit einer ccu3 / RMatik sein soll, kann echt eine spassige Angelegenheit sein.
Da kann ich auch ein Liedchen von singen.

sobald das ^ benutzt wird, kriegst du ohne umweg das script nicht ins programm. mit der WebUI gehts dann nicht mehr.

und wie du gemerkt hast \\ bzw \\\ tuts nicht so wie erwartet und wenn in dem einen system funktioniert dann im anderen nicht mehr.

black
Wenn das Fernsehprogramm immer mehr durch nervende Werbung unterbrochen wird und der Radiomoderator nur noch Müll erzählt, ist es besser, die Zeit für sinnvolle Dinge zu nutzen -
mal aufs Klo zu gehen, ein Bier zu holen oder einfach mal den roten AUS-Knopf zu drücken. Klick - und weg

Script Time Scheduler V1.3
AstroSteuerung über Zeitmodul flexibel mit Offset / spätestens, frühestens
SDV 5.03.01 Das umfassende Entwicklungs und Diagnosetool für Homematik
Selektive Backups - Nützliche Dinge, die die WebUI nicht kann

Intel NUC6 Celeron 16GB mit 512GB SSD unter Proxxmox mit insgesamt 5 VM: 2 x bloatwarebefreiter Raspberrymatik, 2 x IOBroker als Middleware und einer MariaDB zur Archivierung. Verbrauch: 6W

technical contribution against annoying advertising

Benutzeravatar
jmaus
Beiträge: 9817
Registriert: 17.02.2015, 14:45
System: Alternative CCU (auf Basis OCCU)
Wohnort: Dresden
Hat sich bedankt: 459 Mal
Danksagung erhalten: 1855 Mal
Kontaktdaten:

Re: JSON-APIs auswerten

Beitrag von jmaus » 04.08.2021, 18:38

Tyfys hat geschrieben:
04.08.2021, 14:41
Das sollte doch so gehen :

Code: Alles auswählen

rueck = rueck.Replace("\",'/');
Das wird zwar auf einer CCU3 bzw. CCU2 mit aktueller Firmware (3.59.x/2.59x) noch gehen, aber syntaktisch ist das falsch und in Zukunft wird es dazu Updates geben, die eine neuere ReGaHss version mit sich bringen werden die das dann reparieren und es dann notwendig machen das man das korrekterweise wie folgt schreibt:

Code: Alles auswählen

rueck = rueck.Replace("\\",'/');
Denn ein einzelnes Backslash (\) ist genau dafür da (wie man das erwarten sollte) das darauf folgende Zeichen zu escapen. Insofern ist das "\" eben falsch weil das Backslash das darauf folgende " zeichen escapt und dann erwartet das danach noch ein " zum schließen der zeichenkette folgt oder aber es sind eben zwei aufeinanderfolgende Backslash (\\) die dann eben unterm Strich ein einzelnes im String auftauchen lassen.

Wenn man das als kompatibel zu kommenden Versionen bzw. zu RaspberryMatic (weil das schon die aktuellste ReGaHss einsetzt) halten will, dann muss man hier in der Tat folgenden Aufruf verwenden:

Code: Alles auswählen

rueck = rueck.Replace(^\^,'/');
Und eben folglich den "super-char" (^) verwenden der normalerweise innerhalb seines content (d.h. also bis zum nächsten ^) keinerlei escaping zulässt und somit ein einzelnes \ darin i.O. ist. Das Problem hierbei ist jedoch, das durch einen anderen Bug in der WebUI selbst (d.h. im Programm-Editor) es mitunter nicht möglich ist den super-char (^) im WebUI Editor für Programme zu verwenden. Auch das ist in RaspberryMatic bereits repariert, aber eben noch nicht in die CCU3 Firmware zurückgeflossen.
RaspberryMatic 3.75.6.20240316 @ ProxmoxVE – ~200 Hm-RF/HmIP-RF/HmIPW Geräte + ioBroker + HomeAssistant – GitHub / Sponsors / PayPal / ☕️

Antworten

Zurück zu „Projektvorstellungen“