BaseSystemLib hinzugefügt

This commit is contained in:
2026-06-29 16:28:48 +02:00
parent a51a0c6fd1
commit 14a1c5172d
168 changed files with 6797 additions and 0 deletions
@@ -0,0 +1,6 @@
LibraryType:
Guid: 1bccc25d-f0e3-41bf-bf8f-556451b48635
LibraryVersion:
VersionNumber: 0.0.1
Author: e.yueksel
IsDefault: true
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_CheckSumTel_MCopy.scl
Hash: zcrADDK8lZALDCIxGb5qBh+pGgaCJUi9wXbHiZvlHdw=
LibraryMetaFileHash: TNziG1GxJT4svgIKOyJQgS92gdrlR+wYUjQB1GtjE54=
LibraryVersion:
Guid: 904645a8-99b5-49ae-958e-8bd0900b6f5c
DependsOn:
- TypeName: FC_LenTel_DigitSingle_MCopy
VersionNumber: 0.0.1
@@ -0,0 +1,77 @@
FUNCTION "FC_CheckSumTel_MCopy" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
"Byte" : Array[1..10] of Byte;
END_VAR
VAR_OUTPUT
nOutCheckSum : UDInt;
xOutError : Bool;
END_VAR
VAR_TEMP
TempInt : Array[1..10] of UDInt;
TempError : Array[1..10] of Bool;
TempResult : UDInt;
TempErrorIndex : USInt;
TempIntIndex : USInt;
END_VAR
BEGIN
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[1],
nOut => #TempInt[1],
xOutError => #TempError[1]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[2],
nOut => #TempInt[2],
xOutError => #TempError[2]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[3],
nOut => #TempInt[3],
xOutError => #TempError[3]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[4],
nOut => #TempInt[4],
xOutError => #TempError[4]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[5],
nOut => #TempInt[5],
xOutError => #TempError[5]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[6],
nOut => #TempInt[6],
xOutError => #TempError[6]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[7],
nOut => #TempInt[7],
xOutError => #TempError[7]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[8],
nOut => #TempInt[8],
xOutError => #TempError[8]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[9],
nOut => #TempInt[9],
xOutError => #TempError[9]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[10],
nOut => #TempInt[10],
xOutError => #TempError[10]);
FOR #TempErrorIndex := 1 TO 10 DO
IF #TempError[#TempErrorIndex] THEN
#nOutCheckSum := 0;
#xOutError := true;
FOR #TempIntIndex := 1 TO 10 DO
#TempInt[#TempIntIndex] := 0;
END_FOR;
EXIT;
END_IF;
#xOutError := false;
END_FOR;
#TempResult := (#TempInt[1] * 1000000000) + (#TempInt[2] * 100000000) + (#TempInt[3] * 10000000) + (#TempInt[4] * 1000000) + (#TempInt[5] * 100000) + (#TempInt[6] * 10000) + (#TempInt[7] * 1000) + (#TempInt[8] * 100) + (#TempInt[9] * 10) + (#TempInt[10] * 1);
IF #TempResult <= 4294967295 AND #TempResult > 0 THEN
#nOutCheckSum := #TempResult;
#xOutError := false;
ELSE
#nOutCheckSum := 0;
#xOutError := TRUE;
END_IF;
END_FUNCTION
@@ -0,0 +1,6 @@
LibraryType:
Guid: be300a29-366c-4af7-86d4-03b57ad189ac
LibraryVersion:
VersionNumber: 0.0.1
Author: e.yueksel
IsDefault: true
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: FC_LenTel_DigitSingle_MCopy.scl
Hash: vMlfZS59FkD9vRhU7J4yRkq5IFleg7ON3Y9Ou2gbBCY=
LibraryMetaFileHash: LM23JFYgY7nJI+beJASWy2jiG1lV0xBvHBKcbXzbl5Q=
LibraryVersion:
Guid: 4649d6fe-3163-4b85-9cac-01dbba1c2535
@@ -0,0 +1,53 @@
FUNCTION "FC_LenTel_DigitSingle_MCopy" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
bIn : Byte;
END_VAR
VAR_OUTPUT
nOut : UDInt;
xOutError : Bool;
END_VAR
BEGIN
CASE #bIn OF
16#30:
#nOut := 0;
#xOutError := FALSE;
16#31:
#nOut := 1;
#xOutError := FALSE;
16#32:
#nOut := 2;
#xOutError := FALSE;
16#33:
#nOut := 3;
#xOutError := FALSE;
16#34:
#nOut := 4;
#xOutError := FALSE;
16#35:
#nOut := 5;
#xOutError := FALSE;
16#36:
#nOut := 6;
#xOutError := FALSE;
16#37:
#nOut := 7;
#xOutError := FALSE;
16#38:
#nOut := 8;
#xOutError := FALSE;
16#39:
#nOut := 9;
#xOutError := FALSE;
ELSE
#xOutError := TRUE
;
END_CASE;
END_FUNCTION
@@ -0,0 +1,6 @@
LibraryType:
Guid: c2de9ced-3384-4ae5-b061-c56131670178
LibraryVersion:
VersionNumber: 0.0.1
Author: e.yueksel
IsDefault: true
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_LenTel_MCopy.scl
Hash: T4kd83QvV4KwH5zjQ+4AcNWXs+c3obLLTTuar2wzbFQ=
LibraryMetaFileHash: SSQYpgHCkqDK4frap08MmA/MXYZ+UPnlm5mGZAunOks=
LibraryVersion:
Guid: 72381b85-e571-49f5-9b1e-12b557d735ff
DependsOn:
- TypeName: FC_LenTel_DigitSingle_MCopy
VersionNumber: 0.0.1
@@ -0,0 +1,68 @@
FUNCTION "FC_LenTel_MCopy" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
"Byte" : Array[1..7] of Byte;
END_VAR
VAR_OUTPUT
nOutLen : Int;
xOutError : Bool;
END_VAR
VAR_TEMP
TempInt : Array[1..7] of UDInt;
TempError : Array[1..7] of Bool;
TempResult : UDInt;
TempErrorIndex : USInt;
TempIntIndex : USInt;
END_VAR
BEGIN
"FC_LenTel_DigitSingle_MCopy"(bIn:= #Byte[1],
nOut=> #TempInt[1],
xOutError=> #TempError[1]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[2],
nOut => #TempInt[2],
xOutError => #TempError[2]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[3],
nOut => #TempInt[3],
xOutError => #TempError[3]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[4],
nOut => #TempInt[4],
xOutError => #TempError[4]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[5],
nOut => #TempInt[5],
xOutError => #TempError[5]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[6],
nOut => #TempInt[6],
xOutError => #TempError[6]);
"FC_LenTel_DigitSingle_MCopy"(bIn := #Byte[7],
nOut => #TempInt[7],
xOutError => #TempError[7]);
FOR #TempErrorIndex := 1 TO 7 DO
IF #TempError[#TempErrorIndex] THEN
#nOutLen := 0;
#xOutError := true;
FOR #TempIntIndex := 1 TO 7 DO
#TempInt[#TempIntIndex] := 0;
END_FOR;
EXIT;
END_IF;
#xOutError := false;
END_FOR;
#TempResult := (#TempInt[1] * 1000000) + (#TempInt[2] * 100000) + (#TempInt[3] * 10000) + (#TempInt[4] * 1000) + (#TempInt[5] * 100) + (#TempInt[6] * 10) + (#TempInt[7] * 1);
IF #TempResult <= 65535 AND #TempResult > 0 THEN
#nOutLen := UDINT_TO_INT(#TempResult);
#xOutError := false;
ELSE
#nOutLen := 0;
#xOutError := TRUE;
END_IF;
END_FUNCTION
@@ -0,0 +1,6 @@
LibraryType:
Guid: 3d599b5b-0213-46f8-8892-325ed0394c19
LibraryVersion:
VersionNumber: 0.0.1
Author: e.yueksel
IsDefault: true
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: LGF_CalcCRC32Advanced_MCopy.scl
Hash: 1qqS4TkbI0CoSZdszKz6k+3lkVQa0jWbmnNgukz1Iqg=
LibraryMetaFileHash: KkCWyXRn3OXenxTY0Y4Iwgskl07io9/EARfgdrNs/mE=
LibraryVersion:
Guid: 31658ecf-f5da-4a76-a463-cd1e98d4aa4e
@@ -0,0 +1,175 @@
FUNCTION "LGF_CalcCRC32Advanced_MCopy" : DWord
TITLE = LGF_CalcCRC32Advanced
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Siemens_Industry_Support
FAMILY : LGF
NAME : LGF_CRC32Advanced
//Die CRC-Berechnung wird für die Fehlererkennung bei der Datenübertragung verwendet. Das Ergebnis einer Berechnung liefert einen CRC-Wert über die gesendeten Daten. Der Empfänger erkennt eine fehlerhafte Übertragung aufgrund des ungleichen CRC-Werts. Die Funktion `LGF_CalcCRC32Advanced` verwendet als Generatorpolynom (Maske) 32 Bit sowie die Parameter `finalXorValue`, `reflectInput` und `reflectResult`.
VAR_INPUT
initValue { S7_PredefinedAssignment := '16#00'} : DWord; // Startwert, mit dem die Berechnung durchgeführt wird. Wenn keinen Startwert notwendig ist - 16#00 zuweisen.
mask { S7_PredefinedAssignment := '16#00'} : DWord; // Generatorpolynom, mit dem die Berechnung durchgeführt wird. (Maske / CRC Polynom)
finalXorValue { S7_PredefinedAssignment := '16#00'} : DWord; // Wert, mit dem am Ende eine weitere XOR-Operation durchgeführt wird
nInLowerLimit : Int;
nInUpperLimit : Int;
reflectInput { S7_PredefinedAssignment := 'FALSE'} : Bool; // TRUE: wird die Reihenfolge der Bits innerhalb des Eingangsbytes gespiegelt. Aus der Reihenfolge 0…7 wird 7…0.
reflectResult { S7_PredefinedAssignment := 'FALSE'} : Bool; // TRUE: wird die Reihenfolge der Bits innerhalb des Ergebnisses gespiegelt. Aus der Reihenfolge 0…7 wird 7…0.
END_VAR
VAR_IN_OUT
"array" : Array[*] of Byte; // Datenstrom, für den der CRC-Wert berechnet werden soll.
END_VAR
VAR_TEMP
tempInput : Byte; // Temp aktuelles eingangs Byte
tempCRC : DWord; // Temp CRC Prüfsumme
tempInvCRC : DWord; // Temp invertierte CRC Prüfsumme
tempLowerLimit : DInt; // Temp Untergrenze Eingangs Array
tempUpperLimit : DInt; // Temp Obergrenze Eingangs Array
tempIndexArray : DInt; // Temp Array schleifen Index
tempIndexCRC : DInt; // Temp CRC Schleifen Index
END_VAR
VAR CONSTANT
SHIFT_ONE_BIT : UInt := 1; // Schieben der CRC Berechnung um ein Bit
SHIFT_THREE_BYTE : UInt := 24; // Schieben um drei Byte (= 24 Bit)
ARRAY_FIRST_DIMENSION : UInt := 1; // Erste Dimension im Array
CRC_LOOP_LOWER_LIMIT : DInt := 0; // Untere Grenze für die CRC Berechnungsschleife
CRC_LOOP_UPPER_LIMIT : DInt := 7; // Obere Grenze für die CRC Berechnungsschleife
END_VAR
BEGIN
REGION Block info header
//===============================================================================
// SIEMENS AG / (c)Copyright 2019
//-------------------------------------------------------------------------------
// Title: LGF_CRC32Advanced
// Comment/Function: This function makes a CRC calculation according
// to the CRC-32 algorithm
// advanced because of reflect In/Out and final XOR combination
// Library/Family: LGF (Library General Functions)
// Author: Siemens Digital Industry Support
// Tested with: CPU 1515F-2 PN FW:V2.6
// Engineering: TIA Portal V15.1 Update 2
// Restrictions: ENO disabled - no error handling, no failure possible
// Requirements: PLC (S7-1200 / S7-1500)
//-------------------------------------------------------------------------------
// Change log table:
// Version | Date | Expert in charge | Changes applied
//----------|------------|------------------------|------------------------------
// 01.00.00 03.07.2018 Siemens Industry Online Support
// First released version
// 01.00.01 17.08.2018 Siemens Industry Online Support
// Upgrade: TIA V15 Update 2
// 01.00.02 23.11.2018 Siemens Industry Online Support
// Upgrade: TIA V15.1
// 01.00.03 09.10.2019 Simatic Systems Support
// Code refactoring, comments added
// 03.00.00 23.04.2020 Simatic Systems Support
// Set version to V3.0.0, harmonize the version of the whole library
// 03.00.01 12.11.2020 Simatic Systems Support
// Insert documentation
// Assign default start values to optional inputs - `initValue`, `mask`, `finalXorValue`, `reflectInput`, `reflectResult`
//=============================================================================
END_REGION Block info header
REGION DESCRIPTION
(/*
Die Funktion berechnet aus einem beliebig großen Datenstrom den CRC-Wert. Der Datenstrom setzt sich aus den einzelnen Elementen des Arrays am Ein- / Ausgangsparameter `array` zusammen. Der Startwert `initValue` und das Generatorpolynom `mask` sind frei wählbar.
Über die booleschen Eingangsparameter `reflectInput` und `reflectResult` können Sie optional die Bits der Eingangsdaten bzw. des CRC-Werts spiegeln. Außerdem wird mit dem CRC-Wert am Ende und dem Wert `finalXorValue` eine XOR-Operation durchgeführt.
Hinweis
: Für die Berechnung der CRC-Werte stehen verschiedene Online-Tools zur Verfügung. Die Funktion des Bausteins wurde mit folgendem Online-Tool getestet, da es die Eingangsparameter `mask` (Polynom) und `initValue` (Initial Value) unterstützt:
: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
*/)
END_REGION DESCRIPTION
REGION Initialization and input data processing
// Input array size calculation
#tempLowerLimit := #nInLowerLimit;//LOWER_BOUND(ARR := #array, DIM := #ARRAY_FIRST_DIMENSION);
#tempUpperLimit := #nInUpperLimit;//UPPER_BOUND(ARR := #array, DIM := #ARRAY_FIRST_DIMENSION);
// Defining initial value for algorithm
#tempCRC := #initValue;
END_REGION
REGION CRC calculation
FOR #tempIndexArray := #tempLowerLimit TO #tempUpperLimit DO
IF #reflectInput THEN
// Reverse bit order in input byte
#tempInput.%X7 := #array[#tempIndexArray].%X0;
#tempInput.%X6 := #array[#tempIndexArray].%X1;
#tempInput.%X5 := #array[#tempIndexArray].%X2;
#tempInput.%X4 := #array[#tempIndexArray].%X3;
#tempInput.%X3 := #array[#tempIndexArray].%X4;
#tempInput.%X2 := #array[#tempIndexArray].%X5;
#tempInput.%X1 := #array[#tempIndexArray].%X6;
#tempInput.%X0 := #array[#tempIndexArray].%X7;
ELSE
#tempInput := #array[#tempIndexArray];
END_IF;
// Perform division using XOR function for appropriate DWord in array (with shift byte into MSB of 32bit CRC)
#tempCRC := #tempCRC XOR SHL(IN := BYTE_TO_DWORD(#tempInput), N := #SHIFT_THREE_BYTE);
FOR #tempIndexCRC := #CRC_LOOP_LOWER_LIMIT TO #CRC_LOOP_UPPER_LIMIT DO
// Check if MSB is set
IF #tempCRC.%X31 THEN
// Shift left and perform division by mask polynomial using XOR function
#tempCRC := SHL(IN := #tempCRC, N := #SHIFT_ONE_BIT) XOR #mask;
ELSE
// Shift left without division
#tempCRC := SHL(IN := #tempCRC, N := #SHIFT_ONE_BIT);
END_IF;
END_FOR;
END_FOR;
END_REGION
REGION Outputs assignment
IF #reflectResult THEN
// Reverse bit order in CRC checksum
#tempInvCRC.%X31 := #tempCRC.%X0;
#tempInvCRC.%X30 := #tempCRC.%X1;
#tempInvCRC.%X29 := #tempCRC.%X2;
#tempInvCRC.%X28 := #tempCRC.%X3;
#tempInvCRC.%X27 := #tempCRC.%X4;
#tempInvCRC.%X26 := #tempCRC.%X5;
#tempInvCRC.%X25 := #tempCRC.%X6;
#tempInvCRC.%X24 := #tempCRC.%X7;
#tempInvCRC.%X23 := #tempCRC.%X8;
#tempInvCRC.%X22 := #tempCRC.%X9;
#tempInvCRC.%X21 := #tempCRC.%X10;
#tempInvCRC.%X20 := #tempCRC.%X11;
#tempInvCRC.%X19 := #tempCRC.%X12;
#tempInvCRC.%X18 := #tempCRC.%X13;
#tempInvCRC.%X17 := #tempCRC.%X14;
#tempInvCRC.%X16 := #tempCRC.%X15;
#tempInvCRC.%X15 := #tempCRC.%X16;
#tempInvCRC.%X14 := #tempCRC.%X17;
#tempInvCRC.%X13 := #tempCRC.%X18;
#tempInvCRC.%X12 := #tempCRC.%X19;
#tempInvCRC.%X11 := #tempCRC.%X20;
#tempInvCRC.%X10 := #tempCRC.%X21;
#tempInvCRC.%X9 := #tempCRC.%X22;
#tempInvCRC.%X8 := #tempCRC.%X23;
#tempInvCRC.%X7 := #tempCRC.%X24;
#tempInvCRC.%X6 := #tempCRC.%X25;
#tempInvCRC.%X5 := #tempCRC.%X26;
#tempInvCRC.%X4 := #tempCRC.%X27;
#tempInvCRC.%X3 := #tempCRC.%X28;
#tempInvCRC.%X2 := #tempCRC.%X29;
#tempInvCRC.%X1 := #tempCRC.%X30;
#tempInvCRC.%X0 := #tempCRC.%X31;
#LGF_CalcCRC32Advanced_MCopy := #tempInvCRC XOR #finalXorValue;
ELSE
#LGF_CalcCRC32Advanced_MCopy := #tempCRC XOR #finalXorValue;
END_IF;
// no error handling needed
ENO := TRUE;
END_REGION
END_FUNCTION
@@ -0,0 +1,10 @@
LibraryType:
Guid: 80cf5fc6-be82-4277-af7f-88c3b4ff7626
Comment:
de-DE: Siemens OUC TCP Kommunikationsbaustein
LibraryVersion:
VersionNumber: 2.0.0
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Siemens OUC TCP Kommunikationsbaustein
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FB_OUC_TCP.scl
Hash: nwFqWTIjLRoxAWgy6RXq3N+7xBPUodzEt9DMk5oKkW0=
LibraryMetaFileHash: 8xXIwLyl8E96ICjYbs61bN17CHdQJRj0Fx8Ez/i9uKI=
LibraryVersion:
Guid: 0db585c5-46ed-491e-9e90-b7934568d4b8
DependsOn:
- TypeName: typeDiagnostics
VersionNumber: 1.0.0
@@ -0,0 +1,382 @@
FUNCTION_BLOCK "FB_OUC_TCP"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : SIOS
FAMILY : OUC
VERSION : 2.0
VAR_INPUT
enable : Bool;
send : Bool;
rcvLen : UDInt;
sendLen : UDInt;
adhocMode : Bool;
connParam {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'} : TCON_IP_v4;
END_VAR
VAR_OUTPUT
valid { ExternalWritable := 'False'} : Bool;
done { ExternalWritable := 'False'} : Bool;
ndr { ExternalWritable := 'False'} : Bool;
busy { ExternalWritable := 'False'} : Bool;
error { ExternalWritable := 'False'} : Bool;
status { ExternalWritable := 'False'} : Word := #STATUS_NO_CALL;
diagnostics { ExternalWritable := 'False'} : "typeDiagnostics";
rcvdLen { ExternalWritable := 'False'} : UDInt;
END_VAR
VAR_IN_OUT
rcvdData : Array[*] of Byte;
sendData : Array[*] of Byte;
END_VAR
VAR
statEnableOld { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statSendOld { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statValid { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statDone { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statNdr { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statBusy { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statErrorUserCleared { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statErrorAutoCleared { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statStatus { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Word := #STATUS_NO_CALL;
statSubfunctionStatus { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Word;
statFBErrorState { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt;
statFBState { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt := #FB_STATE_NO_PROCESSING;
statDisablingCompleted { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statEmptyDiagnostics { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : "typeDiagnostics";
statConnParam {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : TCON_IP_v4;
instTCon {InstructionName := 'TCON'; LibVersion := '4.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : TCON;
instTRcv {InstructionName := 'TRCV'; LibVersion := '4.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : TRCV;
instTSend {InstructionName := 'TSEND'; LibVersion := '4.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : TSEND;
instTDiscon {InstructionName := 'TDISCON'; LibVersion := '2.1'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : TDISCON;
statRcvdLen { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UDInt;
statRcvEnable { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statConReq { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statDisconReq { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statSendReq { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
END_VAR
VAR_TEMP
tempEnable : Bool;
tempSend : Bool;
tempAdhocMode : Bool;
tempRcvLen : UDInt;
tempSendLen : UDInt;
END_VAR
VAR CONSTANT
FB_STATE_NO_PROCESSING : DInt := 0;
FB_STATE_ENABLING : DInt := 10;
FB_STATE_CONNECTED : DInt := 50;
FB_STATE_DISABLING : DInt := 90;
STATUS_EXECUTION_FINISHED : Word := 16#0000;
STATUS_NO_CALL : Word := 16#7000;
STATUS_FIRST_CALL : Word := 16#7001;
STATUS_SUBSEQUENT_CALL : Word := 16#7002;
SUB_STATUS_NO_ERROR : Word := 16#0000;
ERR_IN_BLOCK_OPERATION : Word := 16#8001;
ERR_PARAMETRIZATION : Word := 16#8200;
ERR_PROCESSING_EXTERN : Word := 16#8400;
ERR_PROCESSING_INTERN : Word := 16#8600;
ERR_UNDEFINED_STATE : Word := 16#8600;
ERR_TCON : Word := 16#8601;
ERR_TSEND : Word := 16#8602;
ERR_TRCV : Word := 16#8603;
ERR_AREA_RESERVED : Word := 16#8800;
ERR_USER_DEFINED_CLASSES : Word := 16#9000;
ERR_OUC_PARTNER_TERMINATED_CONNECTION : Word := 16#80C5;
ERR_OUC_CANNOT_REACH_PARTNER : Word := 16#80C6;
END_VAR
BEGIN
REGION BLOCK INFO HEADER
//===============================================================================
// (company) / (c)Copyright (year)
//-------------------------------------------------------------------------------
// Title: (Title of this Block / Enable Template)
// Comment/Function: (that is implemented in the block)
// (Template for an FB with Enable / Valid handling based on PLCopen standard "Function Blocks for Motion Control" V2.0)
// Library/Family: (that the source is dedicated to)
// Author: (department / person in charge / contact)
// Tested with: (test system with FW version)
// Engineering: TIA Portal (SW version)
// Restrictions: (OB types, etc.)
// Requirements: (hardware, technological package, memory needed, etc.)
//-------------------------------------------------------------------------------
// Change log table:
// Version | Date | Expert in charge | Changes applied
//----------|------------|------------------------|------------------------------
// 01.00.00 | yyyy-mm-dd | (name of expert) | First released version
//===============================================================================
END_REGION
// Create process image
#tempEnable := #enable;
#tempSend := #send;
#tempAdhocMode := #adhocMode;
IF #tempAdhocMode = TRUE THEN // ignore parameter rcvLen in ad-hoc mode
#tempRcvLen := 0;
ELSIF #tempAdhocMode = FALSE THEN // normal mode
#tempRcvLen := #rcvLen;
END_IF;
#tempSendLen := #sendLen;
REGION ENABLING/DISABLING
IF (#tempEnable = TRUE) AND (#statStatus = #STATUS_NO_CALL) THEN // Enable FB
// First call; initialize FB
#statValid := TRUE;
#statBusy := TRUE;
#statError := FALSE;
#statErrorUserCleared := FALSE;
#statErrorAutoCleared := FALSE;
#statSubfunctionStatus := #SUB_STATUS_NO_ERROR;
#statFBErrorState := 0;
#diagnostics := #statEmptyDiagnostics;
#statDisablingCompleted := FALSE;
// State machine - start functionality
#statFBState := #FB_STATE_ENABLING;
#statStatus := #STATUS_FIRST_CALL;
#statConReq := FALSE;
#statDisconReq := FALSE;
#statRcvEnable := FALSE;
#statSendReq := FALSE;
#statRcvdLen := 0;
#statConnParam := #connParam;
#statDone := FALSE;
#statNdr := FALSE;
ELSIF (#tempEnable = FALSE) AND (#statEnableOld = TRUE) THEN // Disable FB
#statFBState := #FB_STATE_DISABLING;
ELSIF (#statStatus = #STATUS_FIRST_CALL) THEN // Set status identifier of subsequent call
#statStatus := #STATUS_SUBSEQUENT_CALL;
END_IF;
// Edge detection 'enable' input
#statEnableOld := #tempEnable;
END_REGION ENABLING/DISABLING
IF (#statStatus = #STATUS_NO_CALL) THEN // Nothing to do -> End here to reduce "system load"
RETURN;
END_IF;
REGION STATE_MACHINE
CASE #statFBState OF // State machine of FB
#FB_STATE_NO_PROCESSING:
REGION no processing
// No processing active (Note: this state must always be present and left empty)
;
END_REGION no processing
#FB_STATE_ENABLING: // Enabling active
#statConReq := true; // Set here to create new rising edge after partner refused connection
REGION enabling
IF (#instTCon.DONE = true) THEN
#statConReq := false;
#statRcvEnable := true; // Enable receiving
#statErrorAutoCleared := false; // Reset possible errors
#statFBState := #FB_STATE_CONNECTED; // TODO: Replace with #FB_STATE_SEND if data is sent before anything is expected
ELSIF (#instTCon.ERROR = true) THEN
#statConReq := false;
#statStatus := #ERR_TCON;
#statSubfunctionStatus := #instTCon.STATUS;
#statFBErrorState := #statFBState;
IF (#instTCon.STATUS = #ERR_OUC_PARTNER_TERMINATED_CONNECTION)
OR (#instTCon.STATUS = #ERR_OUC_CANNOT_REACH_PARTNER)
THEN // Error can be cleared automatically
#statErrorAutoCleared := true;
// Remain in enabling state and wait for partner
ELSE // Error must be cleared by user
#statErrorUserCleared := true;
END_IF;
END_IF;
END_REGION enabling
#FB_STATE_CONNECTED: // connection is established
REGION connected
// Further processing state
// TODO: Use this state for further application specific code
// In this template sending and receiving is processed simultaneously. If sequential processing is required, move the following code to separate states
#statNdr := false; // reset ndr after one cycle
REGION receive
IF #instTRcv.NDR = TRUE THEN // new data received
REGION ndr
#statNdr := TRUE;
#statRcvdLen := #instTRcv.RCVD_LEN; // Save received length
END_REGION
ELSIF (#instTRcv.ERROR = true) THEN
REGION error occured
#statErrorAutoCleared := true; // In this template no error of TRCV causes the processing of the FB to stop
#statStatus := #ERR_TRCV;
#statSubfunctionStatus := #instTRcv.STATUS;
#statFBErrorState := #statFBState;
END_REGION
ELSIF (#instTRcv.ERROR = FALSE AND #statStatus = #ERR_TRCV) THEN
REGION error cleared
#statErrorAutoCleared := FALSE; // Reset any errors
#statStatus := #STATUS_SUBSEQUENT_CALL; // Reset status
END_REGION
END_IF;
END_REGION receive
REGION send
REGION trigger
IF #tempSend = TRUE AND #statSendOld = FALSE THEN
#statSendReq := TRUE;
ELSIF (#tempSend = FALSE AND (#statDone = TRUE OR #statError = TRUE)) THEN // Reset outputs
#statDone := FALSE;
IF #statStatus = #STATUS_EXECUTION_FINISHED OR #statStatus = #ERR_TSEND THEN
#statErrorAutoCleared := FALSE; // Reset possible errors
#statStatus := #STATUS_SUBSEQUENT_CALL;
END_IF;
END_IF;
#statSendOld := #tempSend;
END_REGION
IF (#instTSend.DONE = true) THEN // data was sent succcessfully
REGION successful
#statSendReq := false;
#statDone := true;
#statStatus := #STATUS_EXECUTION_FINISHED;
END_REGION
ELSIF (#instTSend.ERROR = true) THEN
REGION error occured
#statSendReq := false;
#statErrorAutoCleared := true; // In this template no error of TSEND causes the processing of the FB to stop
#statStatus := #ERR_TSEND;
#statSubfunctionStatus := #instTSend.STATUS;
#statFBErrorState := #statFBState;
END_REGION
END_IF;
END_REGION send
END_REGION connected
#FB_STATE_DISABLING: // Disabling active
REGION disabling
#statConReq := false;
#statSendReq := false;
#statRcvEnable := false;
#statDisconReq := true;
IF (#instTDiscon.DONE = true OR #instTDiscon.ERROR = true) THEN // Ignore errors from TDISCON
#statDisconReq := false;
#statFBState := #FB_STATE_NO_PROCESSING;
#statDisablingCompleted := TRUE;
END_IF;
END_REGION disabling
ELSE // Undefined state in state machine reached
REGION undefined state
#statStatus := #ERR_UNDEFINED_STATE;
#statErrorUserCleared := TRUE;
END_REGION undefined state
END_CASE;
END_REGION STATE_MACHINE
REGION INSTRUCTIONS
// call TCON to establish the connection
#instTCon(REQ := #statConReq,
ID := #statConnParam.ID,
CONNECT := #statConnParam);
// call TDISCON to disconnect the connection
#instTDiscon(REQ := #statDisconReq,
ID := #statConnParam.ID);
// call TRCV to receive data
#instTRcv(EN_R := #statRcvEnable,
ID := #statConnParam.ID,
LEN := #tempRcvLen,
ADHOC := #tempAdhocMode,
DATA := #rcvdData); // TODO: Replace with internal buffer if data shall be processed instead of output
// call TSEND to send data
#instTSend(REQ := #statSendReq,
ID := #statConnParam.ID,
LEN := #tempSendLen,
DATA := #sendData);
END_REGION INSTRUCTIONS
REGION OUTPUTS
// Write outputs
IF (#statDisablingCompleted = TRUE) THEN
REGION disabling
// Reset outputs if disabling completed
#statValid := FALSE;
#statBusy := FALSE;
#statError := FALSE;
#statErrorUserCleared := FALSE;
#statErrorAutoCleared := FALSE;
#statStatus := #STATUS_NO_CALL;
// TODO: Reset application specific outputs
#statRcvdLen := 0;
#statDone := false;
#statNdr := false;
END_REGION disabling
ELSIF (#statErrorUserCleared = TRUE) AND (#statError = FALSE) THEN
REGION error user cleared
// Error can only be cleared by user; rising edge at enable input is needed to continue
#statValid := FALSE;
#statBusy := FALSE;
#statError := TRUE;
// Write diagnostics
#diagnostics.status := #statStatus;
#diagnostics.subfunctionStatus := #statSubfunctionStatus;
#diagnostics.stateNumber := #statFBErrorState;
// execution aborted --> set state no processing
#statFBState := #FB_STATE_NO_PROCESSING;
END_REGION error user cleared
ELSIF (#statErrorAutoCleared = TRUE) AND (#statError = FALSE) THEN
REGION error auto cleared
// Error can be reset by FB automatically
#statValid := FALSE;
#statBusy := TRUE;
#statError := TRUE;
// Write diagnostics
#diagnostics.status := #statStatus;
#diagnostics.subfunctionStatus := #statSubfunctionStatus;
#diagnostics.stateNumber := #statFBErrorState;
END_REGION error auto cleared
ELSIF (#statErrorAutoCleared = FALSE) AND (#statErrorUserCleared = FALSE) AND (#statError = TRUE) THEN
REGION after user/auto cleared
// If autocleared error is acknowledged
#statValid := TRUE;
#statBusy := TRUE;
#statError := FALSE;
#statStatus := #STATUS_SUBSEQUENT_CALL;
END_REGION after user/auto cleared
END_IF;
REGION Write static values to outputs
#valid := #statValid;
#done := #statDone;
#ndr := #statNdr;
#busy := #statBusy;
#error := #statError;
#status := #statStatus;
// if ENO mechanism is not used / not wanted replace the following line by --> ENO := TRUE;
ENO := NOT #statError;
// TODO: Write application specific static values to outputs
#rcvdLen := #statRcvdLen;
END_REGION Write static values to outputs
END_REGION OUTPUTS
END_FUNCTION_BLOCK
@@ -0,0 +1,6 @@
LibraryType:
Guid: 0062fd19-6682-49cc-834f-95307dbd2d72
LibraryVersion:
VersionNumber: 0.0.7
Author: e.yueksel
IsDefault: true
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: FB_TcpCommServer.scl
Hash: qFYsYkF16gjWmp+OcWlum9zmD3C/2IJo/WHaJF8To0Y=
LibraryMetaFileHash: eq0DDd4Z/WCx1XQLK2W2QhViASdtBjgypX7yqdQG/aY=
LibraryVersion:
Guid: 74221796-361b-4eaa-939e-0e1c0aadbd3e
@@ -0,0 +1,622 @@
FUNCTION_BLOCK "FB_TcpCommServer"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : SiemensAG
FAMILY : OpenUserComm
VERSION : 1.0
VAR_INPUT
enable : Bool; // enables TCP/IP connection
sendRequest : Bool; // triggers a send request
rcvLen : UDInt; // length of data you want to receive from partner (opt. DBs = 0)
sendLen : UDInt; // length of date so send to partner
adhocMode : Bool; // activate adhoc Mode to receive data with variable len
tcpConnParam {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'} : TCON_IP_v4; // Connection Parameters
END_VAR
VAR_OUTPUT
connectionEstablished : Bool; // connection to partner established
ndr : Bool; // new data received
done : Bool; // send request finished successully
busy : Bool; // block is busy
error : Bool; // error occurred
rcvdLen : UDInt; // length of received data (in byte)
statusID : UInt; // error location in block
status : Word; // status word from OUC blocks
END_VAR
VAR_IN_OUT
sendData : Array[*] of Byte; // data to send to partner
rcvData : Array[*] of Byte; // received data from partner
END_VAR
VAR
instTcon {InstructionName := 'TCON'; LibVersion := '4.0'} : TCON;
instTdiscon {InstructionName := 'TDISCON'; LibVersion := '2.1'} : TDISCON;
instTrcv {InstructionName := 'TRCV'; LibVersion := '4.0'} : TRCV;
instTsend {InstructionName := 'TSEND'; LibVersion := '4.0'} : TSEND;
statTcpConnParam {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'} : TCON_IP_v4;
instTimer {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;
statStartTimer : Bool;
statStoppTimer : Bool;
statTimeRun : Time;
statEdgeCon : Bool;
statEdgeConOld : Bool;
statEdgeDiscon : Bool;
statEdgeDisconOld : Bool;
statEdgeSendReq : Bool;
statEdgeSendReqOld : Bool;
statConnID : Word;
statConActive : Bool;
statStateValue : Int;
statStatus : Word;
statStatusId : UInt;
statConReEstablish : Bool;
statSendActive : Bool;
statPartnerDisconnected : Bool;
statTimerEnd : Bool;
statErrorIntern : Bool;
statDataBufferRcv : Array[1..65536] of Byte;
statRcvdLen : UDInt;
statRcvLen : UDInt;
statRcvFrameLen : DInt;
statRcvFrameLenSave : DInt;
statRcvBusy : Bool;
statCntRecv : Int;
statRcvDataLen : DWord;
statNdr : Bool;
statLenDetected : Bool;
statCntNdr : UInt;
statRcvLenTest : UDInt;
statLowerBoundSend : DInt;
statLowerBoundRcv : DInt;
statUpperBoundSend : DInt;
statUpperBoundRcv : DInt;
statRcvdLenNotDetected : Bool;
END_VAR
VAR_TEMP
tempRetVal : Int;
tempPos : DInt;
END_VAR
VAR CONSTANT
STATE_IDLE : Int := 1; // idle mode - wating for events
STATE_PARAM : Int := 2; // take over IsoOnTcp parameters
STATE_CONNECT : Int := 3; // establish IsoOnTcp connection
STATE_DISCONNECT : Int := 4; // disconnect IsoOnTcp connection
STATE_SEND : Int := 5; // send data to partner
STATE_RECEIVE : Int := 6; // receive data
STATE_CONNECTED : Int := 7; // connection established
STATE_ERROR : Int := 8; // error state
STATUS_ID_INT_ERROR : UInt := 1; // error location state - initialization
STATUS_ID_CON : UInt := 2; // error location state - connect
STATUS_ID_DISCON : UInt := 5; // error location - disconnect
STATUS_ID_SEND : UInt := 4; // error location -send data
STATUS_ID_RCV : UInt := 3; // error location - receive data
ERR_COMM_NOT_STARTED : Word := 16#8101; // communication not startet
ERR_WATCHDOG_TIMER : Word := 16#8102; // watchdog timer expired
ERR_COMM_ID_IN_USE : Word := 16#80A3; // connection ID is already used (TCON)
ERR_COMM_TEMP : Word := 16#80C4; // temporary communication error
ERR_COMM_TCON_NOT_COMPLETED : Word := 16#80A7; // executed "TDISCON" before "TCON" had completed
ERR_COMM_PARTNER_TERMINATE_CONNETION : Word := 16#80C5; // connection partner refuses to establish connection or terminated connection actively
ERR_COMM_CONNECTION_NOT_EXIST : Word := 16#80A3; // connection does exist (TDISCON)
ERR_COMM_CONNECTION_TERMINATED : Word := 16#80A1; // communication already terminated
CONST_LEN_HEADER : UDInt := 4;
CONST_WATCHDOG_TIME : Time := T#180s; // watchdog time
CONST_WORD_0 : Word := 16#0000;
CONST_UINT_0 : UInt := 0;
CONST_UDINT_0 : UDInt := 0;
CONST_DINT_0 : DInt := 0;
CONST_MAX_RCVD_DATA_LEN : UDInt := 65536;
CONST_MIN_RCVD_DATA_LEN : UDInt := 0;
END_VAR
BEGIN
//=============================================================================
//SIEMENES AG
//(c)Copyright 2020 All Rights Reserved
//-----------------------------------------------------------------------------
//Library: LOpenUserComm
//Tested with: (S7-1500 V2.8; S7-1200 V4.4)
//Engineering: TIA Portal V16
//Restrictions: call in cyclic main OB
//Requirements:
//Functionality: Open User Communication Template for TCP connections
// Shows the basic steps to use the OUC blocks to establish
// reliable TCP/IP connections in an state machine
// ....
//NEUER TEST
//-----------------------------------------------------------------------------
//Change log table:
//Version Date Expert in charge Changes applied
//01.01.02 18.02.2020 (DI CS SD CSS KMT) Update of the released version V1.1.1
//=============================================================================
#statLowerBoundSend:=LOWER_BOUND(ARR := #sendData, DIM := 1);
#statLowerBoundRcv:= LOWER_BOUND(ARR:=#rcvData, DIM:=1);
#statUpperBoundSend := UPPER_BOUND(ARR := #sendData, DIM := 1);
#statUpperBoundRcv := UPPER_BOUND(ARR := #rcvData, DIM := 1);
REGION edgeDetection
//evaluluate pos edge on input enable for connection establishment
#statEdgeCon := #enable AND NOT
#statEdgeConOld;
#statEdgeConOld := #enable;
//evaluluate neg edge on input enable for connection termination
#statEdgeDiscon := NOT #enable AND
#statEdgeDisconOld;
#statEdgeDisconOld := #enable;
//evaluluate pos edge on input sendRequest
#statEdgeSendReq := #sendRequest AND NOT
#statEdgeSendReqOld;
#statEdgeSendReqOld := #sendRequest;
END_REGION
REGION initStates // evaluates the correct init state due to the input parameters
//establish connection to partner
IF (#statEdgeCon = true)
THEN
IF (#busy = false)
THEN
#busy := true;
#statStateValue := #STATE_PARAM;
ELSE
#statStatusId := #STATUS_ID_INT_ERROR; // internal initialization error
#statStatus := #ERR_COMM_NOT_STARTED; // 16#8101: communication not startet
#statStateValue := #STATE_ERROR;
END_IF;
END_IF;
//If disconnect required, set state to STATE_DISCONNECT
IF (#statEdgeDiscon = true)
THEN
#statStateValue := #STATE_DISCONNECT;
END_IF;
//If sendRequest is required and connection is established set state to STATE_SEND
IF ((#statEdgeSendReq = true)
AND (#statConActive = true))
THEN
#statStateValue := #STATE_SEND;
END_IF;
// Watchdog timer to supervise connection
#instTimer(IN := #statStartTimer,
PT := #CONST_WATCHDOG_TIME,
Q => #statStoppTimer,
ET => #statTimeRun);
// Go to state STATE_DISCONNECT when watchdog timer expired during connection establishment.
IF (#statStoppTimer = true)
THEN
#error := false;
#statStartTimer := false; //reset watchdog timer
#statTimerEnd := true; // trigger watchdog timer is expired
#statStateValue := #STATE_DISCONNECT; //when watchdog timer is expired got to STATE_DISCONNECT for connection termination
END_IF;
END_REGION
REGION stateMachine // contains the state machine
// TCP/IP management
// This section manages all the states to handle the Open User Communication blocks in a coordinated state machine.
CASE #statStateValue OF
#STATE_IDLE: // idle mode, waiting for events
#busy := false;
#error := false;
#status := #CONST_WORD_0;
#statusID := #CONST_UINT_0;
#statStatus := #CONST_WORD_0;
#statStatusId := #CONST_UINT_0;
#ndr := false;
#done := false;
#rcvdLen := #CONST_UDINT_0;
#statRcvdLen := #CONST_UDINT_0;
#statRcvFrameLen := #CONST_DINT_0;
#connectionEstablished := false;
#statStartTimer := false; //reset watchdog timer
#instTcon.REQ := false; //stop all TCON activities
#instTdiscon.REQ := false; //stop all TDISCON activities
#instTrcv.EN_R := false; // stop all TRCV activities
#statSendActive := false;
#STATE_PARAM: // read connection parameters from input
#instTcon.REQ := false; //stop all TCON activities
#instTdiscon.REQ := false; //stop all TDISCON activities
#instTrcv.EN_R := false; // stop all TRCV activities
#statTcpConnParam := #tcpConnParam; //connection parameters
#statConnID := #statTcpConnParam.ID; //unique connection ID
#statStateValue := #STATE_CONNECT; //set state machine to STATE_CONNECT
#STATE_CONNECT: //establish connection
REGION connect
IF (#statConActive = false) //no active connection
THEN
#instTcon.REQ := true; //activate TCON block
#statStartTimer := true; //activate watchdog timer to supervise connection process
ELSIF (#statConActive = true) //connection already active
THEN
#statStateValue := #STATE_CONNECTED; //set state machine to STATE_CONNECTED
END_IF;
IF ((#instTcon.DONE = TRUE)
AND (#instTcon.BUSY = FALSE)) //connection is established
THEN
#instTcon.REQ := false;
#statStartTimer := false; //reset watchdog timer
#statConActive := true; //conenction is active
ELSIF (#instTcon.ERROR = true) //error on establishing Tcp connection
THEN
//prepare error location information
#instTcon.REQ := false;
#statStatusId := #STATUS_ID_CON; //error occurred while establishing connection
#statStatus := #instTcon.STATUS; //error code from OUC block TCON
#statStateValue := #STATE_ERROR; // set state machine to STATE_ERROR while connection establishment
END_IF;
END_REGION
#STATE_DISCONNECT: //disconnect connection
REGION disconnect
//TDISCON is activated:
IF ((#statConActive = true) //when disconnect is required by input enable=0 and conenction is active,
OR (#statConReEstablish = true) //before connection is re-established
OR (#statTimerEnd = true)) //when watch dog timer is expired
THEN
#instTdiscon.REQ := true; //activate TDISCON block
ELSIF (#statConActive = false) // connection is not active
THEN
#statStateValue := #STATE_IDLE; //go to STATE_IDLE because connection is not active
END_IF;
IF (#instTdiscon.DONE = TRUE)
THEN
#instTdiscon.REQ := false; //conenction is disconnected
#statConActive := false; // connection isn`t active
#statConReEstablish := false; //reset trigger for connection termination before re-establishment
END_IF;
IF (#instTdiscon.ERROR = true) //error on disconnecting Tcp connection
THEN
//prepare error location information
#instTdiscon.REQ := false;
#statStatus := #instTdiscon.STATUS; //error code from OUC block TDISCON
#statStatusId := #STATUS_ID_DISCON; //error occurred while disconnecting connection
#statStateValue := #STATE_ERROR; // set state machine to STATE_ERROR while connection termination
#statConReEstablish := false; //reset trigger for connection termination before re-establishment
END_IF;
END_REGION
#STATE_CONNECTED: //connection is successful established to partner
REGION connected
// REGION connected
#done := false;
#ndr := false; //reset output ndr=0
#busy := true;
#rcvdLen := #CONST_UINT_0; // reset output rcvdLen=0;
#instTrcv.EN_R := true; //activate TRCV block for incoming telegrams
#connectionEstablished := NOT (#statPartnerDisconnected);
#statRcvdLenNotDetected := false;
IF #adhocMode = TRUE
THEN
#statRcvLen := 0;
ELSIF #adhocMode=FALSE
THEN
#statRcvLen := #rcvLen;
END_IF;
IF (#instTrcv.NDR = TRUE) //New Data Received
THEN
IF #statCntNdr >= 50
THEN
#statCntRecv := 0;
END_IF;
#statCntNdr := #statCntNdr + 1;
#statRcvdLen := #instTrcv.RCVD_LEN; // set output rcvdLen to the length of received data
#statRcvLenTest := #instTrcv.RCVD_LEN;
#statStateValue := #STATE_RECEIVE;
ELSIF (#instTrcv.ERROR = true) // error occurred on receiving data in block TRCV
THEN
//prepare error location information
#statStatusId := #STATUS_ID_RCV; //error occurred while receiving data
#statStatus := #instTrcv.STATUS; //error code from OUC block TRCV
#statStateValue := #STATE_ERROR; // set state machine to STATE_ERROR while receiving data
ELSE
#status := #CONST_WORD_0;
#statusID := #CONST_UINT_0;
#error := false;
#statPartnerDisconnected := false;
END_IF;
END_REGION
#STATE_SEND: //send data to partner
REGION sendData
IF (#statSendActive = false)
THEN
#instTsend.REQ := true; //activate TSEND block
#statSendActive := true; //send job is active (no other request to sendRequest is possible)
END_IF;
IF (#instTsend.DONE) // data send successfully
THEN
#statSendActive := false; // no send job active
#statStateValue := #STATE_CONNECTED; // set state to STATE_CONNECTED
#done := true; // send request is finished successfully
#busy := false; // set busy=false
ELSIF #instTsend.ERROR = true //error on send data
THEN
//prepare error location information
#statSendActive := false;
#statStatusId := #STATUS_ID_SEND; //error occurred while sending data
#statStatus := #instTsend.STATUS; //error code from OUC block TSEND
#statStateValue := #STATE_ERROR; // set state machine to STATE_ERROR while sending data
END_IF;
END_REGION
#STATE_RECEIVE:
REGION receiveData
// handle here the received data individual for your purposes
// in this template received data is simply copied to paramter #rcvData
// adhoc mode is activated
IF #adhocMode = TRUE
THEN
IF #statLenDetected = FALSE
// THEN
// #statRcvDataLen.%B0 := #statDataBufferRcv[4];
// #statRcvDataLen.%B1 := #statDataBufferRcv[3];
// #statRcvDataLen.%B2 := #statDataBufferRcv[2];
// #statRcvDataLen.%B3 := #statDataBufferRcv[1];
// IF (DWORD_TO_UDINT(#statRcvDataLen) >= #CONST_MIN_RCVD_DATA_LEN)
// AND (DWORD_TO_UDINT(#statRcvDataLen) <= #CONST_MAX_RCVD_DATA_LEN)
THEN
#statLenDetected := true;
#tempRetVal := MOVE_BLK_VARIANT(SRC := #statDataBufferRcv,
COUNT := #statRcvdLen,
SRC_INDEX := #CONST_DINT_0,
DEST_INDEX := #CONST_DINT_0,
DEST => #rcvData);
// ELSE
// #rcvdLen := 0;
// #statRcvFrameLen := 0;
// #statRcvdLen := 0;
// #statRcvdLenNotDetected := true;
// END_IF;
ELSE
#tempRetVal := MOVE_BLK_VARIANT(SRC := #statDataBufferRcv,
COUNT := #statRcvdLen,
SRC_INDEX := #CONST_DINT_0,
DEST_INDEX := #statRcvFrameLen,
DEST => #rcvData);
END_IF;
#statRcvFrameLen := #statRcvFrameLen + UDINT_TO_DINT(#statRcvdLen);
IF (#statRcvFrameLen >= #statRcvDataLen)
AND (#statRcvdLenNotDetected = false)
THEN
#statRcvFrameLenSave := #statRcvFrameLen;
#rcvdLen := DINT_TO_UDINT(#statRcvFrameLen);
#statRcvFrameLen := 0;
#statRcvdLen := 0;
#statLenDetected := false;
#ndr := true;
END_IF;
//adhoc mode is deactivated
ELSE
#tempRetVal := MOVE_BLK_VARIANT(SRC := #statDataBufferRcv,
COUNT := #statRcvdLen,
SRC_INDEX := 0,
DEST_INDEX := 0,
DEST => #rcvData);
#ndr := true;
#rcvdLen := #statRcvdLen;
END_IF;
IF #statCntRecv >= 50
THEN
#statCntRecv := 0;
END_IF;
#statCntRecv := #statCntRecv + 1;
#statStateValue := #STATE_CONNECTED;
END_REGION
#STATE_ERROR: // error handling
REGION errorHandling
//Error source: occurred in STATE_CONNECT - establishing connection
IF (#statStatusId = #STATUS_ID_CON)
THEN
// re-establishment of connection nesccessary when:
IF ((#statStatus = #ERR_COMM_ID_IN_USE) //16#80A3 ID is used by a connection created by the user program, which uses the same connection description at the CONNECT parameter.
OR (#statStatus = #ERR_COMM_TCON_NOT_COMPLETED)) // 16#80A7 Communication error: You executed "TDISCON" before "TCON" had completed.
THEN
#statConReEstablish := true; //trigger for re-establishment
#statStateValue := #STATE_DISCONNECT; // set state to STATE_DISCONNECT for connection termination before re-establishment
// go to STATE_CONNECT again, when client isn`t connected
//16#80C5: connection partner refuses to establish connection or terminated connection actively.
ELSIF (#statStatus = #ERR_COMM_PARTNER_TERMINATE_CONNETION)
THEN
#statStateValue := #STATE_CONNECT; // set state to STATE_CONNECT
#statErrorIntern := true;
ELSE
#statStateValue := #STATE_IDLE; //set state to STATE_IDLE in any other error cases and wait for new user events
END_IF;
//Error source: occurred in STATE_DISCONNECT - disconnecting connection
ELSIF (#statStatusId = #STATUS_ID_DISCON)
THEN
IF (#statStatus = #ERR_COMM_CONNECTION_NOT_EXIST) // 16#80A3 Connection doesn`t exist or isn`t established
THEN
//When watchdog timer is expired connection isn`t established. TDISCON shows status 16#80A3.
//In this case change error location information
IF (#statTimerEnd = TRUE)
THEN
#statTimerEnd := false; //reset trigger watchdog timer expired
#statStatusId := #STATUS_ID_INT_ERROR; //internal error
#statStatus := #ERR_WATCHDOG_TIMER; //16#8102 watchdog timer is expired
END_IF;
#statConActive := false; //no active connection
#statStateValue := #STATE_IDLE; //When status 16#80A3 isn`t cause by watchdog timmer go to STATE_IDLE
ELSE
#statStateValue := #STATE_DISCONNECT; // in any other error cases go to STATE_DISCONNECT for connection termination
END_IF;
//Error source: occurred in STATE_CONNECTED - receive new data
ELSIF #statStatusId = #STATUS_ID_RCV
THEN
// connection is terminated or temporary communication error
IF ((#statStatus = #ERR_COMM_TEMP)
OR (#statStatus = #ERR_COMM_CONNECTION_TERMINATED))
THEN
IF (#enable = true) //when input enable = true partner has terminated the connection
THEN
#statPartnerDisconnected := true; // trigger that partner has disconnected the connection
#statErrorIntern := true; // Trigger internal Error -> no action by user neccessary
#statStateValue := #STATE_CONNECTED; // when partner has terminated connection stay in STATE_CONNECTED and wait for the partner
ELSE // connection termination was required via input enable = 0
#statStateValue := #STATE_IDLE; // set state to IDLE_STATE
END_IF;
// The partner has disconnected
ELSIF (#statStatus = #ERR_COMM_PARTNER_TERMINATE_CONNETION)
THEN
#statPartnerDisconnected := true; // trigger that partner has disconnected the connection
#statErrorIntern := true; // Trigger internal Error -> no action by user neccessary
#statStateValue := #STATE_CONNECTED; // when partner has terminated connection stay in STATE_CONNECTED and wait for the partner
ELSE //any other error cases
#statStateValue := #STATE_DISCONNECT; //set state to STATE_DISCONNECT for connection termination
END_IF;
ELSIF (#statStatusId = #STATUS_ID_SEND) //Error source: occurred in STATE_SEND - send data
THEN
// connection is terminated or temporary communication error
IF ((#statStatus = #ERR_COMM_TEMP)
OR (#statStatus = #ERR_COMM_CONNECTION_TERMINATED))
THEN
IF (#enable = true) //when input enable = true partner has terminated the connection
THEN
#statPartnerDisconnected := true; //when input enable = true partner has terminated the connection
#statErrorIntern := true; // Trigger internal Error -> no action by user neccessary
#statStateValue := #STATE_CONNECTED; // when partner has terminated connection stay in STATE_CONNECTED and wait for the partner
ELSE // connection termination was required via input enable = 0
#statStateValue := #STATE_IDLE; // set state to IDLE_STATE
END_IF;
// The partner has disconnected
ELSIF (#statStatus = #ERR_COMM_PARTNER_TERMINATE_CONNETION)
THEN
#statPartnerDisconnected := true; //when input enable = true partner has terminated the connection
#statErrorIntern := true; // Trigger internal Error -> no action by user neccessary
#statStateValue := #STATE_CONNECTED; // when partner has terminated connection stay in STATE_CONNECTED and wait for the partner
ELSE //any other error cases
#statStateValue := #STATE_DISCONNECT; //set state to STATE_DISCONNECT for connection termination
END_IF;
ELSIF (#statStatusId = #STATUS_ID_INT_ERROR)
THEN
#statStateValue:=#STATE_IDLE;
END_IF;
//set output parameters
IF (#statErrorIntern = true) // internal error (no activity by the user neccessary)
THEN
#statErrorIntern := false;
#busy := true; // do not reset the output busy (FB works)
ELSE //other error cases
#busy := false; //reset output #busy (FB doesn't works)
END_IF;
#status := #statStatus;
#statusID := #statStatusId;
#error := true;
END_REGION
ELSE // Statement section ELSE
#statStateValue := #STATE_IDLE;
END_CASE;
END_REGION
REGION callOUCBlocks // call of all OUC blocks
// TCON
#instTcon(ID := #statConnID,
CONNECT := #statTcpConnParam);
// TDISCON
#instTdiscon(ID := #statConnID);
// TRCV
#instTrcv(ID := #statConnID,
ADHOC := #adhocMode,
LEN := #statRcvLen,
DATA := #statDataBufferRcv);
//TSEND
#instTsend(ID := #statConnID,
LEN := #sendLen,
DATA := #sendData);
#instTsend.REQ := false;
END_REGION
END_FUNCTION_BLOCK
@@ -0,0 +1,10 @@
LibraryType:
Guid: 507f060d-3ada-4f0d-be55-ad0a573f4197
Comment:
de-DE: Logging integriert
LibraryVersion:
VersionNumber: 0.0.14
Author: t.schiller
IsDefault: true
Comment:
de-DE: Logging integriert
@@ -0,0 +1,13 @@
DocumentHash:
- FileName: FB_EventLog_Root.scl
Hash: dYC6DBRTM3y/UqKlq9GtiXf0RMqTdz95JqM4YR4MH4I=
LibraryMetaFileHash: Z07lDSYlhb8WZYii7fMbAe/9XKI4zUKNS6ioRRiae8s=
LibraryVersion:
Guid: 0eb2e25d-8a3e-4933-a967-d5e3f0e48bb4
DependsOn:
- TypeName: FC_DateAsString
VersionNumber: 0.0.14
- TypeName: FC_TimeAsString
VersionNumber: 0.0.14
- TypeName: FC_Loglevel_to_String
VersionNumber: 0.0.14
@@ -0,0 +1,57 @@
FUNCTION_BLOCK "FB_EventLog_Root"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
xInTrigger : Bool;
sInInstance : String[50]; // he instance that called the function - see Beckhoff {attribute 'instance-path'} or library example project for how to retrieve this automatically.
nInLogLevel : Int;
sInMessage : String;
END_VAR
VAR
fbProgram_Alarm {InstructionName := 'Program_Alarm'; LibVersion := '1.0'} : Program_Alarm;
wStatus : Word;
xTriggerFlag : Bool;
END_VAR
VAR_TEMP
xError : Bool;
sLogMessage : String;
xLogEnable : Bool;
END_VAR
VAR CONSTANT
cSeperationChar : String := ';';
END_VAR
BEGIN
//#sInInstanceName := GetInstancePath(size:=1);
#xLogEnable := #nInLogLevel <= "DB_MachineGlobal".nLogLevel;
REGION Meldetext
IF #xInTrigger AND NOT #xTriggerFlag THEN
#sLogMessage := CONCAT_STRING(IN1 := "FC_DateAsString"(),
IN2 := #cSeperationChar,
IN3 := "FC_TimeAsString"(),
IN4 := #cSeperationChar,
IN5 := "FC_Loglevel_to_String"(#nInLogLevel),
IN6 := #cSeperationChar,
IN7 := #sInInstance,
IN8 := #cSeperationChar,
IN9 := #sInMessage);
END_IF;
END_REGION
REGION Program Alarm
#fbProgram_Alarm(SIG := #xInTrigger AND NOT #xTriggerFlag AND #xLogEnable,
SD_1 := #sLogMessage,
Status => #wStatus,
Error => #xError);
END_REGION
REGION Flanken
#xTriggerFlag := #xInTrigger;
END_REGION
END_FUNCTION_BLOCK
@@ -0,0 +1,10 @@
LibraryType:
Guid: ec1c1f34-0a2d-4751-84a8-f9c4ee84884b
Comment:
de-DE: Logging integriert
LibraryVersion:
VersionNumber: 0.0.14
Author: t.schiller
IsDefault: true
Comment:
de-DE: Logging integriert
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: FC_DateAsString.scl
Hash: sxW9MGlJNzQwHlUucUIrXWLqFFj9XVJTFDBvIpZg2Qs=
LibraryMetaFileHash: wzQfhgpRB7r0PHMXGTocBFU9yvk1Vr0feBlk7pR9Mcs=
LibraryVersion:
Guid: 4adee4de-c703-4794-9700-da57684c5c9f
@@ -0,0 +1,38 @@
FUNCTION "FC_DateAsString" : String
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
tInt : Int;
tDTL {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
sTmp : String[5];
END_VAR
BEGIN
// Format: '21-05-12'
#tInt := RD_LOC_T(#tDTL);
#sTmp := UINT_TO_STRING(#tDTL.YEAR);
#FC_DateAsString[1] := #sTmp[4];
#FC_DateAsString[2] := #sTmp[5];
#FC_DateAsString[3] := '-';
#sTmp := USINT_TO_STRING(#tDTL.MONTH);
IF #tDTL.MONTH <= 9 THEN
#FC_DateAsString[4] := '0';
#FC_DateAsString[5] := #sTmp[2];
ELSE
#FC_DateAsString[4] := #sTmp[2];
#FC_DateAsString[5] := #sTmp[3];
END_IF;
#FC_DateAsString[6] := '-';
#sTmp := USINT_TO_STRING(#tDTL.DAY);
IF #tDTL.DAY <= 9 THEN
#FC_DateAsString[7] := '0';
#FC_DateAsString[8] := #sTmp[2];
ELSE
#FC_DateAsString[7] := #sTmp[2];
#FC_DateAsString[8] := #sTmp[3];
END_IF;
END_FUNCTION
@@ -0,0 +1,10 @@
LibraryType:
Guid: ecdcb816-c5f6-4500-b05f-1b5b1f79ef0b
Comment:
de-DE: Logging integriert
LibraryVersion:
VersionNumber: 0.0.14
Author: t.schiller
IsDefault: true
Comment:
de-DE: Logging integriert
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: FC_Loglevel_to_String.scl
Hash: 0nOn7U6FrudaUAoJ0lbC3MqMbfsVeEOSIk31dwrXw8U=
LibraryMetaFileHash: pC45QV67Xh2HrolPKgzDv3+YCEc3tG189rMarPR4Ym8=
LibraryVersion:
Guid: 85d69f29-f857-4428-90a9-872b80e36573
@@ -0,0 +1,25 @@
FUNCTION "FC_Loglevel_to_String" : String
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
nLogLevel : Int;
END_VAR
BEGIN
CASE #nLogLevel OF
"E_LogLevel.DEBUG":
#FC_Loglevel_to_String := 'DEBUG';
"E_LogLevel.ERROR":
#FC_Loglevel_to_String := 'ERROR';
"E_LogLevel.INFO":
#FC_Loglevel_to_String := 'INFO';
"E_LogLevel.INT_ERROR":
#FC_Loglevel_to_String := 'INT_ERROR';
"E_LogLevel.WARNING":
#FC_Loglevel_to_String := 'WARNING';
ELSE
#FC_Loglevel_to_String := 'UNKNOWN';
END_CASE;
END_FUNCTION
@@ -0,0 +1,10 @@
LibraryType:
Guid: e790056b-d8d1-47bb-bce9-c6e26c157eec
Comment:
de-DE: Logging integriert
LibraryVersion:
VersionNumber: 0.0.14
Author: t.schiller
IsDefault: true
Comment:
de-DE: Logging integriert
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: FC_TimeAsString.scl
Hash: 3WJUl9RFht2vorDlH8QAIOs7AhSUh8JVzkcdrRKQwZo=
LibraryMetaFileHash: 4RB0ELjNFkABN8RO9ZmmvbU+HNP4H+TccEh5oYuI2rI=
LibraryVersion:
Guid: 36b9f032-4747-42aa-b87f-9637f121af9c
@@ -0,0 +1,83 @@
FUNCTION "FC_TimeAsString" : String
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_TEMP
tInt : DInt;
tDTL {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
sTmp : String[10];
END_VAR
BEGIN
#tInt := RD_LOC_T(#tDTL);
#sTmp := UINT_TO_STRING(#tDTL.HOUR);
IF #tDTL.HOUR < 10 THEN
#FC_TimeAsString[1] := '0';
#FC_TimeAsString[2] := #sTmp[2];
ELSE
#FC_TimeAsString[1] := #sTmp[2];
#FC_TimeAsString[2] := #sTmp[3];
END_IF;
#FC_TimeAsString[3] := ':';
#sTmp := USINT_TO_STRING(#tDTL.MINUTE);
IF #tDTL.MINUTE < 10 THEN
#FC_TimeAsString[4] := '0';
#FC_TimeAsString[5] := #sTmp[2];
ELSE
#FC_TimeAsString[4] := #sTmp[2];
#FC_TimeAsString[5] := #sTmp[3];
END_IF;
#FC_TimeAsString[6] := ':';
#sTmp := USINT_TO_STRING(#tDTL.SECOND);
IF #tDTL.SECOND < 10 THEN
#FC_TimeAsString[7] := '0';
#FC_TimeAsString[8] := #sTmp[2];
ELSE
#FC_TimeAsString[7] := #sTmp[2];
#FC_TimeAsString[8] := #sTmp[3];
END_IF;
#FC_TimeAsString[9] := ',';
#sTmp := UDINT_TO_STRING(#tDTL.NANOSECOND);
IF #tDTL.NANOSECOND < 1000000 THEN
#FC_TimeAsString[10] := '0';
#FC_TimeAsString[11] := '0';
#FC_TimeAsString[12] := '0';
ELSIF #tDTL.NANOSECOND < 10000000 THEN
#FC_TimeAsString[10] := '0';
#FC_TimeAsString[11] := '0';
#FC_TimeAsString[12] := #sTmp[2];
ELSIF #tDTL.NANOSECOND < 100000000 THEN
#FC_TimeAsString[10] := '0';
#FC_TimeAsString[11] := #sTmp[2];
#FC_TimeAsString[12] := #sTmp[3];
ELSE
#FC_TimeAsString[10] := #sTmp[2];
#FC_TimeAsString[11] := #sTmp[3];
#FC_TimeAsString[12] := #sTmp[4];
END_IF;
END_FUNCTION
@@ -0,0 +1,8 @@
LibraryType:
Guid: 7462bbc8-2811-4b0d-bdf1-031a6aa286ee
LibraryVersion:
VersionNumber: 0.0.6
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Inkonsistenz bereinigen
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_ParseCheckForEnd.scl
Hash: 9/ZVb2UiTOhclEguONKnCzWJfK1tn9Z9sOJsqztg35M=
LibraryMetaFileHash: l4eOdmK051pj+qL8jJiaNVxTNzEGtoXFkqzf7GlEhpQ=
LibraryVersion:
Guid: c0b69439-324f-4624-bfa7-02fc724e52f7
DependsOn:
- TypeName: UDT_TelegramDefinition
VersionNumber: 0.0.5
@@ -0,0 +1,44 @@
FUNCTION "FC_ParseCheckForEnd" : Bool
TITLE = FC_ParseCheckForEnd
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : 'e.yueksel'
FAMILY : Parser
VERSION : 0.1
//Diese Baustein überprüft neue Telegramme auf Endekennung entsprechend der Telegrammdefinition.
VAR_INPUT
bInNewData : Byte; // The byte we compare to the end marker
arInBuffer : Array[*] of Byte; // The buffer (Array of bytes) we are currently parsing
nInBufferLen : DInt; // Length of the buffer
stInTelegramDefinition : "UDT_TelegramDefinition"; // The definition of the telegram (Parameters)
END_VAR
VAR_TEMP
j : DInt; // Loop variable
END_VAR
BEGIN
IF (#stInTelegramDefinition.nEndMarkerLen > 0) THEN
IF (#bInNewData = #stInTelegramDefinition.sEndMarker[#stInTelegramDefinition.nEndMarkerLen] AND
#nInBufferLen >= UDINT_TO_DINT(#stInTelegramDefinition.nStartMarkerLen + #stInTelegramDefinition.nEndMarkerLen)) THEN
FOR #j := 0 TO UDINT_TO_DINT(#stInTelegramDefinition.nEndMarkerLen - 1) DO
IF (#arInBuffer[#nInBufferLen - 1 - #j] <> #stInTelegramDefinition.sEndMarker[UDINT_TO_DINT(#stInTelegramDefinition.nEndMarkerLen) - #j]) THEN
#FC_ParseCheckForEnd := FALSE;
RETURN;
END_IF;
END_FOR;
IF (#stInTelegramDefinition.nLength > 0) THEN
#FC_ParseCheckForEnd := (#nInBufferLen = UDINT_TO_DINT(#stInTelegramDefinition.nLength));
ELSE
#FC_ParseCheckForEnd := TRUE;
END_IF;
ELSE
#FC_ParseCheckForEnd := FALSE;
END_IF;
ELSE
#FC_ParseCheckForEnd := (#nInBufferLen = UDINT_TO_DINT(#stInTelegramDefinition.nLength));
END_IF;
END_FUNCTION
@@ -0,0 +1,8 @@
LibraryType:
Guid: 9058dc9e-b9e7-4405-8e1d-e48b9273bd5f
LibraryVersion:
VersionNumber: 0.0.6
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Inkonsistenz bereinigen
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_ParseCheckForStart.scl
Hash: 9k9Nch0mhI2FlPOZygpnN+PfrnpwH9iV2hqhIx8frpQ=
LibraryMetaFileHash: RvU2tTT+yCMb2ZwWGKDCVMASSZnGv/yIPXb59NkUwLY=
LibraryVersion:
Guid: 592d2c58-e2fc-4ba6-a0b2-d15ffd39706c
DependsOn:
- TypeName: UDT_TelegramDefinition
VersionNumber: 0.0.5
@@ -0,0 +1,39 @@
FUNCTION "FC_ParseCheckForStart" : Bool
TITLE = FC_ParseCheckForStart
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : 'e.yueksel'
FAMILY : Parser
VERSION : 0.1
//Diese Baustein überprüft neue Telegramme auf Anfangskennung entsprechend der Telegrammdefinition.
VAR_INPUT
bInNewData : Byte; // The byte we compare to the Start marker
arInBuffer : Array[*] of Byte; // The buffer (Array of bytes) we are parsing
nInBufferLen : DInt; // Length of the buffer
stInTelegramDefinition : "UDT_TelegramDefinition"; // The definition of the telegram (Parameters)
END_VAR
VAR_TEMP
j : DInt; // Loop variable
END_VAR
BEGIN
IF (#stInTelegramDefinition.nStartMarkerLen > 0) THEN
IF (#bInNewData = #stInTelegramDefinition.sStartMarker[#stInTelegramDefinition.nStartMarkerLen] AND
(#nInBufferLen >= UDINT_TO_DINT(#stInTelegramDefinition.nStartMarkerLen))) THEN
FOR #j := 0 TO UDINT_TO_DINT(#stInTelegramDefinition.nStartMarkerLen - 1) DO
IF (#arInBuffer[#nInBufferLen -1 - #j] <> #stInTelegramDefinition.sStartMarker[UDINT_TO_DINT(#stInTelegramDefinition.nStartMarkerLen)-#j]) THEN
#FC_ParseCheckForStart := FALSE;
RETURN;
END_IF;
END_FOR;
#FC_ParseCheckForStart := TRUE;
ELSE
#FC_ParseCheckForStart := FALSE;
END_IF;
ELSE
#FC_ParseCheckForStart := FALSE; // In case there is no start pattern specified, the parser state machine recognizes the telegram start itself regarding to its state.
END_IF;
END_FUNCTION
@@ -0,0 +1,10 @@
LibraryType:
Guid: 9e889e59-adc4-4817-8885-2d408e4ff768
Comment:
de-DE: This function adds a data field to the specified telegram structure.
LibraryVersion:
VersionNumber: 0.0.9
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Inkonsistenzen bereinigen
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_TeleAddDataField.scl
Hash: 63DCFc6AOKpwg1krHbJjA5Tz/waL4QqqsZvV9AMenTU=
LibraryMetaFileHash: G0WbKZtqy7nLffNAddkbfu3qRl0eIzYFamjIKGv99uQ=
LibraryVersion:
Guid: 6be99168-8a2f-46e7-a409-2f15f6e67651
DependsOn:
- TypeName: UDT_TelegramData_Send
VersionNumber: 0.0.7
@@ -0,0 +1,27 @@
FUNCTION "FC_TeleAddDataField" : Bool
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
sData : String; // The data field string to be added to the telegram structure.
END_VAR
VAR_IN_OUT
stInOutTelegram : "UDT_TelegramData_Send"; // The telegram structure the data field has to be added to.
END_VAR
BEGIN
IF (#stInOutTelegram.nDataCount < "TELEGRAM_DATA_MAX") THEN
IF (#stInOutTelegram.nDataCount < 0) THEN
#stInOutTelegram.nDataCount := 0;
END_IF;
#stInOutTelegram.nDataCount := #stInOutTelegram.nDataCount + 1;
#stInOutTelegram.arDataString[#stInOutTelegram.nDataCount] := #sData;
#FC_TeleAddDataField := TRUE;
ELSE
#FC_TeleAddDataField := FALSE;
END_IF;
END_FUNCTION
@@ -0,0 +1,10 @@
LibraryType:
Guid: 272019d6-a5d4-42eb-ab50-ec388ffd3f94
Comment:
de-DE: Clears all data from a telegram structure.
LibraryVersion:
VersionNumber: 0.0.9
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Inkonsistenz bereinigen
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_TeleClear.scl
Hash: hEY0IFNekUPh+kWKDAoyWT+QezW7yIaW/5arbGJdFpo=
LibraryMetaFileHash: EF4Y+gXJ2WtV4auuc+0dAkuvfHCj+O0RUGVJzamyNVU=
LibraryVersion:
Guid: 28843e37-741d-4597-b662-bf6665818a62
DependsOn:
- TypeName: UDT_TelegramData_Send
VersionNumber: 0.0.7
@@ -0,0 +1,34 @@
FUNCTION "FC_TeleClear" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_IN_OUT
stInOutTelegram : "UDT_TelegramData_Send"; // The telegram structure that will be cleared
END_VAR
VAR_TEMP
i : DInt; // Loop-Variable
j : DInt; // Loop-Variable
k : DInt; // Loop-Variable
END_VAR
BEGIN
#stInOutTelegram.sIDString := '';
#stInOutTelegram.nID := 0;
#stInOutTelegram.xCRC32ValidationResult := FALSE;
// FOR #i := 1 TO "TELEGRAM_DATA_MAX" DO
// FOR #j := 1 TO "TELEGRAM_DATA_FIELD_MAX" DO
// #stInOutTelegram.arData[#i, #j] := 0;
// END_FOR;
// END_FOR;
FOR #k := 1 TO "TELEGRAM_DATA_MAX" DO
#stInOutTelegram.arDataString[#k] := '';
END_FOR;
#stInOutTelegram.nDataCount := 1;
END_FUNCTION
@@ -0,0 +1,10 @@
LibraryType:
Guid: 99766d0f-bd08-454b-9e46-328d2cb77a29
Comment:
de-DE: Function for setting specific data fields in a telegram
LibraryVersion:
VersionNumber: 0.0.9
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Inkonsistenz bereinigen
@@ -0,0 +1,9 @@
DocumentHash:
- FileName: FC_TeleSetData.scl
Hash: wbtLBqYtEiaMEj2GtP61PV9zGa+soXeltzAIYTqOOLI=
LibraryMetaFileHash: EOKSC9YV8b05PN8z3LARS3fY6EjohMYHJjagmgMXWfA=
LibraryVersion:
Guid: 60db9e8b-a41d-46fc-a29c-9293ce5b3b45
DependsOn:
- TypeName: UDT_TelegramData_Send
VersionNumber: 0.0.7
@@ -0,0 +1,27 @@
FUNCTION "FC_TeleSetData" : Bool
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
nDataField : UDInt; // The number of the data field to be modified, starts with "1".
sData : String; // The string that overwrites the existing data field value.
END_VAR
VAR_IN_OUT
stInOutTelegram : "UDT_TelegramData_Send"; // The telegram structure that contains the data field to be modified.
END_VAR
BEGIN
IF (#nDataField >= 1 AND UDINT_TO_DINT(#nDataField) <= "TELEGRAM_DATA_MAX") THEN
#stInOutTelegram.arDataString[#nDataField] := #sData;
IF (#stInOutTelegram.nDataCount < UDINT_TO_DINT(#nDataField)) THEN
#stInOutTelegram.nDataCount := UDINT_TO_DINT(#nDataField);
END_IF;
#FC_TeleSetData := TRUE;
ELSE
#FC_TeleSetData := FALSE;
END_IF;
END_FUNCTION
@@ -0,0 +1,8 @@
LibraryType:
Guid: f88be0d9-1f28-4bcb-a5a1-4b77b0e34878
LibraryVersion:
VersionNumber: 0.0.8
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Inkonsistenz bereinigen
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: UDT_TelegramData.xml
Hash: onl5A2ZBXD1Osb9HpyJYM94U0gKjCtdo5NXjCUPG6d4=
LibraryMetaFileHash: Oe4DDTrGKgyFYBb5byBV2S5tlyI6GYHDaPGbe9u0en4=
LibraryVersion:
Guid: 98b089a9-4b8e-4a6f-8a92-5ae5a1509c03
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V20" />
<SW.Types.PlcStruct ID="0">
<AttributeList>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="None">
<Member Name="sIDString" Datatype="String">
<Comment>
<MultiLanguageText Lang="de-DE">Wenn es eine Telegramm-ID gibt, wird sie hier angezeigt (not implemented)</MultiLanguageText>
</Comment>
</Member>
<Member Name="nID" Datatype="DInt">
<Comment>
<MultiLanguageText Lang="de-DE">Telegramm-ID als Nummer, wenn diese in der Telegramm-Definition vorgesehen wurde (not implemented)</MultiLanguageText>
</Comment>
</Member>
<Member Name="xCRC32ValidationResult" Datatype="Bool">
<Comment>
<MultiLanguageText Lang="de-DE">Wenn eine Validierung mit CRC32 im Telegramm implementiert ist, dann steht hier das Ergebnis (TRUE = erfolgreich, FALSE = nicht erfolgreich/ nicht definiert)</MultiLanguageText>
</Comment>
</Member>
<Member Name="arDataString" Datatype="Array[1..&quot;TELEGRAM_DATA_MAX&quot;] of String[&quot;TELEGRAM_DATA_FIELD_MAX&quot;]">
<Comment>
<MultiLanguageText Lang="de-DE">Die Telegrammdaten als Array of String. Jeder String entspricht einem Datenfeld.</MultiLanguageText>
</Comment>
</Member>
<Member Name="nDataCount" Datatype="DInt">
<Comment>
<MultiLanguageText Lang="de-DE">Anzahl der Datenfelder. </MultiLanguageText>
</Comment>
<StartValue>1</StartValue>
</Member>
</Section>
</Sections></Interface>
<Name>UDT_TelegramData</Name>
<Namespace />
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="3" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Types.PlcStruct>
</Document>
@@ -0,0 +1,6 @@
LibraryType:
Guid: 8ba5f026-f6a4-48b6-99af-dc7e461fdb45
LibraryVersion:
VersionNumber: 0.0.7
Author: e.yueksel
IsDefault: true
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: UDT_TelegramData_Send.xml
Hash: BQpYkFSPgx9BESwMa3p6bcSG7B5zPwgblsfSmxuhoMM=
LibraryMetaFileHash: cHNawuU7EPzVTRSwJgxUEYciiM7gvcd4ltOMZa0wIIg=
LibraryVersion:
Guid: 03564d6e-8226-4e22-a3ea-f92edd06e200
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V20" />
<SW.Types.PlcStruct ID="0">
<AttributeList>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="None">
<Member Name="sIDString" Datatype="String">
<Comment>
<MultiLanguageText Lang="de-DE">Wenn es eine Telegramm-ID gibt, wird sie hier angezeigt (not implemented)</MultiLanguageText>
</Comment>
</Member>
<Member Name="nID" Datatype="DInt">
<Comment>
<MultiLanguageText Lang="de-DE">Telegramm-ID als Nummer, wenn diese in der Telegramm-Definition vorgesehen wurde (not implemented)</MultiLanguageText>
</Comment>
</Member>
<Member Name="xCRC32ValidationResult" Datatype="Bool">
<Comment>
<MultiLanguageText Lang="de-DE">Wenn eine Validierung mit CRC32 im Telegramm implementiert ist, dann steht hier das Ergebnis (TRUE = erfolgreich, FALSE = nicht erfolgreich/ nicht definiert)</MultiLanguageText>
</Comment>
</Member>
<Member Name="arDataString" Datatype="Array[1..&quot;TELEGRAM_SEND_DATA_MAX&quot;] of String[&quot;TELEGRAM_DATA_FIELD_MAX&quot;]">
<Comment>
<MultiLanguageText Lang="de-DE">Die Telegrammdaten als Array of String. Jeder String entspricht einem Datenfeld.</MultiLanguageText>
</Comment>
</Member>
<Member Name="nDataCount" Datatype="DInt">
<Comment>
<MultiLanguageText Lang="de-DE">Anzahl der Datenfelder. </MultiLanguageText>
</Comment>
<StartValue>1</StartValue>
</Member>
</Section>
</Sections></Interface>
<Name>UDT_TelegramData_Send</Name>
<Namespace />
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="3" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>cs-CZ</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="5" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="6" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="7" CompositionName="Items">
<AttributeList>
<Culture>en-US</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
<MultilingualTextItem ID="8" CompositionName="Items">
<AttributeList>
<Culture>cs-CZ</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Types.PlcStruct>
</Document>
@@ -0,0 +1,8 @@
LibraryType:
Guid: 1e3c4983-857e-4011-8c76-51027a08bc9f
LibraryVersion:
VersionNumber: 0.0.5
Author: e.yueksel
IsDefault: true
Comment:
de-DE: Added string limitation for start and end markers
@@ -0,0 +1,6 @@
DocumentHash:
- FileName: UDT_TelegramDefinition.xml
Hash: 0cV/CYkCUk207NJBfTvndbGASucn+Kzead/vMTVLarM=
LibraryMetaFileHash: TDtZpXRWGqg0j67MMPtliOMgW6X9H+XAL8n1wjhMMGs=
LibraryVersion:
Guid: 2d1cc429-2c73-4e6c-80c3-aba5ed21dc9a
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Document>
<Engineering version="V20" />
<SW.Types.PlcStruct ID="0">
<AttributeList>
<Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
<Section Name="None">
<Member Name="sStartMarker" Datatype="String[&quot;TELEGRAM_MARKER_MAX&quot;]">
<Comment>
<MultiLanguageText Lang="de-DE">Start marker / Start pattern of the telegram </MultiLanguageText>
</Comment>
</Member>
<Member Name="nStartMarkerLen" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">Length of the start marker</MultiLanguageText>
</Comment>
</Member>
<Member Name="sEndMarker" Datatype="String[&quot;TELEGRAM_MARKER_MAX&quot;]">
<Comment>
<MultiLanguageText Lang="de-DE">End marker / End pattern of the telegram</MultiLanguageText>
</Comment>
</Member>
<Member Name="nEndMarkerLen" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">Length of the end marker</MultiLanguageText>
</Comment>
</Member>
<Member Name="sStartMarkerSend" Datatype="String[&quot;TELEGRAM_MARKER_MAX&quot;]">
<Comment>
<MultiLanguageText Lang="de-DE">Start marker / Start pattern of the telegram (for sending)</MultiLanguageText>
</Comment>
</Member>
<Member Name="nStartMarkerLenSend" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">Length of the start marker (for sending)</MultiLanguageText>
</Comment>
</Member>
<Member Name="sEndMarkerSend" Datatype="String[&quot;TELEGRAM_MARKER_MAX&quot;]">
<Comment>
<MultiLanguageText Lang="de-DE">End marker / End pattern of the telegram (for sending)</MultiLanguageText>
</Comment>
</Member>
<Member Name="nEndMarkerLenSend" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">Length of the end marker (for sending)</MultiLanguageText>
</Comment>
</Member>
<Member Name="bSeparatorByte" Datatype="Byte">
<Comment>
<MultiLanguageText Lang="de-DE">The byte, used for separation of telegram content</MultiLanguageText>
</Comment>
</Member>
<Member Name="nLength" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">The length of the telegram including start and end byte or zero to ignore the setting (fixed telegram length)</MultiLanguageText>
</Comment>
</Member>
<Member Name="nTelegramIDDataField" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">The number of the data field that contains the telegram ID or zero to ignore the setting (Not implemented)</MultiLanguageText>
</Comment>
</Member>
<Member Name="xTelegramIDIsNumber" Datatype="Bool">
<Comment>
<MultiLanguageText Lang="de-DE">Indicates whether the telegram ID is a number. When this parameter is set to TRUE, the ID string will be converted automatically (Not implemented)</MultiLanguageText>
</Comment>
</Member>
<Member Name="nCRC32ValidationDataField" Datatype="UDInt">
<Comment>
<MultiLanguageText Lang="de-DE">The number of the data field that contains the CRC32-Checksum or zero to ignore the setting</MultiLanguageText>
</Comment>
</Member>
</Section>
</Sections></Interface>
<Name>UDT_TelegramDefinition</Name>
<Namespace />
</AttributeList>
<ObjectList>
<MultilingualText ID="1" CompositionName="Comment">
<ObjectList>
<MultilingualTextItem ID="2" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
<MultilingualText ID="3" CompositionName="Title">
<ObjectList>
<MultilingualTextItem ID="4" CompositionName="Items">
<AttributeList>
<Culture>de-DE</Culture>
<Text />
</AttributeList>
</MultilingualTextItem>
</ObjectList>
</MultilingualText>
</ObjectList>
</SW.Types.PlcStruct>
</Document>