Production Recipe
In diesem Szenario wird gezeigt, wie der TwinCAT Database Server mit beliebig strukturierten XML‑Dateien umgeht. Aus einer XML-Datei wird das Produktionsrezept zum Bauen des Produkts ausgelesen und aus einer anderen Datei die entsprechenden Testparameter. Zudem werden die Testergebnisse in eine vorhandene XML-Datei geschrieben.

Kategorie | SQL Expert Mode |
Verwendete Datenbank | XML (als freie XML Dokumente) |
Kompatible Datenbanken | XML |
Verwendete SPS Funktionsbausteine | |
Verwendete SPS Bibliotheken | Tc3_Database, Tc3_Eventlogger |
Download |
Rezept XML:

Test XML:

FB_ProductionConfigData
GetConfig (Methode)
Diese Methode liest das Produktionsrezept eines Produkts aus einer XML-Datei aus. Mithilfe von XPath Queries kann nach dem richtigen Rezept gesucht werden.
METHOD GetConfig : BOOL
VAR_INPUT
nTypeNum : DINT;
END_VAR
VAR_OUTPUT
stConfig : ST_Config;
END_VAR
GetConfig:= FALSE;
arrPara[0].sParaName := 'rLength';
arrPara[0].eParaType := Tc3_Database.E_ExpParameterType.Float32;
arrPara[0].nParaSize := 4;
arrPara[1].sParaName := 'rWidth';
arrPara[1].eParaType := Tc3_Database.E_ExpParameterType.Float32;
arrPara[1].nParaSize := 4;
arrPara[2].sParaName := 'rHeight';
arrPara[2].eParaType := Tc3_Database.E_ExpParameterType.Float32;
arrPara[2].nParaSize := 4;
arrPara[3].sParaName := 'iQuantity';
arrPara[3].eParaType := Tc3_Database.E_ExpParameterType.Int32;
arrPara[3].nParaSize := 4;
arrPara[4].sParaName := 'iCounter';
arrPara[4].eParaType := Tc3_Database.E_ExpParameterType.Int32;
arrPara[4].nParaSize := 4;
sCmd := CONCAT(CONCAT('XPATH_SEL<SUBTAG>#ProductionConfig/Config[@TypeNum
= ', DINT_TO_STRING(nTypeNum)), ']');
CASE nState_GetConfig OF
0:
IF fbPLCDBCmd.ExecuteDataReturn(
hDBID:= 1,
pExpression:= ADR(sCmd),
cbExpression:= SIZEOF(sCmd),
pData:= 0,
cbData:= 0,
pParameter:= ADR(arrPara),
cbParameter:= SIZEOF(arrPara[0])*5,
nStartIndex:= 0,
nRecordCount:= 1,
pReturnData:= ADR(_stConfig),
cbReturnData:= SIZEOF(_stConfig),
pRecords:= 0) THEN
ipResultEvt := fbPLCDBCmd.ipTcResult;
nState_GetConfig := 100;
END_IF
100:
IF _SetResultInfo(1033) THEN
GetConfig := TRUE;
stConfig := _stConfig;
nState_GetConfig := 0;
END_IF
END_CASE
GetTestParameter (Methode)
Diese Methode liest die produktspezifischen Testparameter aus.
METHOD GetTestParameter : BOOL
VAR_INPUT
nTypeNum : DINT;
END_VAR
VAR_OUTPUT
sTestNum : STRING(8);
stTestPara: ST_TestParameter;
END_VAR
GetTestParameter := FALSE;
CASE nState_GetTestPara OF
0:
arrPara[0].sParaName := 'Test';
arrPara[0].eParaType := Tc3_Database.E_ExpParameterType.STRING_;
arrPara[0].nParaSize := 8;
sCmd := CONCAT(CONCAT('XPATH_SEL<ATTR>#ProductionConfig/Config
[@TypeNum = ', DINT_TO_STRING(nTypeNum)), ']');
IF fbPLCDBCmd.ExecuteDataReturn(
hDBID:= 1,
pExpression:= ADR(sCmd),
cbExpression:= SIZEOF(sCmd),
pData:= 0,
cbData:= 0,
pParameter:= ADR(arrPara),
cbParameter:= SIZEOF(arrPara[0]),
nStartIndex:= 0,
nRecordCount:= 1,
pReturnData:= ADR(_sTestNum),
cbReturnData:= SIZEOF(_sTestNum),
pRecords:= 0) THEN
bError := fbPLCDBCmd.bError;
sErrClass := fbPLCDBCmd.ipTcResultEvent.EventClassDisplayName;
nErrID := fbPLCDBCmd.ipTcResultEvent.EventId;
sErrText := fbPLCDBCmd.ipTcResultEvent.Text;
IF fbPLCDBCmd .bError THEN
ipResultEvt := fbPLCDBCmd.ipTcResult;
nState_GetTestPara:= 100;
ELSE
nState_GetTestPara:= 1;
END_IF
END_IF
1:
arrPara[0].sParaName := 'MaxTemp';
arrPara[0].eParaType := Tc3_Database.E_ExpParameterType.Float32;
arrPara[0].nParaSize := 4;
arrPara[1].sParaName := 'MinTemp';
arrPara[1].eParaType := Tc3_Database.E_ExpParameterType.Float32;
arrPara[1].nParaSize := 4;
arrPara[2].sParaName := 'MaxPSI';
arrPara[2].eParaType := Tc3_Database.E_ExpParameterType.Int32;
arrPara[2].nParaSize := 4;
sCmd := CONCAT(CONCAT('XPATH_SEL<SUBTAG>#ProductionConfig/
TestParameter/Test[@Num = $'', _sTestNum), '$']');
IF fbPLCDBCmd.ExecuteDataReturn(
hDBID:= 2,
pExpression:= ADR(sCmd),
cbExpression:= SIZEOF(sCmd),
pData:= 0,
cbData:= 0,
pParameter:= ADR(arrPara),
cbParameter:= SIZEOF(arrPara[0])*3,
nStartIndex:= 0,
nRecordCount:= 1,
pReturnData:= ADR(_stTest),
cbReturnData:= SIZEOF(_stTest),
pRecords:= 0) THEN
ipResultEvt := fbPLCDBCmd.ipTcResult;
nState_GetTestPara:= 100;
100:
IF _SetResultInfo(1033) THEN
nState_GetTestPara := 0;
stTestPara := _stTest;
sTestNum := _sTestNum;
GetTestParameter := TRUE;
END_IF
END_CASE
AddTestEntry (Methode)
Diese Methode fügt das Testergebnis in die Test-XML-Datei ein.
METHOD AddTestEntry : BOOL
VAR_INPUT
sTestNum : STRING(8);
nTypeNum : DINT;
sTimestamp : STRING;
sTester : STRING;
sResult : STRING;
END_VAR
AddTestEntry := FALSE;
arrPara[0].sParaName := 'TestNum';
arrPara[0].eParaType := Tc3_Database.E_ExpParameterType.STRING_;
arrPara[0].nParaSize := 8;
arrPara[1].sParaName := 'TypeNum';
arrPara[1].eParaType := Tc3_Database.E_ExpParameterType.Int32;
arrPara[1].nParaSize := 4;
arrPara[2].sParaName := 'Timestamp';
arrPara[2].eParaType := Tc3_Database.E_ExpParameterType.STRING_;
arrPara[2].nParaSize := 81;
arrPara[3].sParaName := 'Tester';
arrPara[3].eParaType := Tc3_Database.E_ExpParameterType.STRING_;
arrPara[3].nParaSize := 81;
arrPara[4].sParaName := 'Result';
arrPara[4].eParaType := Tc3_Database.E_ExpParameterType.STRING_;
arrPara[4].nParaSize := 81;
arrPara[5].sParaName := 'Test';
arrPara[5].eParaType := Tc3_Database.E_ExpParameterType.XMLTAGName;
arrPara[5].nParaSize := 0;
sCmd := 'XPATH_ADD<ATTR>#ProductionConfig/Tests';
stTest.sTestNum := sTestNum;
stTest.nTypeNum := nTypeNum;
stTest.sTimestamp := sTimestamp;
stTest.sTester := sTester;
stTest.sResult := sResult;
CASE nState_AddEntry OF
0:
IF fbPLCDBCmd.Execute(
hDBID:= 2,
pExpression:= ADR(sCmd),
cbExpression:= SIZEOF(sCmd),
pData:= ADR(stTest),
cbData:= SIZEOF(stTest),
pParameter:= ADR(arrPara),
cbParameter:= SIZEOF(arrPara)) THEN
ipResultEvt := fbPLCDBCmd.ipTcResult;
nState_AddEntry:= 100;
END_IF
100:
IF _SetResultInfo(1033) THEN
nState_AddEntry:= 0;
AddTestEntry:= TRUE;
END_IF
END_CASE
_SetResultInfo (Private Methode)
In der privaten Methode _SetResultInfo wird das Nachrichten-Interface I_Message vom TwinCAT Eventlogger ausgewertet.
METHOD _SetResultInfo : BOOL
VAR_INPUT
nLangId : INT := 1033;
END_VAR
_SetResultInfo := FALSE;
CASE nState_SetResInfo OF
0:
IF ipResultEvt.RequestEventText(nLangId, EventText, SIZEOF(EventText)) THEN
nState_SetResInfo := 1;
END_IF
1:
IF ipResultEvt.RequestEventClassName(nLangId, EventClassName, SIZEOF(EventClassName)) THEN
EventId := ipResultEvt.nEventId;
bError := (ipResultEvt.eSeverity = TcEventSeverity.Error) OR
(ipResultEvt.eSeverity = TcEventSeverity.Critical);
nState_SetResInfo:=0;
_SetResultInfo := TRUE;
END_IF
END_CASE