分享
 
 
 

由云台协议DLL浅谈插件程序的编写(上)【原创】

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

由云台协议DLL浅谈插件程序的编写(上)【原创】

前言:本文通过一个简单的工程描述了一种插件设计的思想。复杂设计和模块化分解能力是衡量一个程序员水平的重要标志,欢迎大家和我探讨。

1.我们的目的是在Plug-Ins目录里面查找“ptz*.dll”格式的云台插件的动态链接库。每个库可支持多个协议,通过查找该目录下的合法插件,有此插件创建出某个协议的实例,达到通过该协议操作云台的目的。

2.结构体定义:ComParam为串口通信参数:(定义在include\ComManager\ComParam.h文件中)

class COMPARAMEXT_API ComParam

{

public:

ComParam( int nBaudRate, // 波特率

int nByteSize = 8, // 数据位

int nParity = 0, // 校验位 0 - NOPARITY

int nStopBits = 0); // 停止位 0 - ONESTOPBIT(参考winbase.h中的定义)

};

3.为了达到使用dll的目的,先封装几个简单的类:

CDllLoad类:src\PTZ_Test\controls\DllLoad.h(这个类仅在src\PTZ_Test\controls\PTZDll.h)

// DllLoad.h

#pragma once

class CDllLoad

{

public:

CDllLoad()

{

}

virtual ~CDllLoad(void)

{

Close();

}

void Open(LPCTSTR lpszName) // 加载DLL

{

if (m_hModule)

{

Close();

}

m_hModule = ::LoadLibrary(lpszName);

}

void Close()

{

::FreeLibrary(m_hModule); // 卸载DLL

m_hModule = NULL;

}

operator HMODULE() { return m_hModule;}

PROC GetProcAddress(LPCSTR lpProcName)

{

return ::GetProcAddress(m_hModule, lpProcName); // 取得函数入口地址

}

protected:

HMODULE m_hModule;

};

CPTZDll类:src\PTZ_Test\controls\DllLoad.h(主要功能:根据插件产生出该DLL的支持的协议对象,然后由该对象的函数调用需要的功能,由于函数调用时实际使用的是dll的类的成员函数,所以对象存在时必须也有一份CPTZDll的实例而且是打开状态的。)

// PTZDll.h

#pragma once

#include "DllLoad.h"

#include "PTZInterface.h"

class CPTZDll

{

typedef CPTZInterface * (__stdcall* CREATE_PTZ_INSTANCE)(const char * pszProtocolsName);

public:

CPTZDll() // 成员初始化

: m_pDllLoad(0)

, m_pfnCreatePTZInstance(0)

, m_ppProtocolsName(0)

{

}

~CPTZDll()

{

Close();

delete m_pDllLoad;

m_pDllLoad =0;

}

BOOL OpenPlugIn(LPCTSTR lpszName) // 打开插件,如果是有效的插件返回TRUE,否则FALSE

{

if (m_pDllLoad)

Close();

else

{

m_pDllLoad = new CDllLoad();

m_pDllLoad->Open(lpszName);

}

m_pfnCreatePTZInstance = (CREATE_PTZ_INSTANCE)m_pDllLoad->GetProcAddress("CreatePTZInstance");

m_ppProtocolsName = (const char **)m_pDllLoad->GetProcAddress("ProtocolNames");

return (m_ppProtocolsName && m_ppProtocolsName[0]);

}

void Close()

{

m_pfnCreatePTZInstance = 0;

m_ppProtocolsName = 0;

if (m_pDllLoad)

m_pDllLoad->Close();

}

const char ** GetSupportProtocols()

{

return m_ppProtocolsName;

}

CPTZInterface * CreatePTZInstance(LPCTSTR lpszProtolName) // 根据该插件内的某个协议产生出一个对象

{

if (m_pfnCreatePTZInstance)

{

return m_pfnCreatePTZInstance(lpszProtolName);

}

return 0;

}

private:

CDllLoad * m_pDllLoad;

CREATE_PTZ_INSTANCE m_pfnCreatePTZInstance;

const char ** m_ppProtocolsName;

};

CPlugInInfo类:src\PTZ_Test\controls\PTZProtocolFind.h和src\PTZ_Test\controls\ptzprotocolfind.cpp

//=========================================================

//

// Copyright (c) 2000-2004 iWise Technologies,Co. Ltd.

// All Rights Reserved.

//

// Product: iW988

// File: PTZProtocolFind.h

// Created: 天衣有缝

// Data :2004.12.22 PM

// Description:

// ValueAdded main program for iW988.

// Contact:

// waterpub@mail.csdn.net

//

//=========================================================

#pragma once

class CPlugInInfo // 插件信息类

{

public:

string szFileName ; // 文件名

vector<string> Protocols ; // 协议列表

string szFullPath ; // 文件全路径

public:

CPlugInInfo(void)

{

}

~CPlugInInfo(void)

{

}

};

class CPTZProtocolFind

{

public:

CPTZProtocolFind(void);

~CPTZProtocolFind(void);

public:

void EnumPlugIns(vector<CPlugInInfo>& PlugInList); // 枚举Plug-Ins目录的所以ptz文件

};

//=========================================================

//

// Copyright (c) 2000-2004 iWise Technologies,Co. Ltd.

// All Rights Reserved.

//

// Product: iW988

// File: PTZProtocolFind.cpp

// Created: 天衣有缝

// Data :2004.12.22 PM

// Description:

// ValueAdded main program for iW988.

// Contact:

// waterpub@mail.csdn.net

//

//=========================================================

#include "StdAfx.h"

#include "ptzprotocolfind.h"

#include "PTZDll.h"

CPTZProtocolFind::CPTZProtocolFind(void)

{

}

CPTZProtocolFind::~CPTZProtocolFind(void)

{

}

// 枚举“Plug-Ins”目录下的所有有效插件

void CPTZProtocolFind::EnumPlugIns(vector<CPlugInInfo>& PlugInList)

{

char szFilePath[MAX_PATH];

::GetModuleFileName(NULL, szFilePath, MAX_PATH);

char * pFind = strrchr(szFilePath, '\\');

*pFind = '\0';

strcat(szFilePath, "\\Plug-Ins\\ptz*.dll"); // 查找的匹配字符串

CFileFind find;

BOOL bFind;

bFind = find.FindFile(szFilePath);

while (bFind)

{

CPTZDll dll;

bFind = find.FindNextFile();

if (find.IsArchived()) // 文件而非文件夹

{

// 输出这个文件:

XTRACE("路径:%s\n", find.GetFilePath());

if ( dll.OpenPlugIn(find.GetFilePath()) ) // 如果是云台插件,则枚举出它的协议

{

CPlugInInfo info;

const char ** ppProtocols = dll.GetSupportProtocols();

if(!ppProtocols)

{

continue;

}

while(0 != *ppProtocols)

{

string _string = *ppProtocols;

info.Protocols.push_back(_string);

ppProtocols ++;

}

info.szFullPath = find.GetFilePath();

info.szFileName = find.GetFileName();

PlugInList.push_back(info);

}

}

dll.Close();

}

find.Close();

// 下面是调试代码

XTRACE("插件数量:%d\n",PlugInList.size());

vector<CPlugInInfo>::iterator it = PlugInList.begin();

for(; it != PlugInList.end(); it++)

{

XTRACE("文件名:%s----》文件路径:%s\n", (*it).szFileName.c_str(), (*it).szFullPath.c_str());

}

}

4.在对话框工程的窗体中加入两个成员变量:

CPTZDll m_PTZdll ; // dll加载对象

CPTZInterface* m_PTZInterface ; // 正在使用的插件协议对象

用户选择一个插件:BOOL bReturn = m_PTZdll.OpenPlugIn(m_strProtocolPath);

然后根据该插件选择一个协议:m_PTZInterface = m_PTZdll.CreatePTZInstance(m_strProtocolName); // 参数是一个表示协议的字符串

这时我们可以利用这个m_PTZInterface对象来执行各种操作。

说明:m_PTZInterface的类“CPTZInterface”是一个抽象类,由此派生出各种各样的协议。

其定义如下:

//PTZInterface.h

//iWise DVR PTZ Interface define header file.

#pragma once

#include "PTZDef.h"

#include "ComParam.h"

class CPTZInterface

{

public:

virtual void SetPTZSettings(int nComPort, int nAddrID, const ComParam & param) = 0;

virtual void Move(MOVEMENT_DIR nDirection) = 0;

virtual void Action(int nActionID, int param) = 0;

virtual int SetSpeed(int nSpeedTrgID, int nSpeed) = 0;

virtual void DeviceSwitch(int nDeviceID, bool bSwitchOn) = 0;

virtual int SetPreset(int nIndex) = 0;

virtual int CallPreset(int nIndex) = 0;

virtual void Reset() = 0;

virtual int SelfCheck() = 0;

virtual int GetCaps(int nCapID, void * lParam) = 0;

virtual int ExtendOp(int nExOpID, void * lParam) = 0;

virtual void Destroy() = 0;

};

参考文档:

云台控制协议插件开发文档

本文档描述有关iWise-DVR云台控制协议插件的程序结构、设计原理、插件接口等重要信息,iWisePTZTest为插件的测试程序(插件也可以直接放到iWise-DVR环境中测试)。本文档以下出现的“DVR”均指“iWise-DVR”,本文档适用于使用串口的云台控制设备的基于DVR的云台控制协议插件的开发。

插件工作原理

云台控制有多种不同的控制协议,DVR提供统一的插件接口以支持不同的云台控制协议,通过协议插件来进行对云台的控制操作。DVR启动时会扫描Plug-Ins目录里面的所有文件名以“ptz”开头的动态连接库(DLL),并判断这些DLL是否为有效的云台控制协议插件。DVR定义了一套云台控制的基本操作,插件必须提供这些操作的具体实现,当用户要对云台进行控制时,DRV最终将调用插件的方法来控制云台,插件需要根据协议特征产生相应的指令数据并向串口设备发送这些指令。同时DVR提供向串口发送数据的统一的方法。

云台控制协议插件接口

DVR定义class CPTZInterface作为云台控制协议接口,该类是接口的核心,插件必须使用CPTZInterface派生一个类并实现所有的方法。CPTZInterface类详细定义如下:

class CPTZInterface

{

public:

virtual void SetPTZSettings(int nComPort, int nAddrID,

const ComParam & param) = 0;

virtual void Move(MOVEMENT_DIR nDirection) = 0;

virtual void Action(int nActionID, int param) = 0;

virtual int SetSpeed(int nSpeedTrgID, int nSpeed) = 0;

virtual void DeviceSwitch(int nDeviceID, bool bSwitchOn) = 0;

virtual int SetPreset(int nIndex) = 0;

virtual int CallPreset(int nIndex) = 0;

virtual void Reset() = 0;

virtual int SelfCheck() = 0;

virtual int GetCaps(int nCapID, void * lParam) = 0;

virtual int ExtendOp(int nExOpID, void * lParam) = 0;

virtual void Destroy() = 0;

};

SetPTZSettings函数设置云台设备所在的串口号、地址码及通信参数。

nComPort - 云台设备所在串口号

nAddrID - 设备地址码

param - 通信参数,ComParam结构的引用(请参考《iWise-DVR环境串口操作接口使用说明》)。

Move函数控制云台在各方向上的运动。

nDirection–运动方向,由MOVEMENT_DIR定义

enum MOVEMENT_DIR

{

MD_STOP, // 停止运动

MD_LEFT, // 向左

MD_RIGHT, // 向右

MD_UP, // 向上

MD_DOWN, // 向下

MD_LEFT_UP, // 左上

MD_LEFT_DOWN, // 左下

MD_RIGHT_UP, // 右上

MD_RIGHT_DOWN, // 右下

};

Action函数控制云台摄像机的动作。

nActionID–动作定义

ACTION_ZOOM 缩放,param = 0时为缩小 param = 1时为放大

ACTION_ZOOM_STOP 停止缩放

ACTION_FOCUS 聚焦,param = 0时为往近处聚焦 1为往远处

ACTION_FOCUS_STOP 停止聚焦

ACTION_AUTO_FOCUS 自动聚焦

ACTION_AUTO_FOCUS_STOP 停止自动聚焦

ACTION_AUTO_SCAN 自动扫描

ACTION_AUTO_SCAN_STOP 停止自动扫描

SetSpeed设置云台运动或摄像机动作的速度。

nSpeedTrgID–欲设置速度的目标

SPEED_TRG_PAN 水平方向运动

SPEED_TRG_TILT 垂直方向运动

ACTION_AUTO_SCAN 自动扫描

ACTION_AUTO_SCAN_STOP 停止自动扫描

nSpeed –速度值 (0x00-0x40)

如果成功,该函数返回设置后的速度,否则返回0。

DeviceSwitch函数提供打开、关闭某设备的功能。

nDeviceID–设备ID定义

DEVICE_CAMERA照相机

DEVICE_LIGHT灯光

DEVICE_RAINBRUSH 雨刷

DEVICE_IRIS 镜头光圈

bSwitchOn–true为打开设备,false为关闭设备

SetPreset函数设置预置点。

nIndex–预置点索引号,从1开始,使用GetCaps取得设备可以支持的预置点总数。

返回0为成功,否则失败

CallPreset函数调用预置点,将云台摄象机移动到指定预置点位置。

nIndex–预置点索引号,对使用SetPreset设置成功的索引号有效。

返回0为成功,否则失败

Reset函数使云台摄象机设备恢复到初始状态。

SelfCheck函数使云台摄象机设备自检。

返回0为成功,否则失败

GetCaps函数可以取得设备所能提供的能力。

nCapID–欲取得的能力的ID定义,请参考以下值

GC_BASAL 取得基本能力, lParam为指向PTZBasalCaps结构的指针。

lParam–指向特定能力结构的指针。

返回0为成功,否则失败

ExtendOp函数对CPTZInterface接口提供扩展功能。

nExOpID–扩展功能ID定义。

lParam–根据不同的nExOpID有不同的意义。

该函数目前未使用

Destroy函数负责销毁自身对象。

销毁方式必须和CreatePTZInstance的创建方式一致。

设备基本能力结构定义:

struct PTZBasalCaps

{

int nSize; // PTZBasalCaps结构的大小

int nPresetCount; // 支持预置点的个数

int nMinSpeed; // 云台移动速度最小值

int nMaxSpeed; // 云台移动速度最大值

bool bAutoScanSupported; // 是否支持自动扫描

}

插件DLL接口约定

插件DLL在实现了CPTZInterface的具体实现方法之后,必须提供一致的构建和销毁CPTZInterface对象的方法,因此必须导出如下函数:

• CPTZInterface * __declspec(dllexport) CreatePTZInstance(

const char * pszProtocolsName);

pszProtocolsName – 协议索名称,该名称由GetSupportProtocols函数取得。

该函数构造一个协议接口对象并返回其指针,该函数创建的对象必须由CPTZInterface::Destroy()函数自销毁。为安全起见,插件在卸载时也可以销毁使用者没有销毁的所有对象。

• const char ** __declspec(dllexport) GetSupportProtocols();

nProtocols – 支持的协议数目

该函数返回插件所支持的协议名称列表指针

GetSupportProtocols代码示例:

char * szProtocol[] = {

"PELCO-D",

"PELCO-P",

0 // 必须以0表示结束

};

const char ** __declspec(dllexport) GetSupportProtocols()

{

return (const char **)szProtocol;

}

以上代码表示该插件支持"PELCO-D"、"PELCO-P"两种协议。

class CPTZInterface声明在ptzInterface.h中。

有关串口指令的发送请参考《iWise-DVR环境串口操作接口使用说明》。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有