基于VBS脚本的WinCC操作日志系统设计
WinCC内置的操作日志功能在实际应用中存在诸多限制,特别是在处理模拟量设定值变更时,仅能显示变量名而无法灵活定制操作设备及内容描述。本文介绍了一种利用VBS脚本实现完善操作日志记录的技术方案。
该解决方案的核心技术点包括:
1、利用Microsoft Access数据库进行数据读写操作,用于存储操作目标的基础信息及变更前后的数值;
2、解决操作日志触发机制问题;
3、区分两类操作场景:开关控制类和参数配置类。
核心数据库操作函数
1、Access数据库连接与断开函数
Function ConnectDatabase(connObj, dbName)
'通过ADO.Connection建立Access数据库连接,connObj为ADO.Connection对象
'连接成功返回1,数据库文件不存在返回-2,路径错误返回-1,连接失败返回0
On Error Resume Next
Dim result, fso, projectPath, dbPath
projectPath = HMIRuntime.ActiveProject.Path + "\WinccDataFolder"
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FolderExists(projectPath) Then
dbPath = projectPath & "\" & dbName & ".mdb"
If fso.FileExists(dbPath) Then
Set connObj = CreateObject("ADODB.Connection")
connObj.ConnectionString = "Provider=Microsoft.JET.OLEDB.4.0;Data Source=" & dbPath
connObj.CursorLocation = 3
connObj.Open
If connObj.State = 1 Then
result = 1
Else
result = 0
End If
Else
result = -2
End If
Else
result = -1
End If
Set fso = Nothing
ConnectDatabase = result
End Function
Sub DisconnectDatabase(connObj)
'关闭数据库连接
On Error Resume Next
If connObj.State = 1 Then
connObj.Close
End If
End Sub
2、数据库查询函数
Function GetValueFromDB(connObj, dbName, tableName, targetField, conditionField, conditionValue)
On Error Resume Next
ConnectDatabase connObj, dbName
Dim sqlQuery, recordSet
sqlQuery = "SELECT " & targetField & " FROM " & tableName & " WHERE " & conditionField & "='" & conditionValue & "'"
Set recordSet = connObj.execute(sqlQuery)
If IsNull(recordSet.fields(0).value) = True Then
GetValueFromDB = ""
Else
GetValueFromDB = recordSet.fields(0).value
End If
Set recordSet = Nothing
DisconnectDatabase connObj
End Function
3、数据库更新函数
Function SetValueToDB(connObj, dbName, tableName, targetField, targetValue, conditionField, conditionValue)
On Error Resume Next
ConnectDatabase connObj, dbName
Dim sqlQuery, recordSet
sqlQuery = "UPDATE " & tableName & " SET " & targetField & "='" & targetValue & "' WHERE " & conditionField & "='" & conditionValue & "'"
Set recordSet = connObj.execute(sqlQuery)
Set recordSet = Nothing
DisconnectDatabase connObj
End Function
开关操作日志实现
1、工作原理
利用按钮点击事件触发日志记录脚本,从Access数据库读取相关设备信息,在WinCC中生成对应的报警记录,最后对报警信息进行筛选展示。
2、在WinCC中创建报警编号2021101
3、配置过程变量块,使用过程变量8、9、10分别表示操作目标、操作说明和操作用户。
4、数据库结构设计
<1>、在WinCC项目目录下新建WinCCDataFolder文件夹;
<2>、在此文件夹内创建Access数据库SwitchLog.mdb;
<3>、数据库中建立Switch表,包含TagID、TagName、DeviceName、OperationDesc四个字段;
<4>、填入数据,TagName对应按钮名称,DeviceName对应被操作设备,OperationDesc描述具体操作内容。
5、实现代码
Function LogSwitchAction(buttonName)
On Error Resume Next
Dim alarmObj, dbConn
Set alarmObj = HMIRuntime.Alarms(2021101)
alarmObj.State = 1
alarmObj.ProcessValues(10) = HMIRuntime.tags("@NOP::@CurrentUserName").read
alarmObj.ProcessValues(8) = GetValueFromDB(dbConn, "SwitchLog", "Switch", "DeviceName", "TagName", buttonName)
alarmObj.ProcessValues(9) = GetValueFromDB(dbConn, "SwitchLog", "Switch", "OperationDesc", "TagName", buttonName)
alarmObj.Create "CustomApp"
Set alarmObj = Nothing
End Function
'在按钮Click事件中调用:
LogSwitchAction item.ObjectName
参数设置日志实现
1、工作原理
监听IO域的输出变更事件(经测试此事件最稳定),触发参数设置日志记录。从数据库获取设备信息,在WinCC中生成报警记录并筛选展示。
2、创建报警编号2021102
3、配置过程变量块2、3、8、9、10,分别表示变更前值、变更后值、操作目标、操作说明和操作用户。
4、数据库扩展设计
<1>、在SwitchLog数据库中新增ParamTable表,包含TagID、TagName、Description、OldValue、NewValue、Unit、ParamDesc七个字段;
<2>、字段说明:
TagName为IO域名称;
Description表示参数含义(如频率);
OldValue存储设置前的值;
NewValue存储设置后的值;
Unit表示参数单位;
ParamDesc描述参数设置操作(如频率设定)。
5、实现代码
Function LogParameterChange(ioFieldName)
On Error Resume Next
Dim oldValue, newValue, tempVal, dbConn
'检查用户登录状态
If ioFieldName = "@CurrentUserName" And HMIRuntime.tags("@NOP::" + ioFieldName).read = "" Then
oldValue = "未登录"
Else
oldValue = CStr(HMIRuntime.tags("@NOP::" + ioFieldName).read)
End If
'读取上次保存的值作为新值
newValue = CStr(GetValueFromDB(dbConn, "SwitchLog", "ParamTable", "NewValue", "TagName", ioFieldName))
'更新旧值记录
SetValueToDB dbConn, "SwitchLog", "ParamTable", "OldValue", newValue, "TagName", ioFieldName
If oldValue <> newValue Then
SetValueToDB dbConn, "SwitchLog", "ParamTable", "NewValue", oldValue, "TagName", ioFieldName
End If
Dim alarmItem, currentUser, objName, paramUnit
paramUnit = GetValueFromDB(dbConn, "SwitchLog", "ParamTable", "Unit", "TagName", ioFieldName)
If HMIRuntime.tags("@NOP::@CurrentUserName").read = "" Then
currentUser = "未登录"
Else
currentUser = HMIRuntime.tags("@NOP::@CurrentUserName").read
End If
If Trim(CStr(oldValue)) <> Trim(CStr(newValue)) And Trim(CStr(oldValue)) <> "" And Trim(CStr(newValue)) <> "" Then
If ioFieldName <> "@CurrentUserName" Then
Set alarmItem = HMIRuntime.Alarms(2021102)
Else
Set alarmItem = HMIRuntime.Alarms(2021104)
End If
With alarmItem
.State = 1
.ProcessValues(10) = currentUser
'数值格式化处理
If InStr(CStr(oldValue), ".") = 0 And ioFieldName <> "@CurrentUserName" Then
.ProcessValues(3) = CStr(oldValue) + ".0"
Else
.ProcessValues(3) = CStr(oldValue)
End If
If InStr(CStr(newValue), ".") = 0 And ioFieldName <> "@CurrentUserName" Then
.ProcessValues(2) = CStr(newValue) + ".0"
Else
.ProcessValues(2) = CStr(newValue)
End If
.ProcessValues(8) = GetValueFromDB(dbConn, "SwitchLog", "ParamTable", "Description", "TagName", ioFieldName)
If ioFieldName <> "@CurrentUserName" Then
.ProcessValues(9) = GetValueFromDB(dbConn, "SwitchLog", "ParamTable", "ParamDesc", "TagName", ioFieldName) + "(单位:" + paramUnit + ")"
Else
.ProcessValues(9) = GetValueFromDB(dbConn, "SwitchLog", "ParamTable", "ParamDesc", "TagName", ioFieldName)
End If
.Create "CustomApp"
End With
Set alarmItem = Nothing
End If
End Function
'在IO域OutputChange事件中调用:
LogParameterChange item.ObjectName
6、报警组件配置
<1>、在报警视图中选择相应的报警块,配置显示字段包括日期、时间、操作用户、操作目标、操作说明、变更前值和变更后值,并调整字体大小、对齐方式和列宽等属性。
<2>、设置过滤条件,按报警编号2021101和2021102进行筛选。