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

由云台协议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环境串口操作接口使用说明》。

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
1、中文简繁互换:在简体中文和繁体中文之间进行转换。 2、进制转换:在二进制、八进制、十进制、十六进制之间相互转换。 3、人民币大小写互换:在Excel中,很多时候需要将小写的金额数字转换成大写,而Excel提供的函数转换出来的格式并不符合中国人的习惯,所以... 4、数字签名:对Excel表格中的内容进行签名保护,主要是防止提供者提供的内容被非法修改。可以用于Excel公文的电子签名,实现真正的无纸办公... 5、保存为图片文件:相当于Excel的照相机功能(有过之而无不及)。可以将Excel中的元格区域、Shape对象、图片、图表等(甚至是组合形式)以gif、jpg、bmp等各式保存到磁盘中。 6、全功能批注----真正所见即所得的批注编辑器。 7、VB/VBA代码归纳与重写:对VB/VBA代码进行混淆,大大降低代码的可读性,是一种保护VB/VBA代码的很有效的方法。详细的注释说明和一目了然的名称将有助于设计阶段的调试和查错,但是代码一旦发布后,这些优点将会使黑客轻而易举地破解你的成果,呵呵,用这个吧,保证黑客对您的VB/VBA代码一点兴趣和胃口都没有!! 8、解除Excel文档的内部密码。很多时候,我们需要设置Excel表格/工作簿的保护密码,可是随着时间的推移,这些密码很可能遗忘了,怎么办?很着急啊!!!哈哈,用这个保证在2分钟之内解决问题(换个角度:不要再自欺欺人了,Excel的内部密码形同虚设)。 9、信息加密/解密。对Excel文档中的一些敏感信息进行加密处理,即使文档被破解了,里面的信息仍然很安全。可以说这个功能是对Excel安全的一个有力补充。 10、工程代码锁定解锁器。可以撤销Excel的VBA保护密码(对word、Access同样有效) 11、控制和保存功能。这个功能能满足我们不用记一个密码就能非常有效地保护我们的Excel文档,而且可以免除来自微软的威胁。 12、Cookie管理器。在信息时代,没有网络怎么可以?上网时间长了,就会发现在临时文件夹中挤满了cookies,不但占据磁盘空间,而且还可能泄露秘密。用“清理cookie”命令吧,又觉得有些没有必要删,否则下次还得再输一遍;一个一个删吧,东西太多,想都不能想。怎么办??用这个啊!!只要一次性设置要保留的cookie并选中“退出Excel时自动清理”即可。以后只要退出Excel,你的cookies目录中就不会再有其它乱七八糟的cookie了。 13、超级预览。可以根据当前的选择内容自动调整预览对象。如果选中的是元格区域,就只预览你选中的区域;如果选中的是图表,则仅预览选中的图表;如果只是一个元格,则自动显示分页符... ... 14、屏幕锁定。当我们需要临时离开电脑而又不想关闭Excel文档时(并不局限于Excel文档,也可以是其它,但前提是要运行Excel),可以启动这个功能,这样其他人就不可能看到您不希望他们看到的东西。 15、尝试打开忘记密码的文件。暴力破解Excel的打开密码,注意:这个仅对拥有密码设计方案的人有效。 16、Excel加载项/宏管理器。对当前Excel环境下的加载宏/加载项/VBA加载项进行列表,并可以查看相关属性、修改运行状态,甚至是一键破解。 17、Excel对象管理器,可以批量转换Excel中的对象(图片、Shape、图表等)到图片文件; 18、在Excel中播放背景音乐、定时执行特定的程序、整点报时,一定很惬意... 19、屏幕录像及捕捉。哦,这个功能很强大啊。可以截取屏幕图像、录制屏幕变化、图片格式转换、批量bmp转成AVI文件、AVI文件转成动画GIF文件、图片标注... ...强大的不行啦,赶快去看看吧。快捷键:Ctrl+Alt+SpaceBar 或者 Ctrl+左WinKey(微软左徽标键) 20、DLL神探,DLL的最大威胁就是注入到系统进程中,让人防不胜防... 21、一键恢复Excel的系统菜。这个功能... ... 22、Excel版简易游戏。只是几个可以在Excel中玩的游戏... 23、计划横道图(甘特图)。偶觉得还是用Excel来做横道图最方便了... ... 24、偶将呆板的网络调查和网络投票移植到OBS.DLL中了,变被动为主动! 。。。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值