mirror of https://github.com/ArduPilot/ardupilot
AP_ONVIF: add initial wsdl2h generated header for onvif devicemgmt
This commit is contained in:
parent
7c9a17b9fb
commit
45f58367d0
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* This file is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Code by Michael Oborne and Siddharth Bharat Purohit, Cubepilot Pty.
|
||||
*/
|
||||
|
||||
#include "AP_ONVIF.h"
|
||||
#include <AP_ONVIF/MediaBinding.nsmap>
|
||||
|
||||
#include "onvifhelpers.h"
|
||||
// For ChibiOS we will use HW RND # generator
|
||||
#include <stdlib.h> //rand()
|
||||
|
||||
|
||||
#ifndef USERNAME
|
||||
#define USERNAME "admin"
|
||||
#endif
|
||||
|
||||
#ifndef PASSWORD
|
||||
#define PASSWORD "admin"
|
||||
#endif
|
||||
|
||||
#ifndef ONVIF_HOSTNAME
|
||||
#define ONVIF_HOSTNAME "http://10.211.55.3:10000"
|
||||
#endif
|
||||
|
||||
#define DEVICE_ENDPOINT ONVIF_HOSTNAME"/onvif/device_service"
|
||||
#define MEDIA_ENDPOINT ONVIF_HOSTNAME"/onvif/media_service"
|
||||
#define PTZ_ENDPOINT ONVIF_HOSTNAME"/onvif/ptz_service"
|
||||
|
||||
#ifndef PRINT
|
||||
#define PRINT(fmt,args...) do {printf(fmt "\n", ## args); } while(0)
|
||||
#endif
|
||||
|
||||
const char *wsse_PasswordDigestURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";
|
||||
const char *wsse_Base64BinaryURI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary";
|
||||
|
||||
// static AP _ONVIF *_singleton;
|
||||
extern const AP_HAL::HAL &hal;
|
||||
|
||||
bool AP_ONVIF::init()
|
||||
{
|
||||
srand ((time_t)(hal.util->get_hw_rtc()/1000000ULL));
|
||||
soap = soap_new1(SOAP_XML_CANONICAL | SOAP_C_UTFSTRING);
|
||||
soap->connect_timeout = soap->recv_timeout = soap->send_timeout = 30; // 30 sec
|
||||
|
||||
proxy_device = new DeviceBindingProxy(soap);
|
||||
proxy_media = new MediaBindingProxy(soap);
|
||||
proxy_ptz = new PTZBindingProxy(soap);
|
||||
|
||||
if (proxy_device == nullptr ||
|
||||
proxy_media == nullptr ||
|
||||
proxy_ptz == nullptr) {
|
||||
AP_HAL::panic("AP_ONVIF: Failed to allocate gSOAP Proxy objects.");
|
||||
return false;
|
||||
}
|
||||
/// TODO: Need to find a way to store this in parameter system
|
||||
// or it could be just storage, we will see
|
||||
proxy_device->soap_endpoint = DEVICE_ENDPOINT;
|
||||
if (!probe_onvif_server()) {
|
||||
PRINT("Failed to probe onvif server.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_ONVIF::update, void), "onvif",
|
||||
4096, AP_HAL::Scheduler::PRIORITY_IO, 0)) {
|
||||
PRINT("Failed to create onvif thread");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AP_ONVIF::update()
|
||||
{
|
||||
while(true) {
|
||||
float pan = pan_norm;
|
||||
float tilt = tilt_norm;
|
||||
|
||||
// translate them into actual commands using cmd limits
|
||||
pan = ((pan + 1) * (pan_tilt_limit_max.x - pan_tilt_limit_min.x)/2.0) + pan_tilt_limit_min.x;
|
||||
tilt = ((tilt + 1) * (pan_tilt_limit_max.y - pan_tilt_limit_min.y)/2.0) + pan_tilt_limit_min.y;
|
||||
PRINT("PAN: %f TILT: %f", pan, tilt);
|
||||
// don't send the same request again
|
||||
if (uint32_t(pan*100.0) != uint32_t(last_pan_cmd*100.0) || uint32_t(tilt*100.0) != uint32_t(last_tilt_cmd*100.0)) {
|
||||
// actually send the command
|
||||
set_absolutemove(pan, tilt, 0.0);
|
||||
last_pan_cmd = pan;
|
||||
last_tilt_cmd = tilt;
|
||||
}
|
||||
hal.scheduler->delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
void AP_ONVIF::report_error()
|
||||
{
|
||||
PRINT("ONVIF ERROR:\n");
|
||||
if (soap_check_state(soap)) {
|
||||
PRINT("Error: soap struct state not initialized");
|
||||
} else if (soap->error) {
|
||||
const char **c, *v = NULL, *s, *d;
|
||||
c = soap_faultcode(soap);
|
||||
if (!*c) {
|
||||
soap_set_fault(soap);
|
||||
c = soap_faultcode(soap);
|
||||
}
|
||||
if (soap->version == 2) {
|
||||
v = soap_fault_subcode(soap);
|
||||
}
|
||||
s = soap_fault_string(soap);
|
||||
d = soap_fault_detail(soap);
|
||||
PRINT("%s%d fault %s [%s]\n%s\nDetail: %s",(soap->version ? "SOAP 1." : "Error "),
|
||||
(soap->version ? (int)soap->version : soap->error),
|
||||
*c, (v ? v : "no subcode"), (s ? s : "[no reason]"),
|
||||
(d ? d : "[no detail]"));
|
||||
}
|
||||
}
|
||||
|
||||
bool AP_ONVIF::probe_onvif_server()
|
||||
{
|
||||
_tds__GetDeviceInformation GetDeviceInformation;
|
||||
_tds__GetDeviceInformationResponse GetDeviceInformationResponse;
|
||||
set_credentials();
|
||||
if (proxy_device->GetDeviceInformation(&GetDeviceInformation, GetDeviceInformationResponse)) {
|
||||
PRINT("Failed to fetch Device Information");
|
||||
report_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
PRINT("Manufacturer: %s",GetDeviceInformationResponse.Manufacturer.c_str());
|
||||
PRINT("Model: %s",GetDeviceInformationResponse.Model.c_str());
|
||||
PRINT("FirmwareVersion: %s",GetDeviceInformationResponse.FirmwareVersion.c_str());
|
||||
PRINT("SerialNumber: %s",GetDeviceInformationResponse.SerialNumber.c_str());
|
||||
PRINT("HardwareId: %s",GetDeviceInformationResponse.HardwareId.c_str());
|
||||
|
||||
// get device capabilities and print media
|
||||
_tds__GetCapabilities GetCapabilities;
|
||||
_tds__GetCapabilitiesResponse GetCapabilitiesResponse;
|
||||
set_credentials();
|
||||
if (proxy_device->GetCapabilities(&GetCapabilities, GetCapabilitiesResponse)) {
|
||||
PRINT("Failed to fetch Device Capabilities");
|
||||
report_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetCapabilitiesResponse.Capabilities || !GetCapabilitiesResponse.Capabilities->Media) {
|
||||
PRINT("Missing device capabilities info");
|
||||
} else {
|
||||
PRINT("XAddr: %s", GetCapabilitiesResponse.Capabilities->Media->XAddr.c_str());
|
||||
if (GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities) {
|
||||
if (GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities->RTPMulticast) {
|
||||
PRINT("RTPMulticast: %s",(*GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities->RTPMulticast ? "yes" : "no"));
|
||||
}
|
||||
if (GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities->RTP_USCORETCP) {
|
||||
PRINT("RTP_TCP: %s", (*GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities->RTP_USCORETCP ? "yes" : "no"));
|
||||
}
|
||||
if (GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP) {
|
||||
PRINT("RTP_RTSP_TCP: %s", (*GetCapabilitiesResponse.Capabilities->Media->StreamingCapabilities->RTP_USCORERTSP_USCORETCP ? "yes" : "no"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set the Media proxy endpoint to XAddr
|
||||
proxy_media->soap_endpoint = MEDIA_ENDPOINT;
|
||||
|
||||
// get device profiles
|
||||
_trt__GetProfiles GetProfiles;
|
||||
_trt__GetProfilesResponse GetProfilesResponse;
|
||||
set_credentials();
|
||||
if (proxy_media->GetProfiles(&GetProfiles, GetProfilesResponse)){
|
||||
PRINT("Failed to fetch profiles");
|
||||
report_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetProfilesResponse.Profiles.size()) {
|
||||
PRINT("Profiles Received %lu", GetProfilesResponse.Profiles.size());
|
||||
} else {
|
||||
PRINT("Error: No Profiles Received");
|
||||
return false;
|
||||
}
|
||||
|
||||
// for each profile get snapshot
|
||||
for (uint32_t i = 0; i < GetProfilesResponse.Profiles.size(); i++) {
|
||||
PRINT("Profile name: %s", GetProfilesResponse.Profiles[i]->Name.c_str());
|
||||
}
|
||||
|
||||
// Just use first one for now
|
||||
profile_token = GetProfilesResponse.Profiles[0]->token;
|
||||
|
||||
proxy_ptz->soap_endpoint = PTZ_ENDPOINT;
|
||||
|
||||
// _tptz__GetServiceCapabilities GetCapabilities;
|
||||
// _tptz__GetServiceCapabilitiesResponse GetCapabilitiesResponse;
|
||||
// GetCapabilities.Category = tt__CapabilityCategory__PTZ;
|
||||
// set_credentials();
|
||||
// if (proxy_ptz->GetServiceCapabilities(&GetCapabilities, GetCapabilitiesResponse)) {
|
||||
// PRINT("Failed to fetch PTZ Capabilities");
|
||||
// report_error();
|
||||
// return false;
|
||||
// }
|
||||
// if (!GetCapabilitiesResponse.Capabilities) {
|
||||
|
||||
// }
|
||||
// GetCapabilitiesResponse.Capabilities->PTZ
|
||||
|
||||
// get PTZ Token
|
||||
_tptz__GetConfigurations GetConfigurations;
|
||||
_tptz__GetConfigurationsResponse GetConfigurationsResponse;
|
||||
set_credentials();
|
||||
if (proxy_ptz->GetConfigurations(&GetConfigurations, GetConfigurationsResponse)) {
|
||||
PRINT("Failed to fetch Configurations");
|
||||
report_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetConfigurationsResponse.PTZConfiguration.size()) {
|
||||
PRINT("PTZ Tokens Received");
|
||||
} else {
|
||||
PRINT("Error: No Profiles Received");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < GetConfigurationsResponse.PTZConfiguration.size(); i++) {
|
||||
PRINT("PTZ: %s", GetConfigurationsResponse.PTZConfiguration[i]->Name.c_str());
|
||||
}
|
||||
//GetConfigurationsResponse.PTZConfiguration[0]->token
|
||||
pan_tilt_limit_max = Vector2f(GetConfigurationsResponse.PTZConfiguration[0]->PanTiltLimits->Range->XRange->Max,
|
||||
GetConfigurationsResponse.PTZConfiguration[0]->PanTiltLimits->Range->YRange->Max);
|
||||
pan_tilt_limit_min = Vector2f(GetConfigurationsResponse.PTZConfiguration[0]->PanTiltLimits->Range->XRange->Min,
|
||||
GetConfigurationsResponse.PTZConfiguration[0]->PanTiltLimits->Range->YRange->Min);
|
||||
zoom_min = GetConfigurationsResponse.PTZConfiguration[0]->ZoomLimits->Range->XRange->Min;
|
||||
zoom_max = GetConfigurationsResponse.PTZConfiguration[0]->ZoomLimits->Range->XRange->Max;
|
||||
|
||||
PRINT("Pan: %f %f Tilt: %f %f", pan_tilt_limit_min.x, pan_tilt_limit_max.x,
|
||||
pan_tilt_limit_min.y, pan_tilt_limit_max.y);
|
||||
// Get PTZ status
|
||||
_tptz__GetStatus GetStatus;
|
||||
_tptz__GetStatusResponse GetStatusResponse;
|
||||
GetStatus.ProfileToken = profile_token;
|
||||
set_credentials();
|
||||
if (proxy_ptz->GetStatus(&GetStatus, GetStatusResponse)) {
|
||||
PRINT("Failed to recieve PTZ status");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetStatusResponse.PTZStatus->Error) {
|
||||
PRINT("ErrorStatus: %s", GetStatusResponse.PTZStatus->Error->c_str());
|
||||
}
|
||||
if (GetStatusResponse.PTZStatus->MoveStatus->PanTilt) {
|
||||
PRINT("PTStatus: %d", *GetStatusResponse.PTZStatus->MoveStatus->PanTilt);
|
||||
}
|
||||
if (GetStatusResponse.PTZStatus->MoveStatus->Zoom) {
|
||||
PRINT("ZoomStatus: %d", *GetStatusResponse.PTZStatus->MoveStatus->Zoom);
|
||||
}
|
||||
PRINT("Pan: %f Tilt: %f", GetStatusResponse.PTZStatus->Position->PanTilt->x,
|
||||
GetStatusResponse.PTZStatus->Position->PanTilt->y);
|
||||
PRINT("Zoom: %f", GetStatusResponse.PTZStatus->Position->Zoom->x);
|
||||
|
||||
soap_destroy(soap);
|
||||
soap_end(soap);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AP_ONVIF::rand_nonce(char *nonce, size_t noncelen)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t r = (uint32_t)(hal.util->get_hw_rtc()/1000000ULL);
|
||||
(void)memcpy((void *)nonce, (const void *)&r, 4);
|
||||
for (i = 4; i < noncelen; i += 4)
|
||||
{
|
||||
r = rand();
|
||||
(void)memcpy((void *)(nonce + i), (const void *)&r, 4);
|
||||
}
|
||||
}
|
||||
#define TEST_NONCE "LKqI6G/AikKCQrN0zqZFlg=="
|
||||
#define TEST_TIME "2010-09-16T07:50:45Z"
|
||||
#define TEST_PASS "userpassword"
|
||||
#define TEST_RESULT "tuOSpGlFlIXsozq4HFNeeGeFLEI="
|
||||
#define TEST 0
|
||||
void AP_ONVIF::set_credentials()
|
||||
{
|
||||
soap_wsse_delete_Security(soap);
|
||||
soap_wsse_add_Timestamp(soap, "Time", 60);
|
||||
|
||||
_wsse__Security *security = soap_wsse_add_Security(soap);
|
||||
const char *created = soap_dateTime2s(soap, (time_t)(hal.util->get_hw_rtc()/1000000ULL));
|
||||
char HA[SHA1_DIGEST_SIZE] {};
|
||||
char HABase64fin[29] {};
|
||||
char nonce[16], *nonceBase64;
|
||||
sha1_ctx ctx;
|
||||
uint16_t HABase64len;
|
||||
char *HABase64enc;
|
||||
uint16_t noncelen;
|
||||
|
||||
/* generate a nonce */
|
||||
rand_nonce(nonce, 16);
|
||||
|
||||
sha1_begin(&ctx);
|
||||
#if TEST
|
||||
char* test_nonce = (char*)base64_decode((const unsigned char*)TEST_NONCE, strlen(TEST_NONCE), &noncelen);
|
||||
sha1_hash((const unsigned char*)test_nonce, noncelen, &ctx);
|
||||
sha1_hash((const unsigned char*)TEST_TIME, strlen(TEST_TIME), &ctx);
|
||||
sha1_hash((const unsigned char*)TEST_PASS, strlen(TEST_PASS), &ctx);
|
||||
nonceBase64 = (char*)base64_encode((unsigned char*)test_nonce, 16, &noncelen);
|
||||
PRINT("Created:%s Hash64:%s", TEST_TIME, HABase64fin);
|
||||
#else
|
||||
sha1_hash((const unsigned char*)nonce, 16, &ctx);
|
||||
sha1_hash((const unsigned char*)created, strlen(created), &ctx);
|
||||
sha1_hash((const unsigned char*)PASSWORD, strlen(PASSWORD), &ctx);
|
||||
nonceBase64 = (char*)base64_encode((unsigned char*)nonce, 16, &noncelen);
|
||||
#endif
|
||||
sha1_end((unsigned char*)HA, &ctx);
|
||||
HABase64enc = (char*)base64_encode((unsigned char*)HA, SHA1_DIGEST_SIZE, &HABase64len);
|
||||
if (HABase64len > 29) {
|
||||
//things have gone truly bad time to panic
|
||||
PRINT("Error: Invalid Base64 Encode!");
|
||||
free(HABase64enc);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(HABase64fin, HABase64enc, HABase64len);
|
||||
|
||||
if (soap_wsse_add_UsernameTokenText(soap, "Auth", USERNAME, HABase64fin)) {
|
||||
report_error();
|
||||
}
|
||||
/* populate the remainder of the password, nonce, and created */
|
||||
security->UsernameToken->Password->Type = (char*)wsse_PasswordDigestURI;
|
||||
security->UsernameToken->Nonce = (struct wsse__EncodedString*)soap_malloc(soap, sizeof(struct wsse__EncodedString));
|
||||
security->UsernameToken->Salt = NULL;
|
||||
security->UsernameToken->Iteration = NULL;
|
||||
if (!security->UsernameToken->Nonce) {
|
||||
return;
|
||||
}
|
||||
soap_default_wsse__EncodedString(soap, security->UsernameToken->Nonce);
|
||||
security->UsernameToken->Nonce->__item = nonceBase64;
|
||||
security->UsernameToken->Nonce->EncodingType = (char*)wsse_Base64BinaryURI;
|
||||
security->UsernameToken->wsu__Created = soap_strdup(soap, created);
|
||||
}
|
||||
|
||||
bool AP_ONVIF::set_absolutemove(float x, float y, float z)
|
||||
{
|
||||
_tptz__AbsoluteMove AbsoluteMove;
|
||||
_tptz__AbsoluteMoveResponse AbsoluteMoveResponse;
|
||||
AbsoluteMove.Position = soap_new_tt__PTZVector(soap);
|
||||
AbsoluteMove.Position->PanTilt = soap_new_tt__Vector2D(soap);
|
||||
AbsoluteMove.Position->Zoom = soap_new_tt__Vector1D(soap);
|
||||
AbsoluteMove.Position->PanTilt->x = constrain_float(x, pan_tilt_limit_min.x, pan_tilt_limit_max.x);
|
||||
AbsoluteMove.Position->PanTilt->y = constrain_float(y, pan_tilt_limit_min.y, pan_tilt_limit_max.y);
|
||||
AbsoluteMove.Position->Zoom->x = constrain_float(z, zoom_min, zoom_max);
|
||||
AbsoluteMove.Speed = NULL;
|
||||
AbsoluteMove.ProfileToken = profile_token;
|
||||
// PRINT("Setting AbsoluteMove: %f %f %f", AbsoluteMove.Position->PanTilt->x,
|
||||
// AbsoluteMove.Position->PanTilt->y,
|
||||
// AbsoluteMove.Position->Zoom->x);
|
||||
set_credentials();
|
||||
if (proxy_ptz->AbsoluteMove(&AbsoluteMove, AbsoluteMoveResponse)) {
|
||||
PRINT("Failed to sent AbsoluteMove cmd");
|
||||
report_error();
|
||||
soap_destroy(soap);
|
||||
soap_end(soap);
|
||||
return false;
|
||||
}
|
||||
soap_destroy(soap);
|
||||
soap_end(soap);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* This file is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Code by Michael Oborne and Siddharth Bharat Purohit, Cubepilot Pty.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AP_HAL/AP_HAL.h>
|
||||
#include <AP_ONVIF/onvifDeviceBindingProxy.h>
|
||||
#include <AP_ONVIF/onvifMediaBindingProxy.h>
|
||||
#include <AP_ONVIF/onvifPTZBindingProxy.h>
|
||||
#include <plugin/wsseapi-lite.h>
|
||||
#include <AP_Math/AP_Math.h>
|
||||
|
||||
class AP_ONVIF {
|
||||
public:
|
||||
bool init();
|
||||
void set_credentials();
|
||||
bool set_absolutemove(float pan, float tilt, float zoom);
|
||||
void set_pan_norm(float pan) { pan_norm = pan; }
|
||||
void set_tilt_norm(float tilt) { tilt_norm = tilt; }
|
||||
|
||||
// get singleton instance
|
||||
// static AP_ONVIF *get_singleton() { return _singleton; }
|
||||
|
||||
private:
|
||||
void report_error();
|
||||
bool probe_onvif_server();
|
||||
void rand_nonce(char *nonce, size_t noncelen);
|
||||
void update();
|
||||
|
||||
Vector2f pan_tilt_limit_min;
|
||||
Vector2f pan_tilt_limit_max;
|
||||
float pan_norm, tilt_norm;
|
||||
float last_pan_cmd, last_tilt_cmd;
|
||||
|
||||
float zoom_min, zoom_max;
|
||||
std::string profile_token;
|
||||
struct soap *soap;
|
||||
DeviceBindingProxy *proxy_device;
|
||||
MediaBindingProxy *proxy_media;
|
||||
PTZBindingProxy *proxy_ptz;
|
||||
static AP_ONVIF *_singleton;
|
||||
char* media_endpoint;
|
||||
};
|
||||
|
||||
|
||||
// namespace AP {
|
||||
// AP_ONVIF *onvif();
|
||||
// };
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Base64 encoding/decoding (RFC1341)
|
||||
* Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
/*
|
||||
* This file is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Code by Siddharth Bharat Purohit
|
||||
*/
|
||||
|
||||
#include "onvifhelpers.h"
|
||||
|
||||
static const uint8_t base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const uint8_t base64url_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
|
||||
|
||||
/**
|
||||
* base64_encode - Base64 encode
|
||||
* @src: Data to be encoded
|
||||
* @len: Length of the data to be encoded
|
||||
* @out_len: Pointer to output length variable, or %nullptr if not used
|
||||
* Returns: Allocated buffer of out_len bytes of encoded data,
|
||||
* or %nullptr on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer. Returned buffer is
|
||||
* nul terminated to make it easier to use as a C string. The nul terminator is
|
||||
* not included in out_len.
|
||||
*/
|
||||
uint8_t* base64_encode_global(const uint8_t *src, uint16_t len, uint16_t *out_len, const uint8_t* table, bool urlsafe)
|
||||
{
|
||||
uint8_t *out, *pos;
|
||||
const uint8_t *end, *in;
|
||||
uint16_t olen;
|
||||
int16_t line_len;
|
||||
|
||||
olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
|
||||
if (!urlsafe) {
|
||||
olen += olen / 72; /* line feeds */
|
||||
}
|
||||
|
||||
olen++; /* nul termination */
|
||||
if (olen < len) {
|
||||
return nullptr; /* integer overflow */
|
||||
}
|
||||
out = (uint8_t*)malloc(olen);
|
||||
if (out == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
end = src + len;
|
||||
in = src;
|
||||
pos = out;
|
||||
line_len = 0;
|
||||
while (end - in >= 3) {
|
||||
*pos++ = table[in[0] >> 2];
|
||||
*pos++ = table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
|
||||
*pos++ = table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
|
||||
*pos++ = table[in[2] & 0x3f];
|
||||
in += 3;
|
||||
// if (!urlsafe) {
|
||||
// line_len += 4;
|
||||
// if (line_len >= 72) {
|
||||
// *pos++ = '\n';
|
||||
// line_len = 0;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
if (end - in) {
|
||||
*pos++ = table[in[0] >> 2];
|
||||
if (end - in == 1) {
|
||||
*pos++ = table[(in[0] & 0x03) << 4];
|
||||
if(!urlsafe) {
|
||||
*pos++ = '=';
|
||||
}
|
||||
} else {
|
||||
*pos++ = table[((in[0] & 0x03) << 4) |
|
||||
(in[1] >> 4)];
|
||||
*pos++ = table[(in[1] & 0x0f) << 2];
|
||||
}
|
||||
if (!urlsafe) {
|
||||
*pos++ = '=';
|
||||
}
|
||||
line_len += 4;
|
||||
}
|
||||
|
||||
// if (line_len && !urlsafe) {
|
||||
// *pos++ = '\n';
|
||||
// }
|
||||
|
||||
*pos = '\0';
|
||||
if (out_len) {
|
||||
*out_len = pos - out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
uint8_t* base64_encode(const uint8_t *src, uint16_t len, uint16_t *out_len)
|
||||
{
|
||||
return base64_encode_global(src, len, out_len, base64_table, false);
|
||||
}
|
||||
|
||||
//Reference: https://tools.ietf.org/html/rfc4648#section-5
|
||||
uint8_t* base64url_encode(const uint8_t *src, uint16_t len, uint16_t *out_len)
|
||||
{
|
||||
return base64_encode_global(src, len, out_len, base64url_table, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* base64_decode - Base64 decode
|
||||
* @src: Data to be decoded
|
||||
* @len: Length of the data to be decoded
|
||||
* @out_len: Pointer to output length variable
|
||||
* Returns: Allocated buffer of out_len bytes of decoded data,
|
||||
* or %nullptr on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer.
|
||||
*/
|
||||
uint8_t* base64_decode(const uint8_t *src, uint16_t len, uint16_t *out_len)
|
||||
{
|
||||
uint8_t dtable[256], *out, *pos, block[4], tmp;
|
||||
uint16_t i, count, olen;
|
||||
int16_t pad = 0;
|
||||
|
||||
memset(dtable, 0x80, 256);
|
||||
for (i = 0; i < sizeof(base64_table) - 1; i++) {
|
||||
dtable[base64_table[i]] = (uint8_t) i;
|
||||
}
|
||||
dtable['='] = 0;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (dtable[src[i]] != 0x80) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0 || count % 4) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
olen = count / 4 * 3;
|
||||
pos = out = (uint8_t*)malloc(olen);
|
||||
if (out == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
tmp = dtable[src[i]];
|
||||
if (tmp == 0x80) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (src[i] == '=') {
|
||||
pad++;
|
||||
}
|
||||
block[count] = tmp;
|
||||
count++;
|
||||
if (count == 4) {
|
||||
*pos++ = (block[0] << 2) | (block[1] >> 4);
|
||||
*pos++ = (block[1] << 4) | (block[2] >> 2);
|
||||
*pos++ = (block[2] << 6) | block[3];
|
||||
count = 0;
|
||||
if (pad) {
|
||||
if (pad == 1) {
|
||||
pos--;
|
||||
} else if (pad == 2) {
|
||||
pos -= 2;
|
||||
} else {
|
||||
/* Invalid padding */
|
||||
free(out);
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_len = pos - out;
|
||||
return out;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
#include <AP_HAL/AP_HAL.h>
|
||||
#include <AP_ONVIF/AP_ONVIF.h>
|
||||
// #include <DeviceBinding.nsmap>
|
||||
// #include <MediaBinding.nsmap>
|
||||
// #include <PTZBinding.nsmap>
|
||||
|
||||
void setup();
|
||||
void loop();
|
||||
|
||||
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
|
||||
|
||||
AP_ONVIF onvif;
|
||||
|
||||
void setup()
|
||||
{
|
||||
printf("AP_ONVIF library test\n");
|
||||
if (!onvif.init()) {
|
||||
AP_HAL::panic("Failed to initialise onvif");
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
static float pan = 0.0, tilt = 0.0;
|
||||
static bool move_up;
|
||||
printf("Sending: %f %f\n", pan, tilt);
|
||||
onvif.set_absolutemove(pan, tilt, 0);
|
||||
if (pan < 1.0 && move_up) {
|
||||
pan += 0.1;
|
||||
tilt += 0.1;
|
||||
} else if(pan > -1.0 && !move_up) {
|
||||
pan -= 0.1;
|
||||
tilt -= 0.1;
|
||||
}
|
||||
if (pan >= 1.0 && move_up) {
|
||||
move_up = false;
|
||||
}
|
||||
if (pan <= -1.0 && !move_up) {
|
||||
move_up = true;
|
||||
}
|
||||
hal.scheduler->delay(10000);
|
||||
}
|
||||
|
||||
AP_HAL_MAIN();
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
def build(bld):
|
||||
bld.ap_example(
|
||||
use='ap',
|
||||
)
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 01/08/2005
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Size of SHA1 digest */
|
||||
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
/* type to hold the SHA1 context */
|
||||
|
||||
typedef struct
|
||||
{ uint32_t count[2];
|
||||
uint32_t hash[5];
|
||||
uint32_t wbuf[16];
|
||||
} sha1_ctx;
|
||||
|
||||
void sha1_begin(sha1_ctx ctx[1]);
|
||||
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1]);
|
||||
void sha1_end(unsigned char hval[], sha1_ctx ctx[1]);
|
||||
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len);
|
||||
uint8_t* base64_encode(const uint8_t *src, uint16_t len, uint16_t *out_len);
|
||||
uint8_t* base64_decode(const uint8_t *src, uint16_t len, uint16_t *out_len);
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 01/08/2005
|
||||
|
||||
This is a byte oriented version of SHA1 that operates on arrays of bytes
|
||||
stored in memory.
|
||||
*/
|
||||
|
||||
#include <string.h> /* for memcpy() etc. */
|
||||
|
||||
#include "onvifhelpers.h"
|
||||
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
|
||||
#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
|
||||
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
|
||||
|
||||
#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define bsw_32(p,n) \
|
||||
{ int _i = (n); while(_i--) ((uint32_t*)p)[_i] = bswap_32(((uint32_t*)p)[_i]); }
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define bsw_32(p,n)
|
||||
#endif
|
||||
|
||||
#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
|
||||
|
||||
#if 0
|
||||
|
||||
#define ch(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define parity(x,y,z) ((x) ^ (y) ^ (z))
|
||||
#define maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
|
||||
#else /* Discovered by Rich Schroeppel and Colin Plumb */
|
||||
|
||||
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define parity(x,y,z) ((x) ^ (y) ^ (z))
|
||||
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
|
||||
|
||||
#endif
|
||||
|
||||
/* Compile 64 bytes of hash data into SHA1 context. Note */
|
||||
/* that this routine assumes that the byte order in the */
|
||||
/* ctx->wbuf[] at this point is in such an order that low */
|
||||
/* address bytes in the ORIGINAL byte stream will go in */
|
||||
/* this buffer to the high end of 32-bit words on BOTH big */
|
||||
/* and little endian systems */
|
||||
|
||||
#ifdef ARRAY
|
||||
#define q(v,n) v[n]
|
||||
#else
|
||||
#define q(v,n) v##n
|
||||
#endif
|
||||
|
||||
#define one_cycle(v,a,b,c,d,e,f,k,h) \
|
||||
q(v,e) += rotr32(q(v,a),27) + \
|
||||
f(q(v,b),q(v,c),q(v,d)) + k + h; \
|
||||
q(v,b) = rotr32(q(v,b), 2)
|
||||
|
||||
#define five_cycle(v,f,k,i) \
|
||||
one_cycle(v, 0,1,2,3,4, f,k,hf(i )); \
|
||||
one_cycle(v, 4,0,1,2,3, f,k,hf(i+1)); \
|
||||
one_cycle(v, 3,4,0,1,2, f,k,hf(i+2)); \
|
||||
one_cycle(v, 2,3,4,0,1, f,k,hf(i+3)); \
|
||||
one_cycle(v, 1,2,3,4,0, f,k,hf(i+4))
|
||||
|
||||
static void sha1_compile(sha1_ctx ctx[1])
|
||||
{ uint32_t *w = ctx->wbuf;
|
||||
|
||||
#ifdef ARRAY
|
||||
uint32_t v[5];
|
||||
memcpy(v, ctx->hash, 5 * sizeof(uint32_t));
|
||||
#else
|
||||
uint32_t v0, v1, v2, v3, v4;
|
||||
v0 = ctx->hash[0]; v1 = ctx->hash[1];
|
||||
v2 = ctx->hash[2]; v3 = ctx->hash[3];
|
||||
v4 = ctx->hash[4];
|
||||
#endif
|
||||
|
||||
#define hf(i) w[i]
|
||||
|
||||
five_cycle(v, ch, 0x5a827999, 0);
|
||||
five_cycle(v, ch, 0x5a827999, 5);
|
||||
five_cycle(v, ch, 0x5a827999, 10);
|
||||
one_cycle(v,0,1,2,3,4, ch, 0x5a827999, hf(15)); \
|
||||
|
||||
#undef hf
|
||||
#define hf(i) (w[(i) & 15] = rotl32( \
|
||||
w[((i) + 13) & 15] ^ w[((i) + 8) & 15] \
|
||||
^ w[((i) + 2) & 15] ^ w[(i) & 15], 1))
|
||||
|
||||
one_cycle(v,4,0,1,2,3, ch, 0x5a827999, hf(16));
|
||||
one_cycle(v,3,4,0,1,2, ch, 0x5a827999, hf(17));
|
||||
one_cycle(v,2,3,4,0,1, ch, 0x5a827999, hf(18));
|
||||
one_cycle(v,1,2,3,4,0, ch, 0x5a827999, hf(19));
|
||||
|
||||
five_cycle(v, parity, 0x6ed9eba1, 20);
|
||||
five_cycle(v, parity, 0x6ed9eba1, 25);
|
||||
five_cycle(v, parity, 0x6ed9eba1, 30);
|
||||
five_cycle(v, parity, 0x6ed9eba1, 35);
|
||||
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 40);
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 45);
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 50);
|
||||
five_cycle(v, maj, 0x8f1bbcdc, 55);
|
||||
|
||||
five_cycle(v, parity, 0xca62c1d6, 60);
|
||||
five_cycle(v, parity, 0xca62c1d6, 65);
|
||||
five_cycle(v, parity, 0xca62c1d6, 70);
|
||||
five_cycle(v, parity, 0xca62c1d6, 75);
|
||||
|
||||
#ifdef ARRAY
|
||||
ctx->hash[0] += v[0]; ctx->hash[1] += v[1];
|
||||
ctx->hash[2] += v[2]; ctx->hash[3] += v[3];
|
||||
ctx->hash[4] += v[4];
|
||||
#else
|
||||
ctx->hash[0] += v0; ctx->hash[1] += v1;
|
||||
ctx->hash[2] += v2; ctx->hash[3] += v3;
|
||||
ctx->hash[4] += v4;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sha1_begin(sha1_ctx ctx[1])
|
||||
{
|
||||
ctx->count[0] = ctx->count[1] = 0;
|
||||
ctx->hash[0] = 0x67452301;
|
||||
ctx->hash[1] = 0xefcdab89;
|
||||
ctx->hash[2] = 0x98badcfe;
|
||||
ctx->hash[3] = 0x10325476;
|
||||
ctx->hash[4] = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
/* SHA1 hash data in an array of bytes into hash buffer and */
|
||||
/* call the hash_compile function as required. */
|
||||
|
||||
void sha1_hash(const unsigned char data[], unsigned long len, sha1_ctx ctx[1])
|
||||
{ uint32_t pos = (uint32_t)(ctx->count[0] & SHA1_MASK),
|
||||
space = SHA1_BLOCK_SIZE - pos;
|
||||
const unsigned char *sp = data;
|
||||
|
||||
if((ctx->count[0] += len) < len)
|
||||
++(ctx->count[1]);
|
||||
|
||||
while(len >= space) /* tranfer whole blocks if possible */
|
||||
{
|
||||
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, space);
|
||||
sp += space; len -= space; space = SHA1_BLOCK_SIZE; pos = 0;
|
||||
bsw_32(ctx->wbuf, SHA1_BLOCK_SIZE >> 2);
|
||||
sha1_compile(ctx);
|
||||
}
|
||||
|
||||
memcpy(((unsigned char*)ctx->wbuf) + pos, sp, len);
|
||||
}
|
||||
|
||||
/* SHA1 final padding and digest calculation */
|
||||
|
||||
void sha1_end(unsigned char hval[], sha1_ctx ctx[1])
|
||||
{ uint32_t i = (uint32_t)(ctx->count[0] & SHA1_MASK);
|
||||
|
||||
/* put bytes in the buffer in an order in which references to */
|
||||
/* 32-bit words will put bytes with lower addresses into the */
|
||||
/* top of 32 bit words on BOTH big and little endian machines */
|
||||
bsw_32(ctx->wbuf, (i + 3) >> 2);
|
||||
|
||||
/* we now need to mask valid bytes and add the padding which is */
|
||||
/* a single 1 bit and as many zero bits as necessary. Note that */
|
||||
/* we can always add the first padding byte here because the */
|
||||
/* buffer always has at least one empty slot */
|
||||
ctx->wbuf[i >> 2] &= 0xffffff80 << 8 * (~i & 3);
|
||||
ctx->wbuf[i >> 2] |= 0x00000080 << 8 * (~i & 3);
|
||||
|
||||
/* we need 9 or more empty positions, one for the padding byte */
|
||||
/* (above) and eight for the length count. If there is not */
|
||||
/* enough space, pad and empty the buffer */
|
||||
if(i > SHA1_BLOCK_SIZE - 9)
|
||||
{
|
||||
if(i < 60) ctx->wbuf[15] = 0;
|
||||
sha1_compile(ctx);
|
||||
i = 0;
|
||||
}
|
||||
else /* compute a word index for the empty buffer positions */
|
||||
i = (i >> 2) + 1;
|
||||
|
||||
while(i < 14) /* and zero pad all but last two positions */
|
||||
ctx->wbuf[i++] = 0;
|
||||
|
||||
/* the following 32-bit length fields are assembled in the */
|
||||
/* wrong byte order on little endian machines but this is */
|
||||
/* corrected later since they are only ever used as 32-bit */
|
||||
/* word values. */
|
||||
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
|
||||
ctx->wbuf[15] = ctx->count[0] << 3;
|
||||
sha1_compile(ctx);
|
||||
|
||||
/* extract the hash value as bytes in case the hash buffer is */
|
||||
/* misaligned for 32-bit words */
|
||||
for(i = 0; i < SHA1_DIGEST_SIZE; ++i)
|
||||
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> (8 * (~i & 3)));
|
||||
}
|
||||
|
||||
void sha1(unsigned char hval[], const unsigned char data[], unsigned long len)
|
||||
{ sha1_ctx cx[1];
|
||||
|
||||
sha1_begin(cx); sha1_hash(data, len, cx); sha1_end(hval, cx);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
|||
cp ../../../modules/gsoap/gsoap/typemap.dat .
|
||||
wsdl2h -O4 -P -x -o onvif.h \
|
||||
http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl \
|
||||
http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl \
|
||||
http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl
|
||||
# http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl \
|
||||
# http://www.onvif.org/onvif/ver10/deviceio.wsdl \
|
||||
# http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl \
|
||||
|
||||
# http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl \
|
||||
# http://www.onvif.org/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
'''
|
||||
build generated bindings from bindings.desc for AP_Scripting
|
||||
'''
|
||||
|
||||
from waflib.TaskGen import after_method, before_method, feature
|
||||
import os
|
||||
|
||||
def configure(cfg):
|
||||
"""
|
||||
setup environment for mavlink header generator
|
||||
"""
|
||||
cfg.find_program('soapcpp2')
|
||||
env = cfg.env
|
||||
env.SOAP_DIR = cfg.srcnode.make_node('libraries/AP_ONVIF/soap').abspath()
|
||||
env.SOAP_IMPORT = cfg.srcnode.make_node('modules/gsoap/gsoap/import').abspath()
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'] = []
|
||||
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'] += ['onvifDeviceBindingProxy.cpp',
|
||||
'onvifMediaBindingProxy.cpp',
|
||||
'onvifPTZBindingProxy.cpp']
|
||||
name = 'onvif'
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'] += ['{}C.cpp'.format(name)]
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'].append(cfg.srcnode.make_node('modules/gsoap/gsoap/stdsoap2.cpp').abspath())
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'].append(cfg.srcnode.make_node('modules/gsoap/gsoap/dom.cpp').abspath())
|
||||
# cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'].append(cfg.srcnode.make_node('modules/gsoap/gsoap/plugin/smdevp.c').abspath())
|
||||
# cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'].append(cfg.srcnode.make_node('modules/gsoap/gsoap/plugin/mecevp.c').abspath())
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'].append(cfg.srcnode.make_node('modules/gsoap/gsoap/plugin/wsseapi-lite.cpp').abspath())
|
||||
cfg.env.AP_LIB_EXTRA_SOURCES['AP_ONVIF'].append(cfg.srcnode.make_node('modules/gsoap/gsoap/custom/struct_timeval.cpp').abspath())
|
||||
cfg.env.INCLUDES += [cfg.srcnode.make_node('modules/gsoap/gsoap/').abspath()]
|
||||
cfg.env.DEFINES += [
|
||||
'SOAP_H_FILE=AP_ONVIF/onvifH.h',
|
||||
]
|
||||
env.append_value('GIT_SUBMODULES', 'gsoap')
|
||||
|
||||
|
||||
def relpath(bld, node):
|
||||
'''make a build relative path. This is needed for CI to pass on azure'''
|
||||
blddir = bld.bldnode.make_node(".").abspath()
|
||||
return os.path.relpath(node.abspath(), blddir)
|
||||
|
||||
|
||||
def build(bld):
|
||||
output_dir = bld.bldnode.make_node('libraries/AP_ONVIF').abspath()
|
||||
gsoap_dir = bld.srcnode.make_node('modules/gsoap/gsoap').abspath()
|
||||
import_dir = bld.srcnode.make_node('modules/gsoap/gsoap/import').abspath()
|
||||
src = bld.srcnode.ant_glob('libraries/AP_ONVIF/soap/onvif.h')
|
||||
name = 'onvif'
|
||||
generated_cpp = [bld.bldnode.find_or_declare('libraries/AP_ONVIF/{}C.cpp'.format(name))]
|
||||
generated_h = [bld.bldnode.find_or_declare('libraries/AP_ONVIF/{}H.h'.format(name))]
|
||||
bld(
|
||||
source=src,
|
||||
rule="$(cd %s;%s -2 -Cp onvif -I%s:%s -j -x ../../${SRC})" % (output_dir,
|
||||
bld.env.get_flat('SOAPCPP2'),
|
||||
import_dir, gsoap_dir),
|
||||
target=generated_cpp + generated_h,
|
||||
group='dynamic_sources'
|
||||
)
|
Loading…
Reference in New Issue