Neueste Beiträge

Seiten: 1 ... 4 5 [6] 7 8 ... 10
51
oscat.lib fuer CoDeSys 3 / Re: FTP funktioniert mit OSCATNetwork nicht
« Letzter Beitrag von mauskopf am 13. Oktober 2022, 10:41:40 »
Habe ich was falsch gemacht bei meiner Frage Stellung?
52
oscat.lib fuer CoDeSys 3 / FTP funktioniert mit OSCATNetwork nicht
« Letzter Beitrag von mauskopf am 13. Oktober 2022, 09:35:21 »
Guten Morgen,
ich bin ganz neu hier.
Ich habe mir die OSCATNetwork LIB geholt da ich die Notwendigkeit habe von meiner Berghof SPS per FTP ein CSV File zu übertragen.
Leider mache ich Irgendwas falsch da es nicht funktioniert.

Ich bekomme folgende Fehler Meldung.
ERROR_C gibt 16#FF000000
ERROR_T gibt 16#03

Was mache ich falsch bzw wie kann ich den Fehler debugen?
53
Modulentwicklung / Re: Neuer Baustein zum Parsen von JSON-Streams
« Letzter Beitrag von mattsches am 11. Oktober 2022, 20:41:56 »
Update, falls jemand außer mir den Baustein im Einsatz haben sollte: Das gute Stück kam nicht mit negativen Werte und leeren Objekten ( {} )  klar, wie mir erst jetzt aufgefallen ist, wo ich ebenfalls einen Fronius-Wechselrichter damit anzapfen wollte. Anbei eine überarbeitete Version, mit der das bei mir nun funktioniert. Ursprünglich wollte ich eine Datei anhängen, doch die Funktion hier im Forum scheint abgedreht worden zu sein. Daher etwas umständlicher als Quelltext:

Deklaration:
FUNCTION_BLOCK JSON_READER
VAR CONSTANT
MAX_LEVEL : UINT := 19;
END_VAR

VAR_INPUT
RST : BOOL := TRUE; (* reset *)
WATCHDOG : TIME := t#1ms; (* watchdog time *)
START_POS : UINT := 0; (* first byte in network buffer to be processed *)
STOP_POS : UINT := 0; (* last byte in network buffer to be processed *)
BUF : NW_BUF_LONG; (* network buffer that contains the JSON string as byte stream *)
END_VAR

VAR_OUTPUT
COUNT : UINT := 0; (* number of parsed JSON elements *)
LEVEL : UINT := 0; (* nesting level of current JSON element *)
ARRAY_INDEX : ARRAY[1..MAX_LEVEL] OF INT := MAX_LEVEL(-1); (* current array index value (-1: element is not part of an array) *)
PATH : STRING(STRING_LENGTH); (* full path of current JSON element *)
ELEMENT : STRING(STRING_LENGTH); (* name of current JSON element *)
VALUE : STRING(STRING_LENGTH); (* value of current JSON element *)
NEW_DATA : BOOL := FALSE; (* new data is available (next element has been parsed *)
DONE : BOOL := FALSE; (* last element has been parsed *)
ERROR : BOOL := FALSE; (* error occured, see status for details; reset is required *)
STATUS : BYTE := 0; (* ESR compatible status output ( 0=ok,
  1=error: dot not found in path string,
  2=error: closing square bracket not found in path string,
  3=max. nesting level exceeded,
100=element has been parsed,
101=watchdog timer expired *)
END_VAR

VAR
CurrentByte : UINT; (* index of currently scanned byte in network buffer *)
ObjectEmpty : BOOL := FALSE; (* current object is still empty *)
LookForValue : BOOL := FALSE; (* colon has been found, now look for value *)
FirstByte : UINT := 0; (* first byte of string to be extracted from buffer *)
LastByte : UINT := 0; (* last byte of string to be extracted from buffer *)
ElementParsed : BOOL := FALSE; (* element has been parsed *)
PathOverflow : BOOL := FALSE; (* maximum string length exceeded for path variable *)

StringFound : INT := 0; (* position of string within another string *)
LoopCount : INT := 0; (* loop counter *)
WatchdogTimer : TON; (* watchdog timer *)

_Level : UINT := 0; (* nesting level of current JSON element *)
_Path : STRING(STRING_LENGTH); (* full path of current JSON element *)
_ArrayIndex : ARRAY[1..MAX_LEVEL] OF INT := MAX_LEVEL(-1); (* current array index value (-1: element is not part of an array) *)
_Element : STRING(STRING_LENGTH); (* name of current JSON element *)
_Value : STRING(STRING_LENGTH); (* value of current JSON element *)

pValueString : POINTER TO ARRAY[0..STRING_LENGTH] OF BYTE;
END_VAR


(*

version 1.1 11 oct 2022
programmer md
tested by md

JSON_READER allows to parse a JSON string stored in a byte array (buffer) and extract the JSON elements one after another.

The parsing is monitored by a watchdog timer such that the block does cause a delay of the PLC program of more than the
configured time. The block further automatically interrupts the parsing as soon as an element and its value have been found.
It then provides both at the CTRL structured variable for external processing and continues to search for the next element
when it is called again (next cycle).

Values are always provided as strings, conversion to numeric data types needs to be done by the calling program.

*)


Code:
(* reset/initialize *)
IF RST THEN
CurrentByte := START_POS;
ObjectEmpty := FALSE;
LookForValue := FALSE;
FirstByte := 0;
LastByte := 0;

FOR LoopCount := 1 TO MAX_LEVEL DO
_ArrayIndex[LoopCount] := -1;
END_FOR

ElementParsed := FALSE;
PathOverflow := FALSE;

_Level := 0;
_Element := '';
_Path := '';
_Value := '';

COUNT := 0;
LEVEL := 0;
ELEMENT := '';
PATH := '';
VALUE := '';
NEW_DATA := FALSE;
DONE := FALSE;
ERROR := FALSE;
STATUS := 0;
END_IF;


(* reset watchdog timer *)
WatchdogTimer(IN:=FALSE , PT:= WATCHDOG, Q=> , ET=> );

(* reset new data flag *)
NEW_DATA := FALSE;

(* loop through buffer until buffer end reached OR element has been parsed OR watchdog timer has expired *)
WHILE (CurrentByte <= STOP_POS AND NOT ElementParsed AND NOT WatchdogTimer.Q AND NOT ERROR AND NOT RST AND NOT DONE) DO

WatchdogTimer(IN:=TRUE , PT:= WATCHDOG, Q=> , ET=> ); (* call watchdog timer *)

CASE BUF[CurrentByte] OF (* evaluate current character *)

0: (* end of string *)
DONE := TRUE;

123: (* '{' object start *)
IF _Level < MAX_LEVEL THEN
_Level := _Level + 1;
ObjectEmpty := TRUE;
LookForValue := FALSE;
FirstByte := 0;
_Element := '';
_Value := '';
ELSE
ERROR := TRUE;
STATUS := 3;
END_IF

125: (* '}' object end *)
IF LookForValue AND _Value <> '' THEN (* element has been parsed *)
ElementParsed := TRUE;
EXIT; (* exit loop immediately in order to first copy the element details to the output parameters *)
END_IF

IF _Level > 1 AND NOT PathOverflow THEN
_Element := '';
_Value := '';
_Level := _Level - 1; (* up one level *)
LookForValue := FALSE; (* next string must be a key, not a value *)
FirstByte := 0;

IF NOT ObjectEmpty THEN (* don't change path if current object is still empty, i. e. nothing has been appended to the path before *)
StringFound := FINDB(_Path, '.');
IF StringFound > 1 THEN
_Path := LEFT(_Path, StringFound - 1); (* remove last element from path string *)
ELSE (* error: dot has not been found *)
ERROR := TRUE;
STATUS := 1;
END_IF
END_IF

ObjectEmpty := FALSE;
END_IF

91: (* '[' array start *)
IF LEN(_Path) + 3 < STRING_LENGTH AND NOT PathOverflow THEN
_Path := CONCAT(_Path, '[0]'); (* append array index to path *)
ELSE
_Path := 'OVERFLOW';
PathOverflow := TRUE;
END_IF
_Element := CONCAT(_Element, '[0]'); (* append array index to path *)
_ArrayIndex[_Level] := 0; (* array index *)

93: (* ']' array end *)
IF LookForValue AND _Value <> '' THEN (* element has been parsed *)
ElementParsed := TRUE;
EXIT; (* exit loop immediately in order to first copy the element details to the output parameters *)
END_IF

IF NOT PathOverflow THEN
StringFound := FINDB(_Path, '[');
IF StringFound > 1 THEN (* remove array index from path string *)
_Path := LEFT(_Path, StringFound - 1);
_Element := LEFT(_Element, FINDB(_Path, '[') - 1);
_Value := '';
_ArrayIndex[_Level] := -1; (* reset array index *)
ELSE (* error: opening square bracket has not been found *)
ERROR := TRUE;
STATUS := 2;
END_IF
END_IF


58: (* ':' key delimiter *)
LookForValue := TRUE;

44: (* ',' element delimiter *)
IF LookForValue AND _Value <> '' THEN (* element has been parsed *)
ElementParsed := TRUE;
EXIT; (* exit loop immediately in order to first copy the element details to the output parameters *)
END_IF

IF RIGHT(_Path, 1) = ']' THEN (* previous element is part of an array *)
IF LEN(LEFT(_Path, FINDB(_Path, '['))) + LEN(INT_TO_STRING(_ArrayIndex[_Level] + 1)) + 1 <= STRING_LENGTH THEN
_ArrayIndex[_Level] := _ArrayIndex[_Level] + 1; (* increment array index *)
_Path := LEFT(_Path, FINDB(_Path, '['));
_Path := CONCAT(_Path, INT_TO_STRING(_ArrayIndex[_Level]));
_Path := CONCAT(_Path, ']');
ELSE
_Path := 'OVERFLOW';
PathOverflow := TRUE;
END_IF
ELSE (* previous element is not part of an array *)
StringFound := FINDB(_Path, '.');
IF StringFound > 1 THEN (* remove last element from path string *)
_Path := LEFT(_Path, StringFound - 1);
ELSE (* previous element was root, empty path variable *)
_Path := '';
END_IF
_Element := '';
_Value := '';
END_IF

34: (* '"' quotation mark *)
IF FirstByte = 0 THEN
FirstByte := CurrentByte + 1;
ELSE
IF NOT LookForValue THEN (* key has been parsed *)
ObjectEmpty := FALSE;
_Element := BUFFER_TO_STRING(PT:=ADR(BUF),SIZE:=STOP_POS + 1,START:=FirstByte,STOP:=CurrentByte - 1);
IF _Path = '' THEN (* path empty, use element as root for path *)
_Path := _Element;
ELSE (* append key to path *)
IF LEN(_Path) + LEN(_Element) + 1 <= STRING_LENGTH THEN
_Path := CONCAT(_Path, '.');
_Path := CONCAT(_Path, _Element);
ELSE
_Path := 'OVERFLOW';
PathOverflow := TRUE;
END_IF
END_IF
ELSE (* value has been parsed *)
_Value := BUFFER_TO_STRING(PT:=ADR(BUF),SIZE:=STOP_POS + 1,START:=FirstByte,STOP:=CurrentByte - 1);
ElementParsed := TRUE;
END_IF
FirstByte := 0;
END_IF

45, 48..57, 46, 110, 117, 108: (* minus, numbers and dot + characters for "null" (not as string but as null value *)
IF LookForValue AND FirstByte = 0 THEN
pValueString := ADR(_Value);
pValueString^[LEN(_Value) + 1] := 0;
pValueString^[LEN(_Value)] := BUF[CurrentByte];
END_IF

END_CASE
CurrentByte := CurrentByte + 1; (* proceed to next byte *)

END_WHILE

IF ElementParsed THEN
ElementParsed := FALSE;
LookForValue := FALSE;
COUNT := COUNT + 1; (* copy output values to interface *)
LEVEL := _Level;
PATH := _Path;
ARRAY_INDEX := _ArrayIndex;
ELEMENT := _Element;
VALUE := _Value;
NEW_DATA := TRUE;
STATUS := 100;
END_IF

IF CurrentByte > STOP_POS THEN (* end of string to be parsed reached *)
DONE := TRUE;
ELSIF WatchdogTimer.Q THEN
STATUS := 101;
END_IF


(* revision history
md 10 Jul 2019 rev 1.0
original version

md 11 Oct 2022 rev 1.1
fixed negative values not being recognized
fixed empty objects breaking path handling
*)

Wie cool wäre es, das über Github machen zu können...
54
Codesys 2 / Re: Messenger Telegramm (API) versenden per HTTP
« Letzter Beitrag von annD am 05. Oktober 2022, 08:09:24 »
Hallo Trud,

gute Info und Idee von dir. Funktioniert irgendeine andere Webfunktion (Weather, usw.) auf deinem System?
Wenn ich Zeit finde, würde ich das Senden von Telegram-Nachrichten bei mir testen, weil ich das vom IoBroker ohnehin laufend verwende.

Gruß annD
55
Codesys 2 / Messenger Telegramm (API) versenden per HTTP
« Letzter Beitrag von trud am 01. Oktober 2022, 15:39:01 »
Hallo Zusammen,

ich möchte gerne via OSCAT eine Nachricht via Telegramm Messenger versenden. Hierzu bietet sich ein Telegramm Bot via API an.

Bot ist eingerichtet und funktioniert auch. Hierzu hatte ich bereits schon die LIB von Codesys IIot verwendet, allerdings möchte ich aus Kostengründen diese nicht lizenzieren.


Um eine Nachricht via HTTP zu versenden genügt es via API lediglich ein HTTP Request zusenden - z.B.:

https://api.telegram.org/(BOT_NAME):(TOKEN)/sendMessage?chat_id=(CHAT-ID)&text=Hallo

BOT-NAME, TOKEN und CHAT-ID durch die eigenen Kennungen ersetzen

Sobald dies zb. im Explorer eingegeben wird, wird die Nachricht gesendet....

Ich habe diese Adresse als URL in HTTP-Demo eingesetzt, aber nichts geht... Das Programm habe ich in den Task eingefügt.


Ich habe mir hierzu die Weather und HTTP Demos angeschaut, allerdings bekomme ich es nicht hin, dass eine Nachricht gesendet wird.

Selbst im DEMO Programm GET_WAN bekomme ich keine Adresse... obwohl ich hier den DNS meines Routers eingetragen habe. Internetverbindung besteht!



Verwendete Hardware: Raspberry Pi (Lizenzierte Runtime)
Codesys-Version: 3.5 P18
OSCAT Basic: 3.3.4.0
OSCAT Network: 1.3.5.2

Hat von euch schon jemand eine Telegramm Message versendet?

56
oscat.lib fuer TwinCAT/CoDeSys / Heat_Meter Max Zählerstand
« Letzter Beitrag von tiego am 29. September 2022, 21:15:22 »
Hallo,
erstmals vielen dank euch für die Entwicklung und Pflege der Biblioteken, sie helfen mir sehr weiter, vor allem mir als Anfänger.

Meine fragen zum Heat_Meter und Flow_Meter Baustein:
 -> Was ist der Maximale Wert (Ausgang Y) welchen der Zähler ausgeben kann?
      Ich habe aktuell 256.845.000 Wh (924.642.000.000 J) und mir kommt vor als würde die Zählung bei kleinem Verbrauch nicht mehr richtig
      funktionieren. Kann das sein?
      oder wäre es möglich den Baustein umzuschreiben das er Funktioniert wie der Flow_Meter welcher die Ganzzahlen als UDint und die Komastellen als
      Real ausgibt?

-> Die Ausgabe der Aktuellen Leistung (Ausgang C) ist bei mir sehr sprunghaft,...
     Welche Einstellung sollte hier bei "AVG_TIME" gemacht werden bei einem Zähler der alle 0,25l einen Impuls ausgibt?
     Die selbe Frage habe ich bei den Flow_Meter welchen ich bei der Fernwärme und Wasserverbrauch einsetze:
     A. 1000Wh      ein Impuls
     B.        10l      ein Impuls
     C.          0,25l ein Impuls
     Was wären den hier die optimalen Einstellungen für "UPDATE_TIME" ?

P.s. nur so als Notiz: um beim Ausgang C auf W zu kommen dividiere ich den Wert durch 3600
                              um beim Ausgang Y auf Wh zu kommen dividiere ich den Wert durch 3600
                               das ist so Richtig oder?

Danke wenn Ihr mir hier weiterhelft.




57
oscat.lib fuer PC WorX/MULTIPROG / Re: PC WORX: SMTP_CLIENT geht mit GMX nicht mehr?
« Letzter Beitrag von cole_joos am 23. September 2022, 22:11:50 »
Hello, has anyone figured this out? I am trying to use the SMTP_CLIENT function block and it gets stuck on step 40..
I know this isn't the best, but I commented the conditional in the IF in step 40 "IF ssl_mode >= BYTE#1 AND TON_WAIT.ET > T#1s THEN"
and then it gets stuck on step 1110 and the rcv_text is "520 5.7.0 Must issue a STARTTLS command first.m41-20....... - gsmtp"

My URL is "TLS://username:password@smtp.gmail.com:587"
I am able to ping smtp.gmail.com with the device without issue.

What can I try to get this to work?
Do I have to find a SMTP server that uses port 25 without encryption?
58
oscat.lib fuer CoDeSys 3 / Re: SysSockClose Raspberry PI
« Letzter Beitrag von RCD am 22. September 2022, 19:25:20 »
Hallo,
ich habe das gleiche Problem.
Doch leider kann ich das Bild und den Anhang von mg nicht mehr sehe.
Dort steht [gelöscht durch Administrator]
Wer kann helfen?

Besten Dank!

Gruß Stefan
59
oscat.lib fuer TwinCAT/CoDeSys / neue Blind_shade probleme
« Letzter Beitrag von Peliphan am 08. September 2022, 15:02:24 »
Hi,
ich habe mal wieder ein wenig optimieren wollen an meiner Raffstore Steuerung.
konkret wollte ich bei den derzeit hohen Außentemperaturen so wenig sonne wie nötig in die Wohnung lassen.

mein Ziel war also die Beschattung so nachzufahren so dass eine komplette Beschattung gegeben ist.
 Da ich immer wieder ein paar kleine "dünne" Sonnenstreifen auf meinem Boden abgebildet hatte habe ich mit der Feinjustierung begonnen. (wenn man frei hat dann hat man für solche Spielchen ja Zeit...)

Eigentlich ist jetzt alles super, habe mit den Werten
- slat_width
- slat_spacing
ein wenig nachjustiert so dass nun alles super ist.

Was mir leider unerklärlich ist, ist die Ursache dafür dass nach der Beschattung der Raffstore nicht hochfährt sondern komplett beschattet.
ich hatte diese Problem vorher nicht, bekomme es aber auch mit dem "zurückstellen" der Parameter nicht mehr gelöst.
ich habe bereits die komplette Steuerung zurückgesetzt und das Program neu aufgespielt in der Hoffnung dass dies evtl. die Lösung ist.

hat irgendwer eine idee wo ich hier noch suchen könnte?
mir fällt leider nichts mehr ein.
Mastermode an Blind_input = TRUE


bin wie immer für jede Hilfe Dankbar.

Gruß und Danke
Peli
 
60
Codesys 2 / Re: DLOG_STORE_FILE_CSV append
« Letzter Beitrag von laruso am 24. August 2022, 13:39:53 »
After a deep dive into the code I understand a few things and found a solution for my problem.

First thought was to modify the function block DLOG_STORE_FILE_CSV, but if the OSCAT library will be changed in the future, the function block will differ (I would like to prevent that scenario).
Second thought was to modify the call of the function block. To do so I did:

- Previous to the call of DLOG_STORE_FILE_CSV, a separate FILE_SERVER is used to try to open the file. When there is no error code, the file exist. Then only the DLOG_SAVE.FN_REM has to be manipulated by copying the filename to it. Then the function block DLOG_STORE_FILE_CSV is called and thinks that it was already written to this filename and therefore only append the additional entries. Thats like the filename was stored in the retained variable.
When there is an error while trying to open the file, the DLOG_SAVE.FN_REM will be erased and the enabled will be set to FALSE for some cycles/time. Therefore the function DLOG_STORE_FILE_CSV thinks, that there it wasn't written to that filename in the past. Therefore a new file will be created with new header line.

Sounds complicated and it is ;-) But it's (just) a preconfiguration for a non existent feature of DLOG_STORE_FILE_CSV. It would be nice if some can switch the functionality in the interface of the function call. To either use retained variables or directly check if the file exist at write request.

But I also would understand that this will complex the code to much by adding a feature select.

This is my code to preconfigure the implementation to add this feature.
Declaration:
VAR
R_TRIG_LogExportRequest: R_TRIG;
xFileExistChecked: BOOL;
xFileExist: BOOL;
usiStep1: USINT := 1;
usiStep2: USINT := 1;
FS : OSCAT_NETWORK.FILE_SERVER;
FSD : OSCAT_NETWORK.FILE_SERVER_DATA;
PT : OSCAT_NETWORK.NETWORK_BUFFER;
trig_m : BOOL; // Manual trigger (for storage of values to new line of file)
trig_m_last : BOOL; // Last manual trigger (for storage of values to new line of file)
filename: STRING := 'Log'; // Name of file   'Log#A-#D-#H'
error_c: DWORD; // Corresponding error code
error_t: BYTE; // Corresponding error type
tonEnable: STANDARD.TON := (PT:=T#1000MS);
x1 : OSCAT_NETWORK.DLOG_DT := (COLUMN:='Time stamp'); // Logger input for STRING, used for Time stamp
x2 : OSCAT_NETWORK.DLOG_STRING := (COLUMN:='Event type'); // Logger input for STRING, used for Event type
x3 : OSCAT_NETWORK.DLOG_STRING := (COLUMN:='Description'); // Logger input for STRING, used for Description
x : OSCAT_NETWORK.DLOG_DATA; // Data exchange for logging and file storage
RTC_2: OSCAT_NETWORK.OSCAT_BASIC.RTC_2; // Clock needed for (tsv) file write
DLOG_STORE_FILE_TSV : DLOG_STORE_FILE_CSV; // File storage (tsv)
END_VAR

VAR RETAIN
save_data : OSCAT_NETWORK.DLOG_SAVE;
END_VAR

Code:
R_TRIG_LogExportRequest(CLK:=(LogExport.uiTxBufferCount > 0));
IF R_TRIG_LogExportRequest.Q THEN
xFileExistChecked := FALSE;
xFileExist := FALSE;
usiStep1 := 1;
usiStep2 := 1;
END_IF


IF NOT xFileExistChecked THEN

CASE usiStep1 OF

01: FSD.MODE := 5; // Close the possibly opened file
FSD.FILENAME:='Log'; // with filename "Log"
usiStep1 := 2;

02: IF FSD.MODE = 0 THEN // Close operation finished
usiStep1 := 3;
END_IF

03: FSD.MODE := 1; // Open+read file
usiStep1 := 4;

04: IF FSD.MODE = 0 THEN // Open+read operation finished
usiStep1 := 5;
END_IF

05: IF FSD.ERROR = 0 THEN // Open+read w/o error = file exist
xFileExist := TRUE;
ELSIF FSD.ERROR = 5 THEN // Open+read w error = file not exist
xFileExist := FALSE;
END_IF
xFileExistChecked := TRUE;

END_CASE;

FS(FSD:=FSD,PT:=PT); // File server operation

END_IF



IF xFileExistChecked THEN

CASE usiStep2 OF

01: IF xFileExistChecked AND xFileExist THEN // File exist = enable (to only open+write)
enable := TRUE;
save_data.FN_REM := 'Log'; // copy the file name to remanent variable to prevent "create+write"
ELSIF xFileExistChecked AND NOT xFileExist THEN // File not exist = not enable -> enable (to create new file with header)
enable := FALSE;
save_data.FN_REM := ''; // delete file name in remanetn variable to allow "create+write"
END_IF
usiStep2 := 2;

02: IF NOT enable THEN // Reenable when preveiously disabled
enable := TRUE;
END_IF
usiStep2 := 3;

03: IF LogExport.uiTxBufferCount > 0 AND trig_m = trig_m_last AND tonEnable.Q THEN
trig_m := TRUE; // Set the trigger
END_IF
trig_m_last := trig_m;
tonEnable(IN:=enable);

END_CASE



x1(X:=x); // Logger input for STRING, used for Time stamp
x2(X:=x, STR:=LogExport.asTxContent[1].sLogExportText2); // Logger input for STRING, used for Event type
x3(X:=x, STR:=LogExport.asTxContent[1].sLogExportText3); // Logger input for STRING, used for Description
DLOG_STORE_FILE_TSV(X:=x, SAVE_DATA:=save_data, ENABLE:=enable, TRIG_M:=trig_m, FILENAME:=filename, DTI:=RTC_2.UDT, SEP:=9, AUTO_CLOSE:=TIME#10S, ERROR_C=>error_c, ERROR_T=>error_t); // File storage (tsv)

IF trig_m THEN
trig_m := FALSE; // Reset the trigger
FOR iI := 1 TO TO_INT(LogExport.uiTxBufferCount) - 1 DO // Shift every entry one index up
LogExport.asTxContent[iI].sLogExportText2 := LogExport.asTxContent[iI+1].sLogExportText2;
LogExport.asTxContent[iI].sLogExportText3 := LogExport.asTxContent[iI+1].sLogExportText3;;
END_FOR
LogExport.asTxContent[iI].sLogExportText2 := '';
LogExport.asTxContent[iI].sLogExportText3 := ''; // And fill the last one with an empty entry
LogExport.uiTxBufferCount := LogExport.uiTxBufferCount - 1; // And decrement the buffer counter
END_IF

END_IF
Seiten: 1 ... 4 5 [6] 7 8 ... 10