?? driveru.pas
字號:
FPortInfo: TCommPortInfo; //通信設備屬性
FOPCComm: TOPCComm; //通訊操作對象
FDriveStatus: Integer; //通信設備狀態
FRefreshDataPnt: DWord; //查詢數據
FCommStateChkPnt: DWord; //通訊狀態檢查
FCommAddress: string; //通訊端口的
//用于后臺調度的事件
FInputHandler: TInputHandler; //接收端口數據到達事件通知對象
FSendHandler: TInputHandler; //接收下發數據事件通知對象
FSendEvent: THandle; //發送數據事件通知對象
FLoopTimer: TTimerHandler; //輪詢檢測的定時器
FWaitTimer: TTimerHandler; //等待應答的定時器
FWaitCount: Integer; //等待應答次數
FScheduler: TScheduler; //調度事件對象
//發送數據緩沖區
FWindow: TSlidingWindow; //發送數據滑動窗口
FAddressParse: TAddressParse; //設備變量的尋址對象
function GetPortId: DWord;
function SendPktToComm(WriteData: Variant; Address: string): Boolean;
procedure SetDriveStatus(Value: Integer);
procedure CheckReSendTime;
procedure NotifyToSendPkt;
function SendApplicationFrm(Frm: TFrame): Boolean;
function GeneralWriteData(const LocalIndex: Integer; Value: Variant;
var Info: TAppDataInfo): Boolean;
protected
function SendNextDataPacket: Boolean;
procedure ReceiveCommData;
procedure QueryCommData;
//有關事件調度的函數
procedure StartInputHandler;
procedure StartSendHandler;
procedure StartLoopTimer;
procedure StartWaitTimer;
procedure StopInputHandler;
procedure StopSendHandler;
procedure StopLoopTimer;
procedure StopWaitTimer;
public
constructor Create(PortInfo: TCommPortInfo);
destructor Destroy; override;
procedure EventCallback(EventId: Integer); override;
procedure StartDriver; //啟動驅動
procedure StopDriver; //停止驅動
function SendData(const LocalIndex: Integer; Value: Variant): Boolean;
published
property PortId: DWord read GetPortId;
property Status: Integer read FDriveStatus;
property CommAddress: string read FCommAddress;
end;
//通信設備列表類
TDriverList = class(TObjectList)
private
FEvent: THandle;
procedure FreeResource;
public
constructor Create;
destructor Destroy; override;
procedure Add(const Driver: TDriver);
procedure Delete(const Driver: TDriver);
function GetDriver(const ID: DWord): TDriver;
procedure StartDrivers;
procedure StopDrivers;
procedure SetTrgEvent;
class function GetDriverList: TDriverList;
published
property Event: THandle read FEvent;
end;
function GetJobNo: Byte;
var
gDriverList: TDriverList;
gDeviceVarList: TDeviceVarList;
gJobNo: Byte; //SCMS發送的任務號
implementation
{$IFDEF DEBUG}
uses
OPC;
{$ENDIF}
//**************************************************************************
// 類名:TAddressParse
// 功能:設備變量地址解析
//**************************************************************************
{*
* 函數名稱:ItemIsNull
* 函數功能:判斷OPCITEM的名稱是否為空
* 入口參數:1、ItemName: string。 OPCITEM名稱
* 出口參數:無
* 返回值:True -- 該變量為空
*}
function TAddressParse.ItemIsNull(ItemName: string): Boolean;
begin
Result := False;
if (Length(ItemName) = 0) or
(AnsiPos(CONST_NULL_ITEMNAME, UpperCase(ItemName)) <> 0) then
Result := True;
end;
{*
* 函數名稱:SplitValue
* 函數功能:根據地址信息拆分出指定設備變量的數據
* 入口參數:1、DeviceVar: TDeviceVar。設備變量
* 2、DataPkt: TDataPacket。數據
* 出口參數:1、Value: Variant。拆分出的數據
* 返回值:True -- 該變量有數據
*}
function TAddressParse.SplitValue(const DeviceVar: TDeviceVar; DataPkt: Variant;
var Value: Variant): Boolean;
begin
try
case DeviceVar.AddressInfo.dwDataSort of
Const_DataSort_Sta
: Value := Integer(DataPkt);
Const_DataSort_Num
: Value := Integer(DataPkt);
Const_DataSort_Chr
: Value := String(DataPkt);
Const_DataSort_Bln
: Value := Integer(StrToBool(String(DataPkt)));
else
Value := DataPkt;
end;
Result := True;
except
WriteDebugLog('在SplitValue函數中,根據變量的類型進行類型轉換時發生錯誤');
Result := False;
end;
end;
{*
* 函數名稱:FindItems
* 函數功能:根據地址信息查找設備變量的索引信息
* 入口參數:1、Addr: TAddressInfo。設備變量地址信息
* 出口參數:無
* 返回值:TIntegerArray。設備變量索引數組
*}
function TAddressParse.FindItems(Addr: TAddressInfo): TIntegerArray;
var
I, J, K: Integer;
begin
SetLength(Result, 0);
for I := 0 to High(FReadListInfos) do
begin
for J := 0 to High(FReadListInfos[I].rcdReadInfo) do
begin
if AnsiCompareText(Addr.dwReadItem, FReadListInfos[I].rcdReadInfo[J].szItemName) = 0 then
begin
SetLength(Result, Length(FReadListInfos[I].rcdReadInfo[J].arrVarList));
for K := 0 to High(FReadListInfos[I].rcdReadInfo[J].arrVarList) do
Result[K] := FReadListInfos[I].rcdReadInfo[J].arrVarList[K];
Exit;
end;
end;
end;
end;
{*
* 函數名稱:FindCommErrorItems
* 函數功能:獲得與指定通信端口關聯的設備通信故障變量索引
* 入口參數:無
* 出口參數:無
* 返回值:TIntegerArray。設備變量索引數組
*}
function TAddressParse.FindCommErrorItems: TIntegerArray;
var
I, Count: Integer;
begin
Count := Length(FCommErrorInfos);
SetLength(Result, Count);
for I := 0 to Count - 1 do
Result[I] := FCommErrorInfos[I].dwLocalIndex;
end;
{*
* 函數名稱:FindRTUCommErrorItems
* 函數功能:查找指定RTU連接設備通信故障變量索引
* 入口參數:無
* 出口參數:無
* 返回值:TIntegerArray。設備變量索引數組
*}
function TAddressParse.FindRTUCommErrorItems(RTUNo: DWord): TIntegerArray;
var
I, Count: Integer;
begin
Count := Length(FCommErrorInfos);
SetLength(Result, 0);
for I := 0 to Count - 1 do
begin
if (FCommErrorInfos[I].rcdAddress.dwRTUNo = RTUNo) then
begin
SetLength(Result, Length(Result) + 1);
Result[High(Result)] := FCommErrorInfos[I].dwLocalIndex;
end;
end;
end;
{*
* 函數名稱:Create
* 函數功能:構造函數
* 入口參數:無
* 出口參數:無
* 返回值:無
*}
constructor TAddressParse.Create;
begin
InitializeCriticalSection(FLock);
FRTUFaultList := TList.Create;
SetLength(FSCMSFaultList, 0);
SetLength(FCommErrorInfos, 0);
SetLength(FNormalInfos, 0);
end;
{*
* 函數名稱:Destroy
* 函數功能:析構函數
* 入口參數:無
* 出口參數:無
* 返回值:無
*}
destructor TAddressParse.Destroy;
begin
FNormalInfos := nil;
FCommErrorInfos := nil;
FSCMSFaultList := nil;
FRTUFaultList.Free;
DeleteCriticalSection(FLock);
inherited;
end;
{*
* 函數名稱:AddInfo
* 函數功能:增加設備變量的尋址信息
* 入口參數:1、Info: TAddressParseInfo。設備變量運行信息
* 出口參數:無
* 返回值:無
*}
function TAddressParse.AddInfo(Info: TAddressParseInfo): Integer;
var
I: Integer;
FindIt: Boolean;
WriteInfo: TWriteInfo;
begin
EnterCriticalSection(FLock);
try
Result := -1;
if Info.rcdAddress.dwDataType = Const_Type_CommErr then //通信故障的功能組
begin
SetLength(FCommErrorInfos, Length(FCommErrorInfos) + 1);
FCommErrorInfos[High(FCommErrorInfos)] := Info;
Result := -High(FNormalInfos);
end;
if not ItemIsNull(Info.rcdAddress.dwReadItem) then
begin
//將設備變量的讀地址信息添加到數組中
SetLength(FNormalInfos, Length(FNormalInfos) + 1);
FNormalInfos[High(FNormalInfos)] := Info;
Result := High(FNormalInfos);
end;
if ItemIsNull(Info.rcdAddress.dwReadItem) then
begin
Result := -High(Integer);
end;
//將有效的OPCITEM名稱加入列表中
FindIt := False;
if not ItemIsNull(Info.rcdAddress.dwReadItem) then
begin
for I := 0 to High(FItemNameList) do
begin
if AnsiCompareText(FItemNameList[I], Info.rcdAddress.dwReadItem) = 0 then
begin
FindIt := True;
Break;
end;
end;
if not FindIt then
begin
SetLength(FItemNameList, Length(FItemNameList) + 1);
FItemNameList[High(FItemNameList)] := Info.rcdAddress.dwReadItem;
end;
end;
//將有效的OPCITEM名稱加入列表中
FindIt := False;
if not ItemIsNull(Info.rcdAddress.dwWriteItem) then
begin
for I := 0 to High(FItemNameList) do
begin
if AnsiCompareText(FItemNameList[I], Info.rcdAddress.dwWriteItem) = 0 then
begin
FindIt := True;
Break;
end;
end;
if not FindIt then
begin
SetLength(FItemNameList, Length(FItemNameList) + 1);
FItemNameList[High(FItemNameList)] := Info.rcdAddress.dwWriteItem;
end;
end;
//判斷變量是否需要定時下發
if (Info.rcdAddress.dwFuncGroup = Const_FG_SYSTEM) and
(Info.rcdAddress.dwDataType = Const_Type_RTUCommCheck) then
begin
if ItemIsNull(Info.rcdAddress.dwWriteItem) then
Exit;
FindIt := False;
for I := 0 to High(FAutoWriteInfos) do
begin
if AnsiCompareText(FAutoWriteInfos[I].szItemName, Info.rcdAddress.dwWriteItem) = 0 then
begin
FindIt := True;
Break;
end;
end;
if FindIt then
Exit;
WriteInfo.szItemName := Info.rcdAddress.dwWriteItem;
WriteInfo.dwWriteSample := Info.rcdAddress.dwSampleTime * 1000;
WriteInfo.dwPriorWrite := 0;
WriteInfo.dwWriteValue := 0;
SetLength(FAutoWriteInfos, Length(FAutoWriteInfos) + 1);
FAutoWriteInfos[High(FAutoWriteInfos)] := WriteInfo;
end;
finally
LeaveCriticalSection(FLock);
end;
end;
{*
* 函數名稱:GetItemNameList
* 函數功能:獲得數據項名稱的列表
* 入口參數:無
* 出口參數:無
* 返回值:數據項名稱列表
*}
function TAddressParse.GetItemNameList: TStringArray;
var
I: Integer;
begin
SetLength(Result, Length(FItemNameList));
for I := 0 to High(FItemNameList) do
Result[I] := FItemNameList[I];
end;
{*
* 函數名稱:FinishedAdd
* 函數功能:完成添加設備變量的尋址信息
* 1、根據設備變量尋址信息中的讀地址進行排序
* 2、根據設備變量的尋址信息生成采樣周期判定數組
* 入口參數:無
* 出口參數:無
* 返回值:無
*}
procedure TAddressParse.FinishedAdd;
var
FindIt: Boolean;
ReadInfo: TReadInfo;
I, J, K, Idx, Count: Integer;
begin
EnterCriticalSection(FLock);
try
SetLength(FReadListInfos, 0);
Count := Length(FNormalInfos);
if Count = 0 then
Exit;
for I := 0 to Count - 1 do
begin
//判斷處理的變量是否需要主動查詢
if ItemIsNull(FNormalInfos[I].rcdAddress.dwReadItem) then
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -