Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# CMakeLists.txt fuer vapixconfig
#
SET(vapixconfig_SRCS
config.cpp
httprequesthandler.cpp
request.cpp
vapixconfig.cpp
)
SET(vapixconfig_HDRS
config.h
httprequesthandler.h
request.h
vapixconfig.h
)
NGL_ADD_LIBRARY(AAR SV NO_TRANSLATION vapixconfig SHARED ${vapixconfig_SRCS} ${vapixconfig_HDRS})
NGL_TARGET_INCLUDE_DIRECTORIES(vapixconfig
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(vapixconfig
PRIVATE
Qt5::Network
Qt5::Xml
PUBLIC
Qt5::Core
)
NGL_INSTALL_TARGET(vapixconfig)
+163
View File
@@ -0,0 +1,163 @@
/**
* @RDE_HEADER@
* Config class to parse XML-Files for Axis Camera Configuration
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#include "config.h"
#include <QDebug>
#include <QFile>
using namespace VapixConfig;
Config::Config()
{
}
// init is needed to clear the DomDocument for saving purpose
void Config::init()
{
m_domDocument.clear();
m_root = m_domDocument.createElement(QLatin1String("Camera"));
m_domDocument.appendChild(m_root);
}
// Reads XML and put created maps in maplists
bool Config::processConfig(const QString &xmlConfig)
{
QFile f(xmlConfig);
if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
return 0;
m_domDocument.setContent(&f);
m_root = m_domDocument.documentElement();
if (m_root.tagName() != QLatin1String("Camera"))
return false;
const QDomNodeList image = m_root.elementsByTagName(QLatin1String("Image"));
const QDomNodeList window = m_root.elementsByTagName(QLatin1String("Motion"));
const QDomNodeList server = m_root.elementsByTagName(QLatin1String("EventServer"));
const QDomNodeList event = m_root.elementsByTagName(QLatin1String("Event"));
const QDomNodeList action = m_root.elementsByTagName(QLatin1String("Action"));
for (int i = 0; i <= image.size(); ++i)
{
const QDomElement tempElement = image.at(i).toElement();
QDomElement tempChild = tempElement.firstChild().toElement();
QMap<QString, QString> imageMap;
while (!tempChild.isNull())
{
imageMap[tempChild.tagName()] = tempChild.firstChild().toText().data();
tempChild = tempChild.nextSibling().toElement();
}
if (!imageMap.isEmpty())
{
m_imageList.append(imageMap);
}
}
for (int i = 0; i <= window.size(); ++i)
{
const QDomElement tempElement = window.at(i).toElement();
QDomElement tempChild = tempElement.firstChild().toElement();
QMap<QString, QString> windowMap;
while (!tempChild.isNull())
{
windowMap[tempChild.tagName()] = tempChild.firstChild().toText().data();
tempChild = tempChild.nextSibling().toElement();
}
if (!windowMap.isEmpty())
{
m_windowList.append(windowMap);
}
}
for (int i = 0; i <= server.size(); ++i)
{
const QDomElement tempElement = server.at(i).toElement();
QDomElement tempChild = tempElement.firstChild().toElement();
QMap<QString, QString> serverMap;
while (!tempChild.isNull())
{
serverMap[tempChild.tagName()] = tempChild.firstChild().toText().data();
tempChild = tempChild.nextSibling().toElement();
}
if (!serverMap.isEmpty())
{
m_serverList.append(serverMap);
}
}
for (int i = 0; i <= event.size(); ++i)
{
const QDomElement tempElement = event.at(i).toElement();
QDomElement tempChild = tempElement.firstChild().toElement();
QMap<QString, QString> eventMap;
while (!tempChild.isNull())
{
eventMap[tempChild.tagName()] = tempChild.firstChild().toText().data();
tempChild = tempChild.nextSibling().toElement();
}
if (!eventMap.isEmpty())
{
m_eventList.append(eventMap);
}
}
for (int i = 0; i <= action.size(); ++i)
{
const QDomElement tempElement = action.at(i).toElement();
QDomElement tempChild = tempElement.firstChild().toElement();
QMap<QString, QString> actionMap;
while (!tempChild.isNull())
{
actionMap[tempChild.tagName()] = tempChild.firstChild().toText().data();
tempChild = tempChild.nextSibling().toElement();
}
if (!actionMap.isEmpty())
{
m_actionList.append(actionMap);
}
}
f.close();
return true;
}
//Saves configuration from camera to XML file
void Config::saveConfig(const QString &savePath)
{
QFile saveFile;
saveFile.setFileName(savePath);
if (saveFile.open(QIODevice::WriteOnly))
{
QTextStream stream(&saveFile);
stream << m_domDocument.toString();
saveFile.close();
}
else
qDebug("Failed to write data!");
}
// used to fill XML
void Config::addElementToXml(const QMap<QString, QString> &givenMap, const QString &groupName)
{
QString tempName = groupName;
if (!tempName.compare(QLatin1String("Event.*.Actions")))
tempName = QLatin1String("Action");
if (!tempName.compare(QLatin1String("EventServers")))
tempName = QLatin1String("EventServer");
QDomElement tempElem = m_domDocument.createElement(tempName);
m_root.appendChild(tempElem);
QDomElement tempChild;
QDomText tempText;
for (auto iterator = givenMap.begin(); iterator != givenMap.end(); ++iterator)
{
tempChild = m_domDocument.createElement(iterator.key());
tempElem.appendChild(tempChild);
tempText = m_domDocument.createTextNode(iterator.value());
tempChild.appendChild(tempText);
}
}
+66
View File
@@ -0,0 +1,66 @@
/**
* @RDE_HEADER@
* Config class to parse XML-Files for Axis Camera Configuration
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#pragma once
#include <QDomElement>
#include <QMap>
#include <QVector>
namespace VapixConfig
{
class Config
{
public:
Config();
bool processConfig(const QString &xmlConfig);
void saveConfig(const QString &savePath);
void addElementToXml(const QMap<QString, QString> &givenMap, const QString &gorupName);
void init();
const QVector<QMap<QString, QString>> &getImageList() const
{
return m_imageList;
}
const QVector<QMap<QString, QString>> &getEventList() const
{
return m_eventList;
}
const QVector<QMap<QString, QString>> &getServerList() const
{
return m_serverList;
}
const QVector<QMap<QString, QString>> &getWindowList() const
{
return m_windowList;
}
const QVector<QMap<QString, QString>> &getActionList() const
{
return m_actionList;
}
private:
QDomDocument m_domDocument;
QDomElement m_root;
QDomNodeList m_image;
QDomNodeList m_window;
QDomNodeList m_server;
QDomNodeList m_event;
QDomNodeList m_action;
QDomNodeList m_child;
QVector<QMap<QString, QString>> m_imageList;
QVector<QMap<QString, QString>> m_serverList;
QVector<QMap<QString, QString>> m_eventList;
QVector<QMap<QString, QString>> m_windowList;
QVector<QMap<QString, QString>> m_actionList;
};
} // namespace VapixConfig
+150
View File
@@ -0,0 +1,150 @@
/**
* @RDE_HEADER@
* HTTPRequestHandler sends requests to Axis Cameras initialized in VapixConfig
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#include "httprequesthandler.h"
#include <QDebug>
#include <QEventLoop>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRegularExpression>
using namespace VapixConfig;
HTTPRequestHandler::HTTPRequestHandler()
{}
void HTTPRequestHandler::init(const QString &ip, const QString &password, const QString &username)
{
m_ip = ip;
m_userName = username;
m_password = password;
}
QNetworkReply *HTTPRequestHandler::sendRequest(const QUrl &paramUrl, QNetworkAccessManager *qNam)
{
QNetworkRequest request(paramUrl);
QNetworkReply *reply = qNam->get(request);
// TODO
QEventLoop eventLoop;
QObject::connect(qNam, &QNetworkAccessManager::finished,
&eventLoop, &QEventLoop::quit);
eventLoop.exec();
qDebug() << "Request sent";
return reply;
}
// gets all parameter(configuration) from the camera
QVector<QMap<QString, QString>> HTTPRequestHandler::getParams(const QString &groupName, QNetworkAccessManager *qNam)
{
int amount = getAmount(groupName, qNam);
QVector<QMap<QString, QString>> paramList;
const QString prefix = buildHttpPrefix() + QLatin1String("/axis-cgi/admin/param.cgi?action=list&group=");
QString baseUrl;
paramList.reserve(amount);
for (int i = 0; i < amount; ++i)
{
if (groupName == QLatin1String("Event.*.Actions"))
baseUrl = prefix + QLatin1String("Event.E") + QString::number(i) + QLatin1String(".Actions");
else if (groupName == QLatin1String("EventServers"))
baseUrl = prefix + groupName + QLatin1String(".TCP.T") + QString::number(i);
else if (groupName == QLatin1String("Motion"))
baseUrl = prefix + groupName + QLatin1String(".M") + QString::number(i);
else if (groupName == QLatin1String("Event"))
baseUrl = prefix + groupName + QLatin1String(".E") + QString::number(i);
else if (groupName == QLatin1String("Image"))
baseUrl = prefix + groupName + QLatin1String(".I0.Appearance.Resolution");
else
qDebug() << "Error: Groupname does not exist";
QUrl requestUrl(baseUrl);
QNetworkReply *reply = sendRequest(requestUrl, qNam);
QByteArray replyBytes = reply->readAll();
QString replyText = QString::fromUtf8(replyBytes.data(), replyBytes.size());
QRegularExpression re(QLatin1String("(\\w++=[^_]++)"));
const QVector<QStringRef> replyList = replyText.splitRef(QRegExp(QLatin1String("\n|\r\n|\r")));
QMap<QString, QString> paramMap;
for (const QStringRef &string : replyList)
{
QRegularExpressionMatch match = re.match(string, 0, QRegularExpression::PartialPreferCompleteMatch);
if (!match.captured(0).isNull())
{
const QStringList sl = match.captured(0).split(QLatin1Char('='));
paramMap[sl.at(0)] = sl.at(1);
}
}
reply->deleteLater();
paramList.append(paramMap);
paramMap.clear();
}
return paramList;
}
//removes all modified parameter
void HTTPRequestHandler::removeParams(const QString &groupName, QNetworkAccessManager *qNam)
{
const QString prefix = buildHttpPrefix() + QLatin1String("/axis-cgi/admin/param.cgi?action=list&group=");
QUrl requestUrl(prefix + groupName);
QNetworkReply *reply = sendRequest(requestUrl, qNam);
QByteArray replyBytes = reply->readAll();
QString replyText = QString::fromUtf8(replyBytes.data(), replyBytes.size());
QRegularExpression re(QLatin1String("(\\b\\w{2}\\b)"));
const QVector<QStringRef> replyList = replyText.splitRef(QRegExp(QLatin1String("\n|\r\n|\r")));
QStringList tempList;
for (const QStringRef &string : replyList)
{
QRegularExpressionMatch match = re.match(string, 0, QRegularExpression::NormalMatch);
if (match.capturedRef(0).isNull())
continue;
const QString removeUrl = buildHttpPrefix() + QLatin1String("/axis-cgi/admin/param.cgi?action=remove&group=") +
groupName + QLatin1Char('.') + match.captured(0);
tempList.append(removeUrl);
}
tempList.removeDuplicates();
for (const QString &string : qAsConst(tempList))
{
QUrl url;
url.setUrl(string);
sendRequest(url, qNam);
}
reply->deleteLater();
}
//method to get how many parameter are configurated multiple times
int HTTPRequestHandler::getAmount(const QString &groupName, QNetworkAccessManager *qNam)
{
const QString reqStr = buildHttpPrefix() + QLatin1String("/axis-cgi/admin/param.cgi?action=list&group=");
QString baseUrl;
if (groupName == QLatin1String("Event.*.Actions"))
baseUrl = reqStr + groupName + QLatin1String(".*.Protocol");
else if (groupName == QLatin1String("EventServers"))
baseUrl = reqStr + groupName + QLatin1String(".TCP.*.Name");
else if (groupName == QLatin1String("Image"))
baseUrl = reqStr + groupName + QLatin1String(".I0.Appearance.Resolution");
else
baseUrl = reqStr + groupName + QLatin1String(".*.Name");
QUrl requestUrl(baseUrl);
QNetworkReply *reply = sendRequest(requestUrl, qNam);
QByteArray replyBytes = reply->readAll();
QString bytesString = QString::fromUtf8(replyBytes.data(), replyBytes.size());
QString replyText = QVariant(bytesString).toString();
QStringList replyList = replyText.split(QRegExp(QLatin1String("\n|\r\n|\r")));
reply->deleteLater();
return replyList.count() - 1;
}
QString HTTPRequestHandler::buildHttpPrefix() const
{
QString prefix = QLatin1String("http://");
if (!m_userName.isEmpty())
prefix += m_userName + QLatin1Char(':');
if (!m_password.isEmpty())
prefix += m_password + QLatin1Char('@');
prefix += m_ip;
return prefix;
}
+38
View File
@@ -0,0 +1,38 @@
/**
* @RDE_HEADER@
* HTTPRequestHandler sends requests to Axis Cameras initialized in VapixConfig
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#pragma once
#include <QObject>
#include <QMap>
#include <QVector>
class QNetworkAccessManager;
class QNetworkReply;
class QUrl;
namespace VapixConfig
{
class HTTPRequestHandler : public QObject
{
Q_OBJECT
public:
HTTPRequestHandler();
void init(const QString &ip, const QString &password, const QString &username);
QNetworkReply *sendRequest(const QUrl &paramUrl, QNetworkAccessManager *qNam);
QVector<QMap<QString,QString>> getParams(const QString &groupName, QNetworkAccessManager *qNam);
void removeParams(const QString &groupName, QNetworkAccessManager *qNam);
int getAmount(const QString &groupName, QNetworkAccessManager *qNam);
private:
QString buildHttpPrefix() const;
QString m_ip;
QString m_userName;
QString m_password;
};
} // namespace VapixConfig
+51
View File
@@ -0,0 +1,51 @@
/**
* @RDE_HEADER@
* Solely purpose is to form strings to fit the Axis API Syntax
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#include "request.h"
using namespace VapixConfig;
QString Request::updateImageParams(const QMap<QString, QString> &imageMap, const QString &ipAddress)
{
QString updateString = QLatin1String("http://") + ipAddress + QLatin1String("/axis-cgi/admin/param.cgi?action=update&group=Image.I0.Appearance");
for (auto iterator = imageMap.begin(); iterator != imageMap.end(); ++iterator)
updateString.append(QLatin1Char('.') + iterator.key() + QLatin1Char('=') + iterator.value());
return updateString;
}
QString Request::addEventServer(const QMap<QString, QString> &serverMap, const QString &ipAddress)
{
QString updateString = QLatin1String("http://") + ipAddress + QLatin1String("/axis-cgi/admin/param.cgi?action=add&group=EventServers.TCP&template=tcp_config");
for (auto iterator = serverMap.begin(); iterator != serverMap.end(); ++iterator)
updateString.append(QLatin1String("&EventServers.TCP.T.") + iterator.key() + QLatin1Char('=') + iterator.value());
return updateString;
}
QString Request::addEvent(const QMap<QString, QString> &eventMap, const QString &ipAddress)
{
QString updateString = QLatin1String("http://") + ipAddress + QLatin1String("/axis-cgi/admin/param.cgi?action=add&group=Event&template=event");
for (auto iterator = eventMap.begin(); iterator != eventMap.end(); ++iterator)
updateString.append(QLatin1String("&Event.E.") + iterator.key() + QLatin1Char('=') + iterator.value());
return updateString;
}
QString Request::addActionToEvent(const QMap<QString, QString> &actionMap, int eventID, const QString &ipAddress)
{
QString updateString = QLatin1String("http://") + ipAddress + QLatin1String("/axis-cgi/admin/param.cgi?action=add&group=Event.E") + QString::number(eventID) + QLatin1String(".Actions&template=tcpaction");
for (auto iterator = actionMap.begin(); iterator != actionMap.end(); ++iterator)
updateString.append(QLatin1String("&Event.E") + QString::number(eventID) + QLatin1String(".Actions.A.") + iterator.key() + QLatin1Char('=') + iterator.value());
return updateString;
}
QString Request::addMotionWindow(const QMap<QString, QString> &windowMap, const QString &ipAddress)
{
QString updateString = QLatin1String("http://") + ipAddress + QLatin1String("/axis-cgi/admin/param.cgi?action=add&group=Motion&template=motion");
for (auto iterator = windowMap.begin(); iterator != windowMap.end(); ++iterator)
updateString.append(QLatin1String("&Motion.M.") + iterator.key() + QLatin1Char('=') + iterator.value());
return updateString;
}
+24
View File
@@ -0,0 +1,24 @@
/**
* @RDE_HEADER@
* Solely purpose is to form strings to fit the Axis API Syntax
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#pragma once
#include <QString>
#include <QMap>
namespace VapixConfig
{
namespace Request
{
QString updateImageParams(const QMap<QString, QString> &imageMap, const QString &ipAddress);
QString addEventServer(const QMap<QString, QString> &serverMap, const QString &ipAddress);
QString addEvent(const QMap<QString, QString> &eventMap, const QString &ipAddress);
QString addActionToEvent(const QMap<QString, QString> &actionMap, int eventID, const QString &ipAddress);
QString addMotionWindow(const QMap<QString, QString> &windowMap, const QString &ipAddress);
}
} // namespace VapixConfig
+129
View File
@@ -0,0 +1,129 @@
/**
* @RDE_HEADER@
* VapixConfig configurates Axis Cameras through Axis HTTP API Vapix
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#include "vapixconfig.h"
#include "config.h"
#include "httprequesthandler.h"
#include "request.h"
#include <QDebug>
#include <QUrl>
namespace VapixConfig
{
VapixConfig::VapixConfig(QNetworkAccessManager *networkAccessManager, QObject *parent)
: QObject(parent)
, m_networkAccessManager(networkAccessManager)
, m_requestHandler(new HTTPRequestHandler)
, m_config(new Config)
{
// connect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
}
VapixConfig::~VapixConfig()
{
delete m_requestHandler;
delete m_config;
}
// Init is needed to set the required parameter like ip,password and username.
void VapixConfig::init(const QString &ip, const QString &password, const QString &username)
{
m_ip = ip;
m_password = password;
m_username = username;
m_requestHandler->init(ip, password, username);
connect(this, &VapixConfig::setConfigFinished, this, &VapixConfig::startNextRequest);
connect(this, &VapixConfig::setConfigError, this, &VapixConfig::configError);
}
// Gets the current configuration for initialized camera
void VapixConfig::getConfig()
{
const QVector<QString> tempList({QLatin1String("Image"),
QLatin1String("Motion"),
QLatin1String("EventServers"),
QLatin1String("Event"),
QLatin1String("Event.*.Actions")});
m_config->init();
for (const QString &paramName : tempList)
{
const QVector<QMap<QString,QString>> paramList = m_requestHandler->getParams(paramName, m_networkAccessManager);
typedef QMap<QString,QString> strMap;
for (const strMap &map : paramList)
m_config->addElementToXml(map, paramName);
}
}
// to save the configuration to a XML
void VapixConfig::saveConfig(const QString &savePath)
{
m_config->saveConfig(savePath);
}
void VapixConfig::resetConfig()
{
const QVector<QString> paramList({QLatin1String("Motion"),
QLatin1String("EventServers.TCP"),
QLatin1String("Event")});
for (const QString &paramName : paramList)
m_requestHandler->removeParams(paramName, m_networkAccessManager);
qDebug() << "Parameter resetted!";
}
//Configurates initialized camera
//TO-DO: Need to check for the right Event-ID for "Action"
bool VapixConfig::setConfig(const QString &xmlString)
{
int ID = 0;
if (!m_config->processConfig(xmlString))
{
emit setConfigError(QLatin1String("+++Error while setting config+++"));
return false;
}
// fill queue with urls
for (const auto &map : m_config->getImageList())
m_requestQueue.enqueue(Request::updateImageParams(map, m_ip));
for (const auto &map : m_config->getServerList())
m_requestQueue.enqueue(Request::addEventServer(map, m_ip));
for (const auto &map : m_config->getWindowList())
m_requestQueue.enqueue(Request::addMotionWindow(map, m_ip));
for (const auto &map : m_config->getEventList())
m_requestQueue.enqueue(Request::addEvent(map, m_ip));
for (const auto &map : m_config->getActionList())
m_requestQueue.enqueue(Request::addActionToEvent(map, ID, m_ip));
return true;
}
// dequeues the QQueue and send requests to camera in this recursive method
void VapixConfig::startNextRequest()
{
if (m_requestQueue.isEmpty())
{
qDebug() << "All requests done!";
emit requestsFinished();
return;
}
QUrl requestUrl;
requestUrl.setUrl(m_requestQueue.dequeue());
requestUrl.setUserName(m_username);
requestUrl.setPassword(m_password);
m_requestHandler->sendRequest(requestUrl, m_networkAccessManager);
startNextRequest();
}
void VapixConfig::startRequests()
{
emit setConfigFinished();
}
void VapixConfig::configError(const QString &error)
{
qDebug() << error;
}
} // namespace VapixConfig
+51
View File
@@ -0,0 +1,51 @@
/**
* @RDE_HEADER@
* VapixConfig configurates Axis Cameras through Axis HTTP API Vapix
* $Id$
* $HeadURL$
* $Author$
* Created by Terrell Scharfenberg, SLSE, 2016-05-27
*/
#pragma once
#include <QString>
#include <QObject>
#include <QQueue>
class QNetworkAccessManager;
namespace VapixConfig
{
class HTTPRequestHandler;
class Config;
class VapixConfig : public QObject
{
Q_OBJECT
public:
VapixConfig(QNetworkAccessManager *networkAccessManager, QObject *parent = nullptr);
~VapixConfig();
void init(const QString &ip, const QString &password, const QString &username);
bool setConfig(const QString &xmlString);
void getConfig();
void saveConfig(const QString &savePath);
void resetConfig();
void startRequests();
Q_SIGNALS:
void setConfigFinished();
void setConfigError(const QString &error);
void getConfigFinished(const QString &xmlString);
void getConfigError(const QString &error);
void requestsFinished();
private Q_SLOTS:
void startNextRequest();
void configError(const QString &error);
private:
QQueue<QString> m_requestQueue;
QNetworkAccessManager *m_networkAccessManager;
HTTPRequestHandler *m_requestHandler;
QString m_ip;
QString m_password;
QString m_username;
Config *m_config;
};
} // namespace VapixConfig