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.

Production Recipe 1:

Kategorie

SQL Expert Mode

Verwendete Datenbank

XML (als freie XML Dokumente)

Kompatible Datenbanken

XML

Verwendete SPS Funktionsbausteine

FB_PLCDBCmdEvt

Verwendete SPS Bibliotheken

Tc3_Database, Tc3_Eventlogger

Download

TF6420_Sample4_XMLProductionConfig.zip

Rezept XML:

Production Recipe 2:

Test XML:

Production Recipe 3:

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