VTI aus Programm Picoc beschreiben

Einklappen
X
 
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge
  • Rick_Pa_87
    Dumb Home'r
    • 04.08.2022
    • 17

    #1

    VTI aus Programm Picoc beschreiben

    Hallo zusammen,

    hat jemand ein Beispiel wie ich einen VTI aus einem Picoc Programm beschreiben kann? Ich hab das schon über einen HTTPPost gemacht aber hier schneidet es mit von einem sehr langen Text die hinteren Zeichen ab. Ich vermute der Textausgang des Programmbausteins kann keinen 1500Zeichen. Der Eingang kann es aber. > aus Loxberry -> NodeRed getestet!

    Vielen Dank
  • Tico
    Lox Guru
    • 31.08.2016
    • 1035

    #2
    Wahrscheinlich haben Sie diesen Link bereits, aber stellen Sie ihn für alle Fälle zur Verfügung -

    Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

    Kommentar

    • Labmaster
      Lox Guru
      • 20.01.2017
      • 2592

      #3
      Code:
      char singleString[] = "Das wird ein langer Text, der sicher mehr als 1500 Zeichen haben wird und trotzdem ausgegeben werden sollte ! ";
      char outTxtBuffer[3000];
      unsigned integer cnt;
      int nEvents;
      
      strcpy(outTxtBuffer, singleString);
      for (cnt=0; cnt<=21; cnt++)
      {
          strcat(outTxtBuffer, singleString);
      }
      
      while(True)
      {
          nEvents = getinputevent();
          if (nEvent & 0x08)  // check for change on "Input 1" (Bit 4)
          {
              setoutputtext(0,outTxtBuffer);
          }
      
          sleep(100);
      
      }
      ( keine Gewähr, daß der Code so "Out of the box" funktioniert, heißt ich haben den hier "trocken" getippt und nicht selbst getestet, könnten sich also Tippfehler o.Ä. versteckt haben)

      Der Text sollte damit jedenfalls beim Programm Baustein auf dem ersten Text Ausgang raus kommen immer wenn sich der Wert auf Programm Baustein "Input 1" ändert.
      Bei mir heißt der erste Textausgang am Programmbaustein "TQ1".
      Der Eingang "Input 1" ist bei mir "AI1".
      (habe aber noch die alte Loxone Config eventuell wurde der mittlerweile ja auch umbenannt)
      Zuletzt geändert von Labmaster; 15.09.2023, 06:57.

      Kommentar

      • Rick_Pa_87
        Dumb Home'r
        • 04.08.2022
        • 17

        #4
        Ich kann nur dazu sagen das bei printf die länge passt und bei der Ausgabe über setoutputtext(0,outTxtBuffer) und anschließender Weiterverarbeitung die letzten x stellen abgeschnitten werden!



        FILE *fp1;
        char str1[2028];
        char ps1[2028];
        char p1[2028];
        char* tokenset1 ;
        char* token1 ;
        #define BUFF_SIZE 80001
        #define RD_BLOCK_SIZE 128
        char szBuffer1[2028];
        char szBufferNew1[2028];
        char szBufferNew2[2028];
        char szBufferMes[2028];
        int iLen1;
        int iLenNeu1;
        int i;
        float t;



        float nEvents;

        while(TRUE)
        {
        nEvents = getinput(0);
        if (nEvents !=NULL)
        {


        /* opening file for reading */
        fp1 = fopen("/user/common/smaxtoken.xml", "r");
        fgets(str1, 2028, fp1);
        /* writing content to stdout */
        // puts(str);

        setoutputtext(0,str1);
        printf(str1);

        p1 = strstr(str1,"token");

        tokenset1 = strstrskip(p1,"token");



        setoutputtext(1,tokenset1);

        ps1 = strstr(tokenset1,":"");

        token1= strstrskip(p1,":"");


        strcpy(szBuffer1,token1);
        iLen1 = strlen(szBuffer1);
        setoutput(1,iLen1);
        strncpy(szBufferNew1,szBuffer1,iLen1-3);
        iLenNeu1 = strlen(szBufferNew1);

        setoutputtext(2,szBufferNew1);
        printf(szBufferNew1);

        i++;
        setoutput(0,i);

        setoutput(2,iLenNeu1);



        fclose(fp1);

        free (szBuffer1);
        free (szBufferNew1);


        setoutput(3,1);
        }


        sleeps(30);
        if (nEvents ==NULL)
        { setoutput(3,0);
        setoutputtext(2,NULL);
        sleeps(30); }
        }




        Zuletzt geändert von Rick_Pa_87; 15.09.2023, 07:18.

        Kommentar

        • Tico
          Lox Guru
          • 31.08.2016
          • 1035

          #5
          Hallo Rick_Pa_87. Würden Sie bitte den Inhalt der Datei smaxtoken.xml veröffentlichen (verbergen Sie die vollständigen Token-Informationen für Ihre Privatsphäre).

          Das Forum Tool # (insert [CODE] code) oben kann helfen, die Formatierung zu erhalten.
          Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

          Kommentar

          • Labmaster
            Lox Guru
            • 20.01.2017
            • 2592

            #6
            Zitat von Rick_Pa_87
            Ich kann nur dazu sagen das bei printf die länge passt und bei der Ausgabe über setoutputtext(0,outTxtBuffer) und anschließender Weiterverarbeitung die letzten x stellen abgeschnitten werden!
            ...

            while(TRUE)
            {
            nEvents = getinput(0);
            if (nEvents !=NULL)
            {

            }
            ...
            Das glaub ich gerne, denn alleine mit der Auslegung des Event Handlings befindest du dich in einer Dauerschleife die pro Durchlauf aber vermutlich viel zu lange ist um sie komplett abarbeiten zu können.
            Selbst wenn die Auswertung eines Eingang mit NULL Vergleich funktionieren würde, dann wäre dies Pegelgetriggert und nicht Flankengetriggert was hintereinander zu Mehrfachdruchläufen führen würde.

            Bei dem Code wird wohl auch der Miniserver anderweitig irgendwann instabil werden.

            Schau dir mal explizit die funktion getinputevent(); und deren Ausgabe an, also wie die Bits auszuwerten sind.

            Oberste Priorität bei Miniserver PicoC Programmen ist den Durchlauf zu optimieren und die Zeiten möglichst kurz und selten zu halten, hierzu gehört gut geplantes Event handling und auch das Sparen von Speicherresourcen.

            Also bei Reaktion ist der Grundsatz, hier erst mal immer das Auswerten ob sich ein oder mehrere spezifische Eingänge geändert haben, das geschiet ausschließlich mit getinputevent();​ oder aber dem Abfragen eines spezifischen Werts eines Eingang (aber nicht mit != NULL, das ist eigentlich immer Wahr)
            ich würde trotzdem immer ein getinputevent​() davor setzen, da man damit alle Eingänge auf einmal auf Änderung bekommt und dann erst ganz spezifisch einzelnen Eingänge einlesen/updaten kann und so explizit eine Signalflanke und kein Signalpegel ausgewertet wird.

            Wenn man partou getinputevent() nicht verwenden möchte, dann könnte man sich den zuletzt gelesenen Input auch zwischenspeichern und bei jedem Durchlauf mit dem aktuell vergleich und dann weiteren Code nur ausführen wenn diese beiden unterschiedlich sind. (also auch wieder quasi eine Flanken (Änderungs) Detektion)

            Auch die Sleep Zeit von 30 ist je nach Durchlaufhäufigkeit grenzwertig, denn diese bestimmt im Wesentlichen wieviel Restezeit vorzeitig ins MS Hauptsystem zurück gegeben werden kann.

            Wenn man mit PicoC im MS anfängt sollte man sich vorab ein gutes Event/Zeit Konzept einfallen lassen um dieses dann ordentlich umzusetzen.
            Der Minissever ist schließtlich eine Art SPS mit fixen Zeitscheiben in die sich das intergrieren muß.
            Zuletzt geändert von Labmaster; 15.09.2023, 09:05.

            Kommentar

            • Tico
              Lox Guru
              • 31.08.2016
              • 1035

              #7
              Ich habe den von Labmaster bereitgestellten Code ausprobiert (mit einigen geringfügigen Änderungen).

              Code:
              ​char singleString[] = "a";
              char outTxtBuffer[3000];
              unsigned int cnt;
              int nEvents;
              
              strcpy(outTxtBuffer, singleString);
              for (cnt=0; cnt<=2000; cnt++)
              {
                  strcat(outTxtBuffer, singleString);
              }
              
              while(true)
              {
                  nEvents = getinputevent();
                  if (nEvents & 0x08) // check for change on "Input 1" (Bit 4)
                  {
                      setoutputtext(0,outTxtBuffer);
                  }
              
                  sleep(100);
              
              }​



              Soweit ich das beurteilen kann, beträgt die maximale Zeichenausgabe des Programmblocks 1023 Zeichen. Entweder das, oder der Statusblock ist auf die Anzeige von 1023 Zeichen beschränkt.

              Wie Rick_Pa_87 beobachtet hat, scheint die virtuelle Texteingabe eine weitaus größere Grenze zu haben. Ich habe erfolgreich eine 1740-Zeichen-Zeichenfolge über einen VTI für Authentifizierungszwecke verwendet.

              Hallo zusammen, lese seit langem mit und hatte jetzt endlich den Anlass gefunden auch mal was zu schreiben. Ich habe angefangen einen node für node-red zur
              Zuletzt geändert von Tico; 16.09.2023, 03:18.
              Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

              Kommentar


              • Tico
                Tico kommentierte
                Kommentar bearbeiten
                Ich kann klarstellen, dass der Statusblock keine Zeichenbeschränkung zu haben scheint. Bei Verwendung der oben erwähnten verlinkten Node-Red-Methode zeigt der Statusblock 1960 Zeichen eines OAuth-Tokens an. Die Obergrenze wurde nicht gefunden.

                Die Obergrenze von 1023 Zeichen scheint für den Programmblock zu gelten.
            • Rick_Pa_87
              Dumb Home'r
              • 04.08.2022
              • 17

              #8
              Gibt es einen Möglichkeit den VTI aus dem Programmbaustein zu beschreiben wie es der Node Flow macht? Da mit printf ja auch die korrekte länge ausgegeben wird.

              Kommentar

              • Labmaster
                Lox Guru
                • 20.01.2017
                • 2592

                #9
                Rick_Pa_87

                Du könntest es über die Miniserver http API (webservice) machen, also per PicoC dorthin schreiben;:

                Code:
                http://user:password@ip:port/dev/sps/io/VTIx/text
                ( VTIx <= VTI Nummer des Virtuellen inputs wie in der Loxone Config angelegt )

                siehe auch https://www.loxone.com/dede/kb/webservices/

                Schreiben aus PicoC

                Code:
                #define TCPDEVICE "xxxxx..."
                #define SIZE x
                
                char pTcpCmd[SIZE];​
                
                STREAM* pTcpStream = stream_create(TCPDEVICE, 0, 0)
                stream_write(pTcpStream, pTcpCmd, strlen(pTcpCmd))
                stream_flush(pTcpStream)
                stream_close(pTcpStream)
                ​
                Zuletzt geändert von Labmaster; 20.09.2023, 06:38.

                Kommentar

                • Tico
                  Lox Guru
                  • 31.08.2016
                  • 1035

                  #10
                  Habe das gerade in den Versionshinweisen für Config v14.4 Beta 4 bemerkt -

                  BG-I25997 Programm: Längenbegrenzung für PicoC-Textausgabe auf 4096 Bytes erhöht (von 1023)​

                  Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

                  Kommentar

                  • Tico
                    Lox Guru
                    • 31.08.2016
                    • 1035

                    #11
                    Hello Labmaster. Now the Config v14.4.9.25 is released and supports 4096 bytes from the setoutputtext. I'm trying to 'in-source' an external logic on a Raspberry Pi into the Miniserver logic. My use-case is exactly the same as the intent of the script in this thread. That is to extract a multi-character token from a file saved internally on the Miniserver and set it at the Txt1 output.

                    I'm attempting to modify the script at the beginning of this thread (Post #4) but have little clue with PicoC. I have altered the code to adjust to my application. My file has one instance of the term IDToken and looks like this in the file -

                    "IdToken":"eyJra......etc." (1960 character token)

                    Original line: fp1 = fopen("/user/common/smaxtoken.xml", "r");
                    Altered line: fp1 = fopen("/user/common/zodiac_token.json", "r");

                    Original line:
                    p1 = strstr(str1,"token");
                    tokenset1 = strstrskip(p1,"token");

                    Altered line:
                    p1 = strstr(str1,"IDToken");
                    tokenset1 = strstrskip(p1,"IDToken");


                    This results in the following error -

                    Klicke auf die Grafik für eine vergrößerte Ansicht  Name: PicoC block.png Ansichten: 0 Größe: 10,0 KB ID: 405326


                    Any hints on what to look for? I've consulted ChatGPT but the suggested code ends with ongoing and different error descriptions.

                    edit: ChatGPT says the error occurs because "you are trying to assign a value to a character array (ps1) using the strstr function, which returns a pointer to the first occurrence of the specified substring in the given string. You cannot directly assign a pointer to a character array in C. To fix this issue, you need to use strcpy or strncpy to copy the content of the tokenset1 pointer to the ps1 character array.​"​

                    Full code below -

                    Code:
                    FILE *fp1;
                    char str1[2028];
                    char ps1[2028];
                    char p1[2028];
                    char* tokenset1 ;
                    char* token1 ;
                    #define BUFF_SIZE 80001
                    #define RD_BLOCK_SIZE 128
                    char szBuffer1[2028];
                    char szBufferNew1[2028];
                    char szBufferNew2[2028];
                    char szBufferMes[2028];
                    int iLen1;
                    int iLenNeu1;
                    int i;
                    float t;
                    
                    float nEvents;
                    
                    while(TRUE)
                    {
                    nEvents = getinput(0);
                    if (nEvents !=NULL)
                    {
                    
                    /* opening file for reading */
                    fp1 = fopen("/user/common/zodiac_token.json", "r");
                    fgets(str1, 2028, fp1);
                    /* writing content to stdout */
                    // puts(str);
                    
                    setoutputtext(0,str1);
                    printf(str1);
                    
                    p1 = strstr(str1,"IDToken");
                    
                    tokenset1 = strstrskip(p1,"IDToken");
                    
                    setoutputtext(1,tokenset1);
                    
                    ps1 = strstr(tokenset1,":"");
                    
                    token1= strstrskip(p1,":"");
                    
                    strcpy(szBuffer1,token1);
                    iLen1 = strlen(szBuffer1);
                    setoutput(1,iLen1);
                    strncpy(szBufferNew1,szBuffer1,iLen1-3);
                    iLenNeu1 = strlen(szBufferNew1);
                    
                    setoutputtext(2,szBufferNew1);
                    printf(szBufferNew1);
                    
                    i++;
                    setoutput(0,i);
                    
                    setoutput(2,iLenNeu1);
                    
                    fclose(fp1);
                    
                    free (szBuffer1);
                    free (szBufferNew1);
                    
                    setoutput(3,1);
                    }
                    
                    sleeps(30);
                    if (nEvents ==NULL)
                    { setoutput(3,0);
                    setoutputtext(2,NULL);
                    sleeps(30); }
                    }​
                    Zuletzt geändert von Tico; 30.09.2023, 05:54.
                    Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

                    Kommentar

                    • Jan W.
                      Lox Guru
                      • 30.08.2015
                      • 1398

                      #12
                      @Tico: I'm not sure what substring you are searching for. Is it :" ? Then the quote symbol needs to be escaped with a backslash, see https://stackoverflow.com/questions/...te-in-c-string
                      The resulting line of code would be
                      Code:
                      ps1 = strstr(tokenset1,":\"");
                      (same two lines below)

                      EDIT: it look that pasting in code as normal text with backslash in the forum would result in loosing the backslash. After I have enclosed the code with the code brackets, I got the expected result. That might be the reason why the code from # 4 (that seems to have worked) would result in invalid code when you've copied the code.
                      Zuletzt geändert von Jan W.; 30.09.2023, 10:14.
                      Miniserver v14.5.12.7, 2x Ext., 2x Relay Ext., 2x Dimmer Ext., DMX Ext., 1-Wire Ext., Gira KNX Tastsensor 3 Komfort, Gira KNX Präsenzmelder, Fenster- und Türkontakte, Loxone Regen- und Windsensor, Gira Dual Q Rauchmelder vernetzt, 1x Relais-Modul
                      Loxberry: SmartMeter, MS Backup, CamConnect, Weather4Lox
                      Lüftung: Helios KWL EC 370W ET mit Modbus TCP - via Pico-C
                      Heizung: Stiebel Eltron WPF 5 cool (Sole-Wasser WP) mit ISG, FB-Heizung mit 18 Kreisen, Erdsonde - via modbus/TCP
                      Node-RED: IKEA Tradfri

                      Kommentar

                      • Tico
                        Lox Guru
                        • 31.08.2016
                        • 1035

                        #13
                        Thanks Jan W.

                        I corrected the two lines that appear to have been corrupted by the forum -
                        Code:
                        ps1 = strstr(tokenset1,":\"");
                        
                        token1 = strstrskip(p1,":\"");​
                        That has resolved the error displayed. Unfortunately, I don't get the IDToken displayed at the Txt1 output. The program doesn't appear to do anything.

                        I also assumed the code worked in Post #4. However, I don't know if there's anything special about the file the program was built to use. My file has lots of random text before the token I wish to extract. The specific text that I need to identify is "IdToken":"eyJraWQiOiJsM3V0VHAyZGJReGtyalF.... (cha racters removed for brevity)....SrEZNQ"

                        The text "IDToken" only appears once in my file -
                        Code:
                        ....29A.U3ABrBUFGxQPTMRqfS3zYQ","IdToken":"eyJraWQiOiJsM3V0VHAyZGJReGtyalFMc....
                        ..
                        I need the text output eyJraWQiOiJsM3V0VHAyZGJReGtyalF........SrEZNQ (composed of a 1960 character token).

                        I also don't understand whether the program runs continuously or needs a trigger to start.​
                        Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

                        Kommentar

                        • Jan W.
                          Lox Guru
                          • 30.08.2015
                          • 1398

                          #14
                          Hi Tico,
                          it looks that the missing backslash might not be the only problem. I really like Pico C and have used it for two programs (Helios ventilation system for tricky modbus integration and average wind speed) in my Loxone installation that runs for about 9 years now. Due to limited information, e.g. about the content of the file zodiac_token.json, I may only be able to help you solving the problem to extract the token from the file. Here's some example code for a matching pico c program:

                          Code:
                          FILE *fp1;
                          char str1[4095];
                          char *tokenStart;
                          char *tokenEnd;
                          char token[4095];
                          const char IDtoken[20] = "\"IdToken\":\"";
                          int len;
                          int nEvents;
                          
                          while(TRUE)
                          {
                              nEvents = getinputevent();
                              if (nEvents & 0x08)             // check for change on analogue input 1 (Bit 4) - this is only used as a trigger to run following code
                              {
                                  fp1 = fopen("/user/common/zodiac_token.json", "r");  // open file with token for read
                                  fgets(str1, 4095, fp1);     // copy content of file to string, max. 4094 bytes plus trailing 0
                          
                                  tokenStart = strstr(str1, IDtoken);       // search for IDtoken in string
                                  if (tokenStart != NULL) {
                                      tokenStart += strlen(IDtoken);        // if found then add length of token itself
                                      tokenEnd = strstr(tokenStart, "\"");  // search for final quotation symbol
                                      if (tokenEnd != NULL) {
                                          len = tokenEnd - tokenStart;      // if found then calculate length of token
                                          strncpy(token, tokenStart, len);  // copy n bytes from string to token starting from begin of token
                                          token[len] = 0;                   // add trailing 0 to token string
                                          setoutput(0,len);                 // set analogue output 1 to length of token
                                          setoutputtext(0,token);           // set text output 1 to token
                                      }
                                  } else {
                                      setoutputtext(0,"");                  // clear output if no token is found              
                                      setoutput(0,0);
                                  }
                              }
                                  fclose(fp1);
                              }
                              sleep(500);                                   // sleep for half a second  
                          }​​
                          To run the program, you need a trigger on the AI1, but that input is not used in the program itself. I have no idea, if the token needs to be cleared in the output when no token is found, but the code has some comments and may be a good starting point. Labmaster is right, that the code needs to be efficient and should not run too often to consume as little CPU cycles as needed. I've changed the sleep timer from 30 seconds to 0,5 seconds, but have included an event checker (getinputevent), so the code only consumes a few cycles if there is no change on AI1. A "free" function is only required if dynamic memory is allocated, but not for static strings.

                          I haven't tested the code on my MS so there might be still a syntax error in the code, but without a proper token file and and a connection to a system that requires that token, it would make no sense. However I've tested the main logic code statements online at https://www.tutorialspoint.com/compile_c_online.php with the following code

                          Code:
                          #include <stdio.h>
                          #include <string.h>
                          
                          char str1[4095] = "The specific text that I need to identify is \"IdToken\":\"eyJraWQiOiJsM3V0VHAyZGJReGtyal .... (characters removed for brevity)....SrEZNQ\"bla bla";
                          char *tokenStart;
                          char *tokenEnd;
                          char token[4095];
                          const char IDtoken[20] = "\"IdToken\":\"";
                          int len;
                          
                          int main () {
                                  tokenStart = strstr(str1, IDtoken);
                                  if (tokenStart != NULL) {
                                      tokenStart += strlen(IDtoken);
                                      tokenEnd = strstr(tokenStart, "\"");
                                      if (tokenEnd != NULL) {
                                          len = tokenEnd - tokenStart;
                                          strncpy(token,tokenStart, len);
                                          token[len] = 0;
                                          printf("The token is: >>>%s<<<\n", token);
                                      } else
                                          printf("IDtoken found, but no quotation at the end");
                                  } else
                                      printf("IDtoken not found\n");
                          }​
                          I was surprised that Loxone has extended the length in setoutputtext in v14.4.9.25, and hope that the code might help to solve your problem and may also help to improve the code for Rick_Pa_87.
                          Zuletzt geändert von Jan W.; 01.10.2023, 11:27.
                          Miniserver v14.5.12.7, 2x Ext., 2x Relay Ext., 2x Dimmer Ext., DMX Ext., 1-Wire Ext., Gira KNX Tastsensor 3 Komfort, Gira KNX Präsenzmelder, Fenster- und Türkontakte, Loxone Regen- und Windsensor, Gira Dual Q Rauchmelder vernetzt, 1x Relais-Modul
                          Loxberry: SmartMeter, MS Backup, CamConnect, Weather4Lox
                          Lüftung: Helios KWL EC 370W ET mit Modbus TCP - via Pico-C
                          Heizung: Stiebel Eltron WPF 5 cool (Sole-Wasser WP) mit ISG, FB-Heizung mit 18 Kreisen, Erdsonde - via modbus/TCP
                          Node-RED: IKEA Tradfri

                          Kommentar

                          • Tico
                            Lox Guru
                            • 31.08.2016
                            • 1035

                            #15
                            Thanks Jan W. I'll check it out this week.
                            Ich spreche kein Deutsch. Gib Google Translate die Schuld, wenn ich unverständlich bin.

                            Kommentar

                            Lädt...