⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driveru.pas

📁 omroln OPC 用delphi描述了同OMROLnOPC通讯的过程
💻 PAS
📖 第 1 页 / 共 5 页
字号:

{*
 *                    模块名称:OPC.OMRON设备驱动程序的处理模块
 *                    模块功能:实现与外场设备的数据交互、协议解析
 *                    生成日期:2004/11/05
 *                    模块作者:李杰
 *                    版本说明:1.0版
 *}

unit DriverU;                          

interface
uses
  Windows, Messages, SysUtils, Classes, Controls, Contnrs, Variants, Math, ExtCtrls, ComObj,
  DrvIntfDefinesU, PubDefinesU, EventLogU, CommU;

const
  //**************** 接口定义 ********************

  gsDriverGUID = '{B66EE5D7-4152-4E47-9B67-2A68E638C388}'; //驱动的标识
  gsModuleName = 'OPC.OMRON驱动程序'; //DLL的描述

  grcdDriverInfo: TDriverInfo = (cbSize: SizeOf(TDriverInfo);
    szDriverName: gsModuleName; szDriverVer: '1.0'; szDriverDesc: gsModuleName;
    szDriverGUID: gsDriverGUID; szFileName: 'OPC.DRV';
    szCommPortParam: 'O:MachineName;ServerName;GroupName';
    szCommPortParamDesc: 'O:[机器名];[OPC服务名];[分组名]';
    szVariantParamDesc: '[RTU编号]+[读变量]+[写变量]';
    szAddressConfigDesc: '[变量前缀]';
    dwSampleTime: 1000; dwSyncTime: 0);

  gCommPortAddressItemNumber = 1; //设备的地址信息
  gDriverVariantItemNumber = 7; //设备变量中属性元素的个数(RTU编号 + 读变量 + 写变量)

  //szVariantParam参数说明(例:1+52+1+1 功能组+数据类型+采集周期+数据种类)
  //数据种类: 状态-1、 数值-2、字符串-3
  grcdDriverVariantInfo: array[0..46] of TDriverVarInfo = (
    //(车辆检测器)
    (dwVariantId:90010001; szVariantDesc:'VD车流量';       szVariantParam:'001+052+60+02'),
    (dwVariantId:90010002; szVariantDesc:'VD平均车速';     szVariantParam:'001+053+60+02'),
    (dwVariantId:90010003; szVariantDesc:'VD占有率';       szVariantParam:'001+054+60+02'),
    (dwVariantId:90011001; szVariantDesc:'VD故障';         szVariantParam:'001+001+00+01'),
    (dwVariantId:90011002; szVariantDesc:'VD通信故障';     szVariantParam:'001+099+00+01'),

    //(可变情报板)
    (dwVariantId:90030001; szVariantDesc:'CSLS播放表';       szVariantParam:'004+047+00+03'),
    (dwVariantId:90030002; szVariantDesc:'CMS播放表';        szVariantParam:'004+048+00+03'),
    (dwVariantId:90030003; szVariantDesc:'开屏';             szVariantParam:'004+049+00+01'),
    (dwVariantId:90030004; szVariantDesc:'关屏';             szVariantParam:'004+050+00+01'),
    (dwVariantId:90031001; szVariantDesc:'控制器故障';       szVariantParam:'004+001+20+01'),
    (dwVariantId:90031002; szVariantDesc:'显示模组故障';     szVariantParam:'004+001+20+01'),
    (dwVariantId:90031003; szVariantDesc:'显示模组电源故障'; szVariantParam:'004+001+20+01'),
    (dwVariantId:90031004; szVariantDesc:'单像素管故障';     szVariantParam:'004+001+20+01'),
    (dwVariantId:90031005; szVariantDesc:'检测系统故障';     szVariantParam:'004+001+20+01'),
    (dwVariantId:90031006; szVariantDesc:'输入交流电故障';   szVariantParam:'004+001+20+01'),
    (dwVariantId:90031007; szVariantDesc:'防雷器故障';       szVariantParam:'004+001+20+01'),
    (dwVariantId:90031008; szVariantDesc:'光敏部件故障';     szVariantParam:'004+001+20+01'),
    (dwVariantId:90031009; szVariantDesc:'温度异常故障';     szVariantParam:'004+001+20+01'),
    (dwVariantId:90031010; szVariantDesc:'CMS通信故障';      szVariantParam:'004+099+00+01'),

    //(照明控制系统)
    (dwVariantId:90040001; szVariantDesc:'光照强度数据';     szVariantParam:'194+048+60+02'),
    (dwVariantId:90040002; szVariantDesc:'照明操作模式';     szVariantParam:'194+017+00+01'),
    (dwVariantId:90040003; szVariantDesc:'照明控制级别';     szVariantParam:'194+065+00+01'),
    (dwVariantId:90040004; szVariantDesc:'照明工作模式';     szVariantParam:'194+018+00+01'),
    (dwVariantId:90041001; szVariantDesc:'照明设备自检故障'; szVariantParam:'194+001+00+01'),
    (dwVariantId:90041002; szVariantDesc:'照明设备通信故障'; szVariantParam:'194+099+00+01'),

    //(通风控制系统)
    (dwVariantId:90050001; szVariantDesc:'通风操作模式';     szVariantParam:'195+017+00+01'),
    (dwVariantId:90050002; szVariantDesc:'一氧化碳浓度';     szVariantParam:'195+048+60+02'),
    (dwVariantId:90050003; szVariantDesc:'烟雾浓度';         szVariantParam:'195+049+60+02'),
    (dwVariantId:90050004; szVariantDesc:'风机运行时间';     szVariantParam:'195+056+60+02'),
    (dwVariantId:90050005; szVariantDesc:'风机运行状态';     szVariantParam:'195+064+00+01'),
    (dwVariantId:90050007; szVariantDesc:'风机手动控制';     szVariantParam:'195+065+00+01'),
    (dwVariantId:90050008; szVariantDesc:'隧道内风速';       szVariantParam:'195+051+60+02'),
    (dwVariantId:90050009; szVariantDesc:'隧道内风向';       szVariantParam:'195+052+60+02'),
    (dwVariantId:90051001; szVariantDesc:'通风设备自检故障'; szVariantParam:'195+001+00+01'),
    (dwVariantId:90051002; szVariantDesc:'通风设备通信故障'; szVariantParam:'195+099+00+01'),

    //(火灾告警系统)
    (dwVariantId:90060001; szVariantDesc:'区段自动火灾报警'; szVariantParam:'196+048+00+01'),
    (dwVariantId:90060002; szVariantDesc:'区段手动火灾报警'; szVariantParam:'196+064+00+01'),
    (dwVariantId:90061001; szVariantDesc:'火灾设备自检故障'; szVariantParam:'196+001+00+01'),
    (dwVariantId:90061002; szVariantDesc:'火灾设备通信故障'; szVariantParam:'196+099+00+01'),

    //(交通控制系统)
    (dwVariantId:90070001; szVariantDesc:'交通操作模式';     szVariantParam:'212+017+00+01'),
    (dwVariantId:90070003; szVariantDesc:'信号灯状态';       szVariantParam:'212+064+00+01'),
    (dwVariantId:90070004; szVariantDesc:'交通控制方案';     szVariantParam:'212+065+00+02'),
    (dwVariantId:90071001; szVariantDesc:'交通设备自检故障'; szVariantParam:'212+001+00+01'),
    (dwVariantId:90071002; szVariantDesc:'交通设备通讯故障'; szVariantParam:'212+099+00+01'),

    //RTU通讯状态
    (dwVariantId:90080001; szVariantDesc:'RTU通讯状态';      szVariantParam:'254+078+00+01'),
    (dwVariantId:90080002; szVariantDesc:'RTU通讯保持';      szVariantParam:'254+254+60+02'),
    (dwVariantId:90080003; szVariantDesc:'RTU门开报警';      szVariantParam:'254+002+00+04'));

  //************************************************

  CONST_NULL_ITEMNAME = 'NULL';
  Const_TIME_COMMFAILED = 600000; //10分钟
  Const_TIME_REFRESHDATA = 300000; //5分钟
  Const_RTUCOMM_NORMAL = 0;
  
  //==========================================
  //帧类型
  Const_FrameType_Invalid = 0; //无效数据帧
  Const_FrameType_Normal = 1; //普通数据帧
  Const_FrameType_SCMS = 2; //CMS、CSLS数据帧
  //==========================================

  Const_Event_SendDataReq = 101; //发送数据
  Const_Event_RecvDataInd = 102; //接收数据
  Const_Event_LoopCheck = 103; //查询数据
  Const_Event_WaitAnswer = 104; //等待应答数据(针对SCMS)

  Const_FrameSendTimeOut = 5000; //发送超时时间(5秒)
  Const_FrameSendFailed = 20000; //发送失败检测时间(20秒)

  Const_DataSort_Sta = 1; //状态数据
  Const_DataSort_Num = 2; //数值数据
  Const_DataSort_Chr = 3; //字符串
  Const_DataSort_BLN = 4; //布尔型

  //功能组描述
  Const_FG_TRF = 1; //交通功能组
  Const_FG_SCMS = 4; //情报板功能组
  Const_FG_LIGHT = 194; //照明控制功能组
  Const_FG_Ven = 195; //通风控制功能组
  Const_FG_FIRE = 196; //火灾功能组
  Const_FG_BAS90 = 212; //交通控制功能组
  Const_FG_SYSTEM = 254; //系统功能组

  //==========================================
  //数据类型描述

  //公用数据类型
  Const_Type_Error = 1; //设备故障
  Const_Type_CommErr = 99; //通信故障类型
  Const_Type_Mode = 17; //操作模式的类型

  //VD数据类型
  Const_Type_VDTrf = 52; //VD车流量数据
  Const_Type_VDSpd = 53; //VD车速数据
  Const_Type_VDHld = 54; //VD占有率数据

  //情报板数据类型
  Const_Type_CSLSLST = 47; //限速标志播放表
  Const_Type_CMSLST = 48; //情报板播放表
  Const_Type_OPENSCN = 49; //开屏
  Const_Type_CLOSESCN = 50; //关屏

  //照明数据类型
  Const_Type_BrtValue = 48; //照明强度数据
  Const_Type_BrtLevel = 65; //照明级别

  //通风数据类型
  Const_Type_COValue = 48; //CO浓度
  Const_Type_VIValue = 49; //VI浓度
  Const_Type_FANTime = 56; //风机运行时间
  Const_Type_FANState = 64; //风机运行状态
  Const_Type_FANManu = 65; //风机手动控制
  Const_Type_WindSpd = 51; //风速数据
  Const_Type_WindDct = 52; //风向数据

  //火灾数据类型
  Const_Type_FireAuto = 48; //火灾自动报警
  Const_Type_FireManu = 64; //火灾手动报警

  //交通控制数据类型
  Const_Type_TrfProgram = 65; //交通控制方案
  Const_Type_TrfLightSta = 64; //信号灯状态

  //系统功能组数据类型
  Const_Type_RTUCommState = 78; //RTU通讯状态
  Const_Type_RTUCommCheck = 254; //RTU通讯检查(自动下发数据)
  
  //=================================

  Const_Re_Error = -1; //函数返回失败
  Const_Re_OK = 0; //函数返回成功
  Const_Re_Other = 1; //函数返回其他

type
  TDeviceVar = class;
  TDriver = class;
  TDriverList = class;
  TIntegerArray = array of Integer;
  TDWordArray = array of DWord;
  TStringArray = array of string;
  
  //设备变量寻址信息
  TAddressInfo = record
    dwRTUNo: DWord; //RTU编号
    dwReadItem: string[100]; //读变量名称
    dwWriteItem: string[100]; //写变量名称
    dwFuncGroup: DWord; //功能组
    dwDataType: DWord; //数据类型
    dwSampleTime: DWord; //采集周期(毫秒)
    dwDataSort: DWord; //数据类别
  end;
  TAddressInfoArray = array of TAddressInfo;

  //应用数据结构
  TAppDataInfo = record
    dwLocalIndex: Integer; //本地设备变量索引
    rcdAddress: TAddressInfo; //设备变量的地址信息
    AppData: Variant; //接收数据内容
    dtDateTime: TDateTime; //报文中的时间(或系统时间)
  end;
  TAppDataInfoArray = array of TAppDataInfo;

  //设备变量的运行信息
  PAddressParseInfo = ^TAddressParseInfo;
  TAddressParseInfo = record
    dwDeviceVarId: DWord; //设备变量编号
    dwLocalIndex: Integer; //该设备变量在本地的列表中的索引
    rcdAddress: TAddressInfo; //设备变量地址信息
  end;
  TAddressParseInfoArray = array of TAddressParseInfo;

  //读取数据的地址信息
  PReadInfo = ^TReadInfo;
  TReadInfo = record
    szItemName: string[50]; //数据项的名称
    arrVarList: TIntegerArray; //关联到的设备变量的索引数组
    dwReadSample: DWord; //采样周期(毫秒)
    dwPriorRead: DWord; //上一次读取的时间
  end;
  TReadInfoArray = array of TReadInfo;

  //自动下发数据的地址信息
  PWriteInfo = ^TWriteInfo;
  TWriteInfo = record
    szItemName: string[50]; //数据项的名称
    dwWriteSample: DWord; //采样周期(毫秒)
    dwPriorWrite: DWord; //上一次下发的时间
    dwWriteValue: Word; //随机数
  end;
  TWriteInfoArray = array of TWriteInfo;

  //读取数据的有效地址列表信息
  PReadListInfo = ^TReadListInfo;
  TReadListInfo = record
    dwRTUNo: DWord; //RTU编号
    bCommState: Boolean; //通讯状态
    rcdReadInfo: TReadInfoArray; //读取数据的数组
  end;
  TReadListInfoArray = array of TReadListInfo;

  //CMS通讯故障数据结构
  TCMSCommErrorInfo = record
    szCMSName: string; //CMS的读地址
    dwCount: DWord; //连续中断次数
    bStatus: Boolean; //通讯状态
  end;
  TCMSCommErrorInfoArray = array of TCMSCommErrorInfo;

  //设备变量地址解析
  TAddressParse = class(TObject)
  private
    FLock: TRTLCriticalSection;
    FAutoWriteInfos: TWriteInfoArray; //自动下发的数据项列表
    FItemNameList: TStringArray; //保存有效的OPCITEM名称信息
    FRTUFaultList: TList; //保存RTU通讯中断编号
    FSCMSFaultList: TCMSCommErrorInfoArray; //保存限速标志通讯中断地址信息
    FReadListInfos: TReadListInfoArray; //读取数据的采样列表(该列表按OPC ITEM唯一排序)
    FNormalInfos: TAddressParseInfoArray; //正常节点的列表
    FCommErrorInfos: TAddressParseInfoArray; //通信故障节点的列表
    function ItemIsNull(ItemName: string): Boolean;
    function SplitValue(const DeviceVar: TDeviceVar; DataPkt: Variant;
      var Value: Variant): Boolean;
    function FindItems(Addr: TAddressInfo): TIntegerArray;
    function FindCommErrorItems: TIntegerArray;
    function FindRTUCommErrorItems(RTUNo: DWord): TIntegerArray;
  public
    constructor Create;
    destructor Destroy; override;
    function AddInfo(Info: TAddressParseInfo): Integer;
    function GetItemNameList: TStringArray;
    procedure FinishedAdd;
    procedure SetCommState(State: Boolean);
    procedure SetRecvData(AppDataInfo: TAppDataInfo);
    procedure GetQueryData(var ReadInfos: TReadInfoArray);
    procedure GetWriteData(var WriteInfos: TWriteInfoArray);
    procedure SetRTUFault(RTUNo: DWord; CommState: Boolean);
  end;

  TFrame = class(TObject)
  private
    FDataPkt: Variant; //数据内容(数据帧的数据部分)
    FAddrInfo: TAddressInfo; //数据的地址信息
    FLocalIndex: Integer; //设备变量本地索引
    FItemName: string; //访问OPCITEM的名称
    FFrmType: Integer; //数据帧类型
    FSending: Boolean; //是否发送
    FNeedAck: Boolean; //是否需要回应
    FStarted: DWord; //开始发送的TICKCOUNT
    FDeleted: Boolean; //是否删除
    FFormed: Boolean; //是否打包
  public
    constructor Create(DataPkt: Variant; Xmit: Boolean);
    destructor Destroy; override;
    procedure SetParams(const AddrInfo: TAddressInfo; LocalIndex: Integer = -1);
    procedure FormFrame;
    procedure Marked;
  published
    property DataPacket: Variant read FDataPkt;
    property AddrInfo: TAddressInfo read FAddrInfo;
    property LocalIndex: Integer read FLocalIndex;
    property ItemName: string read FItemName;
    property NeedAck: Boolean read FNeedAck;
    property Sending: Boolean read FSending;
    property Deleted: Boolean read FDeleted;
    property FrmType: Integer read FFrmType;
    property Started: DWord read FStarted;
  end;

  //滑动窗口
  TSlidingWindow = class(TObject)
  private
    FSyncObj: TRTLCriticalSection;
    FFrameList: TStringList; //发送数据帧列表
    function GetFrameCount: Integer;
    procedure ClearFrames;
  public
    constructor Create;
    destructor Destroy; override;
    procedure AddFrame(Frm: TFrame);
    procedure Reset;
    procedure ProcessSendFailed(SendFrm: TFrame);
    function ProcessSendTimeOut(var ItemNameList: TStringArray): TIntegerArray;
    function ProcessRecvAnswer(RecvFrm: TFrame): Boolean;
    function GetNextFrame: TFrame;
  published
    property FrameCount: Integer read GetFrameCount;
  end;

  //设备变量对象
  TDeviceVar = class(TAutoRelease)
  private
    FOwner: TDriver; //所属设备对象

    FDeviceVarId: DWord; //设备变量编号
    FDeviceVarState: Integer; //设备变量状态

    FDeviceVarType: Integer; //设备变量类型
    FServerIndex: Integer; //服务端设备变量对象索引
    FLocalIndex: Integer; //该设备变量在本地的列表中的索引
    FAddressIndex: Integer; //设备变量在地址树中的绝对位置
    FAddressInfo: TAddressInfo; //为了获得测试数据加入的

    FLastSendData: Variant; //最后一次发送的数据内容
    FLastRecvData: Variant; //最后一次接收的数据内容

    procedure SetState(State: Integer);
  public
    constructor Create(AOwner: TDriver; Info: TAddressParseInfo);
    destructor Destroy; override;
    function GetTestValue(var Value: Variant): Boolean;
    function SendData(Value: Variant; ATime: TDateTime): Boolean;
    function RecvData(Value: Variant; ATime: TDateTime): Boolean;
  published
    property Owner: TDriver read FOwner;
    property DeviceVarId: DWord read FDeviceVarId write FDeviceVarId;
    property DeviceVarType: Integer read FDeviceVarType write FDeviceVarType;
    property DeviceVarState: Integer read FDeviceVarState write SetState;
    property ServerIndex: Integer read FServerIndex write FServerIndex;
    property LocalIndex: Integer read FLocalIndex;
    property AddressIndex: Integer read FAddressIndex;
    property AddressInfo: TAddressInfo read FAddressInfo;
    property LastSendData: Variant read FLastSendData;
    property LastRecvData: Variant read FLastRecvData;
  end;

  //设备变量列表对象
  TDeviceVarList = class(TObjectList)
  private
    procedure FreeResource;
  public
    constructor Create;
    destructor Destroy; override;
    function AddItem(const DeviceVar: TDeviceVar): Integer;
    function GetItem(const Index: Integer): TDeviceVar;
    procedure MakeTestData;
    class function AddrAnalyze(Src: String; var Dst: TAddressInfo): Boolean;
    class function GetDeviceVarList: TDeviceVarList;
    class function CreateDeviceVar(AOwner: TDriver; Info: TDeviceVarInfo): TDeviceVar;
  end;

  //通信设备类
  TDriver = class(TLayer)
  private
    FSyncObj: TRTLCriticalSection; //发送数据时的同步对象

    //串口属性

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -