C++ unsigned char * append 字符串

时间: 2025-02-17 22:22:22 浏览: 39
在C++中,`unsigned char*`通常表示无符号字符指针,用于操作字节级别的数据,包括字符串。如果你想要将一个字符串追加到另一个字符串之后,你可以创建一个新的动态数组或者使用已有数组并进行拼接。这里是一个简单的示例: ```cpp #include <cstring> // 包含操作字符串的库函数 // 假设我们有两个字符串,一个是原有字符串,一个是待添加的字符串 std::string originalString = "Hello, "; unsigned char* newString = "World!"; // 将其转换为char* // 首先计算原始字符串长度,并加上新字符串长度减去1(因为null终止符) size_t totalLength = originalString.length() + strlen((const char*)newString) - 1; // 动态分配足够的内存存放新的字符串 unsigned char* appendedString = new unsigned char[totalLength]; // 如果有足够的空间,复制原有字符串,然后添加新字符串 memcpy(appendedString, originalString.c_str(), originalString.length()); memcpy(&appendedString[originalString.length()], (const char*)newString, strlen(newString)); // 添加null终止符 appendedString[totalLength - 1] = '\0'; // 现在appendedString包含了原字符串和新字符串 // 记得在不再需要它的时候释放内存 delete[] appendedString;
阅读全文

相关推荐

#include <assert.h> #include "soapH.h" //#include "wsdd.nsmap" #include "soapStub.h" #include "wsseapi.h" #include "wsaapi.h" #include <map> #define USERNAME "admin" #define PASSWORD "admin888" #define MEDIA_GET_PROFILES_ACTION "http://www.onvif.org/ver10/media/wsdl/GetProfiles". #define SOAP_ASSERT assert #define SOAP_DBGLOG printf #define SOAP_DBGERR printf #define SOAP_TO "urn:schemas-xmlsoap-org:ws:2005:04:discovery" #define SOAP_ACTION "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe" #define SOAP_MCAST_ADDR "soap.udp://239.255.255.250:3702" // onvif规定的组播地址 #define SOAP_ITEM "" // 寻找的设备范围 #define SOAP_TYPES "dn:NetworkVideoTransmitter" // 寻找的设备类型 #define SOAP_SOCK_TIMEOUT (3) // socket超时时间(单秒秒) #define ONVIF_ADDRESS_SIZE (128) // URI地址长度 #define ONVIF_TOKEN_SIZE (65) // token长度 #define SOAP_CHECK_ERROR(result, soap, str) \ do { \ if (SOAP_OK != (result) || SOAP_OK != (soap)->error) { \ soap_perror((soap), (str)); \ if (SOAP_OK == (result)) { \ (result) = (soap)->error; \ } \ goto EXIT; \ } \ } while (0) /* 视频编码器配置信息 */ struct tagVideoEncoderConfiguration { char token[ONVIF_TOKEN_SIZE]; // 唯一标识该视频编码器的令牌字符串 int Width; // 分辨率 int Height; }; /* 设备配置信息 */ struct tagProfile { char token[ONVIF_TOKEN_SIZE]; // 唯一标识设备配置文件的令牌字符串 struct tagVideoEncoderConfiguration venc; // 视频编码器配置信息 }; /* 设备能力信息 */ struct tagCapabilities { char MediaXAddr[ONVIF_ADDRESS_SIZE]; // 媒体服务地址 char EventXAddr[ONVIF_ADDRESS_SIZE]; // 事件服务地址 }; void soap_perror(struct soap* soap, const char* str) { if (nullptr == str) { SOAP_DBGERR("[soap] error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap)); } else { SOAP_DBGERR("[soap] %s error: %d, %s, %s\n", str, soap->error, *soap_faultcode(soap), *soap_faultstring(soap)); } } void* ONVIF_soap_malloc(struct soap* soap, unsigned int n) { void* p = nullptr; if (n > 0) { p = soap_malloc(soap, n); SOAP_ASSERT(nullptr != p); memset(p, 0x00, n); } return p; } struct soap* ONVIF_soap_new(int timeout) { struct soap* soap = nullptr; // soap环境变量 SOAP_ASSERT(nullptr != (soap = soap_new())); soap_set_namespaces(soap, namespaces); // 设置soap的namespaces soap->recv_timeout = timeout; // 设置超时(超过指定时间没有数据就退出) soap->send_timeout = timeout; soap->connect_timeout = timeout; #if defined(__linux__) || defined(__linux) // 参考https://www.genivia.com/dev.html#client-c的修改: soap->socket_flags = MSG_NOSIGNAL; // To prevent connection reset errors #endif soap_set_mode(soap, SOAP_C_UTFSTRING); // 设置为UTF-8编码,否则叠加中文OSD会乱码 return soap; } void ONVIF_soap_delete(struct soap* soap) { soap_destroy(soap); // remove deserialized class instances (C++ only) soap_end(soap); // Clean up deserialized data (except class instances) and temporary data soap_done(soap); // Reset, close communications, and remove callbacks soap_free(soap); // Reset and deallocate the context created with soap_new or soap_copy } /************************************************************************ **函数:ONVIF_init_header **功能:初始化soap描述消息头 **参数: [in] soap - soap环境变量 **返回:无 **备注: 1). 在本函数内部通过ONVIF_soap_malloc分配的内存,将在ONVIF_soap_delete中被释放 ************************************************************************/ void ONVIF_init_header(struct soap* soap) { struct SOAP_ENV__Header* header = nullptr; SOAP_ASSERT(nullptr != soap); header = (struct SOAP_ENV__Header*)ONVIF_soap_malloc(soap, sizeof(struct SOAP_ENV__Header)); soap_default_SOAP_ENV__Header(soap, header); header->wsa__MessageID = (char*)soap_wsa_rand_uuid(soap); header->wsa__To = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_TO) + 1); header->wsa__Action = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_ACTION) + 1); strcpy(header->wsa__To, SOAP_TO); strcpy(header->wsa__Action, SOAP_ACTION); soap->header = header; return; } /************************************************************************ **函数:ONVIF_init_ProbeType **功能:初始化探测设备的范围和类型 **参数: [in] soap - soap环境变量 [out] probe - 填充要探测的设备范围和类型 **返回: 0表明探测到,非0表明未探测到 **备注: 1). 在本函数内部通过ONVIF_soap_malloc分配的内存,将在ONVIF_soap_delete中被释放 ************************************************************************/ void ONVIF_init_ProbeType(struct soap* soap, struct wsdd__ProbeType* probe) { struct wsdd__ScopesType* scope = nullptr; // 用于描述查找哪类的Web服务 SOAP_ASSERT(nullptr != soap); SOAP_ASSERT(nullptr != probe); scope = (struct wsdd__ScopesType*)ONVIF_soap_malloc(soap, sizeof(struct wsdd__ScopesType)); soap_default_wsdd__ScopesType(soap, scope); // 设置寻找设备的范围 scope->__item = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_ITEM) + 1); strcpy(scope->__item, SOAP_ITEM); memset(probe, 0x00, sizeof(struct wsdd__ProbeType)); soap_default_wsdd__ProbeType(soap, probe); probe->Scopes = scope; probe->Types = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_TYPES) + 1); // 设置寻找设备的类型 strcpy(probe->Types, SOAP_TYPES); return; } void ONVIF_DetectDevice(void (*cb)(char* DeviceXAddr)) { int i; int result = 0; unsigned int count = 0; // 搜索到的设备个数 struct soap* soap = nullptr; // soap环境变量 struct wsdd__ProbeType req; // 用于发送Probe消息 struct __wsdd__ProbeMatches rep; // 用于接收Probe应答 struct wsdd__ProbeMatchType* probeMatch; SOAP_DBGLOG("Sending Probe message to multicast address...\n"); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_init_header(soap); // 设置消息头描述 ONVIF_init_ProbeType(soap, &req); // 设置寻找的设备的范围和类型 result = soap_send___wsdd__Probe(soap, SOAP_MCAST_ADDR, nullptr, &req); // 向组播地址广播Probe消息 while (SOAP_OK == result) // 开始循环接收设备发送过来的消息 { memset(&rep, 0x00, sizeof(rep)); result = soap_recv___wsdd__ProbeMatches(soap, &rep); if (SOAP_OK == result) { if (soap->error) { soap_perror(soap, "ProbeMatches"); } else { // 成功接收到设备的应答消息 if (nullptr != rep.wsdd__ProbeMatches) { count += rep.wsdd__ProbeMatches->__sizeProbeMatch; SOAP_DBGLOG("成功接收...\n"); for (i = 0; i < rep.wsdd__ProbeMatches->__sizeProbeMatch; i++) { probeMatch = rep.wsdd__ProbeMatches->ProbeMatch + i; if (nullptr != cb) { cb(probeMatch->XAddrs); // 使用设备服务地址执行函数回调 } } } } } else if (soap->error) { break; } } SOAP_DBGLOG("\ndetect end! It has detected %d devices!\n", count); if (nullptr != soap) { ONVIF_soap_delete(soap); } } /************************************************************************ **函数:ONVIF_SetAuthInfo **功能:设置认证信息 **参数: [in] soap - soap环境变量 [in] username - 用户名 [in] password - 密码 **返回: 0表明成功,非0表明失败 **备注: ************************************************************************/ static int ONVIF_SetAuthInfo(struct soap* soap, const char* username, const char* password) { int result = 0; SOAP_ASSERT(nullptr != USERNAME); SOAP_ASSERT(nullptr != PASSWORD); result = soap_wsse_add_UsernameTokenDigest(soap, nullptr, username, password); SOAP_CHECK_ERROR(result, soap, "add_UsernameTokenDigest"); EXIT: return result; } /************************************************************************ **函数:make_uri_withauth **功能:构造带有认证信息的URI地址 **参数: [in] src_uri - 未带认证信息的URI地址 [in] username - 用户名 [in] password - 密码 [out] dest_uri - 返回的带认证信息的URI地址 [in] size_dest_uri - dest_uri缓存大小 **返回: 0成功,非0失败 **备注: 1). 例子: 无认证信息的uri:rtsp://100.100.100.140:554/av0_0 带认证信息的uri:rtsp://username:[email protected]:554/av0_0 ************************************************************************/ static int make_uri_withauth(const std::string& src_uri, const std::string& username, const std::string& password, std::string* dest_uri) { int result = 0; unsigned int needBufSize = 0; SOAP_ASSERT(!src_uri.empty()); if (username.empty() && password.empty()) { // 生成新的uri地址 *dest_uri = src_uri; } else { std::string::size_type position = src_uri.find("//"); if (std::string::npos == position) { SOAP_DBGERR("can't found '//', src uri is: %s.\n", src_uri.c_str()); result = -1; return result; } position += 2; dest_uri->append(src_uri, 0, position); dest_uri->append(username + ":" + password + "@"); dest_uri->append(src_uri, position, std::string::npos); } return result; } /************************************************************************ **函数:ONVIF_GetDeviceInformation **功能:获取设备基本信息 **参数: [in] DeviceXAddr - 设备服务地址 **返回: 0表明成功,非0表明失败 **备注: ************************************************************************/ int ONVIF_GetDeviceInformation(const char* DeviceXAddr) { int result = 0; struct soap* soap = nullptr; _tds__GetDeviceInformation devinfo_req; _tds__GetDeviceInformationResponse devinfo_resp; SOAP_ASSERT(nullptr != DeviceXAddr); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); result = soap_call___tds__GetDeviceInformation(soap, DeviceXAddr, nullptr, &devinfo_req, devinfo_resp); SOAP_CHECK_ERROR(result, soap, "GetDeviceInformation"); std::cout << " Manufacturer:\t" << devinfo_resp.Manufacturer << "\n"; std::cout << " Model:\t" << devinfo_resp.Model << "\n"; std::cout << " FirmwareVersion:\t" << devinfo_resp.FirmwareVersion << "\n"; std::cout << " SerialNumber:\t" << devinfo_resp.SerialNumber << "\n"; std::cout << " HardwareId:\t" << devinfo_resp.HardwareId << "\n"; EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return result; } /************************************************************************ **函数:ONVIF_GetCapabilities **功能:获取设备能力信息 **参数: [in] DeviceXAddr - 设备服务地址 [in] **返回: 0表明成功,非0表明失败 **备注: 1). 其中最主要的参数之一是媒体服务地址 ************************************************************************/ int ONVIF_GetCapabilities(const std::string& deviceXAddr, std::string* ptzXAddr) { int result = 0; struct soap* soap = nullptr; _tds__GetCapabilities devinfo_req; _tds__GetCapabilitiesResponse devinfo_resp; SOAP_ASSERT(!deviceXAddr.empty()); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); result = soap_call___tds__GetCapabilities(soap, deviceXAddr.c_str(), nullptr, &devinfo_req, devinfo_resp); SOAP_CHECK_ERROR(result, soap, "GetCapabilities"); if (devinfo_resp.Capabilities->PTZ != nullptr) { *ptzXAddr = devinfo_resp.Capabilities->PTZ->XAddr; } EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return result; } int ONVIF_GetProfiles(const std::string& ptzXAddr, std::string* profilesToken) { int result = 0; struct soap* soap = nullptr; _trt__GetProfiles devinfo_req; _trt__GetProfilesResponse devinfo_resp; SOAP_ASSERT(!ptzXAddr.empty()); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); result = soap_call___trt__GetProfiles(soap, ptzXAddr.c_str(), nullptr, &devinfo_req, devinfo_resp); SOAP_CHECK_ERROR(result, soap, "ONVIF_GetProfiles"); SOAP_ASSERT(!devinfo_resp.Profiles.empty()); *profilesToken = devinfo_resp.Profiles[0]->token; EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return result; } /************************************************************************ **函数:ONVIF_GetSnapshotUri **功能:获取设备图像抓拍地址(HTTP) **参数: [in] MediaXAddr - 媒体服务地址 [in] ProfileToken - the media profile token [out] uri - 返回的地址 [in] sizeuri - 地址缓存大小 **返回: 0表明成功,非0表明失败 **备注: 1). 并非所有的ProfileToken都支持图像抓拍地址。举例:XXX品牌的IPC有如下三个配置profile0/profile1/TestMediaProfile,其中TestMediaProfile返回的图像抓拍地址就是空指针。 ************************************************************************/ int ONVIF_GetSnapshotUri(const std::string& MediaXAddr, const std::string& ProfileToken, std::string* snapUri) { int result = 0; struct soap* soap = nullptr; _trt__GetSnapshotUri req; _trt__GetSnapshotUriResponse rep; // 检查参数合法性 if (MediaXAddr.empty() || ProfileToken.empty()) { SOAP_DBGERR("Invalid arguments\n"); return -1; } // 创建 SOAP 环境 soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT); if (!soap) { SOAP_DBGERR("Failed to create SOAP environment\n"); return -1; } // 设置认证信息 if (ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD) != 0) { SOAP_DBGERR("Failed to set authentication info\n"); goto EXIT; } // 设置请求参数 memset(&req, 0, sizeof(req)); req.ProfileToken = soap_strdup(soap, ProfileToken.c_str()); // 调用服务 result = soap_call___trt__GetSnapshotUri(soap, MediaXAddr.c_str(), NULL, &req, rep); if (result != SOAP_OK || soap->error != SOAP_OK) { SOAP_DBGERR("GetSnapshotUri failed: %d, %s\n", soap->error, *soap_faultstring(soap)); result = -1; goto EXIT; } // 处理响应 - 使用正确的成员访问方式 if (rep.MediaUri) { *snapUri = rep.MediaUri->Uri; // Uri 是 std::string 类型,不需要指针检查 SOAP_DBGLOG("Snapshot URI: %s\n", snapUri->c_str()); } else { SOAP_DBGERR("MediaUri is null\n"); result = -1; } EXIT: // 清理资源 if (soap) { ONVIF_soap_delete(soap); } return result; } // 获取当前ptz的位置以及状态 int ONVIF_PTZ_GetStatus(const std::string& ptzXAddr, const std::string& ProfileToken) { int result = 0; struct soap* soap = nullptr; _tptz__GetStatus getStatus; _tptz__GetStatusResponse getStatusResponse; SOAP_ASSERT(!ptzXAddr.empty()); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); getStatus.ProfileToken = const_cast<char*>(ProfileToken.c_str()); result = soap_call___tptz__GetStatus(soap, ptzXAddr.c_str(), nullptr, &getStatus, getStatusResponse); SOAP_CHECK_ERROR(result, soap, "ONVIF_PTZ_GetStatus"); if (*getStatusResponse.PTZStatus->MoveStatus->PanTilt == tt__MoveStatus__IDLE) { std::cout << " 空闲 ... " << std::endl; } else if (*getStatusResponse.PTZStatus->MoveStatus->PanTilt == tt__MoveStatus__MOVING) { std::cout << " 移动中 ... " << std::endl; } else if (*getStatusResponse.PTZStatus->MoveStatus->PanTilt == tt__MoveStatus__UNKNOWN) { std::cout << " 未知 ... " << std::endl; } std::cout << "当前p: " << getStatusResponse.PTZStatus->Position->PanTilt->x << "\n"; std::cout << "当前t: " << getStatusResponse.PTZStatus->Position->PanTilt->y << "\n"; std::cout << "当前z: " << getStatusResponse.PTZStatus->Position->Zoom->x << "\n"; EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return 0; } // 以指定速度移动到指定位置的ptz // p : -1 ~ 1 [] // t : -1 ~ 1 // z : 0 ~ 1 int ONVIF_PTZAbsoluteMove(const std::string& ptzXAddr, const std::string& ProfileToken) { int result = 0; struct soap* soap = nullptr; _tptz__AbsoluteMove absoluteMove; _tptz__AbsoluteMoveResponse absoluteMoveResponse; SOAP_ASSERT(!ptzXAddr.empty() && !ProfileToken.empty()); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); absoluteMove.ProfileToken = const_cast<char*>(ProfileToken.c_str()); absoluteMove.Position = soap_new_tt__PTZVector(soap); absoluteMove.Position->PanTilt = soap_new_tt__Vector2D(soap); absoluteMove.Position->Zoom = soap_new_tt__Vector1D(soap); absoluteMove.Speed = soap_new_tt__PTZSpeed(soap); absoluteMove.Speed->PanTilt = soap_new_tt__Vector2D(soap); absoluteMove.Speed->Zoom = soap_new_tt__Vector1D(soap); absoluteMove.Position->PanTilt->x = 0.440833; // p absoluteMove.Position->PanTilt->y = 0.583455; // t absoluteMove.Position->Zoom->x = 0.0333333; // z // x 和y的绝对值越接近1,表示云台的速度越快 absoluteMove.Speed->PanTilt->x = 0.5; absoluteMove.Speed->PanTilt->y = 0.5; absoluteMove.Speed->Zoom->x = 0.5; result = soap_call___tptz__AbsoluteMove(soap, ptzXAddr.c_str(), nullptr, &absoluteMove, absoluteMoveResponse); SOAP_CHECK_ERROR(result, soap, "ONVIF_PTZAbsoluteMove"); EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return 0; } int ONVIF_PTZStopMove(const std::string& ptzXAddr, const std::string& ProfileToken) { int result = 0; struct soap* soap = nullptr; _tptz__Stop tptzStop; _tptz__StopResponse tptzStopResponse; SOAP_ASSERT(!ptzXAddr.empty() && !ProfileToken.empty()); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); tptzStop.ProfileToken = const_cast<char*>(ProfileToken.c_str()); result = soap_call___tptz__Stop(soap, ptzXAddr.c_str(), nullptr, &tptzStop, tptzStopResponse); SOAP_CHECK_ERROR(result, soap, "ONVIF_PTZStopMove"); EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return result; } enum PTZCMD { PTZ_CMD_LEFT, PTZ_CMD_RIGHT, PTZ_CMD_UP, PTZ_CMD_DOWN, PTZ_CMD_LEFTUP, PTZ_CMD_LEFTDOWN, PTZ_CMD_RIGHTUP, PTZ_CMD_RIGHTDOWN, PTZ_CMD_ZOOM_IN, PTZ_CMD_ZOOM_OUT, }; // speed --> (0, 1] int ONVIF_PTZContinuousMove(const std::string& ptzXAddr, const std::string& ProfileToken, enum PTZCMD cmd, float speed) { int result = 0; struct soap* soap = nullptr; _tptz__ContinuousMove continuousMove; _tptz__ContinuousMoveResponse continuousMoveResponse; SOAP_ASSERT(!ptzXAddr.empty() && !ProfileToken.empty()); SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT))); ONVIF_SetAuthInfo(soap, USERNAME, PASSWORD); continuousMove.ProfileToken = const_cast<char*>(ProfileToken.c_str()); continuousMove.Velocity = soap_new_tt__PTZSpeed(soap); continuousMove.Velocity->PanTilt = soap_new_tt__Vector2D(soap); continuousMove.Velocity->Zoom = soap_new_tt__Vector1D(soap); switch (cmd) { case PTZ_CMD_LEFT: continuousMove.Velocity->PanTilt->x = -speed; continuousMove.Velocity->PanTilt->y = 0; break; case PTZ_CMD_RIGHT: continuousMove.Velocity->PanTilt->x = speed; continuousMove.Velocity->PanTilt->y = 0; break; case PTZ_CMD_UP: continuousMove.Velocity->PanTilt->x = 0; continuousMove.Velocity->PanTilt->y = speed; break; case PTZ_CMD_DOWN: continuousMove.Velocity->PanTilt->x = 0; continuousMove.Velocity->PanTilt->y = -speed; break; case PTZ_CMD_LEFTUP: continuousMove.Velocity->PanTilt->x = -speed; continuousMove.Velocity->PanTilt->y = speed; break; case PTZ_CMD_LEFTDOWN: continuousMove.Velocity->PanTilt->x = -speed; continuousMove.Velocity->PanTilt->y = -speed; break; case PTZ_CMD_RIGHTUP: continuousMove.Velocity->PanTilt->x = speed; continuousMove.Velocity->PanTilt->y = speed; break; case PTZ_CMD_RIGHTDOWN: continuousMove.Velocity->PanTilt->x = speed; continuousMove.Velocity->PanTilt->y = -speed; break; case PTZ_CMD_ZOOM_IN: continuousMove.Velocity->PanTilt->x = 0; continuousMove.Velocity->PanTilt->y = 0; continuousMove.Velocity->Zoom->x = speed; break; case PTZ_CMD_ZOOM_OUT: continuousMove.Velocity->PanTilt->x = 0; continuousMove.Velocity->PanTilt->y = 0; continuousMove.Velocity->Zoom->x = -speed; break; default: break; } // 也可以使用soap_call___tptz__RelativeMove实现 result = soap_call___tptz__ContinuousMove(soap, ptzXAddr.c_str(), nullptr, &continuousMove, continuousMoveResponse); SOAP_CHECK_ERROR(result, soap, "ONVIF_PTZAbsoluteMove"); /* sleep(1); //如果当前soap被删除(或者发送stop指令),就会停止移动 ONVIF_PTZStopMove(ptzXAddr, ProfileToken);*/ EXIT: if (nullptr != soap) { ONVIF_soap_delete(soap); } return result; } void cb_discovery(char* deviceXAddr) { std::cout << "\n==== 发现设备: " << deviceXAddr << " ====" << std::endl; std::string ptzXAddr, profilesToken; // 获取设备能力信息 int ret = ONVIF_GetCapabilities(deviceXAddr, &ptzXAddr); if (ret != 0) { std::cerr << "错误: 获取设备能力失败 (错误码: " << ret << ")" << std::endl; return; } std::cout << " PTZ服务地址: " << ptzXAddr << std::endl; // 获取设备配置文件 ret = ONVIF_GetProfiles(ptzXAddr, &profilesToken); if (ret != 0) { std::cerr << "错误: 获取配置文件失败 (错误码: " << ret << ")" << std::endl; return; } std::cout << " Profile Token: " << profilesToken << std::endl; // 执行PTZ操作 ret = ONVIF_PTZContinuousMove(ptzXAddr, profilesToken, PTZ_CMD_LEFTUP, 0.3); if (ret != 0) { std::cerr << "错误: PTZ操作失败 (错误码: " << ret << ")" << std::endl; return; } // 停止PTZ操作 ret = ONVIF_PTZStopMove(ptzXAddr, profilesToken); if (ret != 0) { std::cerr << "错误: 停止PTZ操作失败 (错误码: " << ret << ")" << std::endl; } else { std::cout << " PTZ操作已停止" << std::endl; } } int main(int argc, char** argv) { ONVIF_DetectDevice(cb_discovery); return 0; } 获取配置文件失败

大家在看

recommend-type

TXT文件合并器一款合并文本文件的工具

TXT文件合并器,一款合并文本文件的工具,可以的。
recommend-type

Scratch语言教程&案例&相关项目资源

这篇文章为想要学习和探索Scratch编程的青少年和初学者们提供了宝贵的教程、案例以及相关项目资源,旨在帮助他们轻松入门Scratch编程,并在实践中不断提升编程能力。 文章首先聚焦于Scratch教程的介绍,强调了教程在Scratch编程学习中的重要性。通过精心挑选的一系列优质教程资源,文章引导读者逐步了解Scratch的基本界面、积木块功能以及编程逻辑等核心概念。这些教程采用图文结合的方式,使得复杂的编程概念变得简单易懂,帮助初学者快速掌握Scratch编程的基础知识。 除了基础教程,文章还深入探讨了Scratch案例学习的价值。通过展示一系列真实而有趣的Scratch案例,文章让读者了解到Scratch在动画设计、游戏制作等领域的广泛应用。这些案例不仅具有创意和趣味性,而且能够帮助读者将所学知识应用到实际项目中,提升解决实际问题的能力。 此外,文章还梳理了与Scratch相关的项目资源,为学习者提供了实践Scratch编程的机会。这些项目资源包括Scratch社区分享的项目、学校或教育机构的实践项目等,为学习者提供了丰富的实战演练场景。通过参与这些项目,学习者不仅可以锻炼编
recommend-type

Xilinx 7系列FPGA手册[打包下载]

Xilinx 7系列FPGA手册打包下载,包括以下手册: 1)ug470_7Series_Config.pdf 2)ug471_7Series_SelectIO.pdf 3)ug472_7Series_Clocking.pdf 4)ug473_7Series_Memory_Resources.pdf 5)ug474_7Series_CLB.pdf 6)ug479_7Series_DSP48E1.pdf 7)ug480_7Series_XADC.pdf 8)ug482_7Series_GTP_Transceivers.pdf
recommend-type

filter LTC1068 模块AD设计 Altium设计 硬件原理图+PCB文件.rar

filter LTC1068 模块AD设计 Altium设计 硬件原理图+PCB文件,2层板设计,Altium Designer 设计的工程文件,包括完整的原理图及PCB文件,可以用Altium(AD)软件打开或修改,可作为你产品设计的参考。
recommend-type

谐响应分析步骤-ANSYS谐响应分析

谐响应分析 第三节:步骤 四个主要步骤: 建模 选择分析类型和选项 施加谐波载荷并求解 观看结果

最新推荐

recommend-type

2022年互联网金融行业分析报告.pptx

2022年互联网金融行业分析报告.pptx
recommend-type

全面解析SOAP库包功能与应用

从给定的文件信息中,我们可以提取到的核心知识点主要集中在“SOAP”这一项技术上,由于提供的信息量有限,这里将尽可能详细地解释SOAP相关的知识。 首先,SOAP代表简单对象访问协议(Simple Object Access Protocol),是一种基于XML的消息传递协议。它主要用于在网络上不同应用程序之间的通信。SOAP定义了如何通过HTTP和XML格式来构造消息,并规定了消息的格式应遵循XML模式。这种消息格式使得两个不同平台或不同编程语言的应用程序之间能够进行松耦合的服务交互。 在分布式计算环境中,SOAP作为一种中间件技术,可以被看作是应用程序之间的一种远程过程调用(RPC)机制。它通常与Web服务结合使用,Web服务是使用特定标准实现的软件系统,它公开了可以通过网络(通常是互联网)访问的API。当客户端与服务端通过SOAP进行通信时,客户端可以调用服务端上特定的方法,而不需要关心该服务是如何实现的,或者是运行在什么类型的服务器上。 SOAP协议的特点主要包括: 1. **平台无关性**:SOAP基于XML,XML是一种跨平台的标准化数据格式,因此SOAP能够跨越不同的操作系统和编程语言平台进行通信。 2. **HTTP协议绑定**:虽然SOAP协议本身独立于传输协议,但是它通常与HTTP协议绑定,这使得SOAP能够利用HTTP的普及性和无需额外配置的优势。 3. **消息模型**:SOAP消息是交换信息的载体,遵循严格的结构,包含三个主要部分:信封(Envelope)、标题(Header)和正文(Body)。信封是消息的外壳,定义了消息的开始和结束;标题可以包含各种可选属性,如安全性信息;正文则是实际的消息内容。 4. **错误处理**:SOAP提供了详细的错误处理机制,可以通过错误码和错误信息来描述消息处理过程中的错误情况。 5. **安全性和事务支持**:SOAP协议可以集成各种安全性标准,如WS-Security,以确保消息传输过程中的安全性和完整性。同时,SOAP消息可以包含事务信息,以便于服务端处理事务性的业务逻辑。 在描述中提到的“所有库包”,这可能意味着包含了SOAP协议的实现、相关工具集或库等。由于信息不足,这里的“库包”具体指的是什么并不清楚,但可以理解为与SOAP相关的软件开发工具包(SDK)或框架,它们使得开发者可以更加方便地创建SOAP消息,处理SOAP请求和响应,以及实现Web服务。 至于“压缩包子文件的文件名称列表”中只有一个单词“soap”,这可能表明实际文件内容仅有一个与SOAP相关的文件,或者是一个压缩包文件的名称为“soap”。由于缺乏更详尽的文件列表,无法进一步分析其可能的内容。 综上所述,SOAP作为一种实现Web服务的技术标准,通过HTTP和XML实现系统间的通信。它支持跨平台、跨语言的服务调用,并具备强大的安全性和错误处理机制。在具体应用中,开发者可能需要用到与之相关的库包或工具集来开发和部署Web服务。
recommend-type

编程语言选择指南:为不同项目量身定制的编程语言策略

# 摘要 选择合适的编程语言对于软件项目的成功至关重要。本文首先探讨了编程语言选择的重要性,并对不同分类和特点的编程语言进行了详尽分析,重点介绍了静态与动态类型、解释型与编译型、面向对象与函数式编程语言的区别和应用场景。接着,文章根据项目需求详细讨论了如何选择适合的编程语言,包括功能需求、性能考量、开发效率和团队技能等关键因素。通过实践案例分析,本文进一步探讨了不同
recommend-type

手写vue2的插件vue-router

<think>我们正在手写一个简化版的vue-router插件,用于Vue2。主要步骤:1.定义一个类VueRouter,包含路由映射、当前路由状态等。2.实现install方法,用于Vue.use()安装插件,在install方法中:-混入beforeCreate生命周期钩子,在组件创建时初始化router。-全局注册router-view和router-link组件。3.实现路由映射:将路由配置转换为路径与组件的映射表。4.监听hashchange事件(或者使用history模式,这里以hash模式为例)来响应路由变化。5.实现router-view组件,根据当前路由渲染对应组件。6.实现
recommend-type

《软件工程:实践者的方法》第6版课件解析

根据提供的文件信息,我们可以推断出以下知识点: 1. 课程名称:“SOFTWARE ENGINEERING A practitioner's approach 6e”,表明这是关于软件工程的课程教材,第6版,针对实践者的教学方法。 2. 版本信息:由于标题中明确指出是第6版(6e),我们知道这是一系列教科书或课件的最新版本,这意味着内容已经根据最新的软件工程理论和实践进行了更新和改进。 3. 课程类型:课程是针对“practitioner”,即实践者的,这表明教材旨在教授学生如何将理论知识应用于实际工作中,注重解决实际问题和案例学习,可能包含大量的项目管理、需求分析、系统设计和测试等方面的内容。 4. 适用范围:文件描述中提到了“仅供校园内使用”,说明这个教材是专为教育机构内部学习而设计的,可能含有某些版权保护的内容,不允许未经授权的外部使用。 5. 标签:“SOFTWARE ENGINEERING A practitioner's approach 6e 软件工程”提供了关于这门课程的直接标签信息。标签不仅重复了课程名称,还强化了这是关于软件工程的知识。软件工程作为一门学科,涉及软件开发的整个生命周期,从需求收集、设计、编码、测试到维护和退役,因此课程内容可能涵盖了这些方面。 6. 文件命名:压缩包文件名“SftEng”是“SOFTWARE ENGINEERING”的缩写,表明该压缩包包含的是软件工程相关的教材或资料。 7. 关键知识点:根据标题和描述,我们可以推测课件中可能包含的知识点有: - 软件工程基础理论:包括软件工程的定义、目标、原则和软件开发生命周期的模型。 - 需求分析:学习如何获取、分析、记录和管理软件需求。 - 系统设计:涉及软件架构设计、数据库设计、界面设计等,以及如何将需求转化为设计文档。 - 实现与编码:包括编程语言的选择、代码编写规范、版本控制等。 - 测试:软件测试的原则、方法和测试用例的设计。 - 项目管理:时间管理、团队协作、风险管理、成本估算等与软件项目成功相关的管理活动。 - 质量保证:软件质量模型、质量度量和质量控制措施。 - 维护和演化:软件部署后如何进行持续维护、升级和系统退役。 - 软件工程的新兴领域:包括敏捷开发方法、DevOps、用户体验设计等现代软件开发趋势。 8. 版权和使用限制:由于是专供校园内使用的教材,课件可能包含版权声明和使用限制,要求用户在没有授权的情况下不得对外传播和用于商业用途。 综上所述,这门课程的课件是为校园内的学生和教职员工设计的,关于软件工程的全面教育材料,覆盖了理论知识和实践技巧,并且在版权方面有所限制。由于是最新版的教材,它很可能包含了最新的软件工程技术和方法论。
recommend-type

QUARTUS II 13.0全攻略:新手到专家的10个必备技能

# 摘要 本文旨在详细介绍QUARTUS II 13.0软件的使用,包括其安装、FPGA基础、项目设置、设计流程、高级功能应用
recommend-type

IllegalArgumentException.class

<think>首先,用户的问题是:“我想查找与Java中IllegalArgumentException类相关的信息请问Java IllegalArgumentExceptionclass usageand examples”。这翻译成英文是:“Iwant tofind informationrelated tothe IllegalArgumentExceptionclass inJava.Please provideusage andexamples ofJavaIllegalArgumentException class.” 根据系统级指令:-所有行内数学表达式必须使用$...$格式,
recommend-type

高效进程监控工具的探索与应用

根据提供的文件信息,我们可以推断出一系列与“监控进程东东”相关的知识点。这些信息暗示了该工具可能是一个用来监控操作系统中运行的进程的应用程序。以下是对这些知识点的详细说明: ### 标题知识点: 1. **监控进程的意义**:在IT行业中,监控进程是指持续跟踪系统中运行的进程状态和行为。进程监控对于系统管理员和开发人员来说至关重要,它可以帮助他们理解系统在特定时刻的行为,以及在出现问题时快速定位问题所在。 2. **“超级好用”的含义**:这通常意味着该监控工具具有用户友好的界面、高效的性能、详细的进程信息展示以及可能具备自动化问题检测与报告的功能。超级好用还可能意味着它易于安装、配置和使用,即使是对于非技术用户。 ### 描述知识点: 1. **重复强调“超级好用”**:这种表述强调该工具的易用性和高效性,暗示它可能采用了直观的用户界面设计,以及优化过的性能,能够减少系统负载,同时提供快速且精准的进程信息。 2. **监控进程工具的常见功能**:通常包括实时进程列表显示、进程资源使用情况监控(CPU、内存、磁盘I/O、网络活动等)、进程启动和结束的跟踪、进程关联性分析(例如父子关系)、以及可能的进程安全监控。 ### 标签知识点: 1. **“监控”标签**:这个标签明确指出了工具的主要用途,即监控。在IT领域,监控是指使用特定的软件或硬件工具来持续检测和记录系统、网络或应用的性能和可用性。 ### 压缩包子文件的文件名称列表知识点: 1. **procexp.chm**:这很可能是一个帮助文件(CHM是Microsoft Compiled HTML Help文件的扩展名),提供了监控进程工具的详细用户指南、使用说明、常见问题解答和功能介绍。CHM文件是将HTML页面、索引和其他资源编译成单一文件的格式,方便用户查阅。 2. **procexp.exe**:这指的是实际的监控进程应用程序的可执行文件。EXE文件是Windows操作系统下的可执行程序文件,用户通过双击它可以启动应用程序。该程序可能包含了用于监控进程的核心功能,比如列出所有运行中的进程,显示它们的详细信息,进行性能分析等。 3. **Eula.txt**:这是一个文本文件,通常包含了最终用户许可协议(End-User License Agreement,EULA)。EULA是供应商和用户之间的法律协议,规定了软件的合法使用条件,包括用户能做什么和不能做什么,以及版权和担保声明。 ### 综合知识点: - **监控进程工具选择标准**:一个优质的监控进程工具应当包括实时更新、多层次的系统信息(如进程树、模块、句柄等)、过滤和搜索功能、安全性高以及对用户行为影响小等特点。 - **监控进程工具在不同场景下的应用**:例如,在开发过程中,开发者可以使用进程监控工具来分析应用程序运行状况,进行性能调优;在安全领域,安全专家可以利用这些工具来发现可疑进程,防止恶意软件的运行。 - **监控进程工具的未来发展**:随着技术的不断进步,监控进程工具也在不断演化,可能会集成更多的智能分析技术,如机器学习算法来预测系统问题,或者提供云平台支持,使得跨区域的进程监控成为可能。 总体来说,上述文件信息所暗示的“超级好用的监控进程东东”可能是一个集多种功能于一身的进程监控工具,它能够帮助用户有效地管理和维护计算机系统,保障其稳定性和安全性。通过提供的文件列表,我们可以得知该工具附带详细的帮助文档,以及用户可能需要的许可协议,这体现了其对用户友好性和专业性的重视。
recommend-type

【Catalyst 9800无线控制器实战手册】:从故障排查到网络优化的必备技能

# 1. Catalyst 9800无线控制器概述 Catalyst 9800无线控制器是思科公司推出的针对企业级无线网络的管理设备,它负责管理和优化无线网络环境。作为一款无线局域网控制器,9800系列在设计上集成了先进的网络功
recommend-type

qcustemplot

<think>我们正在处理关于Qt QCustomPlot的使用问题。根据引用内容,QCustomPlot是一个用于Qt的图表库,支持多种图表类型和交互功能。用户询问的是使用问题,可能涉及安装、集成或基本用法。根据引用[1]和[2],安装QCustomPlot通常需要将头文件和源文件(qcustomplot.h和qcustomplot.cpp)复制到项目目录中,并在项目中包含它们。引用[4]提到,如果是代码方式添加,可以直接声明QCustomPlot对象,并且需要添加printsupport模块(因为QCustomPlot依赖于Qt的打印支持模块)。根据引用[3],用户可以通过在QtDesig