Commit 4c989f93 authored by Matej Frančeškin's avatar Matej Frančeškin

Microhard: Added settings panel similar to Taisync

parent 0c5919d3
......@@ -22,6 +22,7 @@ linux {
CONFIG += LinuxBuild
DEFINES += __STDC_LIMIT_MACROS
DEFINES += QGC_GST_TAISYNC_ENABLED
DEFINES += QGC_GST_MICROHARD_ENABLED
linux-clang {
message("Linux clang")
QMAKE_CXXFLAGS += -Qunused-arguments -fcolor-diagnostics
......@@ -31,12 +32,14 @@ linux {
CONFIG += LinuxBuild
DEFINES += __STDC_LIMIT_MACROS __rasp_pi2__
DEFINES += QGC_GST_TAISYNC_ENABLED
DEFINES += QGC_GST_MICROHARD_ENABLED
} else : android-g++ | android-clang {
CONFIG += AndroidBuild MobileBuild
DEFINES += __android__
DEFINES += __STDC_LIMIT_MACROS
DEFINES += QGC_ENABLE_BLUETOOTH
DEFINES += QGC_GST_TAISYNC_ENABLED
DEFINES += QGC_GST_MICROHARD_ENABLED
target.path = $$DESTDIR
equals(ANDROID_TARGET_ARCH, x86) {
CONFIG += Androidx86Build
......@@ -54,6 +57,7 @@ linux {
CONFIG += WindowsBuild
DEFINES += __STDC_LIMIT_MACROS
DEFINES += QGC_GST_TAISYNC_ENABLED
DEFINES += QGC_GST_MICROHARD_ENABLED
} else {
error("Unsupported Windows toolchain, only Visual Studio 2015 is supported")
}
......@@ -64,6 +68,7 @@ linux {
CONFIG += x86_64
CONFIG -= x86
DEFINES += QGC_GST_TAISYNC_ENABLED
DEFINES += QGC_GST_MICROHARD_ENABLED
equals(QT_MAJOR_VERSION, 5) | greaterThan(QT_MINOR_VERSION, 5) {
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
} else {
......
......@@ -1148,6 +1148,23 @@ contains (DEFINES, QGC_GST_TAISYNC_ENABLED) {
}
}
#-------------------------------------------------------------------------------------
# Microhard
contains (DEFINES, QGC_GST_MICROHARD_ENABLED) {
INCLUDEPATH += \
src/Microhard
HEADERS += \
src/Microhard/MicrohardManager.h \
src/Microhard/MicrohardHandler.h \
src/Microhard/MicrohardSettings.h \
SOURCES += \
src/Microhard/MicrohardManager.cc \
src/Microhard/MicrohardHandler.cc \
src/Microhard/MicrohardSettings.cc \
}
#-------------------------------------------------------------------------------------
# AirMap
......
......@@ -201,6 +201,7 @@
<file alias="SyslinkComponent.qml">src/AutoPilotPlugins/Common/SyslinkComponent.qml</file>
<file alias="TcpSettings.qml">src/ui/preferences/TcpSettings.qml</file>
<file alias="TaisyncSettings.qml">src/Taisync/TaisyncSettings.qml</file>
<file alias="MicrohardSettings.qml">src/Microhard/MicrohardSettings.qml</file>
<file alias="test.qml">src/test.qml</file>
<file alias="UdpSettings.qml">src/ui/preferences/UdpSettings.qml</file>
<file alias="ValuePageWidget.qml">src/FlightMap/Widgets/ValuePageWidget.qml</file>
......
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "MicrohardHandler.h"
#include "SettingsManager.h"
#include "QGCApplication.h"
#include "VideoManager.h"
QGC_LOGGING_CATEGORY(MicrohardLog, "MicrohardLog")
QGC_LOGGING_CATEGORY(MicrohardVerbose, "MicrohardVerbose")
//-----------------------------------------------------------------------------
MicrohardHandler::MicrohardHandler(QObject* parent)
: QObject (parent)
{
}
//-----------------------------------------------------------------------------
MicrohardHandler::~MicrohardHandler()
{
close();
}
//-----------------------------------------------------------------------------
bool MicrohardHandler::close()
{
bool res = (_tcpSocket || _tcpServer);
if(_tcpSocket) {
qCDebug(MicrohardLog) << "Close Microhard TCP socket on port" << _tcpSocket->localPort();
_tcpSocket->close();
_tcpSocket->deleteLater();
_tcpSocket = nullptr;
}
if(_tcpServer) {
qCDebug(MicrohardLog) << "Close Microhard TCP server on port" << _tcpServer->serverPort();;
_tcpServer->close();
_tcpServer->deleteLater();
_tcpServer = nullptr;
}
return res;
}
//-----------------------------------------------------------------------------
bool
MicrohardHandler::_start(uint16_t port, QHostAddress addr)
{
close();
_serverMode = addr == QHostAddress::AnyIPv4;
if(_serverMode) {
if(!_tcpServer) {
qCDebug(MicrohardLog) << "Listen for Microhard TCP on port" << port;
_tcpServer = new QTcpServer(this);
QObject::connect(_tcpServer, &QTcpServer::newConnection, this, &MicrohardHandler::_newConnection);
_tcpServer->listen(QHostAddress::AnyIPv4, port);
}
} else {
_tcpSocket = new QTcpSocket();
QObject::connect(_tcpSocket, &QIODevice::readyRead, this, &MicrohardHandler::_readBytes);
qCDebug(MicrohardLog) << "Connecting to" << addr;
_tcpSocket->connectToHost(addr, port);
if (!_tcpSocket->waitForConnected(1000)) {
close();
return false;
}
emit connected();
}
return true;
}
//-----------------------------------------------------------------------------
void
MicrohardHandler::_newConnection()
{
qCDebug(MicrohardLog) << "New Microhard TCP Connection on port" << _tcpServer->serverPort();
if(_tcpSocket) {
_tcpSocket->close();
_tcpSocket->deleteLater();
}
_tcpSocket = _tcpServer->nextPendingConnection();
if(_tcpSocket) {
QObject::connect(_tcpSocket, &QIODevice::readyRead, this, &MicrohardHandler::_readBytes);
QObject::connect(_tcpSocket, &QAbstractSocket::disconnected, this, &MicrohardHandler::_socketDisconnected);
emit connected();
} else {
qCWarning(MicrohardLog) << "New Microhard TCP Connection provided no socket";
}
}
//-----------------------------------------------------------------------------
void
MicrohardHandler::_socketDisconnected()
{
qCDebug(MicrohardLog) << "Microhard TCP Connection Closed on port" << _tcpSocket->localPort();
if(_tcpSocket) {
_tcpSocket->close();
_tcpSocket->deleteLater();
_tcpSocket = nullptr;
}
emit disconnected();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "QGCLoggingCategory.h"
#include <QTcpServer>
#include <QTcpSocket>
#define MICROHARD_SETTINGS_PORT 23
Q_DECLARE_LOGGING_CATEGORY(MicrohardLog)
Q_DECLARE_LOGGING_CATEGORY(MicrohardVerbose)
class MicrohardHandler : public QObject
{
Q_OBJECT
public:
explicit MicrohardHandler (QObject* parent = nullptr);
~MicrohardHandler ();
virtual bool start () = 0;
virtual bool close ();
virtual bool isServerRunning () { return (_serverMode && _tcpServer); }
protected:
virtual bool _start (uint16_t port, QHostAddress addr = QHostAddress::AnyIPv4);
protected slots:
virtual void _newConnection ();
virtual void _socketDisconnected ();
virtual void _readBytes () = 0;
signals:
void connected ();
void disconnected ();
protected:
bool _serverMode = true;
QTcpServer* _tcpServer = nullptr;
QTcpSocket* _tcpSocket = nullptr;
};
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "MicrohardManager.h"
#include "MicrohardHandler.h"
#include "SettingsManager.h"
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
#include "VideoManager.h"
#include <QSettings>
static const char *kMICROHARD_GROUP = "Microhard";
static const char *kRADIO_MODE = "RadioMode";
static const char *kRADIO_CHANNEL = "RadioChannel";
static const char *kVIDEO_OUTPUT = "VideoOutput";
static const char *kVIDEO_MODE = "VideoMode";
static const char *kVIDEO_RATE = "VideoRate";
static const char *kLOCAL_IP = "LocalIP";
static const char *kREMOTE_IP = "RemoteIP";
static const char *kNET_MASK = "NetMask";
static const char *kRTSP_URI = "RTSPURI";
static const char *kRTSP_ACCOUNT = "RTSPAccount";
static const char *kRTSP_PASSWORD = "RTSPPassword";
//-----------------------------------------------------------------------------
MicrohardManager::MicrohardManager(QGCApplication* app, QGCToolbox* toolbox)
: QGCTool(app, toolbox)
{
connect(&_workTimer, &QTimer::timeout, this, &MicrohardManager::_checkMicrohard);
_workTimer.setSingleShot(true);
QSettings settings;
settings.beginGroup(kMICROHARD_GROUP);
_localIPAddr = settings.value(kLOCAL_IP, QString("192.168.199.33")).toString();
_remoteIPAddr = settings.value(kREMOTE_IP, QString("192.168.199.16")).toString();
_netMask = settings.value(kNET_MASK, QString("255.255.255.0")).toString();
_rtspURI = settings.value(kRTSP_URI, QString("rtsp://192.168.0.2")).toString();
_rtspAccount = settings.value(kRTSP_ACCOUNT, QString("admin")).toString();
_rtspPassword = settings.value(kRTSP_PASSWORD, QString("12345678")).toString();
settings.endGroup();
}
//-----------------------------------------------------------------------------
MicrohardManager::~MicrohardManager()
{
_close();
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_close()
{
if(_mhSettings) {
_mhSettings->close();
_mhSettings->deleteLater();
_mhSettings = nullptr;
}
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_reset()
{
_close();
_isConnected = false;
emit connectedChanged();
_linkConnected = false;
emit linkConnectedChanged();
if(!_appSettings) {
_appSettings = _toolbox->settingsManager()->appSettings();
connect(_appSettings->enableMicrohard(), &Fact::rawValueChanged, this, &MicrohardManager::_setEnabled);
connect(_appSettings->enableMicrohardVideo(), &Fact::rawValueChanged, this, &MicrohardManager::_setVideoEnabled);
}
_setEnabled();
}
//-----------------------------------------------------------------------------
FactMetaData*
MicrohardManager::_createMetadata(const char* name, QStringList enums)
{
FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, name, this);
QQmlEngine::setObjectOwnership(metaData, QQmlEngine::CppOwnership);
metaData->setShortDescription(name);
metaData->setLongDescription(name);
metaData->setRawDefaultValue(QVariant(0));
metaData->setHasControl(true);
metaData->setReadOnly(false);
for(int i = 0; i < enums.size(); i++) {
metaData->addEnumInfo(enums[i], QVariant(i));
}
metaData->setRawMin(0);
metaData->setRawMin(enums.size() - 1);
return metaData;
}
//-----------------------------------------------------------------------------
void
MicrohardManager::setToolbox(QGCToolbox* toolbox)
{
QGCTool::setToolbox(toolbox);
{
//-- Radio Mode
QStringList enums;
enums.append(tr("Auto"));
enums.append(tr("Manual"));
FactMetaData* metaData = _createMetadata(kRADIO_MODE, enums);
_radioMode = new Fact(kMICROHARD_GROUP, metaData, this);
QQmlEngine::setObjectOwnership(_radioMode, QQmlEngine::CppOwnership);
_radioModeList.append("auto");
_radioModeList.append("manual");
connect(_radioMode, &Fact::_containerRawValueChanged, this, &MicrohardManager::_radioSettingsChanged);
}
{
//-- Radio Channel
QStringList enums;
for(int i = 0; i < 14; i++) {
enums.append(QString("ch%1").arg(i));
}
FactMetaData* metaData = _createMetadata(kRADIO_CHANNEL, enums);
_radioChannel = new Fact(kMICROHARD_GROUP, metaData, this);
QQmlEngine::setObjectOwnership(_radioChannel, QQmlEngine::CppOwnership);
connect(_radioChannel, &Fact::_containerRawValueChanged, this, &MicrohardManager::_radioSettingsChanged);
}
{
//-- Video Output
QStringList enums;
enums.append(tr("Stream"));
enums.append(tr("HDMI Port"));
FactMetaData* metaData = _createMetadata(kVIDEO_OUTPUT, enums);
_videoOutput = new Fact(kMICROHARD_GROUP, metaData, this);
QQmlEngine::setObjectOwnership(_videoOutput, QQmlEngine::CppOwnership);
_videoOutputList.append("phone");
_videoOutputList.append("hdmi");
connect(_videoOutput, &Fact::_containerRawValueChanged, this, &MicrohardManager::_videoSettingsChanged);
}
{
//-- Video Mode
QStringList enums;
enums.append("H264");
enums.append("H265");
FactMetaData* metaData = _createMetadata(kVIDEO_MODE, enums);
_videoMode = new Fact(kMICROHARD_GROUP, metaData, this);
QQmlEngine::setObjectOwnership(_videoMode, QQmlEngine::CppOwnership);
connect(_videoMode, &Fact::_containerRawValueChanged, this, &MicrohardManager::_videoSettingsChanged);
}
{
//-- Video Rate
QStringList enums;
enums.append(tr("Low"));
enums.append(tr("Medium"));
enums.append(tr("High"));
FactMetaData* metaData = _createMetadata(kVIDEO_RATE, enums);
_videoRate = new Fact(kMICROHARD_GROUP, metaData, this);
QQmlEngine::setObjectOwnership(_videoRate, QQmlEngine::CppOwnership);
_videoRateList.append("low");
_videoRateList.append("middle");
_videoRateList.append("high");
connect(_videoRate, &Fact::_containerRawValueChanged, this, &MicrohardManager::_videoSettingsChanged);
}
//-- Start it all
_reset();
}
//-----------------------------------------------------------------------------
bool
MicrohardManager::setRTSPSettings(QString uri, QString account, QString password)
{
if(_mhSettings && _isConnected) {
if(_mhSettings->setRTSPSettings(uri, account, password)) {
_rtspURI = uri;
_rtspAccount = account;
_rtspPassword = password;
QSettings settings;
settings.beginGroup(kMICROHARD_GROUP);
settings.setValue(kRTSP_URI, _rtspURI);
settings.setValue(kRTSP_ACCOUNT, _rtspAccount);
settings.setValue(kRTSP_PASSWORD, _rtspPassword);
settings.endGroup();
emit rtspURIChanged();
emit rtspAccountChanged();
emit rtspPasswordChanged();
_needReboot = true;
emit needRebootChanged();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
bool
MicrohardManager::setIPSettings(QString localIP_, QString remoteIP_, QString netMask_)
{
bool res = false;
if(_localIPAddr != localIP_ || _remoteIPAddr != remoteIP_ || _netMask != netMask_) {
//-- If we are connected to the Microhard
if(_isConnected) {
if(_mhSettings) {
//-- Change IP settings
res = _mhSettings->setIPSettings(localIP_, remoteIP_, netMask_);
if(res) {
_needReboot = true;
emit needRebootChanged();
}
}
} else {
//-- We're not connected. Record the change and restart.
_localIPAddr = localIP_;
_remoteIPAddr = remoteIP_;
_netMask = netMask_;
_reset();
res = true;
}
if(res) {
QSettings settings;
settings.beginGroup(kMICROHARD_GROUP);
settings.setValue(kLOCAL_IP, localIP_);
settings.setValue(kREMOTE_IP, remoteIP_);
settings.setValue(kNET_MASK, netMask_);
settings.endGroup();
}
} else {
//-- Nothing to change
res = true;
}
return res;
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_radioSettingsChanged(QVariant)
{
if(_mhSettings && _isConnected) {
_workTimer.stop();
_mhSettings->setRadioSettings(
_radioModeList[_radioMode->rawValue().toInt()],
_radioChannel->enumStringValue());
_reqMask |= REQ_RADIO_SETTINGS;
_workTimer.start(3000);
}
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_videoSettingsChanged(QVariant)
{
if(_mhSettings && _isConnected) {
_workTimer.stop();
_mhSettings->setVideoSettings(
_videoOutputList[_videoOutput->rawValue().toInt()],
_videoMode->enumStringValue(),
_videoRateList[_videoRate->rawValue().toInt()]);
_reqMask |= REQ_VIDEO_SETTINGS;
_workTimer.start(500);
}
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_setEnabled()
{
bool enable = _appSettings->enableMicrohard()->rawValue().toBool();
if(enable) {
if(!_mhSettings) {
_mhSettings = new MicrohardSettings(this);
connect(_mhSettings, &MicrohardSettings::updateSettings, this, &MicrohardManager::_updateSettings);
connect(_mhSettings, &MicrohardSettings::connected, this, &MicrohardManager::_connected);
connect(_mhSettings, &MicrohardSettings::disconnected, this, &MicrohardManager::_disconnected);
}
_reqMask = static_cast<uint32_t>(REQ_ALL);
_workTimer.start(1000);
} else {
//-- Stop everything
_workTimer.stop();
_close();
}
_enabled = enable;
//-- Now handle video support
_setVideoEnabled();
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_restoreVideoSettings(Fact* setting)
{
SettingsFact* pFact = dynamic_cast<SettingsFact*>(setting);
if(pFact) {
pFact->setVisible(qgcApp()->toolbox()->corePlugin()->adjustSettingMetaData(VideoSettings::settingsGroup, *setting->metaData()));
}
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_setVideoEnabled()
{
//-- Check both if video is enabled and Microhard support itself is enabled as well.
bool enable = _appSettings->enableMicrohardVideo()->rawValue().toBool() && _appSettings->enableMicrohard()->rawValue().toBool();
if(enable) {
//-- Set it up the way we need it do be.
VideoSettings* pVSettings = qgcApp()->toolbox()->settingsManager()->videoSettings();
pVSettings->setVisible(false);
pVSettings->udpPort()->setRawValue(5600);
//-- TODO: this AR must come from somewhere
pVSettings->aspectRatio()->setRawValue(1024.0 / 768.0);
pVSettings->videoSource()->setRawValue(QString(VideoSettings::videoSourceUDP));
} else {
//-- Restore video settings.
VideoSettings* pVSettings = qgcApp()->toolbox()->settingsManager()->videoSettings();
_restoreVideoSettings(pVSettings->videoSource());
_restoreVideoSettings(pVSettings->aspectRatio());
_restoreVideoSettings(pVSettings->udpPort());
pVSettings->setVisible(true);
}
_enableVideo = enable;
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_connected()
{
qCDebug(MicrohardLog) << "Microhard Settings Connected";
_isConnected = true;
emit connectedChanged();
_needReboot = false;
emit needRebootChanged();
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_disconnected()
{
qCDebug(MicrohardLog) << "Microhard Settings Disconnected";
_isConnected = false;
emit connectedChanged();
_needReboot = false;
emit needRebootChanged();
_linkConnected = false;
emit linkConnectedChanged();
_reset();
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_checkMicrohard()
{
if(_enabled) {
if(!_isConnected) {
if(_mhSettings) {
if(!_mhSettings->isServerRunning()) {
_mhSettings->start();
}
}
} else {
//qCDebug(MicrohardVerbose) << bin << _reqMask;
while(true) {
if (_reqMask & REQ_LINK_STATUS) {
_mhSettings->requestLinkStatus();
break;
}
if (_reqMask & REQ_DEV_INFO) {
_mhSettings->requestDevInfo();
break;
}
if (_reqMask & REQ_FREQ_SCAN) {
_reqMask &= ~static_cast<uint32_t>(REQ_FREQ_SCAN);
_mhSettings->requestFreqScan();
break;
}
if (_reqMask & REQ_VIDEO_SETTINGS) {
_mhSettings->requestVideoSettings();
break;
}
if (_reqMask & REQ_RADIO_SETTINGS) {
_mhSettings->requestRadioSettings();
break;
}
if (_reqMask & REQ_RTSP_SETTINGS) {
_reqMask &= ~static_cast<uint32_t>(REQ_RTSP_SETTINGS);
_mhSettings->requestRTSPURISettings();
break;
}
if (_reqMask & REQ_IP_SETTINGS) {
_reqMask &= ~static_cast<uint32_t>(REQ_IP_SETTINGS);
_mhSettings->requestIPSettings();
break;
}
//-- Check link status
if(_timeoutTimer.elapsed() > 3000) {
//-- Give up and restart
_disconnected();
break;
}
//-- If it's been too long since we last heard, ping it.
if(_timeoutTimer.elapsed() > 1000) {
_mhSettings->requestLinkStatus();
break;
}
break;
}
}
_workTimer.start(_isConnected ? 500 : 5000);
}
}
//-----------------------------------------------------------------------------
void
MicrohardManager::_updateSettings(QByteArray jSonData)
{
_timeoutTimer.start();
qCDebug(MicrohardVerbose) << jSonData;
QJsonParseError jsonParseError;
QJsonDocument doc = QJsonDocument::fromJson(jSonData, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
qWarning() << "Unable to parse Microhard response:" << jsonParseError.errorString() << jsonParseError.offset;
return;
}
QJsonObject jObj = doc.object();
//-- Link Status?
if(jSonData.contains("\"flight\":")) {
_reqMask &= ~static_cast<uint32_t>(REQ_LINK_STATUS);
bool tlinkConnected = jObj["flight"].toString("") == "online";
if(tlinkConnected != _linkConnected) {
_linkConnected = tlinkConnected;
emit linkConnectedChanged();
}
QString tlinkVidFormat = jObj["videoformat"].toString(_linkVidFormat);
int tdownlinkRSSI = jObj["radiorssi"].toInt(_downlinkRSSI);
int tuplinkRSSI = jObj["hdrssi"].toInt(_uplinkRSSI);
if(_linkVidFormat != tlinkVidFormat || _downlinkRSSI != tdownlinkRSSI || _uplinkRSSI != tuplinkRSSI) {
_linkVidFormat = tlinkVidFormat;
_downlinkRSSI = tdownlinkRSSI;
_uplinkRSSI = tuplinkRSSI;
emit linkChanged();
}
//-- Device Info?
} else if(jSonData.contains("\"firmwareversion\":")) {
_reqMask &= ~static_cast<uint32_t>(REQ_DEV_INFO);
QString tfwVersion = jObj["firmwareversion"].toString(_fwVersion);
QString tserialNumber = jObj["sn"].toString(_serialNumber);
if(tfwVersion != _fwVersion || tserialNumber != _serialNumber) {
_fwVersion = tfwVersion;
_serialNumber = tserialNumber;
emit infoChanged();
}
//-- Radio Settings?
} else if(jSonData.contains("\"freq\":")) {
_reqMask &= ~static_cast<uint32_t>(REQ_RADIO_SETTINGS);
int idx = _radioModeList.indexOf(jObj["mode"].toString(_radioMode->enumStringValue()));
if(idx >= 0) _radioMode->_containerSetRawValue(idx);
idx = _radioChannel->valueIndex(jObj["freq"].toString(_radioChannel->enumStringValue()));
if(idx < 0) idx = 0;
_radioChannel->_containerSetRawValue(idx);
//-- Video Settings?
} else if(jSonData.contains("\"maxbitrate\":")) {
_reqMask &= ~static_cast<uint32_t>(REQ_VIDEO_SETTINGS);
int idx;
idx = _videoMode->valueIndex(jObj["mode"].toString(_videoMode->enumStringValue()));
if(idx < 0) idx = 0;
_videoMode->_containerSetRawValue(idx);
idx = _videoRateList.indexOf(jObj["maxbitrate"].toString(_videoMode->enumStringValue()));
if(idx >= 0) _videoRate->_containerSetRawValue(idx);
idx = _videoOutputList.indexOf(jObj["decode"].toString(_videoOutput->enumStringValue()));
if(idx >= 0) _videoOutput->_containerSetRawValue(idx);
//-- IP Address Settings?
} else if(jSonData.contains("\"usbEthIp\":")) {
QString value;
bool changed = false;
value = jObj["ipaddr"].toString(_localIPAddr);
if(value != _localIPAddr) {
_localIPAddr = value;
changed = true;
emit localIPAddrChanged();
}
value = jObj["netmask"].toString(_netMask);
if(value != _netMask) {
_netMask = value;
changed = true;
emit netMaskChanged();
}
value = jObj["usbEthIp"].toString(_remoteIPAddr);
if(value != _remoteIPAddr) {