LogManager by @lmdejong
PROGRAM LogManager VAR POU_ERROR: BOOL; ManagerState: INT:=0; ErrorAtState: INT:=0; State_eError: FILE.ERROR; hFile: FILE.CAA.HANDLE; filop: FILE.Open; filcl: FILE.Close; filwr: FILE.Write; hDir: FILE.CAA.HANDLE; fildop: FILE.DirOpen; fildcl: FILE.DirClose; fildcr: FILE.DirCreate; LOG30: TBLOG; LOG76: TBLOG; LWD: ARRAY [0..MaxID-1] OF TBTEST; sTarget: STRING; sFileName: STRING; TestID: UINT; xFileExists: BOOL; udiFileSize: UDINT; szFileSize1: FILE.CAA.SIZE := 0; udiCmpError: UDINT; j: UINT; sData: STRING(255); sRaw: STRING(255); sYear: STRING(4); sMonth: STRING(2); sDay: STRING(2); sHour: STRING(2); sMinute: STRING(2); sSecond: STRING(2); sDaySep: STRING(1) := '-'; sTimSep: STRING(1) := ':'; xTrigLog30: BOOL; xTrigLog76: BOOL; END_VAR VAR CONSTANT MaxID: UINT := 3; HeaderNames: STRING(117) := 'DateTime;TestState;TestPaused;TestCounterA;RunTimeStrokeA;RunTimeTotalA;TestCounterB;RunTimeStrokeB;RunTimeTotalB$R$N'; END_VAR //Save log section LOG30.LTT(PT:=gvl_LogUpdateFreq); LOG76.LTT(PT:=gvl_LogUpdateFreq); CASE(ManagerState) OF 0: // Initializing LogManager POU_ERROR := FALSE; fildop( xExecute:=FALSE); IF PLC_R.i_wSdCardStatus <> SEC.PLC_R_SDCARD_STATUS.SDCARD_READWRITE THEN // // SDCARD error ErrorAtState := ManagerState; State_eError := FILE.ERROR.NOT_EXIST; ManagerState := 90; ELSE ManagerState := 10; // Skip folder actions END_IF 10: // SD-card in correct state check if folder exists fildop.sDirName := gvl_sLogDir; fildop( xExecute:=TRUE); IF fildop.xDone THEN hDir := fildop.hDir; IF NOT fildop.xError THEN ManagerState := 11; END_IF END_IF IF fildop.xError THEN //IF fildop.eError = FILE.ERROR.NOT_EXIST THEN ManagerState := 15; (*ELSE State_eError := fildop.eError; ErrorAtState := ManagerState; ManagerState := 90; END_IF*) END_IF IF fildop.xDone THEN fildop( xExecute := FALSE ); END_IF 11: // Close directory fildcl.hDir := hDir; fildcl (xExecute := TRUE); IF fildcl.xDone = TRUE THEN fildcl (xExecute := FALSE); ManagerState := 20; END_IF IF fildcl.xError = TRUE THEN ErrorAtState := ManagerState; State_eError := fildcl.eError; ManagerState := 90; END_IF 15: // Create directory fildcr.sDirName := gvl_sLogDir; fildcr( xExecute := TRUE ); IF fildcr.xDone THEN fildcr.xExecute := FALSE; ManagerState := 0; // Return to check if file has been made END_IF IF fildcr.xError = TRUE THEN ErrorAtState := ManagerState; State_eError := fildcr.eError; ManagerState := 90; END_IF 20: // Waiting for event // Resetting all FB's filop (xExecute := FALSE); filcl (xExecute := FALSE); filwr (xExecute := FALSE); fildop(xExecute := FALSE); fildcr(xExecute := FALSE); //Setting the timer to be linked to wether the test is active or not IF TB30.State = STATE.AUTO THEN LOG30.LTT(IN := TRUE); ELSE LOG30.LTT(IN := FALSE); END_IF IF TB76.State = STATE.AUTO THEN LOG76.LTT(IN := TRUE); ELSE LOG76.LTT(IN := FALSE); END_IF //Checking triggers IF LOG30.State <> TB30.State OR LOG30.Paused <> TB30.Paused OR LOG30.LTT.Q OR xTrigLog30 THEN LWD := TEST_30; ManagerState := 30; LOG30.State := TB30.State; LOG30.Paused := TB30.Paused; IF LOG30.LTT.Q THEN LOG30.LTT( IN := FALSE); END_IF IF xTrigLog30 THEN xTrigLog30 := FALSE; END_IF ELSIF LOG76.State <> TB76.State OR LOG76.Paused <> TB76.Paused OR LOG76.LTT.Q OR xTrigLog76 THEN LWD := TEST_76; ManagerState := 30; LOG76.State := TB76.State; LOG76.Paused := TB76.Paused; IF LOG76.LTT.Q THEN LOG76.LTT( IN := FALSE); END_IF IF xTrigLog76 THEN xTrigLog76 := FALSE; END_IF END_IF 30: // Write start TestID := 0; ManagerState := 34; 34: // Check if enabled and generate name IF LWD[TestID].Enabled THEN //Generate file name IF LWD[TestID].Product = '' THEN LWD[TestID].Product := 'UNKNOWN PRODUCT'; END_IF IF LWD[TestID].ProductID = '' THEN LWD[TestID].ProductID := CONCAT('UNKNOWN PRODUCT ID ', UINT_TO_STRING(TestID)); END_IF sFileName := CONCAT(LWD[TestID].Product, ' - '); sFileName := CONCAT(sFileName, LWD[TestID].ProductID); sFileName := CONCAT(sFileName, '.csv'); sTarget := CONCAT(gvl_sLogDir, sFileName); //sTarget := sFileName; //sTarget := 'TestFile.txt'; ManagerState := 36; ELSE ManagerState := 70; END_IF 36: // Check if file exists udiFileSize := FILE.SysFileGetSize(sTarget, ADR(udiCmpError)); IF udiFileSize = 0 THEN //File doesnt exist or is empty //Header should be created ManagerState := 40; ELSIF udiCmpError = ERR_OK THEN //File exists //File should be directly opened in Append mode ManagerState := 45; ELSE State_eError := FILE.ERROR.ERROR_UNKNOWN; ErrorAtState := ManagerState; ManagerState := 90; END_IF 40: // File doenst exist - Create file filop.sFileName := sTarget; filop.eFileMode := FILE.MODE.MRDWR; filop.xExclusive:= TRUE; filop (xExecute := TRUE ); IF filop.xDone THEN hFile := filop.hFile; ManagerState := 42; END_IF IF filop.xError THEN State_eError := filop.eError; ErrorAtState := ManagerState; ManagerState := 90; END_IF 42: // New file created - Write header filwr.hFile:=hFile; filwr.pBuffer:=ADR(HeaderNames); filwr.szSize := INT_TO_USINT(Len(HeaderNames)); filwr.udiTimeOut:=100000; (* 100ms Timeout *) filwr( xExecute:=TRUE); IF filwr.xDone THEN ManagerState := 49; filwr (xExecute := FALSE); END_IF IF filwr.xError THEN State_eError := filwr.eError; ErrorAtState := ManagerState; ManagerState := 90; END_IF 45: // File exists open in MAPPD filop.sFileName := sTarget; filop.eFileMode := FILE.MODE.MAPPD; filop (xExecute := TRUE ); IF filop.xDone THEN hFile := filop.hFile; ManagerState := 50; END_IF IF filop.xError THEN State_eError := filop.eError; ErrorAtState := ManagerState; ManagerState := 90; END_IF 49: // Reset write FB filwr(xExecute := FALSE); IF NOT filwr.xBusy AND NOT filwr.xDone THEN ManagerState := 50; END_IF 50: // Generate data sYear := Mid(gvl_DT_string, 4, 4); sMonth:= Mid(gvl_DT_string, 2, 9); sDay := Mid(gvl_DT_string, 2, 12); sHour := Mid(gvl_DT_string, 2, 15); sMinute:=Mid(gvl_DT_string, 2, 18); sSecond:=Mid(gvl_DT_string, 2, 21); sRaw := ''; sRaw := CONCAT(sDay, sDaySep); sRaw := CONCAT(sRaw, sMonth); sRaw := CONCAT(sRaw, sDaySep); sRaw := CONCAT(sRaw, sYear); sRaw := CONCAT(sRaw, ' '); sRaw := CONCAT(sRaw, sHour); sRaw := CONCAT(sRaw, sTimSep); sRaw := CONCAT(sRaw, sMinute); sRaw := CONCAT(sRaw, sTimSep); sRaw := CONCAT(sRaw, sSecond); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,StateText(LWD[TestID].TestState)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,BOOL_TO_STRING(LWD[TestID].TestPaused)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,INT_TO_STRING(LWD[TestID].TestCounterA)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,TIME_TO_STRING(LWD[TestID].RunTimeStrokeA)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,TIME_TO_STRING(LWD[TestID].RunTimeTotalA)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,INT_TO_STRING(LWD[TestID].TestCounterB)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,TIME_TO_STRING(LWD[TestID].RunTimeStrokeB)); sRaw := CONCAT(sRaw,';'); sRaw := CONCAT(sRaw,TIME_TO_STRING(LWD[TestID].RunTimeTotalB)); sData := CONCAT(sRaw,'$R$N'); ManagerState := 55; 55: // Write data filwr.hFile:=hFile; filwr.pBuffer:=ADR(sData); filwr.szSize := INT_TO_USINT(Len(sData)); filwr.udiTimeOut:=100000; (* 100ms Timeout *) filwr( xExecute:=TRUE); IF filwr.xDone THEN ManagerState := 60; filwr (xExecute := FALSE); END_IF IF filwr.xError THEN State_eError := filwr.eError; ErrorAtState := ManagerState; ManagerState := 90; END_IF 60: // Writing done, close file filcl.hFile := hFile; filcl( xExecute := TRUE ); IF filcl.xDone THEN ManagerState := 61; END_IF IF filcl.xError THEN State_eError := filcl.eError; ErrorAtState := ManagerState; ManagerState := 90; END_IF 61: // Round up file writing filop(xExecute := FALSE); filcl(xExecute := FALSE); filwr(xExecute := FALSE); IF NOT filop.xBusy AND NOT filop.xDone AND NOT filcl.xBusy AND NOT filcl.xDone AND NOT filwr.xBusy AND NOT filwr.xDone THEN ManagerState := 70; END_IF 70: // Next item state or end cycle TestID := TestID + 1; IF TestID < MaxID THEN ManagerState := 34; ELSE ManagerState := 20; END_IF 90: // Error state POU_ERROR := TRUE; END_CASE