diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index e23ba01..dfd58e4 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -5,7 +5,7 @@ on: - main paths: - 'docs/**' - - 'TcLog/**' + - 'src/**' pull_request: workflow_dispatch: jobs: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f94de91..675a69c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,6 +29,8 @@ Please make sure that your pull request #### TwinCAT and Visual Studio The project uses TwinCAT 3.1.4024.29 and Visual Studio 2019 with .NET 7.0. +Please use the recommended [Zeugwerk IDE settings.](https://doc.zeugwerk.dev/contribute/recom_xae_settings.html) + #### Unit tests [TcUnit](https://tcunit.org/) is used for unit tests in plc project itself. diff --git a/README.md b/README.md index 66be266..af6ac81 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![](docs/images/TcLog_header.svg "TcLog_header") +![](documentation/images/TcLog_header.svg "TcLog_header") *Logging in TwinCAT with the on-board means is limited to the output as ADS event. The TcLog library presented here enables flexible logging to the file system.* It's usage is as simple as this: @@ -6,33 +6,34 @@ It's usage is as simple as this: Configure the core logger in your project: ``` VAR - _coreLogger : TcLogCore(bufferSize := 100 * SIZEOF(BYTE) * MAX_STRINGLENGTH); + _coreLogger : TcLogCore(bufferSize := 100 * SIZEOF(BYTE) * MAX_STRINGLENGTH); END_VAR _coreLogger - .WriteToAds() - .WriteToFile('c:\logs\', 'sensor_data.txt') - .MinimumLevel(LogLevels.Debug) - .RunLogger(); + .WriteToAds() + .WriteToFile('c:\logs\', 'sensor_data.txt') + .MinimumLevel(LogLevels.Debug) + .RunLogger(); ``` Then, maybe in a different POU, use `TcLog` to log messages: ``` VAR - _logger: TcLog; - _myInt : INT := 10; - _myVarInfo : __SYSTEM.VAR_INFO := __VARINFO(_myInt); + _logger: TcLog; + _myInt : INT := 10; + _myVarInfo : __SYSTEM.VAR_INFO := __VARINFO(_myInt); END_VAR _logger - .AppendString('Let´s log some values: ') - .AppendAny(_myInt) - .AppendString(' - or some symbols: ') - .AppendVariable(_myVarInfo, _myInt) - .Error(''); + .AppendString('Let´s log some values: ') + .AppendAny(_myInt) + .AppendString(' - or some symbols: ') + .AppendVariable(_myVarInfo, _myInt) + .Error(''); ``` This will log both messages to both the ADS output and the file system. -**Features** +🚀 **Features** 🚀 + - Log to ADS output - Log to file system - Fluent interface for easy configuration and usage @@ -43,16 +44,18 @@ This will log both messages to both the ADS output and the file system. - Log messages with or without timestamp - Custom log message formatting +🧪 **Tests** 🧪 + The project contains both unit ([TcUnit](https://tcunit.org)) and integration tests ([xUnit](https://xunit.net)). ## Install TcLog -See the [installation guide](docs/userguide/installation.html) for instructions on how to install TcLog. +See the [installation guide](https://bengeisler.github.io/TcLog/userguide/installation.html) for instructions on how to install TcLog. ## Getting started -Get quickly up and running with TcLog: [Get Started](docs/userguide/getting_started.html) +Get quickly up and running with TcLog: [Get Started](https://bengeisler.github.io/TcLog/userguide/getting_started.html) ## API reference -Find the full API reference [here](docs/reference/TcLog/Constants.html). +Find the full API reference [here](https://bengeisler.github.io/TcLog/reference/TcLog/Constants.html). ## License The library is licensed under the [MIT License](LICENSE). diff --git a/docs/docfx.json b/documentation/docfx.json similarity index 100% rename from docs/docfx.json rename to documentation/docfx.json diff --git a/docs/images/TcLog_header.svg b/documentation/images/TcLog_header.svg similarity index 100% rename from docs/images/TcLog_header.svg rename to documentation/images/TcLog_header.svg diff --git a/docs/index.md b/documentation/index.md similarity index 100% rename from docs/index.md rename to documentation/index.md diff --git a/docs/metadata.json b/documentation/metadata.json similarity index 100% rename from docs/metadata.json rename to documentation/metadata.json diff --git a/docs/toc.yml b/documentation/toc.yml similarity index 100% rename from docs/toc.yml rename to documentation/toc.yml diff --git a/docs/userguide/configuration.md b/documentation/userguide/configuration.md similarity index 93% rename from docs/userguide/configuration.md rename to documentation/userguide/configuration.md index ef985ed..c6e4445 100644 --- a/docs/userguide/configuration.md +++ b/documentation/userguide/configuration.md @@ -12,11 +12,11 @@ TcLog offers with `.IncludeInstancePath()` the possibility to include the locati ``` _coreLogger - .WriteToAds() - .IncludeInstancePath() - .MinimumLevel(LogLevels.Warning) - .RunLogger(); - + .WriteToAds() + .IncludeInstancePath() + .MinimumLevel(LogLevels.Warning) + .RunLogger(); + _logger.Error('This is an error message.'); ``` @@ -36,14 +36,14 @@ TcLog brings the option to store logs in the file system in the form of text fil ``` _coreLogger - .IncludeInstancePath() - .MinimumLevel(LogLevels.Warning) - .WriteToFile('c:\logs\', 'test.txt') - .RunLogger(); - + .IncludeInstancePath() + .MinimumLevel(LogLevels.Warning) + .WriteToFile('c:\logs\', 'test.txt') + .RunLogger(); + _loggerTrig - .OnRisingEdge(_log) - .Error('rTrig Test'); + .OnRisingEdge(_log) + .Error('rTrig Test'); ``` ![Logging to the file system](https://benediktgeisler.de/LogMessageInFiileSystem.png "Logging to the file system") diff --git a/docs/userguide/customization.md b/documentation/userguide/customization.md similarity index 76% rename from docs/userguide/customization.md rename to documentation/userguide/customization.md index 553dcda..111fb0d 100644 --- a/docs/userguide/customization.md +++ b/documentation/userguide/customization.md @@ -21,32 +21,32 @@ As wrapper we use an function block that encapsulates `TcLog` and enforces the d ``` FUNCTION_BLOCK UserLog IMPLEMENTS ILog VAR_INPUT - Condition: BOOL; - Identification: STRING; - Value: REAL; - Unit: STRING; + Condition: BOOL; + Identification: STRING; + Value: REAL; + Unit: STRING; END_VAR VAR - _getTimeData: DateTime; - _timestamp: STRING; + _getTimeData: DateTime; + _timestamp: STRING; END_VAR VAR_STAT - _logger: TcLog; + _logger: TcLog; END_VAR _getTimeData(); _timestamp := _getTimeData.ToString('hh:mm:ss'); _logger - .OnCondition(Condition) - .AppendString(_timestamp) - .AppendString(';') - .AppendString(Identification) - .AppendString(';') - .AppendAny(Value) - .AppendString(';') - .AppendString(Unit) - .ToCustomFormat(''); + .OnCondition(Condition) + .AppendString(_timestamp) + .AppendString(';') + .AppendString(Identification) + .AppendString(';') + .AppendAny(Value) + .AppendString(';') + .AppendString(Unit) + .ToCustomFormat(''); ``` We can use the helper function `GenerateTimeData`, which returns the current date and time formatted via the `.ToString(Format)` method. With its help we generate the timestamp of the sensor data. @@ -60,7 +60,7 @@ The interface is implemented by passing the logger reference to the `TcLog` inst ``` METHOD SetLogger : BOOL VAR_INPUT - ref2Core : REFERENCE TO TcLogCore; + ref2Core : REFERENCE TO TcLogCore; END_VAR _logger.SetLogger(ref2Core); @@ -72,35 +72,35 @@ Somewhere in our program `TcLogCore` is called cyclically. If there is more than ``` VAR - _newLogger: TcLogCore; - _rTrigLog : R_TRIG; - _log : BOOL; - _myLog : UserLog; - _myValue: REAL := 1.0; - _myValue2: REAL := 2.0; + _newLogger: TcLogCore; + _rTrigLog : R_TRIG; + _log : BOOL; + _myLog : UserLog; + _myValue: REAL := 1.0; + _myValue2: REAL := 2.0; END_VAR _newLogger - .MinimumLevel(LogLevels.Information) - .SetRollingInterval(RollingIntervals.Hourly) - .WriteToFile('c:\logs\', 'sensor.csv') - .DeleteLogFilesAfterDays(1) - .RunLogger(); - + .MinimumLevel(LogLevels.Information) + .SetRollingInterval(RollingIntervals.Hourly) + .WriteToFile('c:\logs\', 'sensor.csv') + .DeleteLogFilesAfterDays(1) + .RunLogger(); + _myLog.SetLogger(_newLogger); _rTrigLog(CLK := _log); _myLog( - Condition := _rTrigLog.Q, + Condition := _rTrigLog.Q, Identification := '+CC1-B31', - Value := _myValue, - Unit := '°C'); - + Value := _myValue, + Unit := '°C'); + _myLog( - Condition := _rTrigLog.Q, - Identification := '+CC1-B32', - Value := _myValue2, - Unit := '°C'); + Condition := _rTrigLog.Q, + Identification := '+CC1-B32', + Value := _myValue2, + Unit := '°C'); ``` As soon as logging is triggered via `_log`, the csv file and the entries in it are created: diff --git a/docs/userguide/getting_started.md b/documentation/userguide/getting_started.md similarity index 96% rename from docs/userguide/getting_started.md rename to documentation/userguide/getting_started.md index 2c20bcf..d6eb99a 100644 --- a/docs/userguide/getting_started.md +++ b/documentation/userguide/getting_started.md @@ -14,7 +14,7 @@ END_VAR _coreLogger .WriteToAds() - .WriteToFile('c:\logs\', 'sensor_data.txt') + .WriteToFile('c:\logs\', 'sensor_data.txt') .MinimumLevel(LogLevels.Debug) .RunLogger(); ``` diff --git a/docs/userguide/installation.md b/documentation/userguide/installation.md similarity index 100% rename from docs/userguide/installation.md rename to documentation/userguide/installation.md diff --git a/docs/userguide/license.md b/documentation/userguide/license.md similarity index 100% rename from docs/userguide/license.md rename to documentation/userguide/license.md diff --git a/docs/userguide/logging.md b/documentation/userguide/logging.md similarity index 98% rename from docs/userguide/logging.md rename to documentation/userguide/logging.md index 06a07a7..a862187 100644 --- a/docs/userguide/logging.md +++ b/documentation/userguide/logging.md @@ -1,4 +1,6 @@ # Logging +Next, we will look at the logging options of TcLog. + ## Flexible logging TcLog implements a [StringBuilder](https://www.plccoder.com/fluent-code/) which makes it easy to build your own message text: diff --git a/docs/userguide/performance.md b/documentation/userguide/performance.md similarity index 100% rename from docs/userguide/performance.md rename to documentation/userguide/performance.md diff --git a/docs/userguide/toc.yml b/documentation/userguide/toc.yml similarity index 86% rename from docs/userguide/toc.yml rename to documentation/userguide/toc.yml index a163263..fd6107d 100644 --- a/docs/userguide/toc.yml +++ b/documentation/userguide/toc.yml @@ -1,7 +1,5 @@ - name: Installation href: installation.md -- name: User Guide - href: getting_started.md - name: User guide items: - name: Getting started diff --git a/src/TcLog.sln b/src/TcLog.sln index 93306d6..2cc93c9 100644 --- a/src/TcLog.sln +++ b/src/TcLog.sln @@ -39,24 +39,6 @@ Global {84E2C694-C6B7-48C0-A46A-93E9E79E1E4B}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64) {84E2C694-C6B7-48C0-A46A-93E9E79E1E4B}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86) {84E2C694-C6B7-48C0-A46A-93E9E79E1E4B}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT OS (ARMT2) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT CE7 (ARMV7).Build.0 = Debug|TwinCAT CE7 (ARMV7) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT OS (ARMT2).ActiveCfg = Debug|TwinCAT OS (ARMT2) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT OS (ARMT2).Build.0 = Debug|TwinCAT OS (ARMT2) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT RT (x64).ActiveCfg = Debug|TwinCAT RT (x64) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT RT (x64).Build.0 = Debug|TwinCAT RT (x64) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT RT (x86).ActiveCfg = Debug|TwinCAT RT (x86) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Debug|TwinCAT RT (x86).Build.0 = Debug|TwinCAT RT (x86) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|Any CPU.ActiveCfg = Release|TwinCAT OS (ARMT2) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT CE7 (ARMV7).ActiveCfg = Release|TwinCAT CE7 (ARMV7) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT CE7 (ARMV7).Build.0 = Release|TwinCAT CE7 (ARMV7) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT OS (ARMT2).ActiveCfg = Release|TwinCAT OS (ARMT2) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT OS (ARMT2).Build.0 = Release|TwinCAT OS (ARMT2) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT RT (x64).ActiveCfg = Release|TwinCAT RT (x64) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT RT (x64).Build.0 = Release|TwinCAT RT (x64) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT RT (x86).ActiveCfg = Release|TwinCAT RT (x86) - {4D70D393-C90D-46C3-86AE-BDC75C79053F}.Release|TwinCAT RT (x86).Build.0 = Release|TwinCAT RT (x86) {534B7BB3-9B49-4F2B-86CC-2317930EA23D}.Debug|Any CPU.ActiveCfg = Debug|TwinCAT RT (x64) {534B7BB3-9B49-4F2B-86CC-2317930EA23D}.Debug|Any CPU.Build.0 = Debug|TwinCAT RT (x64) {534B7BB3-9B49-4F2B-86CC-2317930EA23D}.Debug|TwinCAT CE7 (ARMV7).ActiveCfg = Debug|TwinCAT CE7 (ARMV7) diff --git a/src/TcLogProj/TcLog/Logger/LogLevelToAdsLogMsgType.TcPOU b/src/TcLogProj/TcLog/Logger/LogLevelToAdsLogMsgType.TcPOU index 11acbce..bc3a28a 100644 --- a/src/TcLogProj/TcLog/Logger/LogLevelToAdsLogMsgType.TcPOU +++ b/src/TcLogProj/TcLog/Logger/LogLevelToAdsLogMsgType.TcPOU @@ -3,29 +3,25 @@ - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Logger/TcLog.TcPOU b/src/TcLogProj/TcLog/Logger/TcLog.TcPOU index eee8359..a9ab2cf 100644 --- a/src/TcLogProj/TcLog/Logger/TcLog.TcPOU +++ b/src/TcLogProj/TcLog/Logger/TcLog.TcPOU @@ -18,22 +18,22 @@ {attribute 'reflection'} FUNCTION_BLOCK TcLog IMPLEMENTS ILog VAR - _logConditionSatisfied : BOOL; // flag that indicates, whether log condition has been satisfied. - // Logging will only be carried out it this evaluates to TRUE. - _logDataInitialized : BOOL; // flag that indicate, whether log data has been initialized. - // Necessary for configuration methods to provide a fluent interface. - _logData : Tc2_System.T_MaxString; // contains message to be logged. - _usedLogger : ILogCore; - {attribute 'instance-path'} + _logConditionSatisfied : BOOL; // flag that indicates, whether log condition has been satisfied. + // Logging will only be carried out it this evaluates to TRUE. + _logDataInitialized : BOOL; // flag that indicate, whether log data has been initialized. + // Necessary for configuration methods to provide a fluent interface. + _logData : Tc2_System.T_MaxString; // contains message to be logged. + _usedLogger : ILogCore; + {attribute 'instance-path'} {attribute 'noinit'} - _instancePath : STRING; // contains instance path + _instancePath : STRING; // contains instance path END_VAR VAR_STAT {attribute 'hide'} - _loggerSingletonInstance : ILogCore; // Wires up TcLog ("Client") to TcLogCore ("Server") (Singleton-Behaviour) + _loggerSingletonInstance : ILogCore; // Wires up TcLog ("Client") to TcLogCore ("Server") (Singleton-Behaviour) END_VAR VAR CONSTANT - InvalidLoggerReference : UDINT := 0; + InvalidLoggerReference : UDINT := 0; END_VAR ]]> @@ -46,7 +46,7 @@ END_VAR METHOD AppendAny : REFERENCE TO TcLog VAR_INPUT /// data to be appended to log string. - data : ANY; + data : ANY; END_VAR ]]> @@ -63,14 +63,14 @@ AppendAny REF= THIS^;]]> METHOD AppendString : REFERENCE TO TcLog VAR_INPUT /// data to be appended to log string. - data : Tc2_System.T_MaxString; + data : Tc2_System.T_MaxString; END_VAR ]]> @@ -81,7 +81,7 @@ AppendString REF= THIS^;]]> /// ``` /// VAR /// Logger: TcLog; -/// myInt : INT := 10; +/// myInt : INT := 10; /// myVarInfo : __SYSTEM.VAR_INFO := __VARINFO(myInt); /// END_VAR /// Logger.AppendVariable(myVarInfo, myInt); @@ -89,14 +89,14 @@ AppendString REF= THIS^;]]> METHOD AppendVariable : REFERENCE TO TcLog VAR_INPUT /// [VAR_INFO](https://infosys.beckhoff.com/index.php?content=../content/1031/tc3_plc_intro/3527777675.html&id=) of variable to be appended to log string. - varInfo : __SYSTEM.VAR_INFO; + varInfo : __SYSTEM.VAR_INFO; /// Value of variable to be appended to log string. - value : ANY; + value : ANY; END_VAR VAR - format : Tc2_Utilities.FB_FormatString; - symbolName : Tc2_System.T_MaxString; - typeName : Tc2_System.T_MaxString; + format : Tc2_Utilities.FB_FormatString; + symbolName : Tc2_System.T_MaxString; + typeName : Tc2_System.T_MaxString; END_VAR ]]> @@ -106,10 +106,10 @@ symbolName := varInfo.Symbol; typeName := varInfo.TypeName; format( - sFormat := '%s [%s] : ', - arg1 := Tc2_Utilities.F_STRING(symbolName), - arg2 := Tc2_Utilities.F_STRING(typeName)); - + sFormat := '%s [%s] : ', + arg1 := Tc2_Utilities.F_STRING(symbolName), + arg2 := Tc2_Utilities.F_STRING(typeName)); + AppendString(format.sOut); AppendAny(value); @@ -117,21 +117,21 @@ AppendVariable REF= THIS^;]]> - InvalidLoggerReference THEN - _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Debug); - ELSE - Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); - END_IF + IF _usedLogger <> InvalidLoggerReference THEN + _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Debug); + ELSE + Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); + END_IF END_IF _logDataInitialized := FALSE;]]> @@ -141,17 +141,17 @@ _logDataInitialized := FALSE;]]> METHOD Error : BOOL VAR_INPUT /// Message to be appended to log string. - message : Tc2_System.T_MaxString; + message : Tc2_System.T_MaxString; END_VAR ]]> InvalidLoggerReference THEN - _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Error); - ELSE - Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); - END_IF + IF _usedLogger <> InvalidLoggerReference THEN + _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Error); + ELSE + Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); + END_IF END_IF _logDataInitialized := FALSE; ]]> @@ -162,17 +162,17 @@ _logDataInitialized := FALSE; METHOD Fatal : BOOL VAR_INPUT /// Message to be appended to log string. - message : Tc2_System.T_MaxString; + message : Tc2_System.T_MaxString; END_VAR ]]> InvalidLoggerReference THEN - _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Fatal); - ELSE - Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); - END_IF + IF _usedLogger <> InvalidLoggerReference THEN + _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Fatal); + ELSE + Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); + END_IF END_IF _logDataInitialized := FALSE;]]> @@ -182,17 +182,17 @@ _logDataInitialized := FALSE;]]> METHOD Information : BOOL VAR_INPUT /// Message to be appended to log string. - message : Tc2_System.T_MaxString; + message : Tc2_System.T_MaxString; END_VAR ]]> InvalidLoggerReference THEN - _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Information); - ELSE - Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); - END_IF + IF _usedLogger <> InvalidLoggerReference THEN + _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Information); + ELSE + Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); + END_IF END_IF _logDataInitialized := FALSE;]]> @@ -202,7 +202,7 @@ _logDataInitialized := FALSE;]]> METHOD PUBLIC Init : BOOL VAR_INPUT /// Reference to TcLoggerCore instance. - ref2Core : ILogCore; + ref2Core : ILogCore; END_VAR ]]> @@ -216,10 +216,10 @@ METHOD PRIVATE InitializeLogData : BOOL ]]> @@ -228,7 +228,7 @@ END_IF]]> METHOD OnCondition : REFERENCE TO TcLog VAR_INPUT /// Logs data only if this condition evaluates to TRUE. - cond : BOOL; + cond : BOOL; END_VAR ]]> @@ -245,7 +245,7 @@ OnCondition REF= THIS^;]]> METHOD SetLogger : BOOL VAR_INPUT /// Reference to Core Logger - ref2Core : ILogCore; + ref2Core : ILogCore; END_VAR ]]> @@ -257,13 +257,13 @@ END_VAR // such as concrete logger instance and plc/project names. METHOD PRIVATE ShortenInstancePath : Tc2_System.T_MaxString VAR_INPUT - path : Tc2_System.T_MaxString; // Instance path to be shortened. + path : Tc2_System.T_MaxString; // Instance path to be shortened. END_VAR VAR - i : UINT; - shortenedPath : Tc2_System.T_MaxString; - positionInString : INT := 0; - positionOfLastDot : INT := 0; + i : UINT; + shortenedPath : Tc2_System.T_MaxString; + positionInString : INT := 0; + positionOfLastDot : INT := 0; END_VAR ]]> @@ -271,9 +271,9 @@ END_VAR // Find last '.' WHILE(Tc2_Standard.FIND(shortenedPath, '.') > 0) DO - positionInString := Tc2_Standard.FIND(shortenedPath, '.'); - shortenedPath := Tc2_Standard.DELETE(shortenedPath, positionInString+1, 0); - positionOfLastDot := positionOfLastDot+positionInString; + positionInString := Tc2_Standard.FIND(shortenedPath, '.'); + shortenedPath := Tc2_Standard.DELETE(shortenedPath, positionInString+1, 0); + positionOfLastDot := positionOfLastDot+positionInString; END_WHILE shortenedPath := Path; @@ -294,14 +294,14 @@ ShortenInstancePath := shortenedPath;]]> METHOD ToAdsLog : BOOL VAR_INPUT /// Log level in which message should be logged to ADS. - logLevel : LogLevels; + logLevel : LogLevels; END_VAR ]]> @@ -313,17 +313,17 @@ _logDataInitialized := FALSE;]]> METHOD ToCustomFormat : BOOL VAR_INPUT /// Message to be appended to log string. - message : Tc2_System.T_MaxString; + message : Tc2_System.T_MaxString; END_VAR ]]> InvalidLoggerReference THEN - _usedLogger.LogCustomFormat(Tc2_Standard.CONCAT(_logData, message)); - ELSE - Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); - END_IF + IF _usedLogger <> InvalidLoggerReference THEN + _usedLogger.LogCustomFormat(Tc2_Standard.CONCAT(_logData, message)); + ELSE + Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); + END_IF END_IF _logDataInitialized := FALSE;]]> @@ -333,80 +333,20 @@ _logDataInitialized := FALSE;]]> METHOD Warning : BOOL VAR_INPUT /// Message to be appended to log string. - message : Tc2_System.T_MaxString; + message : Tc2_System.T_MaxString; END_VAR ]]> InvalidLoggerReference THEN - _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Warning); - ELSE - Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); - END_IF + IF _usedLogger <> InvalidLoggerReference THEN + _usedLogger.LogStandardFormat(Tc2_Standard.CONCAT(_logData, message), ShortenInstancePath(_instancePath), LogLevels.Warning); + ELSE + Tc2_System.ADSLOGSTR(ADSLOG_MSGTYPE_LOG OR LogLevelToAdsLogMsgType(LogLevels.Error), 'usedLogger: No valid reference', ''); + END_IF END_IF _logDataInitialized := FALSE;]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Logger/TcLogCore.TcPOU b/src/TcLogProj/TcLog/Logger/TcLogCore.TcPOU index 7bb5e33..8bd8f04 100644 --- a/src/TcLogProj/TcLog/Logger/TcLogCore.TcPOU +++ b/src/TcLogProj/TcLog/Logger/TcLogCore.TcPOU @@ -12,11 +12,13 @@ /// automatically if enough memory is available. /// /// To set the inital buffer size to accomodate 100 messages, use it like this: -/// ``` +/// +/// ```st /// VAR /// myLogger: TcLogCore(BufferSize := 100 * SIZEOF(BYTE) * Tc2_System.MAX_STRING_LENGTH); /// END_VAR /// ``` +/// {attribute 'hide_all_locals'} FUNCTION_BLOCK TcLogCore IMPLEMENTS ILogCore VAR @@ -462,94 +464,5 @@ _config.FileName := fileName; WriteToFile REF= This^;]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Logger/_DataTypes/LoggingConfiguration.TcDUT b/src/TcLogProj/TcLog/Logger/_DataTypes/LoggingConfiguration.TcDUT index 69701de..0227d4c 100644 --- a/src/TcLogProj/TcLog/Logger/_DataTypes/LoggingConfiguration.TcDUT +++ b/src/TcLogProj/TcLog/Logger/_DataTypes/LoggingConfiguration.TcDUT @@ -4,26 +4,16 @@ +END_TYPE]]> \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Logger/_Tests/TestWrapper_NET.TcPOU b/src/TcLogProj/TcLog/Logger/_Tests/TestWrapper_NET.TcPOU index 0f5b1e2..4d1cf7b 100644 --- a/src/TcLogProj/TcLog/Logger/_Tests/TestWrapper_NET.TcPOU +++ b/src/TcLogProj/TcLog/Logger/_Tests/TestWrapper_NET.TcPOU @@ -3,58 +3,58 @@ @@ -62,147 +62,141 @@ END_VAR // Set up TcLog _coreLogger - .IncludeInstancePath() - .MinimumLevel(LogLevels.Warning) - .SetDelimiter(Delimiter) - .SetRollingInterval(RollingIntervals.Hourly) - .DeleteLogFilesAfterDays(1) - .TimestampFormat('_YYMMDD-hh-mm-ss_') - .WriteToAds() - .WriteToFile(FilePath, FileName) - .RunLogger(); + .IncludeInstancePath() + .MinimumLevel(LogLevels.Warning) + .SetDelimiter(Delimiter) + .SetRollingInterval(RollingIntervals.Hourly) + .DeleteLogFilesAfterDays(1) + .TimestampFormat('_YYMMDD-hh-mm-ss_') + .WriteToAds() + .WriteToFile(FilePath, FileName) + .RunLogger(); IF _flushCache THEN _coreLogger.FlushCache(); END_IF - + // Test drivers _getDateTime(); LocalTimeAsString := _getDateTime.AsLocalSystemTimeString; _setLocalSystemTime( - NETID := '', - TIMESTR := STRING_TO_SYSTEMTIME(NewLocalSystemTimeToBeSet), - START := TriggerNewLocalSystemTime, - TMOUT := T#2S - ); + NETID := '', + TIMESTR := STRING_TO_SYSTEMTIME(NewLocalSystemTimeToBeSet), + START := TriggerNewLocalSystemTime, + TMOUT := T#2S + ); // Execute tests IF Persist_simple_error_message_run THEN - Persist_simple_error_message_run := FALSE; - _logger - .Error(Persist_simple_error_message_data); + Persist_simple_error_message_run := FALSE; + _logger + .Error(Persist_simple_error_message_data); END_IF IF Persist_long_error_message_run THEN - Persist_long_error_message_run := FALSE; - _logger - .Error(Persist_long_error_message_data); + Persist_long_error_message_run := FALSE; + _logger + .Error(Persist_long_error_message_data); END_IF IF Do_not_persist_logs_below_log_level_run THEN - Do_not_persist_logs_below_log_level_run := FALSE; - _logger - .Information('Nothing'); + Do_not_persist_logs_below_log_level_run := FALSE; + _logger + .Information('Nothing'); END_IF IF Log_message_contains_instance_path_run THEN - Log_message_contains_instance_path_run := FALSE; - _logger - .Error('Nothing'); + Log_message_contains_instance_path_run := FALSE; + _logger + .Error('Nothing'); END_IF IF Log_message_uses_correct_delimiter_run THEN - Log_message_uses_correct_delimiter_run := FALSE; - _logger - .Error(Log_message_uses_correct_delimiter_data); + Log_message_uses_correct_delimiter_run := FALSE; + _logger + .Error(Log_message_uses_correct_delimiter_data); END_IF IF Log_message_contains_custom_formatted_timestamp_run THEN - Log_message_contains_custom_formatted_timestamp_run := FALSE; - _logger - .Error('Test message'); + Log_message_contains_custom_formatted_timestamp_run := FALSE; + _logger + .Error('Test message'); END_IF IF Delete_logs_if_expired_run THEN - Delete_logs_if_expired_run := FALSE; - _logger - .Error('Test message'); + Delete_logs_if_expired_run := FALSE; + _logger + .Error('Test message'); END_IF IF New_logfile_is_created_if_rolling_interval_rolls_run THEN - New_logfile_is_created_if_rolling_interval_rolls_run := FALSE; - _logger - .Error('Test message'); + New_logfile_is_created_if_rolling_interval_rolls_run := FALSE; + _logger + .Error('Test message'); END_IF IF Same_log_file_is_used_until_rolling_interval_rolls THEN - Same_log_file_is_used_until_rolling_interval_rolls := FALSE; - _logger - .Error('Test message'); + Same_log_file_is_used_until_rolling_interval_rolls := FALSE; + _logger + .Error('Test message'); END_IF IF Log_in_consecutive_cycles THEN - _logger - .Error(Tc2_Standard.CONCAT('Logging cycle ', INT_TO_STRING(_cycles))); - _cycles := _cycles + 1; - IF _cycles >= Number_of_log_cycles THEN - _cycles := 0; - Log_in_consecutive_cycles := FALSE; - END_IF + _logger + .Error(Tc2_Standard.CONCAT('Logging cycle ', INT_TO_STRING(_cycles))); + _cycles := _cycles + 1; + IF _cycles >= Number_of_log_cycles THEN + _cycles := 0; + Log_in_consecutive_cycles := FALSE; + END_IF END_IF IF Log_multiple_logs_in_one_cycle THEN - FOR _i:= 1 TO DINT_TO_INT(Number_of_logs_per_cycle) DO - _logger. - Error(Tc2_Standard.CONCAT('Logging multiple times per cycle. Current step: ', INT_TO_STRING(_i))); - END_FOR - Log_multiple_logs_in_one_cycle := FALSE; + FOR _i:= 1 TO DINT_TO_INT(Number_of_logs_per_cycle) DO + _logger. + Error(Tc2_Standard.CONCAT('Logging multiple times per cycle. Current step: ', INT_TO_STRING(_i))); + END_FOR + Log_multiple_logs_in_one_cycle := FALSE; END_IF IF Log_multiple_logs_in_multiple_cycles THEN - IF CycleCount <= Number_of_cycles THEN - FOR _i:= 1 TO DINT_TO_INT(Number_of_logs_per_cycle) DO - _logger - .AppendString('Logging multiple times per cycle. Cycle: ') - .AppendString(DINT_TO_STRING(CycleCount)) - .AppendString(' / Step: ') - .AppendString(INT_TO_STRING(_i)) - .Error(''); - END_FOR - CycleCount := CycleCount + 1; - ELSE - CycleCount := 1; - Log_multiple_logs_in_multiple_cycles := FALSE; - END_IF + IF CycleCount <= Number_of_cycles THEN + FOR _i:= 1 TO DINT_TO_INT(Number_of_logs_per_cycle) DO + _logger + .AppendString('Logging multiple times per cycle. Cycle: ') + .AppendString(DINT_TO_STRING(CycleCount)) + .AppendString(' / Step: ') + .AppendString(INT_TO_STRING(_i)) + .Error(''); + END_FOR + CycleCount := CycleCount + 1; + ELSE + CycleCount := 1; + Log_multiple_logs_in_multiple_cycles := FALSE; + END_IF END_IF _persistenceTimeStaysWithinBounds(CLK := (Persistance_time_stays_within_bounds AND _coreLogger.Busy)); IF _persistenceTimeStaysWithinBounds.Q THEN - CycleCount := 1; - Persistance_time_stays_within_bounds := FALSE; + CycleCount := 1; + Persistance_time_stays_within_bounds := FALSE; END_IF IF Persistance_time_stays_within_bounds THEN - Duration_in_cylces := Duration_in_cylces + 1; - IF CycleCount <= Number_of_cycles THEN - FOR _i:= 1 TO DINT_TO_INT(Number_of_logs_per_cycle) DO - _logger - .AppendString('Logging multiple times per cycle. Cycle: ') - .AppendString(DINT_TO_STRING(CycleCount)) - .AppendString(' / Step: ') - .AppendString(INT_TO_STRING(_i)) - .Error(''); - END_FOR - CycleCount := CycleCount + 1; - END_IF + Duration_in_cylces := Duration_in_cylces + 1; + IF CycleCount <= Number_of_cycles THEN + FOR _i:= 1 TO DINT_TO_INT(Number_of_logs_per_cycle) DO + _logger + .AppendString('Logging multiple times per cycle. Cycle: ') + .AppendString(DINT_TO_STRING(CycleCount)) + .AppendString(' / Step: ') + .AppendString(INT_TO_STRING(_i)) + .Error(''); + END_FOR + CycleCount := CycleCount + 1; + END_IF END_IF ]]> - - - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/StringBuilder/StringBuilder.TcPOU b/src/TcLogProj/TcLog/StringBuilder/StringBuilder.TcPOU index eb9080b..d9a185d 100644 --- a/src/TcLogProj/TcLog/StringBuilder/StringBuilder.TcPOU +++ b/src/TcLogProj/TcLog/StringBuilder/StringBuilder.TcPOU @@ -3,8 +3,8 @@ @@ -13,7 +13,7 @@ END_VAR @@ -24,13 +24,13 @@ Append := THIS^;]]> @@ -38,8 +38,8 @@ AppendIf := THIS^;]]> @@ -50,20 +50,20 @@ InsertAtLocation := THIS^;]]> - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/TESTS.TcPOU b/src/TcLogProj/TcLog/TESTS.TcPOU index 92453e9..7477788 100644 --- a/src/TcLogProj/TcLog/TESTS.TcPOU +++ b/src/TcLogProj/TcLog/TESTS.TcPOU @@ -3,10 +3,10 @@ @@ -14,9 +14,5 @@ END_VAR TestWrapper();]]> - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Utils/AnyToString.TcPOU b/src/TcLogProj/TcLog/Utils/AnyToString.TcPOU index 09ac59e..acc56c3 100644 --- a/src/TcLogProj/TcLog/Utils/AnyToString.TcPOU +++ b/src/TcLogProj/TcLog/Utils/AnyToString.TcPOU @@ -4,63 +4,59 @@ - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Utils/DateTime.TcPOU b/src/TcLogProj/TcLog/Utils/DateTime.TcPOU index 747a5cd..1414d6a 100644 --- a/src/TcLogProj/TcLog/Utils/DateTime.TcPOU +++ b/src/TcLogProj/TcLog/Utils/DateTime.TcPOU @@ -5,35 +5,35 @@ {attribute: 'hide_all_locals'} FUNCTION_BLOCK DateTime VAR - _localSystemTime : Tc2_Utilities.FB_LocalSystemTime; - _getSystemTime : Tc2_System.GETSYSTEMTIME; - _timeZoneInfo : Tc2_Utilities.FB_GetTimeZoneInformation; - _localTime : Tc2_Utilities.FB_SystemTimeToTzSpecificLocalTime; - _localSystemTimeValid : Tc2_Standard.R_TRIG; - _utcTime : Tc2_Utilities.FB_TzSpecificLocalTimeToFileTime; + _localSystemTime : Tc2_Utilities.FB_LocalSystemTime; + _getSystemTime : Tc2_System.GETSYSTEMTIME; + _timeZoneInfo : Tc2_Utilities.FB_GetTimeZoneInformation; + _localTime : Tc2_Utilities.FB_SystemTimeToTzSpecificLocalTime; + _localSystemTimeValid : Tc2_Standard.R_TRIG; + _utcTime : Tc2_Utilities.FB_TzSpecificLocalTimeToFileTime; END_VAR ]]> @@ -104,29 +104,29 @@ PROPERTY Done : BOOL {attribute 'hide_all_locals'} METHOD PRIVATE ReplaceFormatPlaceholder : STRING VAR_INPUT - format : STRING; - length : INT; - timeType : STRING(1); + format : STRING; + length : INT; + timeType : STRING(1); END_VAR VAR_INST - i : INT; - replaceString : STRING; - timeString : STRING; + i : INT; + replaceString : STRING; + timeString : STRING; END_VAR VAR - localSystemTime : Tc2_Utilities.TIMESTRUCT; + localSystemTime : Tc2_Utilities.TIMESTRUCT; END_VAR ]]> Tc2_Standard.LEN(timeString) THEN - FOR i:=1 TO length - Tc2_Standard.LEN(timeString) DO - replaceString := Tc2_Standard.CONCAT(replaceString, '0'); - END_FOR - replaceString := Tc2_Standard.CONCAT(replaceString, timeString); + FOR i:=1 TO length - Tc2_Standard.LEN(timeString) DO + replaceString := Tc2_Standard.CONCAT(replaceString, '0'); + END_FOR + replaceString := Tc2_Standard.CONCAT(replaceString, timeString); ELSE - replaceString := Tc2_Standard.RIGHT(timeString, length); + replaceString := Tc2_Standard.RIGHT(timeString, length); END_IF ReplaceFormatPlaceholder := Tc2_Standard.REPLACE(format, replaceString, length, Tc2_Standard.FIND(format, timeType));]]> @@ -147,8 +147,8 @@ ReplaceFormatPlaceholder := Tc2_Standard.REPLACE(format, replaceString, length, @@ -186,18 +186,18 @@ END_VAR inputString := format; WHILE Tc2_Standard.LEN(inputString) > 0 DO - char := Tc2_Standard.LEFT(inputString, 1); - - IF char = 'Y' THEN year := year + 1; - ELSIF char = 'M' THEN month := month + 1; - ELSIF char = 'D' THEN day := day + 1; - ELSIF char = 'h' THEN hour := hour + 1; - ELSIF char = 'm' THEN minute := minute + 1; - ELSIF char = 's' THEN second := second + 1; - ELSIF char = 'i' THEN millisecond := millisecond + 1; - END_IF - - inputString := Tc2_Standard.DELETE(inputString, 1, 1); + char := Tc2_Standard.LEFT(inputString, 1); + + IF char = 'Y' THEN year := year + 1; + ELSIF char = 'M' THEN month := month + 1; + ELSIF char = 'D' THEN day := day + 1; + ELSIF char = 'h' THEN hour := hour + 1; + ELSIF char = 'm' THEN minute := minute + 1; + ELSIF char = 's' THEN second := second + 1; + ELSIF char = 'i' THEN millisecond := millisecond + 1; + END_IF + + inputString := Tc2_Standard.DELETE(inputString, 1, 1); END_WHILE formattedString := ReplaceFormatPlaceholder(format, year, 'Y'); @@ -214,40 +214,5 @@ ToFormatString := formattedString; ]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Utils/DeleteOldFiles.TcPOU b/src/TcLogProj/TcLog/Utils/DeleteOldFiles.TcPOU index 0b45490..6fd0fa9 100644 --- a/src/TcLogProj/TcLog/Utils/DeleteOldFiles.TcPOU +++ b/src/TcLogProj/TcLog/Utils/DeleteOldFiles.TcPOU @@ -4,31 +4,31 @@ @@ -36,75 +36,75 @@ END_VAR // It first enumerates all files in the specified directory // and then deletes all files that have overpassed the specified due date CASE _state OF - DeleteFilesState.Idle: - IF StartScan THEN - _commandType:= eEnumCmd_First; - _deleteFileIndex := 1; - _state := DeleteFilesState.SearchNextFile; - END_IF - - DeleteFilesState.SearchNextFile: - IF _enumBusy.Q THEN - _state := DeleteFilesState.WaitUntilExecutionDone; - END_IF - - DeleteFilesState.WaitUntilExecutionDone: - IF NOT _enumFindFileList.bError THEN - IF NOT _enumFindFileList.bEOE THEN - IF _enumFindFileList.nFindFiles < MaxNumberOfFiles THEN - _state := DeleteFilesState.SearchNextFile; - ELSE - _commandType := eEnumCmd_Abort; - _state := DeleteFilesState.ProcessFoundFiles; - END_IF - ELSE - _state := DeleteFilesState.ProcessFoundFiles; - END_IF - ELSE - _state := DeleteFilesState.Idle; - END_IF - - DeleteFilesState.ProcessFoundFiles: - IF _deleteFileIndex > _enumFindFileList.nFindFiles THEN - _state := DeleteFilesState.Idle; - ELSE - _state := DeleteFilesState.CheckIfFileIsDirectory; - END_IF - - DeleteFilesState.CheckIfFileIsDirectory: - IF NOT _listOfFiles[_deleteFileIndex].fileAttributes.bDirectory THEN - _state := DeleteFilesState.CheckFileTime; - ELSE - _deleteFileIndex := _deleteFileIndex + 1; - _state := DeleteFilesState.ProcessFoundFiles; - END_IF - - DeleteFilesState.CheckFileTime: - IF GetFileAgeInSeconds(CurrentUtcTime, _listOfFiles[_deleteFileIndex]) > (ExpirationInDays * OneDayInSeconds) THEN - _state := DeleteFilesState.DeleteFile; - ELSE - _deleteFileIndex := _deleteFileIndex + 1; - _state := DeleteFilesState.ProcessFoundFiles; - END_IF - - DeleteFilesState.DeleteFile: - _fileNameToDelete := Tc2_Standard.CONCAT(FilePath, _listOfFiles[_deleteFileIndex].sFileName); - - IF _fileDeleteBusy.Q THEN - _deleteFileIndex := _deleteFileIndex + 1; - _fileDeleted := TRUE; - _state := DeleteFilesState.FileDeleted; - END_IF - IF _fileDelete.bError THEN - _state := DeleteFilesState.Idle; - END_IF - - DeleteFilesState.FileDeleted: - // This state is needed to generate a rising edge for FB_FileDelete - IF NOT _fileDeleted THEN - _state := DeleteFilesState.ProcessFoundFiles; - END_IF - _fileDeleted := FALSE; + DeleteFilesState.Idle: + IF StartScan THEN + _commandType:= eEnumCmd_First; + _deleteFileIndex := 1; + _state := DeleteFilesState.SearchNextFile; + END_IF + + DeleteFilesState.SearchNextFile: + IF _enumBusy.Q THEN + _state := DeleteFilesState.WaitUntilExecutionDone; + END_IF + + DeleteFilesState.WaitUntilExecutionDone: + IF NOT _enumFindFileList.bError THEN + IF NOT _enumFindFileList.bEOE THEN + IF _enumFindFileList.nFindFiles < MaxNumberOfFiles THEN + _state := DeleteFilesState.SearchNextFile; + ELSE + _commandType := eEnumCmd_Abort; + _state := DeleteFilesState.ProcessFoundFiles; + END_IF + ELSE + _state := DeleteFilesState.ProcessFoundFiles; + END_IF + ELSE + _state := DeleteFilesState.Idle; + END_IF + + DeleteFilesState.ProcessFoundFiles: + IF _deleteFileIndex > _enumFindFileList.nFindFiles THEN + _state := DeleteFilesState.Idle; + ELSE + _state := DeleteFilesState.CheckIfFileIsDirectory; + END_IF + + DeleteFilesState.CheckIfFileIsDirectory: + IF NOT _listOfFiles[_deleteFileIndex].fileAttributes.bDirectory THEN + _state := DeleteFilesState.CheckFileTime; + ELSE + _deleteFileIndex := _deleteFileIndex + 1; + _state := DeleteFilesState.ProcessFoundFiles; + END_IF + + DeleteFilesState.CheckFileTime: + IF GetFileAgeInSeconds(CurrentUtcTime, _listOfFiles[_deleteFileIndex]) > (ExpirationInDays * OneDayInSeconds) THEN + _state := DeleteFilesState.DeleteFile; + ELSE + _deleteFileIndex := _deleteFileIndex + 1; + _state := DeleteFilesState.ProcessFoundFiles; + END_IF + + DeleteFilesState.DeleteFile: + _fileNameToDelete := Tc2_Standard.CONCAT(FilePath, _listOfFiles[_deleteFileIndex].sFileName); + + IF _fileDeleteBusy.Q THEN + _deleteFileIndex := _deleteFileIndex + 1; + _fileDeleted := TRUE; + _state := DeleteFilesState.FileDeleted; + END_IF + IF _fileDelete.bError THEN + _state := DeleteFilesState.Idle; + END_IF + + DeleteFilesState.FileDeleted: + // This state is needed to generate a rising edge for FB_FileDelete + IF NOT _fileDeleted THEN + _state := DeleteFilesState.ProcessFoundFiles; + END_IF + _fileDeleted := FALSE; END_CASE @@ -126,7 +126,7 @@ _fileDelete(sNetId := '', sPathName := _fileNameToDelete, bExecute := (_state = DeleteFilesState.DeleteFile), tTimeout := T#10S); - + _fileDeleteBusy(CLK := _fileDelete.bBusy); // Error handling @@ -135,20 +135,16 @@ Error.Code := ErrorCodes.None; Error.Info := ''; IF _enumFindFileList.bError THEN - Error.Active := TRUE; - Error.Code := ErrorCodes.EnumeratingFilesInSpecifiedDirectoryFailed; - Error.Info := Tc2_Standard.CONCAT('Enumerating files in specified directory failed. Error thrown by FB_EnumFindFileList. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(_enumFindFileList.nErrId)); + Error.Active := TRUE; + Error.Code := ErrorCodes.EnumeratingFilesInSpecifiedDirectoryFailed; + Error.Info := Tc2_Standard.CONCAT('Enumerating files in specified directory failed. Error thrown by FB_EnumFindFileList. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(_enumFindFileList.nErrId)); END_IF - + IF _fileDelete.bError THEN - Error.Active := TRUE; - Error.Code := ErrorCodes.DeletingFileFailed; - Error.Info := Tc2_Standard.CONCAT('Deleting expired log file in specified directory failed. Error thrown by FB_FileDelete. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(_fileDelete.nErrId)); + Error.Active := TRUE; + Error.Code := ErrorCodes.DeletingFileFailed; + Error.Info := Tc2_Standard.CONCAT('Deleting expired log file in specified directory failed. Error thrown by FB_FileDelete. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(_fileDelete.nErrId)); END_IF]]> - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Utils/DynamicStringBuffer.TcPOU b/src/TcLogProj/TcLog/Utils/DynamicStringBuffer.TcPOU index 4100d54..3eaa2ae 100644 --- a/src/TcLogProj/TcLog/Utils/DynamicStringBuffer.TcPOU +++ b/src/TcLogProj/TcLog/Utils/DynamicStringBuffer.TcPOU @@ -4,14 +4,14 @@ @@ -20,7 +20,7 @@ END_VAR @@ -31,7 +31,7 @@ _fifo.A_AddTail(putValue := Tc2_Standard.CONCAT(text, '$N')); ]]> @@ -42,7 +42,7 @@ _fifo.A_AddTail(putValue := text); ]]> @@ -72,7 +72,7 @@ PROPERTY Busy : BOOL @@ -89,7 +89,7 @@ END_VAR @@ -100,31 +100,31 @@ END_VAR @@ -135,105 +135,105 @@ END_VAR // *** I D L E *** IF state = PersistToFileState.Idle THEN - lockFileWriteToForceRisingEdge := FALSE; - IF _fifo.nCount > 0 THEN - lockFileWriteToForceRisingEdge := FALSE; - state := PersistToFileState.OpenFile; - END_IF + lockFileWriteToForceRisingEdge := FALSE; + IF _fifo.nCount > 0 THEN + lockFileWriteToForceRisingEdge := FALSE; + state := PersistToFileState.OpenFile; + END_IF END_IF - + // *** O P E N F I L E *** fileOpen(sNetId := NetId, sPathName := fileName, nMode := FOPEN_MODEAPPEND OR FOPEN_MODETEXT, - ePath := PATH_GENERIC, bExecute := (state = PersistToFileState.OpenFile), tTimeout := Timeout, - hFile => fileHandle); + ePath := PATH_GENERIC, bExecute := (state = PersistToFileState.OpenFile), tTimeout := Timeout, + hFile => fileHandle); IF state = PersistToFileState.OpenFile THEN - IF fileOpen.bError THEN - state := PersistToFileState.CloseFile; - ELSIF NOT fileOpen.bBusy THEN - state := PersistToFileState.GetStringFromFifo; - END_IF + IF fileOpen.bError THEN + state := PersistToFileState.CloseFile; + ELSIF NOT fileOpen.bBusy THEN + state := PersistToFileState.GetStringFromFifo; + END_IF END_IF // *** P O P F R O M F I F O *** IF state = PersistToFileState.GetStringFromFifo THEN - IF NOT lockFileWriteToForceRisingEdge THEN - currentBufferPos := 0; - FOR i:=0 TO MaxLogsPerCycle DO - IF _fifo.nCount <= 0 THEN EXIT; END_IF - IF currentBufferPos >= MaxBufferPosition THEN EXIT; END_IF - - _fifo.A_RemoveHead(getValue => fifoHeadString); - fifoHeadBytes := MAXSTRING_TO_BYTEARR(fifoHeadString); - fifoHeadLength := INT_TO_UDINT(LEN(fifoHeadString)); - MEMCPY( - destAddr := ADR(buffer) + SIZEOF(BYTE) * currentBufferPos, - srcAddr := ADR(fifoHeadBytes), - n := fifoHeadLength); - currentBufferPos := currentBufferPos + fifoHeadLength; - END_FOR - state := PersistToFileState.AppendDataToFile; - END_IF - lockFileWriteToForceRisingEdge := FALSE; + IF NOT lockFileWriteToForceRisingEdge THEN + currentBufferPos := 0; + FOR i:=0 TO MaxLogsPerCycle DO + IF _fifo.nCount <= 0 THEN EXIT; END_IF + IF currentBufferPos >= MaxBufferPosition THEN EXIT; END_IF + + _fifo.A_RemoveHead(getValue => fifoHeadString); + fifoHeadBytes := MAXSTRING_TO_BYTEARR(fifoHeadString); + fifoHeadLength := INT_TO_UDINT(LEN(fifoHeadString)); + MEMCPY( + destAddr := ADR(buffer) + SIZEOF(BYTE) * currentBufferPos, + srcAddr := ADR(fifoHeadBytes), + n := fifoHeadLength); + currentBufferPos := currentBufferPos + fifoHeadLength; + END_FOR + state := PersistToFileState.AppendDataToFile; + END_IF + lockFileWriteToForceRisingEdge := FALSE; END_IF - + // *** W R I T E T O F I L E *** fileWrite( - sNetId := NetId, - hFile := fileHandle, - pWriteBuff := ADR(buffer), - cbWriteLen := currentBufferPos, - bExecute := state = PersistToFileState.AppendDataToFile, - tTimeout := Timeout); + sNetId := NetId, + hFile := fileHandle, + pWriteBuff := ADR(buffer), + cbWriteLen := currentBufferPos, + bExecute := state = PersistToFileState.AppendDataToFile, + tTimeout := Timeout); IF state = PersistToFileState.AppendDataToFile THEN - lockFileWriteToForceRisingEdge := TRUE; - IF fileWrite.bError THEN - state := PersistToFileState.CloseFile; - ELSIF _fifo.nCount > 0 AND NOT fileWrite.bBusy THEN - state := PersistToFileState.GetStringFromFifo; - ELSIF _fifo.nCount = 0 THEN - state := PersistToFileState.CloseFile; - END_IF + lockFileWriteToForceRisingEdge := TRUE; + IF fileWrite.bError THEN + state := PersistToFileState.CloseFile; + ELSIF _fifo.nCount > 0 AND NOT fileWrite.bBusy THEN + state := PersistToFileState.GetStringFromFifo; + ELSIF _fifo.nCount = 0 THEN + state := PersistToFileState.CloseFile; + END_IF END_IF - + // *** C L O S E F I L E *** fileClose( - sNetId := NetId, hFile := fileHandle, - bExecute := (state = PersistToFileState.CloseFile), tTimeout := Timeout); + sNetId := NetId, hFile := fileHandle, + bExecute := (state = PersistToFileState.CloseFile), tTimeout := Timeout); IF state = PersistToFileState.CloseFile THEN - IF NOT fileClose.bBusy THEN state := PersistToFileState.Idle; END_IF + IF NOT fileClose.bBusy THEN state := PersistToFileState.Idle; END_IF END_IF // Close file in case of error IF fileOpen.bError THEN state := PersistToFileState.CloseFile; END_IF IF fileWrite.bError THEN state := PersistToFileState.CloseFile; END_IF IF NOT _fifo.bOk AND _fifo.nCount > 0 AND state <> PersistToFileState.Idle THEN - state := PersistToFileState.CloseFile; + state := PersistToFileState.CloseFile; END_IF // Error handling IF fileOpen.bError THEN - Error.Active := TRUE; - Error.Code := ErrorCodes.OpeningFileFailed; - Error.Info := Tc2_Standard.CONCAT('Opening file failed. Error thrown by FB_FileOpen. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(fileOpen.nErrId)); + Error.Active := TRUE; + Error.Code := ErrorCodes.OpeningFileFailed; + Error.Info := Tc2_Standard.CONCAT('Opening file failed. Error thrown by FB_FileOpen. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(fileOpen.nErrId)); ELSIF fileWrite.bError THEN - Error.Active := TRUE; - Error.Code := ErrorCodes.WritingToFileFailed; - Error.Info := Tc2_Standard.CONCAT('Writing to file failed. Error thrown by FB_FileWrite. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(fileWrite.nErrId)); + Error.Active := TRUE; + Error.Code := ErrorCodes.WritingToFileFailed; + Error.Info := Tc2_Standard.CONCAT('Writing to file failed. Error thrown by FB_FileWrite. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(fileWrite.nErrId)); ELSIF fileClose.bError THEN - Error.Active := TRUE; - Error.Code := ErrorCodes.ClosingFileFailed; - Error.Info := Tc2_Standard.CONCAT('Closing file failed. Error thrown by FB_FileClose. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(fileClose.nErrId)); + Error.Active := TRUE; + Error.Code := ErrorCodes.ClosingFileFailed; + Error.Info := Tc2_Standard.CONCAT('Closing file failed. Error thrown by FB_FileClose. Consult Beckhoff InfoSys. Internal Error: ', UDINT_TO_STRING(fileClose.nErrId)); ELSIF NOT _fifo.bOk AND _fifo.nCount > 0 THEN - Error.Active := TRUE; - Error.Code := ErrorCodes.FifoOverflow; - Error.Info := 'FIFO overflow. Check if plc has enough free memory.'; + Error.Active := TRUE; + Error.Code := ErrorCodes.FifoOverflow; + Error.Info := 'FIFO overflow. Check if plc has enough free memory.'; ELSE - Error.Active := FALSE; - Error.Code := ErrorCodes.None; - Error.Info := ''; + Error.Active := FALSE; + Error.Code := ErrorCodes.None; + Error.Info := ''; END_IF // Set busy state @@ -242,19 +242,19 @@ Busy := (state <> PersistToFileState.Idle OR _fifo.nCount > 0); (* Uncomment for cyclic logging of state machine, buffer usage & errors ADSLOGSTR(ADSLOG_MSGTYPE_LOG, - Tc2_Standard.CONCAT('****DynamicStringBuffer.state:', - Tc2_Standard.CONCAT(UINT_TO_STRING(state), - Tc2_Standard.CONCAT(', DynamicStringBuffer.hFile:', UINT_TO_STRING(hFile)))), ''); + Tc2_Standard.CONCAT('****DynamicStringBuffer.state:', + Tc2_Standard.CONCAT(UINT_TO_STRING(state), + Tc2_Standard.CONCAT(', DynamicStringBuffer.hFile:', UINT_TO_STRING(hFile)))), ''); ADSLOGSTR(ADSLOG_MSGTYPE_LOG, - Tc2_Standard.CONCAT('****Fifo: used ', - Tc2_Standard.CONCAT(UDINT_TO_STRING(Fifo.cbSize), - Tc2_Standard.CONCAT(' of ', UDINT_TO_STRING(Fifo.cbBuffer)))), ''); - + Tc2_Standard.CONCAT('****Fifo: used ', + Tc2_Standard.CONCAT(UDINT_TO_STRING(Fifo.cbSize), + Tc2_Standard.CONCAT(' of ', UDINT_TO_STRING(Fifo.cbBuffer)))), ''); + IF Error.Active THEN - ADSLOGSTR(ADSLOG_MSGTYPE_LOG, - Tc2_Standard.CONCAT('****DynamicStringBuffer.Error: ', Error.Info), - ''); + ADSLOGSTR(ADSLOG_MSGTYPE_LOG, + Tc2_Standard.CONCAT('****DynamicStringBuffer.Error: ', Error.Info), + ''); END_IF *)]]> @@ -262,7 +262,7 @@ END_IF @@ -274,61 +274,19 @@ PopHead := headString;]]> _fifo.cbBuffer THEN - _dynamicMemoryBuffer.Resize(nSize := requiredSize*SIZEOF(BYTE), bPreserve:=TRUE, bReset:=TRUE); - _fifo.pBuffer := _dynamicMemoryBuffer.pBuffer; - _fifo.cbBuffer := requiredSize; + _dynamicMemoryBuffer.Resize(nSize := requiredSize*SIZEOF(BYTE), bPreserve:=TRUE, bReset:=TRUE); + _fifo.pBuffer := _dynamicMemoryBuffer.pBuffer; + _fifo.cbBuffer := requiredSize; END_IF]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/TcLogProj/TcLog/Utils/GetFileAgeInSeconds.TcPOU b/src/TcLogProj/TcLog/Utils/GetFileAgeInSeconds.TcPOU index a41c9fe..b5c437d 100644 --- a/src/TcLogProj/TcLog/Utils/GetFileAgeInSeconds.TcPOU +++ b/src/TcLogProj/TcLog/Utils/GetFileAgeInSeconds.TcPOU @@ -3,16 +3,16 @@ diff --git a/src/TcLogProj/TcLog/Utils/_Tests/ConvertAnyToString_TEST.TcPOU b/src/TcLogProj/TcLog/Utils/_Tests/ConvertAnyToString_TEST.TcPOU index 6b19af3..e5d6f2a 100644 --- a/src/TcLogProj/TcLog/Utils/_Tests/ConvertAnyToString_TEST.TcPOU +++ b/src/TcLogProj/TcLog/Utils/_Tests/ConvertAnyToString_TEST.TcPOU @@ -28,9 +28,9 @@ ConvertAnyWStringToString();]]> @@ -48,9 +48,9 @@ TEST_FINISHED();]]> @@ -68,9 +68,9 @@ TEST_FINISHED();]]> @@ -88,9 +88,9 @@ TEST_FINISHED();]]> @@ -108,9 +108,9 @@ TEST_FINISHED();]]> @@ -128,9 +128,9 @@ TEST_FINISHED();]]> @@ -148,9 +148,9 @@ TEST_FINISHED();]]> @@ -168,9 +168,9 @@ TEST_FINISHED();]]> @@ -188,9 +188,9 @@ TEST_FINISHED();]]> @@ -208,9 +208,9 @@ TEST_FINISHED();]]> @@ -228,9 +228,9 @@ TEST_FINISHED();]]> @@ -248,9 +248,9 @@ TEST_FINISHED();]]> @@ -268,9 +268,9 @@ TEST_FINISHED();]]> @@ -288,9 +288,9 @@ TEST_FINISHED();]]> @@ -308,9 +308,9 @@ TEST_FINISHED();]]> @@ -328,9 +328,9 @@ TEST_FINISHED();]]> @@ -348,9 +348,9 @@ TEST_FINISHED();]]> @@ -368,9 +368,9 @@ TEST_FINISHED();]]> @@ -388,9 +388,9 @@ TEST_FINISHED();]]> @@ -408,9 +408,9 @@ TEST_FINISHED();]]> @@ -428,9 +428,9 @@ TEST_FINISHED();]]> @@ -448,8 +448,8 @@ TEST_FINISHED();]]> diff --git a/src/TcLogProj/TcLog/Utils/_Tests/DateTime_TEST.TcPOU b/src/TcLogProj/TcLog/Utils/_Tests/DateTime_TEST.TcPOU index 0d7deaa..cf32fbd 100644 --- a/src/TcLogProj/TcLog/Utils/_Tests/DateTime_TEST.TcPOU +++ b/src/TcLogProj/TcLog/Utils/_Tests/DateTime_TEST.TcPOU @@ -9,12 +9,12 @@ @@ -41,15 +41,15 @@ expected := Tc2_Standard.CONCAT(expected, TO_STRING(localSystemTime.wSecond)); expected := Tc2_Standard.CONCAT(expected, '-'); result := sut.ToFormatString('-YYYYMMDD-hh:mm:ss-'); - + IF sut.Done THEN - AssertEquals( - Expected := expected, - Actual := result, - Message := 'Time formatting failed.' - ); + AssertEquals( + Expected := expected, + Actual := result, + Message := 'Time formatting failed.' + ); - TEST_FINISHED(); + TEST_FINISHED(); END_IF ]]> diff --git a/src/TcLogProj/TcLog/Utils/_Tests/DynamicStringBuffer_TEST.TcPOU b/src/TcLogProj/TcLog/Utils/_Tests/DynamicStringBuffer_TEST.TcPOU index 7260562..98bdbf3 100644 --- a/src/TcLogProj/TcLog/Utils/_Tests/DynamicStringBuffer_TEST.TcPOU +++ b/src/TcLogProj/TcLog/Utils/_Tests/DynamicStringBuffer_TEST.TcPOU @@ -9,51 +9,51 @@ 0 THEN - result := logsManyMessagesForManyCyclesLogger.Error.Info; + result := logsManyMessagesForManyCyclesLogger.Error.Info; END_IF IF cycleCount > (Cycles * Messages * 2 + 4) THEN - AssertEquals(Expected := expected, - Actual := result, - Message := result); + AssertEquals(Expected := expected, + Actual := result, + Message := result); - TEST_FINISHED(); + TEST_FINISHED(); END_IF]]>