mobile CCTV,mobile surveillance,police body worn cameras

 forgetPW
 registerNow
search
view: 1518|reply: 1
打印 prevThread nextThread

使用CUSDK做二次开发 串口透传数据的功能说明

[copyURL]

60

主题

1428

帖子

5953

积分

Moderator

Rank: 7Rank: 7Rank: 7

积分
5953
jumpTo
owner
poston 2018-3-29 12:20 | authorOnly 回帖奖励 |倒序浏览 |阅读模式
使用CUSDK做二次开发串口透传数据的功能说明
CUSDK在网盘SDK目录下可下载:
我们所有的软件,目前都通过QQ网盘提供下载:
(包含PC端接收浏览视频的客户端软件:smarteye client以及流媒体服务器smarteye server,SDK,手机拍传软件APP-MPU,手机客户端软件APP-MCU,局域网搜索配置工具、产品手册、文档、固件)
这个网盘链接永久有效,请保留收藏。
1.工程的切入点:
1.先分析MFCDemo工程中打开串口/gps的方案,再结合WinFormDemo的实际情况处理。
2.透明串口和gps功能很接近,可以仿照,从WinFormDemoDialog.cs打开gps切入。
2.具体分析:
概述:整个 OnNMDblclkChannelList 过程需要获取 PU 列表,打开 GPS_TSP 通道(打开通道的时候要对数据进行设定解码);除此以外,其他过程还要负责 GPS 信息框内显示。
如何获取 PU 列表?TSP 通道并不是由服务器泵上去的,因此我们通过人工添加“假通道”来实现服务器泵上去的功能,让他出现在每个 PU列表中的最后方,也就是每当 gps 通道添加完成之后,手动添加 tsp 通道,代码位于 MDataList.cpp 中的 CMDataList::InsertPu:
/* 通道, 用于测试 串口 */
strcpy(onePu->pChannel.szName,"TSP");
onePu->pChannel.iChannelIndex= BVCU_SUBDEV_INDEXMAJOR_MIN_TSP;
onePu->pChannel.iMediaDir =BVCU_MEDIADIR_DATARECV;
onePu->iChannelCount ++;
/* 假通道 */
注:InsertPu 具体由谁调用,以及如何改动不作具体分析,这不是本文档探讨的重点。
       打开GPS_TSP 通道的实现。在 MFCDemoDlg.cpp 中,我们通过 OpenGPS_TSP 打开 GPS/TSP 通道,OpenGPS_TSP 定义于 MLibBVCU.cpp 中,具体定义形式为CMLibBVCU::OpenGPS_TSP,这个函数需要处理四个数据(实际上就是参数的设置),由于 m_session 已经被定义为类 CMLibBVCU 的静态成员,因此只需传递三个参数。GPS/TSP 的区别在于解码的不同;此外显示GPS/TSP 通道里面数据的方法也不一样,这个不是重点,但是在后面的 C# 工程中体现了这一点,因此提一下。
/* 略过部分请看具体工程源码,以后不再赘述 */
int CMLibBVCU::OpenGPS_TSP(BVCU_HDialog* phDialog,constchar* puId,intchannel)
{
……
    /* 参数的设置略过,串口和 gps 很接近,因此可以共用一套方法,区别之一是解码的不同 */
        if(BVCU_SUBDEV_INDEXMAJOR_MIN_GPS <= channel && channel <=BVCU_SUBDEV_INDEXMAJOR_MAX_GPS)
            dlgParam.afterDecode =afterDecode_GPS;
        else
            dlgParam.afterDecode =afterDecode_TSP;
    /* 以下省略的部分不重要,用于设置其他参数的,略过 */
    ……
    returnBVCU_Dialog_Open(phDialog,&dlgParam,&dlgCtrlParam);
    }
    return BVCU_RESULT_E_FAILED;
}
/* 这是具体的解码过程,用到了 m_OnRecvTSPData*/
BVCU_ResultCMLibBVCU::afterDecode_TSP(BVCU_HDialog hDialog, SAVCodec_Context* pCodec,SAV_Frame* pFrame)
{
   if (hDialog && pFrame)
   {
        if(pFrame->ppData[0])
        {
            if(m_OnRecvTSPData)
                m_OnRecvTSPData(hDialog, (char*)pFrame->ppData[0], pFrame->iDataSize[0]);
        }
   }
   return BVCU_RESULT_S_OK;
}
注:具体改动请比较该工程和以前 MLibBVCU.* 区别,“* 包含“.h”“.cpp”,显示部分不再分析,不是重点略过,至此 MFCDemo 工程的重点分析完毕。
现在我们看 WinFormDemo 工程!
    概述:C# 工程因为不能直接调用 C++ 工程代码,因此必须把C++ 工程封装为 dll 调用,而提供 ManagedLayer.dll 的封装层是 ManagedLayer 这个 C++ 工程。在 MFCDemo 中,我们可以共用方法 OpenGPS_TSP 源于两个前提,1.MFCDemo C++ 工程,可以直接调用位于 include 文件中的底层函数BVCU_dialog_open 2.MFCDemo C++ 工程,很多参数可以方便的共享和传入,所以共用方法OpenGPS_TSP 只需传递三个参数(实际设置了四个参数,额外的参数是 m_session),显示 TSP GPS 信息的函数可以共享,也可以单独设立,只需直接调用即可。对比 C# 工程会发现,1.C# 工程无法调用位于 include 文件中的底层函数 BVCU_dialog_open,除非他调用 ManagedLayer 提供的接口,从而间接的调用它 2.C# 工程无法与 C++ 工程直接共享和传递参数,因此打开 GPS 的函数必须由 BVCU.cs 中的 DllImport 载入,并且传递完整的 7 个参数,如同该例子:
[DllImport("ManagedLayer.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int ManagedLayer_CuOpenGpsDialog(IntPtr handle, refIntPtr dialog, IntPtrsession, Byte[] puId, int channelNo,
            EventHandler.BVCU_GpsDialog_OnEvent onDlgEvent, EventHandler.BVCU_GpsDialog_OnDataonDlgData);
        [DllImport("ManagedLayer.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int ManagedLayer_CuOpenTspDialog(IntPtr handle, refIntPtr dialog, IntPtrsession, Byte[] puId, int channelNo,
            EventHandler.BVCU_TspDialog_OnEvent onDlgEvent, EventHandler.BVCU_TspDialog_OnDataonDlgData);
起初,我也尝试了一个上午的时间,试图通过修改 C# 的委托函数 EventHandler.BVCU_GpsDialog_OnEvent , EventHandler.BVCU_GpsDialog_OnData 和 ManagedLayer 工程中的相关函数以达到 GPS 兼容 TSP 的打开,使得 GPS/TSP 共用一套方法。然而,因为 GPS 解码委托的传入参数和TSP 解码委托传入参数有本质的不同,最终宣告失败。
切入思路如法炮制:“假通道”的添加,分别打开 GPS 或 TSP,分别显示 GPS 或 TSP,但是在显示上我们共用GPS 的显示框,所以 TSP 输出内容为:经度框里面显示的实际是接收的字符串,纬度框里面显示的实际是该字符串的长度。
2.1添加“假通道”
    概述:完成一些列初始化登陆之后,EventHandle 会被触发从而使用委托的方式,完成一系列的动作。对于委托,可以这样理解(见下面的标注):
EventHandle.cs 的代码,以下均是:
public EventHandler()
{
    //dialog_OnDialogEvent,我 EventHandle 把下述职责委托于你,使得你负责处理 BVCU_Dialog_OnDialogEvent的所有事件,处理好了向某个人交代。某个人指的是,真正需要处理该事件的方法,处理好了只有在运行时才能决定。
    ……略过原有代码
    //该处是我添加的用于处理串口事件、接收数据的两个委托
BVCU_TspDialog_OnEvent(TspDialog_OnEvent);
            tspDialog_OnData = new BVCU_TspDialog_OnData(TspDialog_OnData);
    ……略过原有代码
    //该处是原有代码,但是在委托给 Cmd_OnGetPuList之后,被委托方使用 Cmd_OnGetPuList(注意区分大小写)的过程中是我修改的代码,添加了“假通道”
            cmd_OnGetPuList = new BVCU_Cmd_OnGetPuList(Cmd_OnGetPuList);
    ……略过原有代码
}
Cmd_OnGetPuList 如何添加“假通道”的(因为我只判断了小写的“gps”,所以 PU 列表中只有包含小写的“gps”通道才会被添加“TSP”通道):
/*
         * Get Pu List
         */
        public BVCU_Cmd_OnGetPuList cmd_OnGetPuList;
        voidCmd_OnGetPuList(IntPtr session, IntPtr ptPuId, IntPtrptPuName, int iStatus, refBVCU_PUOneChannelInfo channel, int iFinished)
        {
           stringpuId = Marshal.PtrToStringAnsi(ptPuId, BVCU.BVCU_MAX_ID_LEN + 1).Split('\0')[0];
            stringpuName = Marshal.PtrToStringAnsi(ptPuName, BVCU.BVCU_MAX_NAME_LEN + 1).Split('\0')[0];
            if(BVCU.TRUE(iFinished))
            {
               m_session.OnGetPuListFinished();
            }
            Session.Channel chnl = newSession.Channel();
            if(iStatus == BVCU.BVCU_ONLINE_STATUS_OFFLINE)
            {
                chnl.online = false;
            }
            else
            {
                chnl.online = true;
            }
            getChannel(chnl, channel);
            m_session.OnGetPu(puName, puId,chnl);
            if(channel.szName.Equals("gps"))
            {
                // 假通道,用于串口测试,这里我只判断了小写的 gps,因为 PU_2740 底下的 gps 是小写的,我所要测试的透明串口就是 PU_2740,如果有变更需要,只需手动修改 if 条件即可
                chnl = newSession.Channel();
                channel.szName = "TSP";
                channel.iPTZIndex = 15;
                channel.iMediaDir = 32;
                channel.iChannelIndex = 65792;
                if(iStatus == BVCU.BVCU_ONLINE_STATUS_OFFLINE)
                {
                    chnl.online = false;
                }
                else
                {
                    chnl.online = true;
               }
                getChannel(chnl, channel);
                m_session.OnGetPu(puName, puId,chnl);
            }
        }
2.2分别打开 GPS TSP
该代码位于Form1.cs中,其中 m_sdkOperator.Dialog.openTspDialog(pu,channelNo) 语句用到的 openTspDialog里面调用了 BVCU.cs 中的 DllImport 的 ManagedLayer_CuOpenTspDialog,参见BVCU.cs:
[DllImport("ManagedLayer.dll", CallingConvention = CallingConvention.Cdecl)]publicstatic extern int ManagedLayer_CuOpenTspDialog(IntPtr handle, refIntPtr dialog, IntPtrsession, Byte[] puId, int channelNo,
            EventHandler.BVCU_TspDialog_OnEvent onDlgEvent, EventHandler.BVCU_TspDialog_OnDataonDlgData);
以下代码位于Form1.cs中:
/*
        * 双击界面上的资源树打开对话
         */
        const int TREE_LEVEL_SESSION = 0;
        const int TREE_LEVEL_PU = 1;
        const int TREE_LEVEL_CHANNEL = 2;
        privatevoid treeViewResList_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgse)
        {
……略过已有代码,else if 是修改的代码,只修改了 if 条件
                elseif (channelNo >= BVCU.BVCU_SUBDEV_INDEXMAJOR_MIN_GPS&& channelNo < BVCU.BVCU_SUBDEV_INDEXMAJOR_MAX_GPS)
                {
              ……未修改
                }
              //此处为添加的代码
                else
                {
                    if(m_sdkOperator.Dialog.openTspDialog(pu, channelNo) == 0)
                    {
                        ListViewItem item = new ListViewItem();
                        item.Text = pu.id;
                        item.Tag = channelNo;
                        ListViewItem.ListViewSubItemTspData = new ListViewItem.ListViewSubItem();
                        ListViewItem.ListViewSubItemlen = new ListViewItem.ListViewSubItem();
                        item.SubItems.AddRange(new ListViewItem.ListViewSubItem[] { TspData, len });
                       listViewGPSData.Items.Add(item);
                    }
                }
            }
        }
openTspDialog 位于 Dialog.cs 中:
ArrayList m_tspDialogs;
        public int openTspDialog(Session.Pu pu, intchannelNo)
        {
            foreach(OneDialog dlg inm_tspDialogs)
            {
                if(dlg.pu.id.Equals(pu.id, StringComparison.CurrentCultureIgnoreCase)
                    && dlg.channelNo ==channelNo)
                {
                    return-1;
                }
            }
            IntPtrdialog = IntPtr.Zero;
           //此处为调用的 ManagedLayer_CuOpenTspDialog
            if(BVCU.ManagedLayer_CuOpenTspDialog(m_bvsdkHandle,ref dialog, m_session.Handle, Encoding.UTF8.GetBytes(pu.id),
                    channelNo,m_bvsdkEventHandler.tspDialog_OnEvent, m_bvsdkEventHandler.tspDialog_OnData)
                == BVCU.BVCU_RESULT_S_OK)
            {
                OneDialogdlg = new OneDialog();
                dlg.dialogHandle = dialog;
                dlg.channelNo = channelNo;
                dlg.pu = pu;
                m_tspDialogs.Add(dlg);
                return0;
            }
            return-1;
        }
2.3 m_bvsdkEventHandler.tspDialog_OnEvent/ tspDialog_OnData回调
              EventHandle.cs中:
        public delegate void BVCU_TspDialog_OnEvent(IntPtrdialog, int eventCode, Int32errorCode);
        public delegate void BVCU_TspDialog_OnData(IntPtrdialog, string pTspData, int len);
        public BVCU_TspDialog_OnData tspDialog_OnData;
        public BVCU_TspDialog_OnEvent tspDialog_OnEvent;
        voidTspDialog_OnEvent(IntPtr dialog, int eventCode, Int32errorCode)
        {
            if(errorCode != BVCU.BVCU_RESULT_S_OK)
            {
                m_dialog.onTspDialogOpenFailed(dialog);
            }
        }
        voidTspDialog_OnData(IntPtr dialog, string pTspData, intlen)
        {
           //以下在 Dialog.cs
            m_dialog.onTspData(dialog,pTspData, len);
        }
Dialog.cs 中:
delegate void OnGetTspData(IntPtr dialog, stringpTspData, int len);
        OnGetTspDatadeleGetTspData;
        public void onTspData(IntPtrdialog, string pTspData, int len)
        {
            if(null == deleGetTspData)
            {
                deleGetTspData = new OnGetTspData(procGetTspData);
            }
           m_mainForm.BeginInvoke(deleGetTspData, newobject[] { dialog, pTspData, len });
        }
        voidprocGetTspData(IntPtr dialog, string pTspData, intlen)
        {
            foreach (OneDialog dlg inm_tspDialogs)
            {
                if(dlg.dialogHandle == dialog)
                {
                   m_mainForm.onGetTspData(dlg.pu.id, pTspData, len);
                    return;
                }
            }
       }
2.4显示 TSP
Form1.cs中:
public void onGetTspData(string puId, string pTspData, int len)
        {
            foreach(ListViewItem item inlistViewGPSData.Items)
            {
                if(item.Text.Equals(puId, StringComparison.CurrentCultureIgnoreCase))
                {
                    ListViewItem.ListViewSubItem TspData = newListViewItem.ListViewSubItem();
                    TspData.Text = pTspData;
                    item.SubItems[1] = TspData;
                    ListViewItem.ListViewSubItem length = newListViewItem.ListViewSubItem();
                    length.Text =len.ToString();
                    item.SubItems[2] = length;
                    return;
                }
            }
        }
2.5底层支持
载入的 ManagedLayer_CuOpenTspDialog 位于工程 ManagedLayer.cpp 中,我在里面添加了这个函数,具体请参考工程代码,ManagedLayer_CuOpenTspDialog 调用了 CBVCU.cpp 中的 openTspDialog,openTspDialog 指定了 dlgParam.OnEvent = tspDialog_OnEvent; 和 dlgParam.afterDecode = tspDialog_OnData; 作为 Tsp 的事件回调和解码回调,这两个回调定义于 CBVCU.cpp 中。
intCBVCU:penTspDialog(BVCU_HDialog* dlg, BVCU_HSession session, char* puId, intchannelNo,
   BVCU_TspDialog_OnEventonDlgEvent, BVCU_TspDialog_OnData onDlgData)
{
   BVCU_DialogParamdlgParam;
   BVCU_DialogControlParamdlgCtlParam;
   memset(&dlgParam,0, sizeof(dlgParam));
   memset(&dlgCtlParam,0, sizeof(dlgCtlParam));
   dlgParam.iSize= sizeof(dlgParam);
   dlgCtlParam.iSize= sizeof(dlgCtlParam);
   dlgParam.hSession= session;
   BVCU_DialogTargettarget;
   strncpy_s(target.szID,BVCU_MAX_ID_LEN+1,puId,_TRUNCATE);
// memset(&target,0, sizeof(BVCU_DialogTarget));
   target.iIndexMajor= channelNo;
// strcpy_s(target.szID,BVCU_MAX_ID_LEN + 1, puId);
   target.iIndexMinor= -1;
   dlgParam.iTargetCount= 1;
   dlgParam.pTarget= &target;
   dlgParam.iAVStreamDir= BVCU_MEDIADIR_DATARECV;
   dlgParam.OnEvent= tspDialog_OnEvent;
   dlgParam.afterDecode= tspDialog_OnData;
   if (NULL == m_procGpsDialogEvent)
   {
      m_procTspDialogEvent= onDlgEvent;
   }
   if (NULL == m_procGpsDialogOnData)
   {
      m_procTspDialogOnData= onDlgData;
   }
   // <TODO>: 参考MLibBVCU.cpp
   return BVCU_Dialog_Open(dlg, &dlgParam,&dlgCtlParam);
}
总结:有了MFCDemo例程,其他的都不是很难,只需仿照就行了。


本帖子中包含更多资源

pls login 才可以下载或查看,没有帐号?registerNow

x
reply

使用道具 report

60

主题

1428

帖子

5953

积分

Moderator

Rank: 7Rank: 7Rank: 7

积分
5953
sofa
 Owner| poston 2018-3-29 12:23 | authorOnly
其它一些测试工具的说明,可不用写代码,直接用管理器测试透明串口的通信。
附上相关文档和图片说明。

本帖子中包含更多资源

pls login 才可以下载或查看,没有帐号?registerNow

x
reply agree Against

使用道具 report

creditRule

QQ|wireless surveillance

GMT+8, 2024-12-23 21:14 , Processed in 0.068355 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

QuickReply backToTop BackToList