CODESYS 输出日志 Log
目录
1.库SysFile
2.定义声明
3.日志输出实现
1.库SysFile
2.定义声明
定义文件个数,文件行数限制 以及触发变量,每次触发则写一行数据
FUNCTION_BLOCK LogOutput
VAR_INPUT
//输入文件个数 默认是5 不超过100个
iFileNum : INT := 100;
//路径以及文件名,不含后缀
sFileName : STRING(255) := 'Info';
//文本行数 默认是50000 ,不超过50000个
NumberTextLines : INT := 50000;
//上升沿生效
bEnable : BOOL;
//文件操作//写一行数据
bWriteLine : BOOL := FALSE;
//最新的输出日志文本行
logLineText : STRING;
END_VAR
VAR_OUTPUT
//创建一定个数的文件完成标志
bCreateFileDone : BOOL;
//写当前文件数据完成标志
bWriteFileDone : BOOL;
END_VAR
VAR
sFileFolder : STRING(255) := 'D:\Logs\';
//文件后缀
suffix : STRING(255) := '.log';
//当前文件名路径
sFileNameMid : STRING(255) := '';
//字符串数组库
asCurrentFileName : ARRAY[1..100] OF STRING(255) ;
abFileSingle : ARRAY[1..100] OF BOOL ;
//文件操作
iFilesStatus : INT;
iWriteDelay : INT;
//当前文件序号
iCurrentFileNum : INT := 1;
//当前文件行
iCurrentTextline : INT := 0;
//计数器
iCounter : INT;
//计算器2
iCounter2 : INT;
//当前文件计算
iCurrentCounterFile: INT := 1;
//创建文件个数标志位
//iCreateFileNum : INT;
//delete 计算器
iDeleteCounter : INT;
//复位文件返回字节数
lwCopyWord : LWORD;
//时间处理
sLine : STRING(255);
sTime : STRING;
sTimeT1 : STRING;
//边沿检测
EnableR_TRTG : R_TRIG;
WriteFilesR_TRIG : R_TRIG;
//Test
lrCounterDataTest : LREAL;
//判断当前文件延时
iDelayHasFile : INT;
Total_Num: INT;
END_VAR
3.日志输出实现
定义文件操作
{attribute 'qualified_only'}
{attribute 'strict'}
TYPE FilesOpStatus :
(
InitFile := 0, //初始化文件
Hasfiles := 10, //检查文件是否存在
CreateFiles := 20, //创建文件
ReadFilesData := 30, //读取文件数据
WriteFilesData:= 40, //写入文件数据
WriteFileReady:= 50, //写文件准备状态
CreateFilesError:= 100 //创建文件失败
);
END_TYPE
日志内容输出,可以自行定义日志输出的样式
字符串拼装的方式
//目录拼接当前日期
sFileFolder:=concat('D:\Logs\',LEFT(GetTimeS(),10));
sFileFolder:=concat(sFileFolder,'\');
//启动信号
EnableR_TRTG(CLK:= bEnable, Q=> );
IF EnableR_TRTG.Q THEN
iFilesStatus := FilesOpStatus.InitFile;
END_IF
//限制
IF iFileNum > 100 THEN
iFileNum := 100;
END_IF
IF NumberTextLines > 50000 THEN
NumberTextLines := 50000;
END_IF
IF NOT(bEnable) THEN
RETURN;
END_IF
//文件操作状态机
CASE iFilesStatus OF
FilesOpStatus.InitFile: //初始化文件
bCreateFileDone := FALSE;
iCurrentCounterFile := 1;
//当前文件标志位复位
FOR iCounter := 1 TO iFileNum BY 1 DO
abFileSingle[iCounter] := FALSE;
END_FOR
iFilesStatus := FilesOpStatus.Hasfiles;
FilesOpStatus.Hasfiles:
//文件都存在的情况下
IF bCreateFileDone THEN
//删除最早生产的文件
DeleteFile(asCurrentFileName[1]);
//依次类推,将最新的往前移
FOR iDeleteCounter := 1 TO (iFileNum - 1) BY 1 DO
CopyFile(asCurrentFileName[iDeleteCounter],asCurrentFileName[iDeleteCounter + 1],ADR(lwCopyWord));
//删除
DeleteFile(asCurrentFileName[iDeleteCounter + 1]);
END_FOR
//最后一个默认是最新的文件
iCurrentCounterFile := iFileNum;
//字符串处理---最后一个文件为最新的文件
//目录拼接
asCurrentFileName[iCurrentCounterFile] := concat(sFileFolder, sFileName);
//文件数拼接
asCurrentFileName[iCurrentCounterFile] := concat(asCurrentFileName[iCurrentCounterFile], INT_TO_STRING(iCurrentCounterFile));
//后缀拼接
asCurrentFileName[iCurrentCounterFile] := concat(asCurrentFileName[iCurrentCounterFile],suffix);
//当前文件
sFileNameMid := asCurrentFileName[iCurrentCounterFile];
//下一状态机
iFilesStatus := FilesOpStatus.CreateFiles;
ELSE
//字符串处理---最后一个文件为最新的文件
//目录拼接
asCurrentFileName[iCurrentCounterFile] := concat(sFileFolder, sFileName);
//文件数拼接
asCurrentFileName[iCurrentCounterFile] := concat(asCurrentFileName[iCurrentCounterFile], INT_TO_STRING(iCurrentCounterFile));
//后缀拼接
asCurrentFileName[iCurrentCounterFile] := concat(asCurrentFileName[iCurrentCounterFile],suffix);
//当前文件
sFileNameMid := asCurrentFileName[iCurrentCounterFile];
//当前文件是否存在
IF HasFile(asCurrentFileName[iCurrentCounterFile]) THEN
//文件是否存在标志
IF NOT(abFileSingle[iCurrentCounterFile]) THEN
abFileSingle[iCurrentCounterFile] := TRUE;
END_IF
END_IF
//延时判断
iDelayHasFile := iDelayHasFile + 1;
IF iDelayHasFile > 15 THEN
iDelayHasFile := 0;
IF (abFileSingle[iCurrentCounterFile]) THEN
iCurrentCounterFile := iCurrentCounterFile + 1;
//创建文件完成
IF iCurrentCounterFile = (iFileNum + 1) THEN
bCreateFileDone := TRUE;
END_IF
ELSE
iFilesStatus := FilesOpStatus.CreateFiles;
END_IF
END_IF
END_IF
FilesOpStatus.CreateFiles: //创建文件,并写入相关标题
//标题六列名称
sLine := '开始记录日志$r$n';//尾部加换行符
//创建文件及标题,已经有文件则覆盖
WriteFile(sFileName:= sFileNameMid, pbyBuffer:= ADR(sLine), ulSize:= len(sLine), WriteMode:= EWriteMode.eWriteCover);
//延时等待标题写完成
iWriteDelay := iWriteDelay + 1;
IF iWriteDelay > 10 THEN
iWriteDelay := 0;
iFilesStatus := FilesOpStatus.ReadFilesData;
END_IF
FilesOpStatus.ReadFilesData: //读取文件数据
//延时计数
iFilesStatus := FilesOpStatus.WriteFileReady;
//获取当前文件的行数
iCurrentTextline := 0;
FilesOpStatus.WriteFilesData: //写入文件数据
//write data
//'Date, Total_Num, OK_Num, NG_Num, ErrorScrewID, ErrorID$r$n' //复位
//获取时间标题
sTime := GetTimeS();
sLine := '[';
sLine := concat(sLine , sTime);
sLine := concat(sLine , ']');
//日志行信息
sLine := concat(sLine,logLineText);
//结束符号
sLine := concat(sLine , '$r$n');
//向文件尾部写数据
WriteFile(sFileName:= sFileNameMid, pbyBuffer:= ADR(sLine), ulSize:= len(sLine), WriteMode:= EWriteMode.eWriteAdd);
iCurrentTextline := iCurrentTextline + 1 ;
//文件内容填充完成
IF iCurrentTextline >= NumberTextLines THEN
iFilesStatus := FilesOpStatus.Hasfiles;
ELSE
iFilesStatus := FilesOpStatus.WriteFileReady;
END_IF
//写文件内容完成
bWriteFileDone := TRUE;
FilesOpStatus.WriteFileReady:
WriteFilesR_TRIG(CLK:= bWriteLine, Q=> );
//启动
IF WriteFilesR_TRIG.Q THEN
//写文件内容完成
bWriteFileDone := FALSE;
iFilesStatus := FilesOpStatus.WriteFilesData;
END_IF
FilesOpStatus.CreateFilesError: //写入文件数据
END_CASE