EasyDarwin开源流媒体云平台之云台ptz控制设计与实现

2023-05-16

本文转自EasyDarwin开源团队成员Alex的博客:http://blog.csdn.net/cai6811376/article/details/51912692

近日,EasyDarwin云平台加入云台控制功能,完善了云平台的功能,提升了用户体验。具体设计以及实现如下。

  • 流程设计

    1. 客户端通过RESTful接口向云平台发送控制命令;

    2. 云平台组织控制报文向设备发送;

    3. 设备执行后向云平台返回控制响应报文;

    4. 云平台接收响应报文后将控制结果返回给客户端。

ptz

  • 接口设计

首先我们设计云台控制的接口,接口为RESTful方式接口。

http://[ip]:[port]/api/ptzcontrol?device=001001000058&channel=0&actiontype=single&c
ommand=down&speed=5&protocol=onvif

device: 设备序列号;
channel: 通道;
protocol: 控制模式, 包括 Onvif、 SDK;
actiontype: ptz 控制模式, 分为连续( Continuous)、 单步( Single);
command: ptz 控制命令包括转动、 变焦等,
stop/up/down/left/right/zoomin/zoomout/focusin/focusout/aperturein/apertureout;
speed: ptz 控制速度。

  • 通讯报文设计
//云平台响应客户端控制
{
   "EasyDarwin" : {
      "Body" : {
         "Channel" : "0",
         "Protocol" : "ONVIF",
         "Reserve" : "1",
         "Serial" : "001001000058"
      },
      "Header" : {
         "CSeq" : "2",
         "ErrorNum" : "200",
         "ErrorString" : "Success OK",
         "MessageType" : "MSG_SC_PTZ_CONTROL_ACK",
         "Version" : "1.0"
      }
   }
}
//云平台向设备发送控制报文
{
   "EasyDarwin" : {
      "Body" : {
         "ActionType" : "SINGLE",
         "Channel" : "0",
         "Command" : "DOWN",
         "From" : "f6a221eec46b47dea8ae1a2bd11f8d02",
         "Protocol" : "ONVIF",
         "Reserve" : "1",
         "Serial" : "001001000058",
         "Speed" : "5",
         "To" : "245d6ec33cd247b7b7524219552db4d8",
         "Via" : "27823d2e8b6b4032b453d435a16b7be8"
      },
      "Header" : {
         "CSeq" : "1",
         "MessageType" : "MSG_SD_CONTROL_PTZ_REQ",
         "Version" : "1.0"
      }
   }
}
//设备响应云平台控制
{
   "EasyDarwin" : {
      "Body" : {
         "Channel" : "0",
         "From" : "245d6ec33cd247b7b7524219552db4d8",
         "Protocol" : "ONVIF",
         "Reserve" : "1",
         "Serial" : "001001000058",
         "To" : "f6a221eec46b47dea8ae1a2bd11f8d02",
         "Via" : "27823d2e8b6b4032b453d435a16b7be8"
      },
      "Header" : {
         "CSeq" : "1",
         "ErrorNum" : "200",
         "ErrorString" : "Success OK",
         "MessageType" : "MSG_DS_CONTROL_PTZ_ACK",
         "Version" : "1.0"
      }
   }
}

格式说明:
Serial:设备序列号;
Channel: 摄像机通道号;
Protocol: 指定 ptz 控制方式, ONVIF 协议或者设备 SDK;
ActionType: ptz 控制类型, 包括连续或者单步;
Command: ptz 控制命令, 包括停止, 上下左右旋转, 变焦等等;
Speed: ptz 控制速度;
From: EasyCMS 接收 Client 访问的 SessionID;
To: EasyCMS 向 Device 发送报文的 SessionID;
Via: EasyCMS 的 ServiceID;

  • 实现
//EasyCMS HTTPSession.cpp
//在session map中查找device session,组织控制报文,通过device session发送给设备
OSRefTableEx* deviceMap = QTSServerInterface::GetServer()->GetDeviceSessionMap();
    OSRefTableEx::OSRefEx* theDevRef = deviceMap->Resolve(chSerial);
    if (theDevRef == NULL)
        return EASY_ERROR_DEVICE_NOT_FOUND;

    OSRefReleaserEx releaser(deviceMap, chSerial);

    HTTPSession* pDevSession = static_cast<HTTPSession *>(theDevRef->GetObjectPtr());

    EasyProtocolACK reqreq(MSG_SD_CONTROL_PTZ_REQ);
    EasyJsonValue headerheader, bodybody;

    char chTemp[16] = { 0 };
    UInt32 uDevCseq = pDevSession->GetCSeq();
    sprintf(chTemp, "%d", uDevCseq);
    headerheader[EASY_TAG_CSEQ] = string(chTemp);
    headerheader[EASY_TAG_VERSION] = EASY_PROTOCOL_VERSION;

    string strProtocol(chProtocol);
    string strActionType(chActionType);
    string strCmd(chCmd);
    boost::to_upper(strProtocol);
    boost::to_upper(strActionType);
    boost::to_upper(strCmd);

    bodybody[EASY_TAG_SERIAL] = chSerial;
    bodybody[EASY_TAG_CHANNEL] = chChannel;
    bodybody[EASY_TAG_PROTOCOL] = strProtocol;
    bodybody[EASY_TAG_RESERVE] = chReserve;
    bodybody[EASY_TAG_ACTION_TYPE] = strActionType;
    bodybody[EASY_TAG_CMD] = strCmd;
    bodybody[EASY_TAG_SPEED] = chSpeed;
    bodybody[EASY_TAG_FROM] = fSessionID;
    bodybody[EASY_TAG_TO] = pDevSession->GetValue(EasyHTTPSessionID)->GetAsCString();
    bodybody[EASY_TAG_VIA] = QTSServerInterface::GetServer()->GetCloudServiceNodeID();

    reqreq.SetHead(headerheader);
    reqreq.SetBody(bodybody);

    string buffer = reqreq.GetMsg();
    StrPtrLen theValue(const_cast<char*>(buffer.c_str()), buffer.size());
    pDevSession->SendHTTPPacket(&theValue, false, false);
//EasyCamera EasyCMSSession.cpp processControlPTZReq
//EasyCamera接收控制报文,调用EasyCameraSource的控制接口

QTSS_Error EasyCMSSession::processControlPTZReq() const
{
    EasyMsgSDControlPTZREQ ctrlPTZReq(fContentBuffer);

    string serial = ctrlPTZReq.GetBodyValue(EASY_TAG_SERIAL);
    string protocol = ctrlPTZReq.GetBodyValue(EASY_TAG_PROTOCOL);
    string channel = ctrlPTZReq.GetBodyValue(EASY_TAG_CHANNEL);
    string reserve = ctrlPTZReq.GetBodyValue(EASY_TAG_RESERVE);
    string actionType = ctrlPTZReq.GetBodyValue(EASY_TAG_ACTION_TYPE);
    string command = ctrlPTZReq.GetBodyValue(EASY_TAG_CMD);
    string speed = ctrlPTZReq.GetBodyValue(EASY_TAG_SPEED);
    string from = ctrlPTZReq.GetBodyValue(EASY_TAG_FROM);
    string to = ctrlPTZReq.GetBodyValue(EASY_TAG_TO);
    string via = ctrlPTZReq.GetBodyValue(EASY_TAG_VIA);

    if (serial.empty() || channel.empty() || command.empty())
    {
        return QTSS_ValueNotFound;
    }

    QTSS_RoleParams params;
    params.cameraPTZParams.inActionType = EasyProtocol::GetPTZActionType(actionType);
    params.cameraPTZParams.inCommand = EasyProtocol::GetPTZCMDType(command);
    params.cameraPTZParams.inSpeed = EasyUtil::String2Int(speed);

    QTSS_Error errCode = QTSS_NoErr;
    UInt32 fCurrentModule = 0;
    UInt32 numModules = QTSServerInterface::GetNumModulesInRole(QTSSModule::kControlPTZRole);
    for (; fCurrentModule < numModules; ++fCurrentModule)
    {
        QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kControlPTZRole, fCurrentModule);
        errCode = theModule->CallDispatch(Easy_ControlPTZ_Role, &params);
    }

    EasyJsonValue body;
    body[EASY_TAG_SERIAL] = serial;
    body[EASY_TAG_CHANNEL] = channel;
    body[EASY_TAG_RESERVE] = reserve;
    body[EASY_TAG_PROTOCOL] = protocol;
    body[EASY_TAG_FROM] = to;
    body[EASY_TAG_TO] = from;
    body[EASY_TAG_VIA] = via;

    EasyMsgDSControlPTZACK rsp(body, ctrlPTZReq.GetMsgCSeq(), getStatusNo(errCode));

    string msg = rsp.GetMsg();
    StrPtrLen jsonContent(const_cast<char*>(msg.data()));
    HTTPRequest httpAck(&QTSServerInterface::GetServerHeader(), httpResponseType);

    if (httpAck.CreateResponseHeader())
    {
        if (jsonContent.Len)
            httpAck.AppendContentLengthHeader(jsonContent.Len);

        //Push msg to OutputBuffer
        char respHeader[2048] = { 0 };
        StrPtrLen* ackPtr = httpAck.GetCompleteHTTPHeader();
        strncpy(respHeader, ackPtr->Ptr, ackPtr->Len);

        fOutputStream->Put(respHeader);
        if (jsonContent.Len > 0)
            fOutputStream->Put(jsonContent.Ptr, jsonContent.Len);
    }

    return errCode;
}
//EasyCamera EasyCameraSource.cpp ControlPTZ
QTSS_Error EasyCameraSource::ControlPTZ(Easy_CameraPTZ_Params* params)
{
    QTSS_Error result = QTSS_RequestFailed;

    if (cameraLogin())
    {
        HI_S32 error;
        if (params->inActionType == EASY_PTZ_ACTION_TYPE_CONTINUOUS)
        {
            error = HI_NET_DEV_PTZ_Ctrl_Standard(m_u32Handle, getPTZCMDFromCMDType(params->inCommand), params->inSpeed);
        }
        else if (params->inActionType == EASY_PTZ_ACTION_TYPE_SINGLE)
        {
            error = HI_NET_DEV_PTZ_Ctrl_StandardEx(m_u32Handle, getPTZCMDFromCMDType(params->inCommand));
        }
        else
        {
            return QTSS_BadArgument;
        }

        if (error == HI_SUCCESS)
        {
            result = QTSS_NoErr;
        }
        else
        {
            result = QTSS_RequestFailed;
        }
    }

    return result;
}

获取更多信息

Github:https://github.com/easydarwin

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Copyright © EasyDarwin.org 2012-2016

EasyDarwin

转载于:https://www.cnblogs.com/babosa/p/9217915.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EasyDarwin开源流媒体云平台之云台ptz控制设计与实现 的相关文章

  • Cannot create property 'default' on boolean 'true'"

    解决办法 xff1a 删除node modules包 xff0c 重新npm i 转载于 https www cnblogs com 92xcd p 10443538 html
  • 怎么增加照片的KB大小

    之前都是要想办法压缩图片的大小 今天有人发来一张1 8MB的图片让我帮忙调到30MB左右 一下子放大这么多着实有点茫然 之后想到了一个办法 首先把图片占用体积变大 xff0c 是不会增加清晰度的 xff0c 而减小占用体积却会降低清晰度 第
  • 参数 返回值

    1 函数 函数是对功能的封装 语法 def 函数名 形参列表 函数体 代码块 return 调用 函数名 实参列表 2 返回值 return 在函数执行的时候 如果遇到return 直接返回 1 如果函数什么都不写 不写return 没有返
  • 抽象类调用自己的抽象方法,实现来自实现类(很常用)

    直接上代码 public abstract class Parent public abstract void dosomething public void say dosomething System out println 34 ww
  • 学习笔记:51单片机(STC89C52)如何定时10ms

    1 定时器如何定时 首先大致描述一下定时器的定时原理 xff0c 其实本质就一句话 xff1a 每经过一个机器周期 xff0c 寄存器就加1 这里就又要解释什么是时钟周期 xff0c 什么是机械周期 我们的51单片机无论是开发板还是最小系统
  • cmake 的使用

    官网教程 xff1a https cmake org cmake tutorial 第一个简单的例子 源文件 xff1a tutorial cpp 1 A simple program that computes the square ro
  • python 读取一个文件夹下的所jpg文件保存到txt中

    最近需要使用统计一个目录下的所有文件 xff0c 使用python比较方便 xff0c 就整理了一下代码 1 import os 2 3 def gci filepath 4 files 61 os listdir filepath 5 f
  • cmake 单个目录多个文件的情况

    参考 xff1a https www hahack com codes cmake 源文件一共有三个 xff1a main cpp MathFunctions h MathFunctions cpp 文件内容分别如下 xff1a main
  • k8s config配置文件

    接着上面的博客继续写 pwd gt etc kubernetes cat config kubernetes system config The following values are used to configure various
  • html5手机web页面底部菜单

    一 效果图 二 HTML代码 lt header class 61 34 text center 34 gt TOP lt header gt lt div id 61 34 content 34 gt lt div gt lt div i
  • redis hset hmset过期时间

    hmset m k v 127 0 0 1 6379 gt hset m k v integer 1 127 0 0 1 6379 gt hget m k 34 v 34 127 0 0 1 6379 gt expire m 30 inte
  • Mac下 .bash_profile 和 .zshrc 两者之间的区别

    这是我碰到的需要 source 之后才能使用环境变量的问题 xff0c 我就不细究了 xff0c 说说我的看法 bash profile 中修改环境变量只对当前窗口有效 xff0c 而且需要 source bash profile才能使用
  • h5页面使用js实现保存当前图片到手机相册

    很可惜 xff0c 这个鬼东西微信内置浏览器不适用 页面 xff1a lt doctype html gt lt html gt lt head gt lt meta charset 61 34 UTF 8 34 gt lt meta co
  • HTTP认证之基本认证——Basic(一)

    导航 HTTP认证之基本认证 Basic xff08 一 xff09 HTTP认证之基本认证 Basic xff08 二 xff09 HTTP认证之摘要认证 Digest xff08 一 xff09 HTTP认证之摘要认证 Digest x
  • android给方法设置进度,Android自定义View实现多节点进度条功能的方法

    Android自定义View实现多节点进度条功能的方法 发布时间 xff1a 2020 07 28 16 05 13 来源 xff1a 亿速云 阅读 xff1a 122 作者 xff1a 小猪 这篇文章主要讲解了Android自定义View
  • Linux 系统中如何查看日志 (常用命令)

    cat tail f 日志文件 日 志 文 件说 明 var log message系统启动后的信息和错误日志 xff0c 是Red Hat Linux中最常用的日志之一 var log secure与安全相关的日志信息 var log m
  • 智能指针(shared_ptr,unique_ptr)作为函数参数或者返回值时的一些注意事项

    智能指针 shared ptr unique ptr 作为函数参数或者返回值时的一些注意事项 当智能指针作为函数的参数或者返回值时 xff0c 一直在纠结到底是用智能指针对象本身还是用原始指针 Herb Sutter大师的文章很好的解决了这
  • CSP-S 模拟测试 51 题解

    考试过程 xff1a 惯例先看一遍三道题 xff0c T1 一开始反应要求割点 xff0c 但是这是有向图 xff0c 肯定不能求割点 xff0c 康了一下数据范围 xff0c 有40 是树的 xff0c 还不错 xff0c 决定待会在打
  • CSP-S 模拟测试57题解

    人生第一次A B层一块考rank2 xff0c 虽然说分差没几分 xff0c 但还是值得纪念 题解 xff1a T1 天空龙 xff1a 大神题 xff0c 因为我从不写快读也没有写考场注释的习惯 xff0c 所以不会做 xff0c 全hz
  • CSP-S 模拟53 题解

    题解 xff1a T1 u xff1a 一看到修改这么多 xff0c 但询问其实只有一个不难想到差分 xff0c 但是他这个形状可以说很不规则 xff0c 于是我们想到分别维护竖着的和斜着的差分 xff0c 然后最后合并即可 考场上瞎调了一

随机推荐