Интерфейсный модуль

Ниже приведен интерфейсный модуль для разработки DLL доступа к данным в среде Borland Delphi. Этот модуль содержит описания используемых интерфейсов.


////////////////////////////////////////////////////////////////////////////////
//
//	 Описание интерфейсов для взаимодействия OPC сервера и DLL доступа к данным.
//	 DLL доступа к данным реализует доступ у специфичному оборудованию.
//
////////////////////////////////////////////////////////////////////////////////

unit PluginInterface;

interface

uses Windows, SysUtils, OPCDA, OPCtypes;

const

	// Коды ошибок при работе с устройством(специфичные):
	// ошибка инициализации
	E_COMPORT_INVALID_PORT_INIT = HResult($CFFF0000);
	// ошибка таймаута
	E_COMPORT_TIMEOUT		 = HResult($CFFF0001);
	// неверная контрольная сумма
	E_INVALID_CRC			 = HResult($CFFF0002);
	// ошибка конфигурации GSM модема
	E_GSM_ERROR_CONFIG		= HResult($CFFF0003);
	// SMS сообщение забуферизировано
	E_GSM_SMS_BUFFERED		= HResult($CFFF0004);
	// Неизвестный формат ответа
	E_UNCKNOWN_ANSWER		 = HResult($CFFF0005);

	// Значения качества(специфичные->младший байт-стандартный, старший байт-специфичный)
	// ошибка инициализации COM порта
	OPC_QUALITY_INVALID_PORT_INIT = $0118;  // OPC_QUALITY_COMM_FAILURE = $18;
	// ошибка таймаута
	OPC_QUALITY_TIMEOUT		 = $0218;  // OPC_QUALITY_COMM_FAILURE = $18;
	// неверная контрольная сумма
	OPC_QUALITY_INVALID_CRC	 = $0318;  // OPC_QUALITY_COMM_FAILURE = $18;
	// ошибка конфигурации GSM модема
	OPC_QUALITY_GSM_ERROR_CONFIG  = $0418;  // OPC_QUALITY_COMM_FAILURE = $18;
	// SMS сообщение забуферизировано
	OPC_QUALITY_GSM_SMS_BUFFERED  = $0518;  // OPC_QUALITY_COMM_FAILURE = $18;
	// Неизвестный формат ответа
	OPC_QUALITY_UNCKNOWN_ANSWER   = $0618;  // OPC_QUALITY_COMM_FAILURE = $18;


	// Сообщения
	WM_USER = $0400;

	// Сообщения для формы конфигурации
	// сообщение - изменена конфигурация
	WM_CONFIGMESS_CHANGE  = WM_USER+300;
	// сообщение - сохранить текущую конфигурацию
	WM_CONFIGMESS_SAVE	= WM_USER+301;
	// сообщение - обновить поля формы
	WM_CONFIGMESS_REFRESH = WM_USER+303;
	// сообщение - закрытие формы
	WM_CONFIGMESS_CLOSE   = WM_USER+304;

	// Сообщения для формы параметров узла при добавлении узла
	// сообщение - кнопка "Добавить" недоступна
	WM_ADDNODEMESS_DISABLE_ADD	 = WM_USER+310;
	// сообщение - кнопка "Добавить" недоступна
	WM_ADDNODEMESS_ENABLE_ADD	= WM_USER+311;
	// сообщение - добавить узел
	WM_ADDNODEMESS_ADD_NODE		= WM_USER+312;
	// сообщение - закрыть форму
	WM_ADDNODEMESS_CLOSE_FORM	= WM_USER+313;
	// сообщение - добавить/изменить узел
	WM_ADDNODEMESS_ADD_CHANGE_NODE = WM_USER+314;
	// сообщение - закрытие формы
	WM_ADDNODEMESS_CLOSE		 = WM_USER+304;

	// Сообщения для формы параметров переменной при добавлении переменной
	// сообщение - кнопка "Добавить" недоступна
	WM_ADDITEMMESS_DISABLE_ADD	 = WM_USER+320;
	// сообщение - кнопка "Добавить" недоступна
	WM_ADDITEMMESS_ENABLE_ADD	= WM_USER+321;
	// сообщение - добавить переменную
	WM_ADDITEMMESS_ADD_ITEM		= WM_USER+322;
	// сообщение - закрыть форму
	WM_ADDITEMMESS_CLOSE_FORM	= WM_USER+323;
	// сообщение - добавить/изменить переменную
	WM_ADDITEMMESS_ADD_CHANGE_ITEM = WM_USER+324;
	// сообщение - закрытие формы
	WM_ADDITEMMESS_CLOSE		 = WM_USER+304;

	// Сообщения для формы параметров узла при изменении узла
	// сообщение - изменить параметры узла
	WM_CHANGENODEMESS_CHANGE_NODE = WM_USER+330;
	// сообщение - обновить поля формы
	WM_CHANGENODEMESS_REFRESH = WM_USER+331;

	// Сообщения для формы параметров переменной при изменении переменной
	// сообщение - изменить параметры переменной
	WM_CHANGEITEMMESS_CHANGE_ITEM = WM_USER+340;
	// сообщение - обновить поля формы
	WM_CHANGEITEMMESS_REFRESH = WM_USER+341;

type
  // свойство переменной
  PItemProperty = ^TItemProperty;
  TItemProperty = record
	vtDataType:		 TVarType;
	wReserved:			Word;
	dwPropertyID:		 DWORD;
	szItemID:			 ShortString;
	szDescription:		ShortString;
	vValue:			 OleVariant;
	hrErrorID:			HResult;
	dwReserved:		 DWORD;
  end;

  PItemAttributes = ^TItemAttributes;
  TItemAttributes = record
	szAccessPath:		 ShortString;
	szItemID:			 ShortString;
	bActive:			BOOL;
	hClient:			OPCHANDLE;
	hServer:			OPCHANDLE;
	dwAccessRights:	 DWORD;
	dwBlobSize:		 DWORD;
	pBlob:				PByteArray; // указатель на массив байтов (array[0..32767] of Byte)
	vtRequestedDataType:  TVarType;
	vtCanonicalDataType:  TVarType;
	dwEUType:			 OPCEUTYPE;
	vEUInfo:			OleVariant;
  end;

  ILcsItem = interface;
  TItemProperties = array of TItemProperty; // свойства переменной
  PItemProperties = ^TItemProperties;
  TTask = (tNone, tSyncRead, tSyncWrite, tAsyncRead, tAsyncWrite);
  TPriority = (prNormal, prHigh, prHighest);
  PResult = ^HRESULT;

  // параметры задачи
  TTaskDef = record
	Task: TTask; 					 // тип задачи
	Item: ILcsItem; 				// переменная
	TransactID: Cardinal; 			// идентификатор транзакции
	ptrItemStr: PChar; 			 // имя переменной
	ptrItemState: POPCITEMSTATE; 	 // состояние переменной
	ptrNodeProperties: PItemProperties;  // свойства узла для данной переменной
	ptrItemProperties: PItemProperties;  // свойства переменной
	ptrReturnState: POPCITEMSTATE;  // состояние в которое возвращается значение переменной
										 // (используется в специфичных ситуациях)
	ptrResult: PResult; 			// результат выполнения задачи (для синхронных задач)
	ptrItemID: PChar; 				// полное имя
  end;
  PTaskDef = ^TTaskDef;
  // права на изменение переменной (узла)
  TAccessChange = (
	acChangeProps,  // изменение свойств
	acAddNode, 	 // добавление узлов
	acAddItem, 	 // добавление переменных
	acDelete, 	// удаление переменной(узла)
	acCopy			 // копирование переменной(узла)
  );
  TAccessChangeItem = set of TAccessChange;


  ILcsOPCServer = interface;
  ILcsComPort = interface;

  //-----------------------------------------------------------------
  // Интерфейс предоставляющий набор функций библиотеки, реализующей доступ
  //   к данным, для OPC сервера (реализуется в DLL)
  ILcsDriver = interface
  ['{31DE528E-EA4E-4AC4-86A4-5E73D18A4FCA}']
	// Инициализация драйвера
	// Вход: AOPCServer - указатель на интерфейс ILcsOPCServer,
		//   AComPort - указатель на интерфейс ILcsComPort
		// Выход: AName - имя DLL доступа к данным,
		//   ADescript - описание DLL доступа к данным,
	//   AHelpFileName - имя файла помощи (без пути,
	//	 расположен в одном каталоге с DLL, если нет помощи - '')
	// P.S. Вызывается два раза. В начале работы чтобы передать указатели на
	//   интерфейсы и получить описание драйвера. И в конце, тогда передаются
	//   AOPCServer = nil и AComPort = nil. В последнем случае необходжимо
	//   обнулить указатели (nil) на интерфейсы ILcsOPCServer и ILcsComPort,
	//   иначе произойдет исключение при обнулении указателей на интерфейсы
	//   если объекты реализующие эти интерфейсы удалены.
	procedure Initial(AOPCServer: ILcsOPCServer; AComPort: ILcsComPort;
	out AName, ADescript, AHelpFileName: ShortString); stdcall;
	// Создание формы конфигурации
	// Вход: AParentHandle - хэндл родительского визуального контейнера
	// Выход: AChildHandle - хэндл дочерней формы,
	//   AWidthChild - ширина дочерней формы,
	//   AHeightChild - высота дочерней формы,
	//   Result - True -> форма конфигурации включена, False -> не включена
	// P.S. 1) На сервере форма отображается с размерами AWidthChild, AHeightChild
	//   2) Связь между формами через сообщения (см. WM_CONFIGMESS_XXX)
	//	 передаваемые окну AChildHandle(обязательно SendMessage)
	function ConfigCreate(AParentHandle: THandle; out AChildHandle: THandle;
	out AWidthChild, AHeightChild: integer): boolean; stdcall;
	// Создание формы добавления узла (группа переменных)
	// Вход: AParentHandle - хэндл родительского визуального контейнера,
	//   AItem - родительская переменная
	// Выход: AChildHandle - хэндл дочерней формы,
	//   AWidthChild - ширина дочерней формы,
	//   AHeightChild - высота дочерней формы,
	//   Result - True -> форма конфигурации включена, False -> не включена
	// P.S. 1) На сервере форма отображается с размерами AWidthChild, AHeightChild
	//   2) Связь между формами через сообщения (см. WM_ADDNODEMESS_XXX)
	//	 передаваемые окну AChildHandle(обязательно SendMessage)
	function AddNodeCreate(AParentHandle: THandle; AItem: ILcsItem;
	out AChildHandle: THandle; out AWidthChild, AHeightChild: integer): boolean; stdcall;
	// Создание формы добавления переменной
	// Вход: AParentHandle - хэндл родительского визуального контейнера,
	//   AItem - родительская переменная,
	//   AProps - свойства родителькой переменной
	// Выход: AChildHandle - хэндл дочерней формы,
	//   AWidthChild - ширина дочерней формы,
	//   AHeightChild - высота дочерней формы,
	//   Result - True -> форма конфигурации включена, False -> не включена
	// P.S. 1) На сервере форма отображается с размерами AWidthChild, AHeightChild
	//   2) Связь между формами через сообщения (см. WM_ADDITEMMESS_XXX)
	//	 передаваемые окну AChildHandle(обязательно SendMessage)
	function AddItemCreate(AParentHandle: THandle; AItem: ILcsItem; AProps: PItemProperties;
	out AChildHandle: THandle; out AWidthChild, AHeightChild: integer): boolean; stdcall;
	// Изменение параметров переменной
	// Вход: AParentHandle - хэндл родительского визуального контейнера,
	//   AItem - родительская переменная,
	//   AItemName - имя переменной,
	//   AFlag - признак узла (OPC_BROWSE_HASCHILDREN -> переменная является узлом, иначе простая переменная),
	//   ANodeProps - свойства родителькой переменной,
	//   AProps - свойства переменной
	// Выход: AChildHandle - хэндл дочерней формы,
	//   AWidthChild - ширина дочерней формы,
	//   AHeightChild - высота дочерней формы,
	//   Result - True -> форма конфигурации включена, False -> не включена
	// P.S. 1) На сервере форма отображается с размерами AWidthChild, AHeightChild
	//   2) Связь между формами через сообщения (см. WM_CHANGENODEMESS_XXX или WM_CHANGEITEMMESS_XXX)
	//	 передаваемые окну AChildHandle(обязательно SendMessage)
	function ChangeChildItem(AParentHandle: THandle; AItem: ILcsItem;
	AItemName: PChar; AFlag: DWORD; ANodeProps, AProps: PItemProperties;
	out AChildHandle: THandle; out AWidthChild, AHeightChild: integer): boolean; stdcall;
	// Добавление задачи (чтение синхронное/асинхронное, запись синхронная/асинхронная)
	// Вход: ATaskDef - задача
	// Выход: Result - S_OK->успешное добавление
	function AddTask(ATaskDef: TTaskDef): HResult; stdcall;
	// Выполнение ранее добавленых задач
	// Вход: APriority - приоритет выполнения
	function RunTasks(APriority: TPriority): HResult; stdcall;
	// Загрузка параметра конфигурации
	// Вход: AParamName - имя параметра,
	//   AParamValue - значение параметра
	function LoadConfig(AParamName, AParamValue: ShortString): boolean; stdcall;
	// Очистить операции связанные с переменной AItem
	// Вход: AItem - переменная
	procedure PurgeAction(AItem: ILcsItem); stdcall;
	// Получение строки - значение данного свойства
	// Вход: APropID-идентификатор пользовательского свойства,
	//   AValue-значение свойства
	// Выход: AStr - строка
	procedure GetPropStr(APropID: DWORD; AValue: OleVariant; out AStr: ShortString) stdcall;
	// Сброс состояния устройства связанного с задачей ATaskDef
	// Вход: ATaskDef - задача
	function ResetDeviceState(ATaskDef: TTaskDef): HResult; stdcall;
	// Очистить все текущие операции
	procedure PurgeActions; stdcall;
	// Установка режима вывода отладочных сообщений
	// Вход: AValue - True->вывод отладочных сообщений, False->не выводить
	procedure SetDebugMode(AValue: boolean) stdcall;
	// Получение времени сброса (watchdog)
	// Вход: ANodeProps - свойства узла,
	//   AProps - свойства переменной
	// Выход: ATimeout - таймаут (мс)
	function GetWatchdogTimeout(ANodeProps, AProps: PItemProperties; out ATimeout: integer): boolean; stdcall;
  end;



  //-----------------------------------------------------------------
  // Интерфейс предоставляющий набор функций OPC сервера для драйвера
  //   (реализован на OPC сервере)
  ILcsOPCServer = interface
  ['{81ED8EB3-BC76-443E-8722-0B004B49C4EF}']
	// Сохранить параметр конфигурации
	// Вход: AParamName - имя параметра,
	//   AParamValue - значение параметра
	function SaveConfig(AParamName, AParamValue: string): boolean; stdcall;
	// Вывод сообщения в лог
	// Вход: AMess - сообщение,
	//   AWiteTime - True->записывать время, False->не записывать время
	procedure WriteToLog(AMess: PChar; AWriteTime: boolean); stdcall;
	// Отладочное сообщение
	// Вход: AName - имя отладочного параметра,
	//   AValue - значение параметра
	procedure DebugValue(AName: PChar; AValue: PChar); stdcall;
	// Сброс watchdog таймера для транзакции
	// Вход: ATransactID - идентификатор транзакции
	procedure ResetWatchdogTimer(ATransactID: Cardinal); stdcall;
	// Присвоение значения переменной с данным набором свойств
	// Вход: AProps-набор свойств,
	//   AItemState-состояние переменной
	function SetItemValue(AProps: TItemProperties; AItemState: OPCITEMSTATE): HResult; stdcall;
  end;



  //-----------------------------------------------------------------
  // Интерфейс предоставляющий набор функций OPC сервера для доступа
  //   к переменной (реализован на OPC сервере)
  ILcsItem = interface
  ['{F2B0EFCD-411F-4E2A-B63D-46A1BBE1C921}']
	// Добавление дочерней переменной
	// Вход: AItemAttrib - атрибуты(описание) переменной
	//   AFlag - 0бит(OPC_BROWSE_HASCHILDREN) =1 -> узел,
	//	 1бит(OPC_BROWSE_ISITEM) =1 -> переменная,
	//   AAccessChange - права на изменение переменной (узла),
	//   AProps - свойства переменной
	//   ALcsDriver - интерфейс доступа к драйверу
	function AddChildItem(AItemAttrib: TItemAttributes; AFlag: DWORD;
	AAccessChange: TAccessChangeItem; AProps: PItemProperties;
	ALcsDriver: ILcsDriver): HResult; stdcall;
	// Завершение чтения значения переменной (при асинхронном чтении)
	// Вход: ATransactID-идентификатор транзакции,
	//   AResult-результат выполнения операции
	// P.S. Значение передается через ATaskDef.ptrItemState передаваемое через
	//   функцию ILcsDriver.AddTask
	procedure OnReadComplete(ATransactID: Cardinal; AResult: HResult); stdcall;
	// Завершение записи значения переменной (при асинхронной записи)
	// Вход: ATransactID-идентификатор транзакции,
	//   AItemState-состояние(в т.ч. значение) переменной,
	//   AResult-результат выполнения операции
	procedure OnWriteComplete(ATransactID: Cardinal; AResult: HResult); stdcall;
	// Изменение параметров переменной
	// Вход: AItemAttrib - атрибуты(описание) переменной,
	//   AProps - свойства переменной
	// Выход: Result - результат операции
	function ChangeItem(AItemAttrib: TItemAttributes; AProps: PItemProperties): HResult; stdcall;
	// Передача кол-ва запросов к устройству
	// Вход: ASuccess - кол-во успешных запросов,
	//   AFail - кол-во не успешных запросов,
	//   ANewQuery - True->новый запрос, False->нет
	// P.S. Если ANewQuery = True, то для всех групп сбрасывается блокировка увеличения счетчика.
	//   Если ANewQuery = False, то счетчик увеличивается только один раз и затем становиться на блокировку.
	//   В простейшем случае ANewQuery всегда True.
	procedure OnCountQuery(ASuccess, AFail: integer; ANewQuery: boolean); stdcall;
  end;

  // тип результата выполнения операции
  TResultAction = (
	rwSuccess,  // успешная операция
	rwErrorInit,  // ошибка инициализации порта
	rwBusy, 	// порт занят другим драйвером устройства
	rwFailed		 // ошибка при записи
  );

  // Номер порта
  TComPortNum = ( pnCOM1, pnCOM2, pnCOM3, pnCOM4, pnCOM5, pnCOM6, pnCOM7,
	 pnCOM8, pnCOM9, pnCOM10, pnCOM11, pnCOM12, pnCOM13,
	 pnCOM14, pnCOM15, pnCOM16 );


  ILcsReceiveData = interface;

  //-----------------------------------------------------------------
  // Интефейс для доступа к COM портам (реализован на OPC сервере)
  ILcsComPort = interface
  ['{740C49CF-02A2-4427-B343-2A76B945E9D9}']
	// Запись данных в порт (асинхронная операция)
	// Вход: AComPortNumber-номер СOM порта,
	//   AData-указатель на данные,
	//   ACount-кол-во байтов данных,
	//   AReceiveData-интерфейс для получения данных
	// Выход: Result - rwSuccess->успешная запись, rwFailed->ошибка при записи,
	//   rwErrorInit->ошибка инициализации порта, rwBusy->порт занят
	// P.S. Ответ возвращается через интерфейс IReceiveData
	function Write(AComPortNum: TComPortNum; const AData: Pointer;
	const ACount: Cardinal; AReceiveData: ILcsReceiveData): TResultAction;  stdcall;
	// Занять СОМ порт (используется для разграничения доступа к одному СОМ порту нескольких драйверов устройств)
	// Вход: AComPortNum - СОМ порт
	//   AReceiveData - интерфейс для получения данных
	// Выход: Result - True->удалось занять порт, False->не удалось занять СОМ порт
	// P.S. В простейшем случае(когда используется только один драйвер имеющий доступ
	//   к СОМ порту) можно использовать только ILcsComPort.Write без функций
	//   ILcsComPort.OccupyPort и ILcsComPort.ReleasePort
	function OccupyPort(AComPortNum: TComPortNum; AReceiveData: ILcsReceiveData): boolean; stdcall;
	// Освободить СОМ порт  (используется для разграничения доступа к одному СОМ порту нескольких драйверов устройств)
	// Вход: AComPortNum - СОМ порт
	//   AReceiveData - объект для получения данных
	// Выход: Result - True->удалось освободить порт, False->ошибка при освобождении СОМ порта
	// P.S. В простейшем случае(когда используется только один драйвер имеющий доступ
	//   к СОМ порту) можно использовать только ILcsComPort.Write без функций
	//   ILcsComPort.OccupyPort и ILcsComPort.ReleasePort
	function ReleasePort(AComPortNum: TComPortNum; AReceiveData: ILcsReceiveData): boolean; stdcall;
  end;


  //-----------------------------------------------------------------
  // Интерфейс для получения данных (реализуется в DLL)
  ILcsReceiveData = interface
  ['{FACC000A-9C12-46B9-A91B-254F02BA51F6}']
	// Получение данных от СОМ порта
	// Вход: AComPort-СОМ порт,
	//   ADataPtr-данные,
	//   ADataSize-размер данных(байт)
	procedure OnReceiveData(AComPortNum: TComPortNum;
	ADataPtr: Pointer; ADataSize: Integer); stdcall;
	// Порт освободился
	// Вход: AComPort-СОМ порт
	procedure OnReleasePort(AComPortNum: TComPortNum); stdcall;
  end;


implementation  

end.