📄 driveru.pas
字号:
* 函数功能:根据设备变量编号和索引查找地址信息并生成发送数据
* 入口参数:1、LocalIndex: Integer。地址索引信息
* 2、Value: Variant。发送数据
* 出口参数:1、Info: TAppDataInfo。应用数据信息
* 返回值:Boolean。执行情况
*}
function TDriver.GeneralWriteData(const LocalIndex: Integer;
Value: Variant; var Info: TAppDataInfo): Boolean;
var
DeviceVar: TDeviceVar;
Data: string;
begin
Result := False;
DeviceVar := TDeviceVarList.GetDeviceVarList.GetItem(LocalIndex);
if not Assigned(DeviceVar) then
begin
WriteErrorLog(Format('下发数据时发生错误!地址索引无效!(%d)', [LocalIndex]));
Exit;
end;
Data := Value;
Info.dwLocalIndex := LocalIndex;
Info.rcdAddress := DeviceVar.AddressInfo;
Info.AppData := Data;
Info.dtDateTime := Now;
Result := True;
end;
{*
* 函数名称:CheckReSendTime
* 函数功能:检查发送数据超时
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.CheckReSendTime;
var
I: Integer;
VarList: TIntegerArray;
ItemNames: TStringArray;
DeviceVar: TDeviceVar;
begin
//超过一定时间没有读写操作则尝试查询
if GetTimeInterval(FRefreshDataPnt) >= Const_TIME_REFRESHDATA then
begin
FRefreshDataPnt := GetTickCount;
FOPCComm.RefershData;
end;
//检查通讯是否中断, 中断后则尝试重新打开端口
if FOPCComm.CommStatus = Const_STATUS_DISCONNECT then
begin
ComObj.CoInitializeEx(nil, 0);
FOPCComm.StopComm;
FOPCComm.StartComm;
FOPCComm.RefershData;
end;
//超过规定的期限则认为通讯中断
if GetTimeInterval(FCommStateChkPnt) >= Const_TIME_COMMFAILED then
begin
FCommStateChkPnt := GetTickCount;
SetDriveStatus(COMM_STATUS_DISCONNECT);
end;
//先获得发送数据帧列表
SetLength(VarList, 0);
//获得超时设备变量索引列表 和 地址列表
VarList := FWindow.ProcessSendTimeOut(ItemNames);
//根据设备变量索引编号设置发送失败
for I := Low(VarList) to High(VarList) do
begin
DeviceVar := TDeviceVarList.GetDeviceVarList.GetItem(VarList[I]);
if Assigned(DeviceVar) then
DeviceVar.SetState(ITEM_STATUS_SendFailed);
NotifyToSendPkt;
end;
end;
{*
* 函数名称:NotifyToSendPkt
* 函数功能:通知调度对象发送数据
* 1、设置FSendEvent对象为有信号状态
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.NotifyToSendPkt;
begin
SetEvent(FSendEvent);
end;
{*
* 函数名称:SendNextDataPacket
* 函数功能:从发送队列中取出一个数据,发送
* 1、发送成功
* 如果是无应答数据帧,则认定发送任务成功
* 如果是应答数据帧,则等待接收数据
* 2、发送失败
* 如果是无应答数据帧,则认定发送任务失败
* 如果是应答数据帧,则认定发送任务失败
* 入口参数:无
* 出口参数:无
* 返回值:True -- 发送成功
*}
function TDriver.SendNextDataPacket: Boolean;
var
Frm: TFrame;
DeviceVar: TDeviceVar;
begin
Result := False;
Frm := FWindow.GetNextFrame;
if Assigned(Frm) then
begin
Frm.FormFrame;
Result := SendPktToComm(Frm.DataPacket, Frm.ItemName);
if Result then //发送成功
begin
if (not Frm.NeedAck) and (Frm.LocalIndex >= 0) then
begin
DeviceVar := TDeviceVarList.GetDeviceVarList.GetItem(Frm.LocalIndex);
if Assigned(DeviceVar) then
DeviceVar.SetState(ITEM_STATUS_SendSuccess);
end;
end
else begin //发送失败,则根据错误码判断通讯中断
FWindow.ProcessSendFailed(Frm);
if (Frm.LocalIndex >= 0) then
begin
DeviceVar := TDeviceVarList.GetDeviceVarList.GetItem(Frm.LocalIndex);
if Assigned(DeviceVar) then
DeviceVar.SetState(ITEM_STATUS_SendFailed);
end;
end;
NotifyToSendPkt;
end;
end;
{*
* 函数名称:QueryCommData
* 函数功能:主动查询变量数据
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.QueryCommData;
var
I, Count: Integer;
ItemName: string;
SendValue: Variant;
ItemNames: TStringArray;
ReadInfos: TReadInfoArray;
WriteInfos: TWriteInfoArray;
begin
//获得当前所有可以读取的模拟量OPCITEM信息
SetLength(ReadInfos, 0);
SetLength(WriteInfos, 0);
FAddressParse.GetQueryData(ReadInfos);
Count := Length(ReadInfos);
if Count > 0 then
begin
SetLength(ItemNames, 0);
for I := 0 to Count - 1 do
begin
if FAddressParse.ItemIsNull(ReadInfos[I].szItemName) then
Continue;
SetLength(ItemNames, Length(ItemNames) + 1);
ItemNames[High(ItemNames)] := ReadInfos[I].szItemName;
end;
FOPCComm.QueryData(ItemNames);
end;
//查询要自动下发的数据,并指定下发
FAddressParse.GetWriteData(WriteInfos);
Count := Length(WriteInfos);
if Count > 0 then
begin
for I := 0 to Count - 1 do
begin
if FAddressParse.ItemIsNull(WriteInfos[I].szItemName) then
Continue;
ItemName := WriteInfos[I].szItemName;
SendValue := WriteInfos[I].dwWriteValue;
FOPCComm.SendData(ItemName, SendValue);
end;
end;
end;
{*
* 函数名称:ReceiveCommData
* 函数功能:从通讯端口读取数据
* 获得当前所有可以读取的地址信息
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.ReceiveCommData;
var
ItemName: string; //数据项名称
ItemTime: TDateTime; //采集时间
ItemValue: Variant; //数据项的数值
AddrInfo: TAddressInfo;
AppDataInfo: TAppDataInfo;
begin
if not FOPCComm.ReadData(ItemName, ItemValue, ItemTime) then
Exit;
SetDriveStatus(COMM_STATUS_CONNECTED);
FRefreshDataPnt := GetTickCount;
FCommStateChkPnt := GetTickCount;
{$IFDEF DEBUG}
FrmOPC.AddPacket(Format('-->: 地址(%s). 数据(%s).', [ItemName, String(ItemValue)]));
WriteDebugLog(Format('-->: 服务(%s). 地址(%s). 数据(%s).', [FOPCComm.MachineName, ItemName, String(ItemValue)]));
{$ENDIF}
AddrInfo.dwReadItem := ItemName;
AppDataInfo.rcdAddress := AddrInfo;
AppDataInfo.AppData := ItemValue;
AppDataInfo.dtDateTime := ItemTime;
try
FAddressParse.SetRecvData(AppDataInfo);
except
WriteDebugLog('sss');
end;
end;
{*
* 函数名称:StartInputHandler
* 函数功能:创建端口数据到达事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StartInputHandler;
begin
if Assigned(FInputHandler) then
Exit;
FInputHandler := TInputHandler.Create(Self, Self);
FInputHandler.InitEvent(FOPCComm.ReadEvent, Const_Event_RecvDataInd);
FScheduler.AddEventHandler(FInputHandler);
end;
{*
* 函数名称:StartSendHandler
* 函数功能:创建发送数据事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StartSendHandler;
begin
if Assigned(FSendHandler) then
Exit;
FSendEvent := CreateEvent(nil, False, False, '');
FSendHandler := TInputHandler.Create(Self, Self);
FSendHandler.InitEvent(FSendEvent, Const_Event_SendDataReq);
FScheduler.AddEventHandler(FSendHandler);
end;
{*
* 函数名称:StartLoopTimer
* 函数功能:启动定时读数事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StartLoopTimer;
begin
FLoopTimer := TTimerHandler.Create(Self, Self);
FLoopTimer.InitEvent(Const_Event_LoopCheck, grcdDriverInfo.dwSampleTime, True);
FScheduler.AddEventHandler(FLoopTimer);
end;
{*
* 函数名称:StartWaitTimer
* 函数功能:启动发送超时检查事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StartWaitTimer;
begin
FWaitTimer := TTimerHandler.Create(Self, Self);
FWaitTimer.InitEvent(Const_Event_WaitAnswer, Const_FrameSendTimeOut, True);
FScheduler.AddEventHandler(FWaitTimer);
end;
{*
* 函数名称:StopInputHandler
* 函数功能:释放端口数据到达事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StopInputHandler;
begin
if not Assigned(FInputHandler) then
Exit;
FInputHandler.SetMarked;
FInputHandler := nil;
end;
{*
* 函数名称:StopSendHandler
* 函数功能:释放发送数据事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StopSendHandler;
begin
if not Assigned(FSendHandler) then
Exit;
FSendHandler.SetMarked;
FSendHandler := nil;
CloseHandle(FSendEvent);
end;
{*
* 函数名称:StopLoopTimer
* 函数功能:停止轮询检查事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StopLoopTimer;
begin
try
if Assigned(FLoopTimer) then
begin
FLoopTimer.SetMarked;
FLoopTimer := nil;
end;
except
WriteDebugLog('停止轮询读数事件失败!');
end;
end;
{*
* 函数名称:StopWaitTimer
* 函数功能:停止发送超时检查事件
* 入口参数:无
* 出口参数:无
* 返回值:无
*}
procedure TDriver.StopWaitTimer;
begin
try
if Assigned(FWaitTimer) then
begin
FWaitTimer.SetMarked;
FWaitTimer := nil;
FWaitCount := 0;
end;
except
WriteDebugLog('停止超时定时事件失败!');
end;
end;
{*
* 函数名称:Create
* 函数功能:构造函数
* 入口参数:1、PortInfo: TCommPortInfo。通信端口参数
* 出口参数:无
* 返回值:无
*}
constructor TDriver.Create(PortInfo: TCommPortInfo);
var
Param: TCommParam;
begin
//初始化属性
FPortInfo := PortInfo;
FDriveStatus := COMM_STATUS_UnKnown;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -