Initial structure
This commit is contained in:
commit
d6db317347
73
.gitignore
vendored
Normal file
73
.gitignore
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
28
libnymea-networkmanager/dbus-interfaces.h
Normal file
28
libnymea-networkmanager/dbus-interfaces.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef DBUSINTERFACES_H
|
||||||
|
#define DBUSINTERFACES_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
static const QString networkManagerServiceString("org.freedesktop.NetworkManager");
|
||||||
|
|
||||||
|
static const QString networkManagerPathString("/org/freedesktop/NetworkManager");
|
||||||
|
static const QString settingsPathString("/org/freedesktop/NetworkManager/Settings");
|
||||||
|
|
||||||
|
static const QString deviceInterfaceString("org.freedesktop.NetworkManager.Device");
|
||||||
|
static const QString wirelessInterfaceString("org.freedesktop.NetworkManager.Device.Wireless");
|
||||||
|
static const QString wiredInterfaceString("org.freedesktop.NetworkManager.Device.Wired");
|
||||||
|
static const QString accessPointInterfaceString("org.freedesktop.NetworkManager.AccessPoint");
|
||||||
|
static const QString settingsInterfaceString("org.freedesktop.NetworkManager.Settings");
|
||||||
|
static const QString connectionsInterfaceString("org.freedesktop.NetworkManager.Settings.Connection");
|
||||||
|
|
||||||
|
#endif // DBUSINTERFACES_H
|
||||||
38
libnymea-networkmanager/libnymea-networkmanager.pro
Normal file
38
libnymea-networkmanager/libnymea-networkmanager.pro
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
TARGET = nymea-networkmanager1
|
||||||
|
TEMPLATE = lib
|
||||||
|
|
||||||
|
target.path = /usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')
|
||||||
|
INSTALLS += target
|
||||||
|
|
||||||
|
QT += dbus network
|
||||||
|
|
||||||
|
QMAKE_CXXFLAGS += -Werror -std=c++11
|
||||||
|
QMAKE_LFLAGS += -std=c++11
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
networkmanager.h \
|
||||||
|
dbus-interfaces.h \
|
||||||
|
networkconnection.h \
|
||||||
|
networkdevice.h \
|
||||||
|
networksettings.h \
|
||||||
|
wirednetworkdevice.h \
|
||||||
|
wirelessaccesspoint.h \
|
||||||
|
wirelessnetworkdevice.h \
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
networkmanager.cpp \
|
||||||
|
networkconnection.cpp \
|
||||||
|
networkdevice.cpp \
|
||||||
|
networksettings.cpp \
|
||||||
|
wirednetworkdevice.cpp \
|
||||||
|
wirelessaccesspoint.cpp \
|
||||||
|
wirelessnetworkdevice.cpp \
|
||||||
|
|
||||||
|
|
||||||
|
# install header file with relative subdirectory
|
||||||
|
for(header, HEADERS) {
|
||||||
|
path = /usr/include/libnymea-networkmanager/$${dirname(header)}
|
||||||
|
eval(headers_$${path}.files += $${header})
|
||||||
|
eval(headers_$${path}.path = $${path})
|
||||||
|
eval(INSTALLS *= headers_$${path})
|
||||||
|
}
|
||||||
115
libnymea-networkmanager/networkconnection.cpp
Normal file
115
libnymea-networkmanager/networkconnection.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "networkconnection.h"
|
||||||
|
#include "dbus-interfaces.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{NetworkConnection} with the given dbus \a objectPath and \a parent. */
|
||||||
|
NetworkConnection::NetworkConnection(const QDBusObjectPath &objectPath, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_objectPath(objectPath)
|
||||||
|
{
|
||||||
|
qDBusRegisterMetaType<ConnectionSettings>();
|
||||||
|
|
||||||
|
m_connectionInterface = new QDBusInterface(networkManagerServiceString, m_objectPath.path(), connectionsInterfaceString, QDBusConnection::systemBus(), this);
|
||||||
|
if(!m_connectionInterface->isValid()) {
|
||||||
|
qWarning() << "Invalid connection dbus interface";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusMessage query = m_connectionInterface->call("GetSettings");
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.arguments().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QDBusArgument &argument = query.arguments().at(0).value<QDBusArgument>();
|
||||||
|
m_connectionSettings = qdbus_cast<ConnectionSettings>(argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Delets this \l{NetworkConnection} in the \l{NetworkManager}. */
|
||||||
|
void NetworkConnection::deleteConnection()
|
||||||
|
{
|
||||||
|
QDBusMessage query = m_connectionInterface->call("Delete");
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage)
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the dbus object path of this \l{NetworkConnection}. */
|
||||||
|
QDBusObjectPath NetworkConnection::objectPath() const
|
||||||
|
{
|
||||||
|
return m_objectPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the connection settings of this \l{NetworkConnection}. */
|
||||||
|
ConnectionSettings NetworkConnection::connectionSettings() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the id of this \l{NetworkConnection}. */
|
||||||
|
QString NetworkConnection::id() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings.value("connection").value("id").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the name of this \l{NetworkConnection}. */
|
||||||
|
QString NetworkConnection::name() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings.value("connection").value("name").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the type of this \l{NetworkConnection}. */
|
||||||
|
QString NetworkConnection::type() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings.value("connection").value("type").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the uuid of this \l{NetworkConnection}. */
|
||||||
|
QUuid NetworkConnection::uuid() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings.value("connection").value("uuid").toUuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the interface name of this \l{NetworkConnection}. */
|
||||||
|
QString NetworkConnection::interfaceName() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings.value("connection").value("interface-name").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if this \l{NetworkConnection} will autoconnect if available. */
|
||||||
|
bool NetworkConnection::autoconnect() const
|
||||||
|
{
|
||||||
|
return m_connectionSettings.value("connection").value("autoconnect").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the timestamp of this \l{NetworkConnection} from the last connection. */
|
||||||
|
QDateTime NetworkConnection::timeStamp() const
|
||||||
|
{
|
||||||
|
return QDateTime::fromTime_t(m_connectionSettings.value("connection").value("timestamp").toUInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, NetworkConnection *networkConnection)
|
||||||
|
{
|
||||||
|
debug.nospace() << "NetworkConnection(" << networkConnection->id() << ", ";
|
||||||
|
debug.nospace() << networkConnection->uuid().toString() << ", ";
|
||||||
|
debug.nospace() << networkConnection->interfaceName() << ", ";
|
||||||
|
debug.nospace() << networkConnection->type() << ", ";
|
||||||
|
debug.nospace() << networkConnection->timeStamp().toString("dd.MM.yyyy hh:mm") << ") ";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
56
libnymea-networkmanager/networkconnection.h
Normal file
56
libnymea-networkmanager/networkconnection.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef NETWORKCONNECTION_H
|
||||||
|
#define NETWORKCONNECTION_H
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDBusMetaType>
|
||||||
|
#include <QDBusObjectPath>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
|
||||||
|
typedef QMap<QString, QVariantMap> ConnectionSettings;
|
||||||
|
|
||||||
|
class NetworkConnection : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit NetworkConnection(const QDBusObjectPath &objectPath, QObject *parent = 0);
|
||||||
|
|
||||||
|
void deleteConnection();
|
||||||
|
|
||||||
|
QDBusObjectPath objectPath() const;
|
||||||
|
ConnectionSettings connectionSettings() const;
|
||||||
|
|
||||||
|
QString id() const;
|
||||||
|
QString name() const;
|
||||||
|
QString type() const;
|
||||||
|
QUuid uuid() const;
|
||||||
|
QString interfaceName() const;
|
||||||
|
bool autoconnect() const;
|
||||||
|
QDateTime timeStamp() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusObjectPath m_objectPath;
|
||||||
|
QDBusInterface *m_connectionInterface;
|
||||||
|
|
||||||
|
ConnectionSettings m_connectionSettings;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, NetworkConnection *networkConnection);
|
||||||
|
|
||||||
|
#endif // NETWORKCONNECTION_H
|
||||||
330
libnymea-networkmanager/networkdevice.cpp
Normal file
330
libnymea-networkmanager/networkdevice.cpp
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/*! \enum guhserver::NetworkDevice::NetworkDeviceState
|
||||||
|
\value NetworkDeviceStateUnknown
|
||||||
|
\value NetworkDeviceStateUnmanaged
|
||||||
|
\value NetworkDeviceStateUnavailable
|
||||||
|
\value NetworkDeviceStateDisconnected
|
||||||
|
\value NetworkDeviceStatePrepare
|
||||||
|
\value NetworkDeviceStateConfig
|
||||||
|
\value NetworkDeviceStateNeedAuth
|
||||||
|
\value NetworkDeviceStateIpConfig
|
||||||
|
\value NetworkDeviceStateIpCheck
|
||||||
|
\value NetworkDeviceStateSecondaries
|
||||||
|
\value NetworkDeviceStateActivated
|
||||||
|
\value NetworkDeviceStateDeactivating
|
||||||
|
\value NetworkDeviceStateFailed
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \enum guhserver::NetworkDevice::NetworkDeviceStateReason
|
||||||
|
\value NetworkDeviceStateReasonNone
|
||||||
|
\value NetworkDeviceStateReasonUnknown
|
||||||
|
\value NetworkDeviceStateReasonNowManaged
|
||||||
|
\value NetworkDeviceStateReasonNowUnmanaged
|
||||||
|
\value NetworkDeviceStateReasonConfigFailed
|
||||||
|
\value NetworkDeviceStateReasonIpConfigUnavailable
|
||||||
|
\value NetworkDeviceStateReasonIpConfigExpired
|
||||||
|
\value NetworkDeviceStateReasonNoSecrets
|
||||||
|
\value NetworkDeviceStateReasonSupplicantDisconnected
|
||||||
|
\value NetworkDeviceStateReasonSupplicantConfigFailed
|
||||||
|
\value NetworkDeviceStateReasonSupplicantFailed
|
||||||
|
\value NetworkDeviceStateReasonSupplicantTimeout
|
||||||
|
\value NetworkDeviceStateReasonPppStartFailed
|
||||||
|
\value NetworkDeviceStateReasonPppDisconnected
|
||||||
|
\value NetworkDeviceStateReasonPppFailed
|
||||||
|
\value NetworkDeviceStateReasonDhcpStartFailed
|
||||||
|
\value NetworkDeviceStateReasonDhcpError
|
||||||
|
\value NetworkDeviceStateReasonDhcpFailed
|
||||||
|
\value NetworkDeviceStateReasonSharedStartFailed
|
||||||
|
\value NetworkDeviceStateReasonSharedFailed
|
||||||
|
\value NetworkDeviceStateReasonAutoIpStartFailed
|
||||||
|
\value NetworkDeviceStateReasonAutoIpError
|
||||||
|
\value NetworkDeviceStateReasonAutoIpFailed
|
||||||
|
\value NetworkDeviceStateReasonModemBusy
|
||||||
|
\value NetworkDeviceStateReasonModemNoDialTone
|
||||||
|
\value NetworkDeviceStateReasonModemNoCarrier
|
||||||
|
\value NetworkDeviceStateReasonModemDialTimeout
|
||||||
|
\value NetworkDeviceStateReasonModemDialFailed
|
||||||
|
\value NetworkDeviceStateReasonModemInitFailed
|
||||||
|
\value NetworkDeviceStateReasonGsmApnFailed
|
||||||
|
\value NetworkDeviceStateReasonGsmRegistrationNotSearching
|
||||||
|
\value NetworkDeviceStateReasonGsmRegistrationDenied
|
||||||
|
\value NetworkDeviceStateReasonGsmRegistrationTimeout
|
||||||
|
\value NetworkDeviceStateReasonGsmRegistrationFailed
|
||||||
|
\value NetworkDeviceStateReasonGsmPinCheckFailed
|
||||||
|
\value NetworkDeviceStateReasonFirmwareMissing
|
||||||
|
\value NetworkDeviceStateReasonRemoved
|
||||||
|
\value NetworkDeviceStateReasonSleeping
|
||||||
|
\value NetworkDeviceStateReasonConnectionRemoved
|
||||||
|
\value NetworkDeviceStateReasonUserRequest
|
||||||
|
\value NetworkDeviceStateReasonCarrier
|
||||||
|
\value NetworkDeviceStateReasonConnectionAssumed
|
||||||
|
\value NetworkDeviceStateReasonSupplicantAvailable
|
||||||
|
\value NetworkDeviceStateReasonModemNotFound
|
||||||
|
\value NetworkDeviceStateReasonBtFailed
|
||||||
|
\value NetworkDeviceStateReasonGsmSimNotInserted
|
||||||
|
\value NetworkDeviceStateReasonGsmSimPinRequired
|
||||||
|
\value NetworkDeviceStateReasonGsmSimPukRequired
|
||||||
|
\value NetworkDeviceStateReasonGsmSimWrong
|
||||||
|
\value NetworkDeviceStateReasonInfinibandMode
|
||||||
|
\value NetworkDeviceStateReasonDependencyFailed
|
||||||
|
\value NetworkDeviceStateReasonBR2684Failed
|
||||||
|
\value NetworkDeviceStateReasonModemManagerUnavailable
|
||||||
|
\value NetworkDeviceStateReasonSsidNotFound
|
||||||
|
\value NetworkDeviceStateReasonSecondaryConnectionFailed
|
||||||
|
\value NetworkDeviceStateReasonDcbFoecFailed
|
||||||
|
\value NetworkDeviceStateReasonTeamdControlFailed
|
||||||
|
\value NetworkDeviceStateReasonModemFailed
|
||||||
|
\value NetworkDeviceStateReasonModemAvailable
|
||||||
|
\value NetworkDeviceStateReasonSimPinIncorrect
|
||||||
|
\value NetworkDeviceStateReasonNewActivision
|
||||||
|
\value NetworkDeviceStateReasonParentChanged
|
||||||
|
\value NetworkDeviceStateReasonParentManagedChanged
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*! \enum guhserver::NetworkDevice::NetworkDeviceType
|
||||||
|
\value NetworkDeviceTypeUnknown
|
||||||
|
\value NetworkDeviceTypeEthernet
|
||||||
|
\value NetworkDeviceTypeWifi
|
||||||
|
\value NetworkDeviceTypeBluetooth
|
||||||
|
\value NetworkDeviceTypeOlpcMesh
|
||||||
|
\value NetworkDeviceTypeWiMax
|
||||||
|
\value NetworkDeviceTypeModem
|
||||||
|
\value NetworkDeviceTypeInfiniBand
|
||||||
|
\value NetworkDeviceTypeBond
|
||||||
|
\value NetworkDeviceTypeVLan
|
||||||
|
\value NetworkDeviceTypeAdsl
|
||||||
|
\value NetworkDeviceTypeBridge
|
||||||
|
\value NetworkDeviceTypeGeneric
|
||||||
|
\value NetworkDeviceTypeTeam
|
||||||
|
\value NetworkDeviceTypeTun
|
||||||
|
\value NetworkDeviceTypeIpTunnel
|
||||||
|
\value NetworkDeviceTypeMacVLan
|
||||||
|
\value NetworkDeviceTypeVXLan
|
||||||
|
\value NetworkDeviceTypeVEth
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*! \fn void NetworkDevice::deviceChanged();
|
||||||
|
This signal will be emitted when the properties of this \l{NetworkDevice} have changed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "networkdevice.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{NetworkDevice} with the given dbus \a objectPath and \a parent. */
|
||||||
|
NetworkDevice::NetworkDevice(const QDBusObjectPath &objectPath, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_objectPath(objectPath),
|
||||||
|
m_mtu(0),
|
||||||
|
m_metered(0),
|
||||||
|
m_deviceState(NetworkDeviceStateUnknown),
|
||||||
|
m_deviceStateReason(NetworkDeviceStateReasonUnknown)
|
||||||
|
{
|
||||||
|
QDBusConnection systemBus = QDBusConnection::systemBus();
|
||||||
|
if (!systemBus.isConnected()) {
|
||||||
|
qWarning() << "NetworkDevice: System DBus not connected";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_networkDeviceInterface = new QDBusInterface(networkManagerServiceString, m_objectPath.path(), deviceInterfaceString, QDBusConnection::systemBus(), this);
|
||||||
|
if(!m_networkDeviceInterface->isValid()) {
|
||||||
|
qWarning() << "NetworkDevice: Invalid DBus device interface" << m_objectPath.path();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_udi = m_networkDeviceInterface->property("Udi").toString();
|
||||||
|
m_interface = m_networkDeviceInterface->property("Interface").toString();
|
||||||
|
m_ipInterface = m_networkDeviceInterface->property("IpInterface").toString();
|
||||||
|
m_driver = m_networkDeviceInterface->property("Driver").toString();
|
||||||
|
m_driverVersion = m_networkDeviceInterface->property("DriverVersion").toString();
|
||||||
|
m_firmwareVersion = m_networkDeviceInterface->property("FirmwareVersion").toString();
|
||||||
|
m_physicalPortId = m_networkDeviceInterface->property("PhysicalPortId").toString();
|
||||||
|
m_mtu = m_networkDeviceInterface->property("Mtu").toUInt();
|
||||||
|
m_metered = m_networkDeviceInterface->property("Metered").toUInt();
|
||||||
|
m_autoconnect = m_networkDeviceInterface->property("Autoconnect").toBool();
|
||||||
|
|
||||||
|
m_deviceState = NetworkDeviceState(m_networkDeviceInterface->property("State").toUInt());
|
||||||
|
m_deviceType = NetworkDeviceType(m_networkDeviceInterface->property("DeviceType").toUInt());
|
||||||
|
|
||||||
|
m_activeConnection = qdbus_cast<QDBusObjectPath>(m_networkDeviceInterface->property("ActiveConnection"));
|
||||||
|
m_ip4Config = qdbus_cast<QDBusObjectPath>(m_networkDeviceInterface->property("Ip4Config"));
|
||||||
|
m_ip6Config = qdbus_cast<QDBusObjectPath>(m_networkDeviceInterface->property("Ip6Config"));
|
||||||
|
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, m_objectPath.path(), deviceInterfaceString, "StateChanged", this, SLOT(onStateChanged(uint,uint,uint)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the dbus object path of this \l{NetworkDevice}. */
|
||||||
|
QDBusObjectPath NetworkDevice::objectPath() const
|
||||||
|
{
|
||||||
|
return m_objectPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the udi of this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::udi() const
|
||||||
|
{
|
||||||
|
return m_udi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the interface name of this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::interface() const
|
||||||
|
{
|
||||||
|
return m_interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the ip interface of this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::ipInterface() const
|
||||||
|
{
|
||||||
|
return m_ipInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the used driver name for this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::driver() const
|
||||||
|
{
|
||||||
|
return m_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the version of the used driver for this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::driverVersion() const
|
||||||
|
{
|
||||||
|
return m_driverVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the firmware version of this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::firmwareVersion() const
|
||||||
|
{
|
||||||
|
return m_firmwareVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the physical port id of this \l{NetworkDevice}. */
|
||||||
|
QString NetworkDevice::physicalPortId() const
|
||||||
|
{
|
||||||
|
return m_physicalPortId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the mtu of this \l{NetworkDevice}. */
|
||||||
|
uint NetworkDevice::mtu() const
|
||||||
|
{
|
||||||
|
return m_mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the metered property of this \l{NetworkDevice}. */
|
||||||
|
uint NetworkDevice::metered() const
|
||||||
|
{
|
||||||
|
return m_metered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if autoconnect is enabled for this \l{NetworkDevice}. */
|
||||||
|
bool NetworkDevice::autoconnect() const
|
||||||
|
{
|
||||||
|
return m_autoconnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the device state of this \l{NetworkDevice}. \sa NetworkDeviceState, */
|
||||||
|
NetworkDevice::NetworkDeviceState NetworkDevice::deviceState() const
|
||||||
|
{
|
||||||
|
return m_deviceState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the human readable device state of this \l{NetworkDevice}. \sa NetworkDeviceState, */
|
||||||
|
QString NetworkDevice::deviceStateString() const
|
||||||
|
{
|
||||||
|
return NetworkDevice::deviceStateToString(m_deviceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the reason for the current state of this \l{NetworkDevice}. \sa NetworkDeviceStateReason, */
|
||||||
|
NetworkDevice::NetworkDeviceStateReason NetworkDevice::deviceStateReason() const
|
||||||
|
{
|
||||||
|
return m_deviceStateReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the device type of this \l{NetworkDevice}. \sa NetworkDeviceType, */
|
||||||
|
NetworkDevice::NetworkDeviceType NetworkDevice::deviceType() const
|
||||||
|
{
|
||||||
|
return m_deviceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the dbus object path of the currently active connection of this \l{NetworkDevice}. */
|
||||||
|
QDBusObjectPath NetworkDevice::activeConnection() const
|
||||||
|
{
|
||||||
|
return m_activeConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the dbus object path from the IPv4 configuration of this \l{NetworkDevice}. */
|
||||||
|
QDBusObjectPath NetworkDevice::ip4Config() const
|
||||||
|
{
|
||||||
|
return m_ip4Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the list of dbus object paths for the currently available connection of this \l{NetworkDevice}. */
|
||||||
|
QList<QDBusObjectPath> NetworkDevice::availableConnections() const
|
||||||
|
{
|
||||||
|
return m_availableConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Disconnect the current connection from this \l{NetworkDevice}. */
|
||||||
|
void NetworkDevice::disconnectDevice()
|
||||||
|
{
|
||||||
|
QDBusMessage query = m_networkDeviceInterface->call("Disconnect");
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage)
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the human readable device type string of the given \a deviceType. \sa NetworkDeviceType, */
|
||||||
|
QString NetworkDevice::deviceTypeToString(const NetworkDevice::NetworkDeviceType &deviceType)
|
||||||
|
{
|
||||||
|
QMetaObject metaObject = NetworkDevice::staticMetaObject;
|
||||||
|
int enumIndex = metaObject.indexOfEnumerator(QString("NetworkDeviceType").toLatin1().data());
|
||||||
|
QMetaEnum metaEnum = metaObject.enumerator(enumIndex);
|
||||||
|
return QString(metaEnum.valueToKey(deviceType)).remove("NetworkDeviceType");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the human readable device state string of the given \a deviceState. \sa NetworkDeviceState, */
|
||||||
|
QString NetworkDevice::deviceStateToString(const NetworkDevice::NetworkDeviceState &deviceState)
|
||||||
|
{
|
||||||
|
QMetaObject metaObject = NetworkDevice::staticMetaObject;
|
||||||
|
int enumIndex = metaObject.indexOfEnumerator(QString("NetworkDeviceState").toLatin1().data());
|
||||||
|
QMetaEnum metaEnum = metaObject.enumerator(enumIndex);
|
||||||
|
return QString(metaEnum.valueToKey(deviceState));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the human readable device state reason string of the given \a deviceStateReason. \sa NetworkDeviceStateReason, */
|
||||||
|
QString NetworkDevice::deviceStateReasonToString(const NetworkDevice::NetworkDeviceStateReason &deviceStateReason)
|
||||||
|
{
|
||||||
|
QMetaObject metaObject = NetworkDevice::staticMetaObject;
|
||||||
|
int enumIndex = metaObject.indexOfEnumerator(QString("NetworkDeviceStateReason").toLatin1().data());
|
||||||
|
QMetaEnum metaEnum = metaObject.enumerator(enumIndex);
|
||||||
|
return QString(metaEnum.valueToKey(deviceStateReason));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkDevice::onStateChanged(uint newState, uint oldState, uint reason)
|
||||||
|
{
|
||||||
|
Q_UNUSED(oldState);
|
||||||
|
qDebug() << m_interface << "--> State changed:" << deviceStateToString(NetworkDeviceState(newState)) << ":" << deviceStateReasonToString(NetworkDeviceStateReason(reason));
|
||||||
|
if (m_deviceState != NetworkDeviceState(newState)) {
|
||||||
|
m_deviceState = NetworkDeviceState(newState);
|
||||||
|
emit deviceChanged();
|
||||||
|
emit stateChanged(m_deviceState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, NetworkDevice *device)
|
||||||
|
{
|
||||||
|
debug.nospace() << "NetworkDevice(" << device->interface() << " - " << NetworkDevice::deviceTypeToString(device->deviceType()) << ", " << device->deviceStateString() << ")";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
|
||||||
206
libnymea-networkmanager/networkdevice.h
Normal file
206
libnymea-networkmanager/networkdevice.h
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef NETWORKDEVICE_H
|
||||||
|
#define NETWORKDEVICE_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusMessage>
|
||||||
|
#include <QDBusContext>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
|
||||||
|
#include "dbus-interfaces.h"
|
||||||
|
|
||||||
|
class NetworkDevice : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_ENUMS(NetworkDeviceType)
|
||||||
|
Q_ENUMS(NetworkDeviceState)
|
||||||
|
Q_ENUMS(NetworkDeviceStateReason)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NetworkDeviceState {
|
||||||
|
NetworkDeviceStateUnknown = 0,
|
||||||
|
NetworkDeviceStateUnmanaged = 10,
|
||||||
|
NetworkDeviceStateUnavailable = 20,
|
||||||
|
NetworkDeviceStateDisconnected = 30,
|
||||||
|
NetworkDeviceStatePrepare = 40,
|
||||||
|
NetworkDeviceStateConfig = 50,
|
||||||
|
NetworkDeviceStateNeedAuth = 60,
|
||||||
|
NetworkDeviceStateIpConfig = 70,
|
||||||
|
NetworkDeviceStateIpCheck = 80,
|
||||||
|
NetworkDeviceStateSecondaries = 90,
|
||||||
|
NetworkDeviceStateActivated = 100,
|
||||||
|
NetworkDeviceStateDeactivating = 110,
|
||||||
|
NetworkDeviceStateFailed = 120
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NetworkDeviceStateReason {
|
||||||
|
NetworkDeviceStateReasonNone = 0,
|
||||||
|
NetworkDeviceStateReasonUnknown = 1,
|
||||||
|
NetworkDeviceStateReasonNowManaged = 2,
|
||||||
|
NetworkDeviceStateReasonNowUnmanaged = 3,
|
||||||
|
NetworkDeviceStateReasonConfigFailed = 4,
|
||||||
|
NetworkDeviceStateReasonIpConfigUnavailable = 5,
|
||||||
|
NetworkDeviceStateReasonIpConfigExpired = 6,
|
||||||
|
NetworkDeviceStateReasonNoSecrets = 7,
|
||||||
|
NetworkDeviceStateReasonSupplicantDisconnected = 8,
|
||||||
|
NetworkDeviceStateReasonSupplicantConfigFailed = 9,
|
||||||
|
NetworkDeviceStateReasonSupplicantFailed = 10,
|
||||||
|
NetworkDeviceStateReasonSupplicantTimeout = 11,
|
||||||
|
NetworkDeviceStateReasonPppStartFailed = 12,
|
||||||
|
NetworkDeviceStateReasonPppDisconnected = 13,
|
||||||
|
NetworkDeviceStateReasonPppFailed = 14,
|
||||||
|
NetworkDeviceStateReasonDhcpStartFailed = 15,
|
||||||
|
NetworkDeviceStateReasonDhcpError = 16,
|
||||||
|
NetworkDeviceStateReasonDhcpFailed = 17,
|
||||||
|
NetworkDeviceStateReasonSharedStartFailed = 18,
|
||||||
|
NetworkDeviceStateReasonSharedFailed = 19,
|
||||||
|
NetworkDeviceStateReasonAutoIpStartFailed = 20,
|
||||||
|
NetworkDeviceStateReasonAutoIpError = 21,
|
||||||
|
NetworkDeviceStateReasonAutoIpFailed = 22,
|
||||||
|
NetworkDeviceStateReasonModemBusy = 23,
|
||||||
|
NetworkDeviceStateReasonModemNoDialTone = 24,
|
||||||
|
NetworkDeviceStateReasonModemNoCarrier = 25,
|
||||||
|
NetworkDeviceStateReasonModemDialTimeout = 26,
|
||||||
|
NetworkDeviceStateReasonModemDialFailed = 27,
|
||||||
|
NetworkDeviceStateReasonModemInitFailed = 28,
|
||||||
|
NetworkDeviceStateReasonGsmApnFailed = 29,
|
||||||
|
NetworkDeviceStateReasonGsmRegistrationNotSearching = 30,
|
||||||
|
NetworkDeviceStateReasonGsmRegistrationDenied = 31,
|
||||||
|
NetworkDeviceStateReasonGsmRegistrationTimeout = 32,
|
||||||
|
NetworkDeviceStateReasonGsmRegistrationFailed = 33,
|
||||||
|
NetworkDeviceStateReasonGsmPinCheckFailed = 34,
|
||||||
|
NetworkDeviceStateReasonFirmwareMissing = 35,
|
||||||
|
NetworkDeviceStateReasonRemoved = 36,
|
||||||
|
NetworkDeviceStateReasonSleeping = 37,
|
||||||
|
NetworkDeviceStateReasonConnectionRemoved = 38,
|
||||||
|
NetworkDeviceStateReasonUserRequest = 39,
|
||||||
|
NetworkDeviceStateReasonCarrier = 40,
|
||||||
|
NetworkDeviceStateReasonConnectionAssumed = 41,
|
||||||
|
NetworkDeviceStateReasonSupplicantAvailable = 42,
|
||||||
|
NetworkDeviceStateReasonModemNotFound = 43,
|
||||||
|
NetworkDeviceStateReasonBtFailed = 44,
|
||||||
|
NetworkDeviceStateReasonGsmSimNotInserted = 45,
|
||||||
|
NetworkDeviceStateReasonGsmSimPinRequired = 46,
|
||||||
|
NetworkDeviceStateReasonGsmSimPukRequired = 47,
|
||||||
|
NetworkDeviceStateReasonGsmSimWrong = 48,
|
||||||
|
NetworkDeviceStateReasonInfinibandMode = 49,
|
||||||
|
NetworkDeviceStateReasonDependencyFailed = 50,
|
||||||
|
NetworkDeviceStateReasonBR2684Failed = 51,
|
||||||
|
NetworkDeviceStateReasonModemManagerUnavailable = 52,
|
||||||
|
NetworkDeviceStateReasonSsidNotFound = 53,
|
||||||
|
NetworkDeviceStateReasonSecondaryConnectionFailed = 54,
|
||||||
|
NetworkDeviceStateReasonDcbFoecFailed = 55,
|
||||||
|
NetworkDeviceStateReasonTeamdControlFailed = 56,
|
||||||
|
NetworkDeviceStateReasonModemFailed = 57,
|
||||||
|
NetworkDeviceStateReasonModemAvailable = 58,
|
||||||
|
NetworkDeviceStateReasonSimPinIncorrect = 59,
|
||||||
|
NetworkDeviceStateReasonNewActivision = 60,
|
||||||
|
NetworkDeviceStateReasonParentChanged = 61,
|
||||||
|
NetworkDeviceStateReasonParentManagedChanged = 62
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NetworkDeviceType {
|
||||||
|
NetworkDeviceTypeUnknown = 0,
|
||||||
|
NetworkDeviceTypeEthernet = 1,
|
||||||
|
NetworkDeviceTypeWifi = 2,
|
||||||
|
NetworkDeviceTypeBluetooth = 5,
|
||||||
|
NetworkDeviceTypeOlpcMesh = 6,
|
||||||
|
NetworkDeviceTypeWiMax = 7,
|
||||||
|
NetworkDeviceTypeModem = 8,
|
||||||
|
NetworkDeviceTypeInfiniBand = 9,
|
||||||
|
NetworkDeviceTypeBond = 10,
|
||||||
|
NetworkDeviceTypeVLan = 11,
|
||||||
|
NetworkDeviceTypeAdsl = 12,
|
||||||
|
NetworkDeviceTypeBridge = 13,
|
||||||
|
NetworkDeviceTypeGeneric = 14,
|
||||||
|
NetworkDeviceTypeTeam = 15,
|
||||||
|
NetworkDeviceTypeTun = 16,
|
||||||
|
NetworkDeviceTypeIpTunnel = 17,
|
||||||
|
NetworkDeviceTypeMacVLan = 18,
|
||||||
|
NetworkDeviceTypeVXLan = 19,
|
||||||
|
NetworkDeviceTypeVEth = 20,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit NetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0);
|
||||||
|
|
||||||
|
QDBusObjectPath objectPath() const;
|
||||||
|
|
||||||
|
QString udi() const;
|
||||||
|
QString interface() const;
|
||||||
|
QString ipInterface() const;
|
||||||
|
QString driver() const;
|
||||||
|
QString driverVersion() const;
|
||||||
|
QString firmwareVersion() const;
|
||||||
|
QString physicalPortId() const;
|
||||||
|
uint mtu() const;
|
||||||
|
uint metered() const;
|
||||||
|
bool autoconnect() const;
|
||||||
|
|
||||||
|
NetworkDeviceState deviceState() const;
|
||||||
|
QString deviceStateString() const;
|
||||||
|
|
||||||
|
NetworkDeviceStateReason deviceStateReason() const;
|
||||||
|
NetworkDeviceType deviceType() const;
|
||||||
|
|
||||||
|
QDBusObjectPath activeConnection() const;
|
||||||
|
QDBusObjectPath ip4Config() const;
|
||||||
|
QList<QDBusObjectPath> availableConnections() const;
|
||||||
|
|
||||||
|
// Method
|
||||||
|
void disconnectDevice();
|
||||||
|
|
||||||
|
static QString deviceTypeToString(const NetworkDeviceType &deviceType);
|
||||||
|
static QString deviceStateToString(const NetworkDeviceState &deviceState);
|
||||||
|
static QString deviceStateReasonToString(const NetworkDeviceStateReason &deviceStateReason);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusInterface *m_networkDeviceInterface;
|
||||||
|
QDBusObjectPath m_objectPath;
|
||||||
|
|
||||||
|
// Device properties
|
||||||
|
QString m_udi;
|
||||||
|
QString m_interface;
|
||||||
|
QString m_ipInterface;
|
||||||
|
QString m_driver;
|
||||||
|
QString m_driverVersion;
|
||||||
|
QString m_firmwareVersion;
|
||||||
|
QString m_physicalPortId;
|
||||||
|
uint m_mtu;
|
||||||
|
uint m_metered;
|
||||||
|
bool m_autoconnect;
|
||||||
|
NetworkDeviceState m_deviceState;
|
||||||
|
NetworkDeviceStateReason m_deviceStateReason;
|
||||||
|
NetworkDeviceType m_deviceType;
|
||||||
|
|
||||||
|
QDBusObjectPath m_activeConnection;
|
||||||
|
QDBusObjectPath m_ip4Config;
|
||||||
|
QDBusObjectPath m_ip6Config;
|
||||||
|
|
||||||
|
QList<QDBusObjectPath> m_availableConnections;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onStateChanged(uint newState, uint oldState, uint reason);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void deviceChanged();
|
||||||
|
void stateChanged(const NetworkDeviceState &state);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, NetworkDevice *device);
|
||||||
|
|
||||||
|
#endif // NETWORKDEVICE_H
|
||||||
421
libnymea-networkmanager/networkmanager.cpp
Normal file
421
libnymea-networkmanager/networkmanager.cpp
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "networkmanager.h"
|
||||||
|
#include "networkconnection.h"
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{NetworkManager} object with the given \a parent. */
|
||||||
|
NetworkManager::NetworkManager(QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_networkManagerInterface(nullptr),
|
||||||
|
m_available(false),
|
||||||
|
m_state(NetworkManagerStateUnknown),
|
||||||
|
m_connectivityState(NetworkManagerConnectivityStateUnknown),
|
||||||
|
m_networkingEnabled(false),
|
||||||
|
m_wirelessEnabled(false)
|
||||||
|
{
|
||||||
|
// Check DBus connection
|
||||||
|
if (!QDBusConnection::systemBus().isConnected()) {
|
||||||
|
qWarning() << "System DBus not connected. NetworkManagre not available.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create interface
|
||||||
|
m_networkManagerInterface = new QDBusInterface(networkManagerServiceString, networkManagerPathString, networkManagerServiceString, QDBusConnection::systemBus(), this);
|
||||||
|
if(!m_networkManagerInterface->isValid()) {
|
||||||
|
qWarning() << "Invalid DBus network manager interface. NetworkManagre not available.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_available = true;
|
||||||
|
|
||||||
|
// Read properties
|
||||||
|
setVersion(m_networkManagerInterface->property("Version").toString());
|
||||||
|
setState((NetworkManagerState)m_networkManagerInterface->property("State").toUInt());
|
||||||
|
setConnectivityState((NetworkManagerConnectivityState)m_networkManagerInterface->property("Connectivity").toUInt());
|
||||||
|
setNetworkingEnabled(m_networkManagerInterface->property("NetworkingEnabled").toBool());
|
||||||
|
setWirelessEnabled(m_networkManagerInterface->property("WirelessEnabled").toBool());
|
||||||
|
|
||||||
|
loadDevices();
|
||||||
|
|
||||||
|
// Connect signals
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, networkManagerPathString, networkManagerServiceString, "StateChanged", this, SLOT(onStateChanged(uint)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, networkManagerPathString, networkManagerServiceString, "DeviceAdded", this, SLOT(onDeviceAdded(QDBusObjectPath)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, networkManagerPathString, networkManagerServiceString, "DeviceRemoved", this, SLOT(onDeviceRemoved(QDBusObjectPath)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, networkManagerPathString, networkManagerServiceString, "PropertiesChanged", this, SLOT(onPropertiesChanged(QVariantMap)));
|
||||||
|
|
||||||
|
// Create settings
|
||||||
|
m_networkSettings = new NetworkSettings(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkManager::~NetworkManager()
|
||||||
|
{
|
||||||
|
qDebug() << "Destroy network manager.";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if the network-manager is available on this system. */
|
||||||
|
bool NetworkManager::available()
|
||||||
|
{
|
||||||
|
return m_available;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if wifi is available on this system. */
|
||||||
|
bool NetworkManager::wirelessAvailable()
|
||||||
|
{
|
||||||
|
return !m_wirelessNetworkDevices.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the list of \l{NetworkDevice}{NetworkDevices} from this \l{NetworkManager}. */
|
||||||
|
QList<NetworkDevice *> NetworkManager::networkDevices() const
|
||||||
|
{
|
||||||
|
return m_networkDevices.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<WirelessNetworkDevice *> NetworkManager::wirelessNetworkDevices() const
|
||||||
|
{
|
||||||
|
return m_wirelessNetworkDevices.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the list of \l{WiredNetworkDevice}{WiredNetworkDevices} from this \l{NetworkManager}. */
|
||||||
|
QList<WiredNetworkDevice *> NetworkManager::wiredNetworkDevices() const
|
||||||
|
{
|
||||||
|
return m_wiredNetworkDevices.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the \l{NetworkDevice} with the given \a interface from this \l{NetworkManager}. If there is no such \a interface returns Q_NULLPTR. */
|
||||||
|
NetworkDevice *NetworkManager::getNetworkDevice(const QString &interface)
|
||||||
|
{
|
||||||
|
foreach (NetworkDevice *device, m_networkDevices.values()) {
|
||||||
|
if (device->interface() == interface)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
return Q_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the version of the running \l{NetworkManager}. */
|
||||||
|
QString NetworkManager::version() const
|
||||||
|
{
|
||||||
|
return m_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the state of this \l{NetworkManager}. \sa NetworkManagerState, */
|
||||||
|
NetworkManager::NetworkManagerState NetworkManager::state() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the human readable string of the current state of this \l{NetworkManager}. \sa NetworkManagerState, */
|
||||||
|
QString NetworkManager::stateString() const
|
||||||
|
{
|
||||||
|
return networkManagerStateToString(m_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the current connectivity state of this \l{NetworkManager}. \sa NetworkManagerConnectivityState, */
|
||||||
|
NetworkManager::NetworkManagerConnectivityState NetworkManager::connectivityState() const
|
||||||
|
{
|
||||||
|
return m_connectivityState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Connect the given \a interface to a wifi network with the given \a ssid and \a password. Returns the \l{NetworkManagerError} to inform about the result. \sa NetworkManagerError, */
|
||||||
|
NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &interface, const QString &ssid, const QString &password, const bool &hidden)
|
||||||
|
{
|
||||||
|
// Check interface
|
||||||
|
if (!getNetworkDevice(interface))
|
||||||
|
return NetworkManagerErrorNetworkInterfaceNotFound;
|
||||||
|
|
||||||
|
// Get wirelessNetworkDevice
|
||||||
|
WirelessNetworkDevice *wirelessNetworkDevice = 0;
|
||||||
|
foreach (WirelessNetworkDevice *networkDevice, wirelessNetworkDevices()) {
|
||||||
|
if (networkDevice->interface() == interface)
|
||||||
|
wirelessNetworkDevice = networkDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wirelessNetworkDevice)
|
||||||
|
return NetworkManagerErrorInvalidNetworkDeviceType;
|
||||||
|
|
||||||
|
// Get the access point object path
|
||||||
|
WirelessAccessPoint *accessPoint = wirelessNetworkDevice->getAccessPoint(ssid);
|
||||||
|
if (!accessPoint)
|
||||||
|
return NetworkManagerErrorAccessPointNotFound;
|
||||||
|
|
||||||
|
// Note: https://developer.gnome.org/NetworkManager/stable/ref-settings.html
|
||||||
|
|
||||||
|
QVariantMap connectionSettings;
|
||||||
|
connectionSettings.insert("autoconnect", true);
|
||||||
|
connectionSettings.insert("id", ssid + " (loop)");
|
||||||
|
connectionSettings.insert("uuid", QUuid::createUuid().toString().remove("{").remove("}"));
|
||||||
|
connectionSettings.insert("type", "802-11-wireless");
|
||||||
|
|
||||||
|
QVariantMap wirelessSettings;
|
||||||
|
wirelessSettings.insert("ssid", ssid.toUtf8());
|
||||||
|
wirelessSettings.insert("mode", "infrastructure");
|
||||||
|
|
||||||
|
// Note: disable power save mode
|
||||||
|
wirelessSettings.insert("powersave", 2);
|
||||||
|
|
||||||
|
if (hidden)
|
||||||
|
wirelessSettings.insert("hidden", true);
|
||||||
|
|
||||||
|
QVariantMap wirelessSecuritySettings;
|
||||||
|
wirelessSecuritySettings.insert("auth-alg", "open");
|
||||||
|
wirelessSecuritySettings.insert("key-mgmt", "wpa-psk");
|
||||||
|
wirelessSecuritySettings.insert("psk", password);
|
||||||
|
|
||||||
|
QVariantMap ipv4Settings;
|
||||||
|
ipv4Settings.insert("method", "auto");
|
||||||
|
|
||||||
|
QVariantMap ipv6Settings;
|
||||||
|
ipv6Settings.insert("method", "auto");
|
||||||
|
|
||||||
|
// Build connection object
|
||||||
|
ConnectionSettings settings;
|
||||||
|
settings.insert("connection", connectionSettings);
|
||||||
|
settings.insert("802-11-wireless", wirelessSettings);
|
||||||
|
settings.insert("ipv4", ipv4Settings);
|
||||||
|
settings.insert("ipv6", ipv6Settings);
|
||||||
|
settings.insert("802-11-wireless-security", wirelessSecuritySettings);
|
||||||
|
|
||||||
|
// Remove old configuration (if there is any)
|
||||||
|
foreach (NetworkConnection *connection, m_networkSettings->connections()) {
|
||||||
|
if (connection->id() == connectionSettings.value("id")) {
|
||||||
|
connection->deleteConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add connection
|
||||||
|
QDBusObjectPath connectionObjectPath = m_networkSettings->addConnection(settings);
|
||||||
|
if (connectionObjectPath.path().isEmpty())
|
||||||
|
return NetworkManagerErrorWirelessConnectionFailed;
|
||||||
|
|
||||||
|
// Activate connection
|
||||||
|
QDBusMessage query = m_networkManagerInterface->call("ActivateConnection", QVariant::fromValue(connectionObjectPath), QVariant::fromValue(wirelessNetworkDevice->objectPath()), QVariant::fromValue(accessPoint->objectPath()));
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return NetworkManagerErrorWirelessConnectionFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NetworkManagerErrorNoError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if the networking of this \l{NetworkManager} is enabled. */
|
||||||
|
bool NetworkManager::networkingEnabled() const
|
||||||
|
{
|
||||||
|
return m_networkingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if the networking of this \l{NetworkManager} could be \a enabled. */
|
||||||
|
bool NetworkManager::enableNetworking(const bool &enabled)
|
||||||
|
{
|
||||||
|
if (m_networkingEnabled == enabled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QDBusMessage query = m_networkManagerInterface->call("Enable", enabled);
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Sets the networking of this \l{NetworkManager} to \a enabled. */
|
||||||
|
void NetworkManager::setNetworkingEnabled(const bool &enabled)
|
||||||
|
{
|
||||||
|
qDebug() << "Networking" << (enabled ? "enabled" : "disabled");
|
||||||
|
m_networkingEnabled = enabled;
|
||||||
|
emit networkingEnabledChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if the wireless networking of this \l{NetworkManager} is enabled. */
|
||||||
|
bool NetworkManager::wirelessEnabled() const
|
||||||
|
{
|
||||||
|
return m_wirelessEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if the wireless networking of this \l{NetworkManager} could be set to \a enabled. */
|
||||||
|
bool NetworkManager::enableWireless(const bool &enabled)
|
||||||
|
{
|
||||||
|
if (m_wirelessEnabled == enabled)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return m_networkManagerInterface->setProperty("WirelessEnabled", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::loadDevices()
|
||||||
|
{
|
||||||
|
// Get network devices
|
||||||
|
QDBusMessage query = m_networkManagerInterface->call("GetDevices");
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.arguments().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QDBusArgument &argument = query.arguments().at(0).value<QDBusArgument>();
|
||||||
|
argument.beginArray();
|
||||||
|
while(!argument.atEnd()) {
|
||||||
|
QDBusObjectPath deviceObjectPath = qdbus_cast<QDBusObjectPath>(argument);
|
||||||
|
onDeviceAdded(deviceObjectPath);
|
||||||
|
}
|
||||||
|
argument.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NetworkManager::networkManagerStateToString(const NetworkManager::NetworkManagerState &state)
|
||||||
|
{
|
||||||
|
QMetaObject metaObject = NetworkManager::staticMetaObject;
|
||||||
|
int enumIndex = metaObject.indexOfEnumerator(QString("NetworkManagerState").toLatin1().data());
|
||||||
|
QMetaEnum metaEnum = metaObject.enumerator(enumIndex);
|
||||||
|
return QString(metaEnum.valueToKey(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NetworkManager::networkManagerConnectivityStateToString(const NetworkManager::NetworkManagerConnectivityState &state)
|
||||||
|
{
|
||||||
|
QMetaObject metaObject = NetworkManager::staticMetaObject;
|
||||||
|
int enumIndex = metaObject.indexOfEnumerator(QString("NetworkManagerConnectivityState").toLatin1().data());
|
||||||
|
QMetaEnum metaEnum = metaObject.enumerator(enumIndex);
|
||||||
|
return QString(metaEnum.valueToKey(state)).remove("NetworkManagerConnectivityState");
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::setVersion(const QString &version)
|
||||||
|
{
|
||||||
|
qDebug() << "Version:" << version;
|
||||||
|
m_version = version;
|
||||||
|
emit versionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::setWirelessEnabled(const bool &enabled)
|
||||||
|
{
|
||||||
|
qDebug() << "Wireless networking" << (enabled ? "enabled" : "disabled");
|
||||||
|
m_wirelessEnabled = enabled;
|
||||||
|
emit wirelessEnabledChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::setConnectivityState(const NetworkManager::NetworkManagerConnectivityState &connectivityState)
|
||||||
|
{
|
||||||
|
qDebug() << "Connectivity state changed:" << networkManagerConnectivityStateToString(connectivityState);
|
||||||
|
m_connectivityState = connectivityState;
|
||||||
|
emit connectivityStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::setState(const NetworkManager::NetworkManagerState &state)
|
||||||
|
{
|
||||||
|
qDebug() << "State changed:" << networkManagerStateToString(state);
|
||||||
|
m_state = state;
|
||||||
|
emit stateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::onDeviceAdded(const QDBusObjectPath &deviceObjectPath)
|
||||||
|
{
|
||||||
|
if (m_networkDevices.keys().contains(deviceObjectPath)) {
|
||||||
|
qWarning() << "Device" << deviceObjectPath.path() << "already added.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get device Type
|
||||||
|
QDBusInterface networkDeviceInterface(networkManagerServiceString, deviceObjectPath.path(), deviceInterfaceString, QDBusConnection::systemBus());
|
||||||
|
if(!networkDeviceInterface.isValid()) {
|
||||||
|
qWarning() << "NetworkDevice: Invalid DBus device interface" << deviceObjectPath.path();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create object
|
||||||
|
NetworkDevice::NetworkDeviceType deviceType = NetworkDevice::NetworkDeviceType(networkDeviceInterface.property("DeviceType").toUInt());
|
||||||
|
switch (deviceType) {
|
||||||
|
case NetworkDevice::NetworkDeviceTypeWifi: {
|
||||||
|
WirelessNetworkDevice *wirelessNetworkDevice = new WirelessNetworkDevice(deviceObjectPath, this);
|
||||||
|
qDebug() << "[+]" << wirelessNetworkDevice;
|
||||||
|
m_networkDevices.insert(deviceObjectPath, wirelessNetworkDevice);
|
||||||
|
m_wirelessNetworkDevices.insert(deviceObjectPath, wirelessNetworkDevice);
|
||||||
|
connect(wirelessNetworkDevice, &WirelessNetworkDevice::deviceChanged, this, &NetworkManager::onWirelessDeviceChanged);
|
||||||
|
emit wirelessDeviceAdded(wirelessNetworkDevice);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NetworkDevice::NetworkDeviceTypeEthernet: {
|
||||||
|
WiredNetworkDevice *wiredNetworkDevice = new WiredNetworkDevice(deviceObjectPath, this);
|
||||||
|
qDebug() << "[+]" << wiredNetworkDevice;
|
||||||
|
m_networkDevices.insert(deviceObjectPath, wiredNetworkDevice);
|
||||||
|
m_wiredNetworkDevices.insert(deviceObjectPath, wiredNetworkDevice);
|
||||||
|
|
||||||
|
connect(wiredNetworkDevice, &WiredNetworkDevice::deviceChanged, this, &NetworkManager::onWiredDeviceChanged);
|
||||||
|
emit wiredDeviceAdded(wiredNetworkDevice);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
NetworkDevice *networkDevice = new NetworkDevice(deviceObjectPath, this);
|
||||||
|
qDebug() << "[+]" << networkDevice;
|
||||||
|
m_networkDevices.insert(deviceObjectPath, networkDevice);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::onDeviceRemoved(const QDBusObjectPath &deviceObjectPath)
|
||||||
|
{
|
||||||
|
if (!m_networkDevices.keys().contains(deviceObjectPath)) {
|
||||||
|
qWarning() << "Unknown network device removed:" << deviceObjectPath.path();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkDevice *networkDevice = m_networkDevices.take(deviceObjectPath);
|
||||||
|
|
||||||
|
if (m_wiredNetworkDevices.contains(deviceObjectPath)) {
|
||||||
|
qDebug() << "[-]" << m_wiredNetworkDevices.value(deviceObjectPath);
|
||||||
|
m_wiredNetworkDevices.remove(deviceObjectPath);
|
||||||
|
emit wiredDeviceRemoved(networkDevice->interface());
|
||||||
|
} else if (m_wirelessNetworkDevices.contains(deviceObjectPath)) {
|
||||||
|
qDebug() << "[-]" << m_wirelessNetworkDevices.value(deviceObjectPath);
|
||||||
|
m_wirelessNetworkDevices.remove(deviceObjectPath);
|
||||||
|
if (!wirelessAvailable())
|
||||||
|
emit wirelessAvailableChanged();
|
||||||
|
|
||||||
|
emit wirelessDeviceRemoved(networkDevice->interface());
|
||||||
|
} else {
|
||||||
|
qDebug() << "[-]" << networkDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkDevice->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::onPropertiesChanged(const QVariantMap &properties)
|
||||||
|
{
|
||||||
|
if (properties.contains("Version"))
|
||||||
|
setVersion(properties.value("Version").toString());
|
||||||
|
|
||||||
|
if (properties.contains("State"))
|
||||||
|
setState((NetworkManagerState)properties.value("State").toUInt());
|
||||||
|
|
||||||
|
if (properties.contains("Connectivity"))
|
||||||
|
setConnectivityState(NetworkManagerConnectivityState(properties.value("Connectivity").toUInt()));
|
||||||
|
|
||||||
|
if (properties.contains("NetworkingEnabled"))
|
||||||
|
setNetworkingEnabled(properties.value("NetworkingEnabled").toBool());
|
||||||
|
|
||||||
|
if (properties.contains("WirelessEnabled"))
|
||||||
|
setWirelessEnabled(properties.value("WirelessEnabled").toBool());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::onWirelessDeviceChanged()
|
||||||
|
{
|
||||||
|
WirelessNetworkDevice *networkDevice = static_cast<WirelessNetworkDevice *>(sender());
|
||||||
|
emit wirelessDeviceChanged(networkDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkManager::onWiredDeviceChanged()
|
||||||
|
{
|
||||||
|
WiredNetworkDevice *networkDevice = static_cast<WiredNetworkDevice *>(sender());
|
||||||
|
emit wiredDeviceChanged(networkDevice);
|
||||||
|
}
|
||||||
|
|
||||||
151
libnymea-networkmanager/networkmanager.h
Normal file
151
libnymea-networkmanager/networkmanager.h
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef NETWORKMANAGER_H
|
||||||
|
#define NETWORKMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusMessage>
|
||||||
|
#include <QDBusContext>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
|
||||||
|
#include "dbus-interfaces.h"
|
||||||
|
#include "wirednetworkdevice.h"
|
||||||
|
#include "wirelessnetworkdevice.h"
|
||||||
|
#include "networksettings.h"
|
||||||
|
|
||||||
|
// Docs: https://developer.gnome.org/NetworkManager/unstable/spec.html
|
||||||
|
|
||||||
|
class NetworkManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_ENUMS(NetworkManagerState)
|
||||||
|
Q_ENUMS(NetworkManagerConnectivityState)
|
||||||
|
Q_ENUMS(NetworkManagerError)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NetworkManagerState {
|
||||||
|
NetworkManagerStateUnknown = 0,
|
||||||
|
NetworkManagerStateAsleep = 10,
|
||||||
|
NetworkManagerStateDisconnected = 20,
|
||||||
|
NetworkManagerStateDisconnecting = 30,
|
||||||
|
NetworkManagerStateConnecting = 40,
|
||||||
|
NetworkManagerStateConnectedLocal = 50,
|
||||||
|
NetworkManagerStateConnectedSite = 60,
|
||||||
|
NetworkManagerStateConnectedGlobal = 70
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NetworkManagerConnectivityState {
|
||||||
|
NetworkManagerConnectivityStateUnknown = 1,
|
||||||
|
NetworkManagerConnectivityStateNone = 2,
|
||||||
|
NetworkManagerConnectivityStatePortal = 3,
|
||||||
|
NetworkManagerConnectivityStateLimited = 4,
|
||||||
|
NetworkManagerConnectivityStateFull = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NetworkManagerError {
|
||||||
|
NetworkManagerErrorNoError,
|
||||||
|
NetworkManagerErrorUnknownError,
|
||||||
|
NetworkManagerErrorWirelessNotAvailable,
|
||||||
|
NetworkManagerErrorAccessPointNotFound,
|
||||||
|
NetworkManagerErrorNetworkInterfaceNotFound,
|
||||||
|
NetworkManagerErrorInvalidNetworkDeviceType,
|
||||||
|
NetworkManagerErrorWirelessNetworkingDisabled,
|
||||||
|
NetworkManagerErrorWirelessConnectionFailed,
|
||||||
|
NetworkManagerErrorNetworkingDisabled,
|
||||||
|
NetworkManagerErrorNetworkManagerNotAvailable
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit NetworkManager(QObject *parent = 0);
|
||||||
|
~NetworkManager();
|
||||||
|
|
||||||
|
bool available();
|
||||||
|
bool wirelessAvailable();
|
||||||
|
|
||||||
|
QList<NetworkDevice *> networkDevices() const;
|
||||||
|
QList<WirelessNetworkDevice *> wirelessNetworkDevices() const;
|
||||||
|
QList<WiredNetworkDevice *> wiredNetworkDevices() const;
|
||||||
|
|
||||||
|
NetworkDevice *getNetworkDevice(const QString &interface);
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
QString version() const;
|
||||||
|
NetworkManagerState state() const;
|
||||||
|
QString stateString() const;
|
||||||
|
NetworkManagerConnectivityState connectivityState() const;
|
||||||
|
|
||||||
|
NetworkManagerError connectWifi(const QString &interface, const QString &ssid, const QString &password, const bool &hidden = false);
|
||||||
|
|
||||||
|
// Networking
|
||||||
|
bool networkingEnabled() const;
|
||||||
|
bool enableNetworking(const bool &enabled);
|
||||||
|
|
||||||
|
// Wireless Networking
|
||||||
|
bool wirelessEnabled() const;
|
||||||
|
bool enableWireless(const bool &enabled);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusInterface *m_networkManagerInterface;
|
||||||
|
|
||||||
|
QHash<QDBusObjectPath, NetworkDevice *> m_networkDevices;
|
||||||
|
QHash<QDBusObjectPath, WirelessNetworkDevice *> m_wirelessNetworkDevices;
|
||||||
|
QHash<QDBusObjectPath, WiredNetworkDevice *> m_wiredNetworkDevices;
|
||||||
|
|
||||||
|
NetworkSettings *m_networkSettings;
|
||||||
|
|
||||||
|
bool m_available;
|
||||||
|
|
||||||
|
QString m_version;
|
||||||
|
|
||||||
|
NetworkManagerState m_state;
|
||||||
|
NetworkManagerConnectivityState m_connectivityState;
|
||||||
|
bool m_networkingEnabled;
|
||||||
|
bool m_wirelessEnabled;
|
||||||
|
|
||||||
|
void loadDevices();
|
||||||
|
|
||||||
|
static QString networkManagerStateToString(const NetworkManagerState &state);
|
||||||
|
static QString networkManagerConnectivityStateToString(const NetworkManagerConnectivityState &state);
|
||||||
|
|
||||||
|
void setVersion(const QString &version);
|
||||||
|
void setNetworkingEnabled(const bool &enabled);
|
||||||
|
void setWirelessEnabled(const bool &enabled);
|
||||||
|
void setConnectivityState(const NetworkManagerConnectivityState &connectivityState);
|
||||||
|
void setState(const NetworkManagerState &state);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void versionChanged();
|
||||||
|
void networkingEnabledChanged();
|
||||||
|
void wirelessEnabledChanged();
|
||||||
|
void wirelessAvailableChanged();
|
||||||
|
void stateChanged();
|
||||||
|
void connectivityStateChanged();
|
||||||
|
|
||||||
|
void wirelessDeviceAdded(WirelessNetworkDevice *wirelessDevice);
|
||||||
|
void wirelessDeviceRemoved(const QString &interface);
|
||||||
|
void wirelessDeviceChanged(WirelessNetworkDevice *wirelessDevice);
|
||||||
|
|
||||||
|
void wiredDeviceAdded(WiredNetworkDevice *wiredDevice);
|
||||||
|
void wiredDeviceRemoved(const QString &interface);
|
||||||
|
void wiredDeviceChanged(WiredNetworkDevice *wiredDevice);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onDeviceAdded(const QDBusObjectPath &deviceObjectPath);
|
||||||
|
void onDeviceRemoved(const QDBusObjectPath &deviceObjectPath);
|
||||||
|
void onPropertiesChanged(const QVariantMap &properties);
|
||||||
|
|
||||||
|
void onWirelessDeviceChanged();
|
||||||
|
void onWiredDeviceChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NETWORKMANAGER_H
|
||||||
94
libnymea-networkmanager/networksettings.cpp
Normal file
94
libnymea-networkmanager/networksettings.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "networksettings.h"
|
||||||
|
#include "dbus-interfaces.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{NetworkSettings} object with the given \a parent. */
|
||||||
|
NetworkSettings::NetworkSettings(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
m_settingsInterface = new QDBusInterface(networkManagerServiceString, settingsPathString, settingsInterfaceString, QDBusConnection::systemBus(), this);
|
||||||
|
if(!m_settingsInterface->isValid()) {
|
||||||
|
qWarning() << "Invalid DBus network settings interface";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadConnections();
|
||||||
|
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, settingsPathString, settingsInterfaceString, "NewConnection", this, SLOT(connectionAdded(QDBusObjectPath)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, settingsPathString, settingsInterfaceString, "ConnectionRemoved", this, SLOT(connectionRemoved(QDBusObjectPath)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, settingsPathString, settingsInterfaceString, "PropertiesChanged", this, SLOT(propertiesChanged(QVariantMap)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Add the given \a settings to this \l{NetworkSettings}. Returns the dbus object path from the new settings. */
|
||||||
|
QDBusObjectPath NetworkSettings::addConnection(const ConnectionSettings &settings)
|
||||||
|
{
|
||||||
|
QDBusMessage query = m_settingsInterface->call("AddConnection", QVariant::fromValue(settings));
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return QDBusObjectPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.arguments().isEmpty())
|
||||||
|
return QDBusObjectPath();
|
||||||
|
|
||||||
|
return query.arguments().at(0).value<QDBusObjectPath>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the list of current \l{NetworkConnection}{NetworkConnections} from this \l{NetworkSettings}. */
|
||||||
|
QList<NetworkConnection *> NetworkSettings::connections() const
|
||||||
|
{
|
||||||
|
return m_connections.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkSettings::loadConnections()
|
||||||
|
{
|
||||||
|
QDBusMessage query = m_settingsInterface->call("ListConnections");
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.arguments().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QDBusArgument &argument = query.arguments().at(0).value<QDBusArgument>();
|
||||||
|
argument.beginArray();
|
||||||
|
while(!argument.atEnd()) {
|
||||||
|
QDBusObjectPath objectPath = qdbus_cast<QDBusObjectPath>(argument);
|
||||||
|
connectionAdded(objectPath);
|
||||||
|
}
|
||||||
|
argument.endArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkSettings::connectionAdded(const QDBusObjectPath &objectPath)
|
||||||
|
{
|
||||||
|
NetworkConnection *connection = new NetworkConnection(objectPath, this);
|
||||||
|
m_connections.insert(objectPath, connection);
|
||||||
|
|
||||||
|
qDebug() << "Settings: [+]" << connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkSettings::connectionRemoved(const QDBusObjectPath &objectPath)
|
||||||
|
{
|
||||||
|
NetworkConnection *connection = m_connections.take(objectPath);
|
||||||
|
qDebug() << "Settings: [-]" << connection;
|
||||||
|
connection->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkSettings::propertiesChanged(const QVariantMap &properties)
|
||||||
|
{
|
||||||
|
Q_UNUSED(properties);
|
||||||
|
//qDebug() << "Settins: properties changed" << properties;
|
||||||
|
}
|
||||||
49
libnymea-networkmanager/networksettings.h
Normal file
49
libnymea-networkmanager/networksettings.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef NETWORKSETTINGS_H
|
||||||
|
#define NETWORKSETTINGS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDBusObjectPath>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
|
||||||
|
#include "networkconnection.h"
|
||||||
|
|
||||||
|
class NetworkConnection;
|
||||||
|
|
||||||
|
class NetworkSettings : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit NetworkSettings(QObject *parent = 0);
|
||||||
|
|
||||||
|
QDBusObjectPath addConnection(const ConnectionSettings &settings);
|
||||||
|
QList<NetworkConnection *> connections() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusInterface *m_settingsInterface;
|
||||||
|
QHash<QDBusObjectPath, NetworkConnection *> m_connections;
|
||||||
|
|
||||||
|
void loadConnections();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void connectionAdded(const QDBusObjectPath &objectPath);
|
||||||
|
void connectionRemoved(const QDBusObjectPath &objectPath);
|
||||||
|
void propertiesChanged(const QVariantMap &properties);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NETWORKSETTINGS_H
|
||||||
87
libnymea-networkmanager/wirednetworkdevice.cpp
Normal file
87
libnymea-networkmanager/wirednetworkdevice.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2018 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "wirednetworkdevice.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{WiredNetworkDevice} with the given dbus \a objectPath and \a parent. */
|
||||||
|
WiredNetworkDevice::WiredNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent) :
|
||||||
|
NetworkDevice(objectPath, parent)
|
||||||
|
{
|
||||||
|
QDBusConnection systemBus = QDBusConnection::systemBus();
|
||||||
|
if (!systemBus.isConnected()) {
|
||||||
|
qWarning() << "WiredNetworkDevice: System DBus not connected";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_wiredInterface = new QDBusInterface(networkManagerServiceString, this->objectPath().path(), wiredInterfaceString, systemBus, this);
|
||||||
|
if(!m_wiredInterface->isValid()) {
|
||||||
|
qWarning() << "WiredNetworkDevice: Invalid wired dbus interface";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMacAddress(m_wiredInterface->property("HwAddress").toString());
|
||||||
|
setBitRate(m_wiredInterface->property("Bitrate").toInt());
|
||||||
|
setPluggedIn(m_wiredInterface->property("Carrier").toBool());
|
||||||
|
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, this->objectPath().path(), wiredInterfaceString, "PropertiesChanged", this, SLOT(propertiesChanged(QVariantMap)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the mac address of this \l{WiredNetworkDevice}. */
|
||||||
|
QString WiredNetworkDevice::macAddress() const
|
||||||
|
{
|
||||||
|
return m_macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the current bit rate [Mb/s] of this \l{WiredNetworkDevice}. */
|
||||||
|
int WiredNetworkDevice::bitRate() const
|
||||||
|
{
|
||||||
|
return m_bitRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if this \l{WiredNetworkDevice} has a cable plugged in. */
|
||||||
|
bool WiredNetworkDevice::pluggedIn() const
|
||||||
|
{
|
||||||
|
return m_pluggedIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiredNetworkDevice::setMacAddress(const QString &macAddress)
|
||||||
|
{
|
||||||
|
m_macAddress = macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiredNetworkDevice::setBitRate(const int &bitRate)
|
||||||
|
{
|
||||||
|
m_bitRate = bitRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiredNetworkDevice::setPluggedIn(const bool &pluggedIn)
|
||||||
|
{
|
||||||
|
m_pluggedIn = pluggedIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiredNetworkDevice::propertiesChanged(const QVariantMap &properties)
|
||||||
|
{
|
||||||
|
if (properties.contains("Carrier"))
|
||||||
|
setPluggedIn(properties.value("Carrier").toBool());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, WiredNetworkDevice *networkDevice)
|
||||||
|
{
|
||||||
|
debug.nospace() << "WiredNetworkDevice(" << networkDevice->interface() << ", ";
|
||||||
|
debug.nospace() << networkDevice->macAddress() << ", ";
|
||||||
|
debug.nospace() << networkDevice->bitRate() << " [Mb/s], ";
|
||||||
|
debug.nospace() << networkDevice->pluggedIn() << ", ";
|
||||||
|
debug.nospace() << networkDevice->deviceStateString() << ") ";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
48
libnymea-networkmanager/wirednetworkdevice.h
Normal file
48
libnymea-networkmanager/wirednetworkdevice.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef WIREDNETWORKDEVICE_H
|
||||||
|
#define WIREDNETWORKDEVICE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDBusObjectPath>
|
||||||
|
|
||||||
|
#include "networkdevice.h"
|
||||||
|
|
||||||
|
class WiredNetworkDevice : public NetworkDevice
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit WiredNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0);
|
||||||
|
|
||||||
|
QString macAddress() const;
|
||||||
|
int bitRate() const;
|
||||||
|
bool pluggedIn() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusInterface *m_wiredInterface;
|
||||||
|
|
||||||
|
QString m_macAddress;
|
||||||
|
int m_bitRate;
|
||||||
|
bool m_pluggedIn;
|
||||||
|
|
||||||
|
void setMacAddress(const QString &macAddress);
|
||||||
|
void setBitRate(const int &bitRate);
|
||||||
|
void setPluggedIn(const bool &pluggedIn);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void propertiesChanged(const QVariantMap &properties);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, WiredNetworkDevice *networkDevice);
|
||||||
|
|
||||||
|
#endif // WIREDNETWORKDEVICE_H
|
||||||
141
libnymea-networkmanager/wirelessaccesspoint.cpp
Normal file
141
libnymea-networkmanager/wirelessaccesspoint.cpp
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/*! \enum guhserver::WirelessAccessPoint::ApSecurityMode
|
||||||
|
\value ApSecurityModeNone
|
||||||
|
\value ApSecurityModePairWep40
|
||||||
|
\value ApSecurityModePairWep104
|
||||||
|
\value ApSecurityModePairTkip
|
||||||
|
\value ApSecurityModePairCcmp
|
||||||
|
\value ApSecurityModeGroupWep40
|
||||||
|
\value ApSecurityModeGroupWep104
|
||||||
|
\value ApSecurityModeGroupTkip
|
||||||
|
\value ApSecurityModeGroupCcmp
|
||||||
|
\value ApSecurityModeKeyMgmtPsk
|
||||||
|
\value ApSecurityModeKeyMgmt8021X
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn void WirelessAccessPoint::signalStrengthChanged();
|
||||||
|
This signal will be emitted when the signalStrength of this \l{WirelessAccessPoint} has changed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wirelessaccesspoint.h"
|
||||||
|
#include "dbus-interfaces.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{WirelessAccessPoint} with the given dbus \a objectPath and \a parent. */
|
||||||
|
WirelessAccessPoint::WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_objectPath(objectPath),
|
||||||
|
m_securityFlags(0)
|
||||||
|
{
|
||||||
|
QDBusInterface accessPointInterface(networkManagerServiceString, m_objectPath.path(), accessPointInterfaceString, QDBusConnection::systemBus());
|
||||||
|
if(!accessPointInterface.isValid()) {
|
||||||
|
qWarning() << "Invalid access point dbus interface";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init properties
|
||||||
|
setSsid(accessPointInterface.property("Ssid").toString());
|
||||||
|
setMacAddress(accessPointInterface.property("HwAddress").toString());
|
||||||
|
setFrequency(accessPointInterface.property("Frequency").toDouble() / 1000);
|
||||||
|
setSignalStrength(accessPointInterface.property("Strength").toUInt());
|
||||||
|
setSecurityFlags(WirelessAccessPoint::ApSecurityModes(accessPointInterface.property("WpaFlags").toUInt()));
|
||||||
|
setIsProtected((bool)accessPointInterface.property("Flags").toUInt());
|
||||||
|
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, objectPath.path(), accessPointInterfaceString, "PropertiesChanged", this, SLOT(onPropertiesChanged(QVariantMap)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the dbus object path of this \l{WirelessAccessPoint}. */
|
||||||
|
QDBusObjectPath WirelessAccessPoint::objectPath() const
|
||||||
|
{
|
||||||
|
return m_objectPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the ssid of this \l{WirelessAccessPoint}. */
|
||||||
|
QString WirelessAccessPoint::ssid() const
|
||||||
|
{
|
||||||
|
return m_ssid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::setSsid(const QString &ssid)
|
||||||
|
{
|
||||||
|
m_ssid = ssid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the mac address of this \l{WirelessAccessPoint}. */
|
||||||
|
QString WirelessAccessPoint::macAddress() const
|
||||||
|
{
|
||||||
|
return m_macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::setMacAddress(const QString &macAddress)
|
||||||
|
{
|
||||||
|
m_macAddress = macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the frequency of this \l{WirelessAccessPoint}. (2.4 GHz or 5GHz) */
|
||||||
|
double WirelessAccessPoint::frequency() const
|
||||||
|
{
|
||||||
|
return m_frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::setFrequency(const double &frequency)
|
||||||
|
{
|
||||||
|
m_frequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the signal strength in percentage [0, 100] % of this \l{WirelessAccessPoint}. */
|
||||||
|
int WirelessAccessPoint::signalStrength() const
|
||||||
|
{
|
||||||
|
return m_signalStrength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::setSignalStrength(const int &signalStrength)
|
||||||
|
{
|
||||||
|
m_signalStrength = signalStrength;
|
||||||
|
emit signalStrengthChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::setIsProtected(const bool &isProtected)
|
||||||
|
{
|
||||||
|
m_isProtected = isProtected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns true if this \l{WirelessAccessPoint} is password protected. */
|
||||||
|
bool WirelessAccessPoint::isProtected() const
|
||||||
|
{
|
||||||
|
return m_isProtected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the security flags of this \l{WirelessAccessPoint}. \sa WirelessAccessPoint::ApSecurityModes */
|
||||||
|
WirelessAccessPoint::ApSecurityModes WirelessAccessPoint::securityFlags() const
|
||||||
|
{
|
||||||
|
return m_securityFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::setSecurityFlags(const WirelessAccessPoint::ApSecurityModes &securityFlags)
|
||||||
|
{
|
||||||
|
m_securityFlags = securityFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessAccessPoint::onPropertiesChanged(const QVariantMap &properties)
|
||||||
|
{
|
||||||
|
if (properties.contains("Strength"))
|
||||||
|
setSignalStrength(properties.value("Strength").toUInt());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, WirelessAccessPoint *accessPoint)
|
||||||
|
{
|
||||||
|
return debug.nospace() << "AccessPoint(" << accessPoint->signalStrength() << "%, " << accessPoint->frequency()<< " GHz, " << accessPoint->ssid() << ", " << (accessPoint->isProtected() ? "protected" : "open" ) << ")";
|
||||||
|
}
|
||||||
83
libnymea-networkmanager/wirelessaccesspoint.h
Normal file
83
libnymea-networkmanager/wirelessaccesspoint.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef WIRELESSACCESSPOINT_H
|
||||||
|
#define WIRELESSACCESSPOINT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFlags>
|
||||||
|
#include <QDBusObjectPath>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
|
||||||
|
class WirelessAccessPoint : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_FLAGS(ApSecurityModes)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum ApSecurityMode{
|
||||||
|
ApSecurityModeNone = 0x000,
|
||||||
|
ApSecurityModePairWep40 = 0x001,
|
||||||
|
ApSecurityModePairWep104 = 0x002,
|
||||||
|
ApSecurityModePairTkip = 0x004,
|
||||||
|
ApSecurityModePairCcmp = 0x008,
|
||||||
|
ApSecurityModeGroupWep40 = 0x010,
|
||||||
|
ApSecurityModeGroupWep104 = 0x020,
|
||||||
|
ApSecurityModeGroupTkip = 0x040,
|
||||||
|
ApSecurityModeGroupCcmp = 0x080,
|
||||||
|
ApSecurityModeKeyMgmtPsk = 0x100,
|
||||||
|
ApSecurityModeKeyMgmt8021X = 0x200,
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(ApSecurityModes, ApSecurityMode)
|
||||||
|
|
||||||
|
|
||||||
|
explicit WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent = 0);
|
||||||
|
|
||||||
|
QDBusObjectPath objectPath() const;
|
||||||
|
|
||||||
|
QString ssid() const;
|
||||||
|
QString macAddress() const;
|
||||||
|
double frequency() const;
|
||||||
|
int signalStrength() const;
|
||||||
|
bool isProtected() const;
|
||||||
|
|
||||||
|
WirelessAccessPoint::ApSecurityModes securityFlags() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusObjectPath m_objectPath;
|
||||||
|
QString m_ssid;
|
||||||
|
QString m_macAddress;
|
||||||
|
double m_frequency;
|
||||||
|
int m_signalStrength;
|
||||||
|
bool m_isProtected;
|
||||||
|
WirelessAccessPoint::ApSecurityModes m_securityFlags;
|
||||||
|
|
||||||
|
void setSsid(const QString &ssid);
|
||||||
|
void setMacAddress(const QString &macAddress);
|
||||||
|
void setFrequency(const double &frequency);
|
||||||
|
void setSignalStrength(const int &signalStrength);
|
||||||
|
void setIsProtected(const bool &isProtected);
|
||||||
|
void setSecurityFlags(const WirelessAccessPoint::ApSecurityModes &securityFlags);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void signalStrengthChanged();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onPropertiesChanged(const QVariantMap &properties);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, WirelessAccessPoint *accessPoint);
|
||||||
|
|
||||||
|
#endif // WIRELESSACCESSPOINT_H
|
||||||
211
libnymea-networkmanager/wirelessnetworkdevice.cpp
Normal file
211
libnymea-networkmanager/wirelessnetworkdevice.cpp
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
/*! \fn void WirelessNetworkDevice::bitRateChanged(const int &bitRate);
|
||||||
|
This signal will be emitted when the \a bitRate of this \l{WirelessNetworkDevice} has changed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \fn void WirelessNetworkDevice::stateChanged(const NetworkDeviceState &state);
|
||||||
|
This signal will be emitted when the current \a state of this \l{WirelessNetworkDevice} has changed.
|
||||||
|
|
||||||
|
\sa NetworkDeviceState
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "dbus-interfaces.h"
|
||||||
|
#include "wirelessnetworkdevice.h"
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
/*! Constructs a new \l{WirelessNetworkDevice} with the given dbus \a objectPath and \a parent. */
|
||||||
|
WirelessNetworkDevice::WirelessNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent) :
|
||||||
|
NetworkDevice(objectPath, parent),
|
||||||
|
m_activeAccessPoint(Q_NULLPTR)
|
||||||
|
{
|
||||||
|
QDBusConnection systemBus = QDBusConnection::systemBus();
|
||||||
|
if (!systemBus.isConnected()) {
|
||||||
|
qWarning() << "WirelessNetworkDevice: System DBus not connected";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_wirelessInterface = new QDBusInterface(networkManagerServiceString, this->objectPath().path(), wirelessInterfaceString, systemBus, this);
|
||||||
|
if (!m_wirelessInterface->isValid()) {
|
||||||
|
qWarning() << "WirelessNetworkDevice: Invalid wireless dbus interface";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, this->objectPath().path(), wirelessInterfaceString, "AccessPointAdded", this, SLOT(accessPointAdded(QDBusObjectPath)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, this->objectPath().path(), wirelessInterfaceString, "AccessPointRemoved", this, SLOT(accessPointRemoved(QDBusObjectPath)));
|
||||||
|
QDBusConnection::systemBus().connect(networkManagerServiceString, this->objectPath().path(), wirelessInterfaceString, "PropertiesChanged", this, SLOT(propertiesChanged(QVariantMap)));
|
||||||
|
|
||||||
|
readAccessPoints();
|
||||||
|
|
||||||
|
setMacAddress(m_wirelessInterface->property("HwAddress").toString());
|
||||||
|
setBitrate(m_wirelessInterface->property("Bitrate").toInt());
|
||||||
|
setActiveAccessPoint(qdbus_cast<QDBusObjectPath>(m_wirelessInterface->property("ActiveAccessPoint")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the mac address of this \l{WirelessNetworkDevice}. */
|
||||||
|
QString WirelessNetworkDevice::macAddress() const
|
||||||
|
{
|
||||||
|
return m_macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the bit rate [Mb/s] of this \l{WirelessNetworkDevice}. */
|
||||||
|
int WirelessNetworkDevice::bitRate() const
|
||||||
|
{
|
||||||
|
return m_bitRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the current active \l{WirelessAccessPoint} of this \l{WirelessNetworkDevice}. */
|
||||||
|
WirelessAccessPoint *WirelessNetworkDevice::activeAccessPoint()
|
||||||
|
{
|
||||||
|
return m_activeAccessPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Perform a wireless network scan on this \l{WirelessNetworkDevice}. */
|
||||||
|
void WirelessNetworkDevice::scanWirelessNetworks()
|
||||||
|
{
|
||||||
|
qDebug() << this << "Request scan";
|
||||||
|
QDBusMessage query = m_wirelessInterface->call("RequestScan", QVariantMap());
|
||||||
|
if (query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << "Scan error:" << query.errorName() << query.errorMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the list of all \l{WirelessAccessPoint}{WirelessAccessPoints} of this \l{WirelessNetworkDevice}. */
|
||||||
|
QList<WirelessAccessPoint *> WirelessNetworkDevice::accessPoints()
|
||||||
|
{
|
||||||
|
return m_accessPointsTable.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the \l{WirelessAccessPoint} with the given \a ssid. If the \l{WirelessAccessPoint} could not be found, return Q_NULLPTR. */
|
||||||
|
WirelessAccessPoint *WirelessNetworkDevice::getAccessPoint(const QString &ssid)
|
||||||
|
{
|
||||||
|
foreach (WirelessAccessPoint *accessPoint, m_accessPointsTable.values()) {
|
||||||
|
if (accessPoint->ssid() == ssid)
|
||||||
|
return accessPoint;
|
||||||
|
}
|
||||||
|
return Q_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Returns the \l{WirelessAccessPoint} with the given \a objectPath. If the \l{WirelessAccessPoint} could not be found, return Q_NULLPTR. */
|
||||||
|
WirelessAccessPoint *WirelessNetworkDevice::getAccessPoint(const QDBusObjectPath &objectPath)
|
||||||
|
{
|
||||||
|
return m_accessPointsTable.value(objectPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::readAccessPoints()
|
||||||
|
{
|
||||||
|
QDBusMessage query = m_wirelessInterface->call("GetAccessPoints");
|
||||||
|
if(query.type() != QDBusMessage::ReplyMessage) {
|
||||||
|
qWarning() << query.errorName() << query.errorMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.arguments().isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QDBusArgument &argument = query.arguments().at(0).value<QDBusArgument>();
|
||||||
|
argument.beginArray();
|
||||||
|
while (!argument.atEnd()) {
|
||||||
|
QDBusObjectPath accessPointObjectPath = qdbus_cast<QDBusObjectPath>(argument);
|
||||||
|
accessPointAdded(accessPointObjectPath);
|
||||||
|
}
|
||||||
|
argument.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::setMacAddress(const QString &macAddress)
|
||||||
|
{
|
||||||
|
m_macAddress = macAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::setBitrate(const int &bitRate)
|
||||||
|
{
|
||||||
|
if (m_bitRate != bitRate / 1000) {
|
||||||
|
m_bitRate = bitRate / 1000;
|
||||||
|
emit deviceChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::setActiveAccessPoint(const QDBusObjectPath &activeAccessPointObjectPath)
|
||||||
|
{
|
||||||
|
if (m_activeAccessPointObjectPath != activeAccessPointObjectPath) {
|
||||||
|
m_activeAccessPointObjectPath = activeAccessPointObjectPath;
|
||||||
|
if (m_accessPointsTable.contains(m_activeAccessPointObjectPath)) {
|
||||||
|
if (m_activeAccessPoint)
|
||||||
|
disconnect(m_activeAccessPoint, &WirelessAccessPoint::signalStrengthChanged, this, &WirelessNetworkDevice::deviceChanged);
|
||||||
|
|
||||||
|
// Set new access point object
|
||||||
|
m_activeAccessPoint = m_accessPointsTable.value(activeAccessPointObjectPath);
|
||||||
|
// Update the device when the signalstrength changed
|
||||||
|
connect(m_activeAccessPoint, &WirelessAccessPoint::signalStrengthChanged, this, &WirelessNetworkDevice::deviceChanged);
|
||||||
|
} else {
|
||||||
|
m_activeAccessPoint = Q_NULLPTR;
|
||||||
|
}
|
||||||
|
emit deviceChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::accessPointAdded(const QDBusObjectPath &objectPath)
|
||||||
|
{
|
||||||
|
QDBusInterface accessPointInterface(networkManagerServiceString, objectPath.path(), accessPointInterfaceString, QDBusConnection::systemBus());
|
||||||
|
if (!accessPointInterface.isValid()) {
|
||||||
|
qWarning() << "WirelessNetworkDevice: Invalid access point dbus interface";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_accessPointsTable.keys().contains(objectPath)) {
|
||||||
|
qWarning() << "WirelessNetworkDevice: Access point already added" << objectPath.path();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WirelessAccessPoint *accessPoint = new WirelessAccessPoint(objectPath, this);
|
||||||
|
//qDebug() << "WirelessNetworkDevice: [+]" << accessPoint;
|
||||||
|
m_accessPointsTable.insert(objectPath, accessPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::accessPointRemoved(const QDBusObjectPath &objectPath)
|
||||||
|
{
|
||||||
|
if (!m_accessPointsTable.keys().contains(objectPath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WirelessAccessPoint *accessPoint = m_accessPointsTable.take(objectPath);
|
||||||
|
if (accessPoint == m_activeAccessPoint)
|
||||||
|
m_activeAccessPoint = Q_NULLPTR;
|
||||||
|
|
||||||
|
//qDebug() << "WirelessNetworkDevice: [-]" << accessPoint;
|
||||||
|
accessPoint->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessNetworkDevice::propertiesChanged(const QVariantMap &properties)
|
||||||
|
{
|
||||||
|
//qDebug() << "WirelessNetworkDevice: Property changed" << properties;
|
||||||
|
|
||||||
|
if (properties.contains("Bitrate"))
|
||||||
|
setBitrate(properties.value("Bitrate").toInt());
|
||||||
|
|
||||||
|
if (properties.contains("ActiveAccessPoint"))
|
||||||
|
setActiveAccessPoint(qdbus_cast<QDBusObjectPath>(properties.value("ActiveAccessPoint")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Writes the given \a device to the given to \a debug. \sa WirelessNetworkDevice, */
|
||||||
|
QDebug operator<<(QDebug debug, WirelessNetworkDevice *device)
|
||||||
|
{
|
||||||
|
debug.nospace() << "WirelessNetworkDevice(" << device->interface() << ", ";
|
||||||
|
debug.nospace() << device->macAddress() << ", ";
|
||||||
|
debug.nospace() << device->bitRate() << " [Mb/s], ";
|
||||||
|
debug.nospace() << device->deviceStateString() << ") ";
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
74
libnymea-networkmanager/wirelessnetworkdevice.h
Normal file
74
libnymea-networkmanager/wirelessnetworkdevice.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef WIRELESSNETWORKMANAGER_H
|
||||||
|
#define WIRELESSNETWORKMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDBusConnection>
|
||||||
|
#include <QDBusInterface>
|
||||||
|
#include <QDBusMessage>
|
||||||
|
#include <QDBusContext>
|
||||||
|
#include <QDBusArgument>
|
||||||
|
|
||||||
|
#include "networkdevice.h"
|
||||||
|
#include "wirelessaccesspoint.h"
|
||||||
|
|
||||||
|
class WirelessNetworkDevice : public NetworkDevice
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit WirelessNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0);
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
QString macAddress() const;
|
||||||
|
int bitRate() const;
|
||||||
|
WirelessAccessPoint *activeAccessPoint();
|
||||||
|
|
||||||
|
// Accesspoints
|
||||||
|
QList<WirelessAccessPoint *> accessPoints();
|
||||||
|
WirelessAccessPoint *getAccessPoint(const QString &ssid);
|
||||||
|
WirelessAccessPoint *getAccessPoint(const QDBusObjectPath &objectPath);
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
void scanWirelessNetworks();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDBusInterface *m_wirelessInterface;
|
||||||
|
|
||||||
|
QString m_macAddress;
|
||||||
|
int m_bitRate;
|
||||||
|
WirelessAccessPoint *m_activeAccessPoint;
|
||||||
|
QDBusObjectPath m_activeAccessPointObjectPath;
|
||||||
|
|
||||||
|
QHash<QDBusObjectPath, WirelessAccessPoint *> m_accessPointsTable;
|
||||||
|
|
||||||
|
void readAccessPoints();
|
||||||
|
|
||||||
|
void setMacAddress(const QString &macAddress);
|
||||||
|
void setBitrate(const int &bitRate);
|
||||||
|
void setActiveAccessPoint(const QDBusObjectPath &activeAccessPointObjectPath);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void accessPointAdded(const QDBusObjectPath &objectPath);
|
||||||
|
void accessPointRemoved(const QDBusObjectPath &objectPath);
|
||||||
|
void propertiesChanged(const QVariantMap &properties);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void bitRateChanged(const int &bitRate);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug debug, WirelessNetworkDevice *device);
|
||||||
|
|
||||||
|
#endif // WIRELESSNETWORKMANAGER_H
|
||||||
6
nymea-networkmanager.pri
Normal file
6
nymea-networkmanager.pri
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
QMAKE_CXXFLAGS *= -Werror -std=c++1z -g
|
||||||
|
QMAKE_LFLAGS *= -std=c++1z
|
||||||
|
|
||||||
|
top_srcdir=$$PWD
|
||||||
|
top_builddir=$$shadowed($$PWD)
|
||||||
|
|
||||||
5
nymea-networkmanager.pro
Normal file
5
nymea-networkmanager.pro
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
TEMPLATE=subdirs
|
||||||
|
|
||||||
|
networkmanager.depends = libnymea-networkmanager
|
||||||
|
|
||||||
|
SUBDIRS += libnymea-networkmanager nymea-networkmanager
|
||||||
439
nymea-networkmanager/bluetooth/bluetoothserver.cpp
Normal file
439
nymea-networkmanager/bluetooth/bluetoothserver.cpp
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "bluetoothserver.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
#include "loopd.h"
|
||||||
|
#include "bluetoothuuids.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
BluetoothServer::BluetoothServer(const QString &machineId, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_machineId(machineId)
|
||||||
|
{
|
||||||
|
m_advertisingTimer = new QTimer(this);
|
||||||
|
m_advertisingTimer->setInterval(60000);
|
||||||
|
m_advertisingTimer->setSingleShot(true);
|
||||||
|
|
||||||
|
connect(m_advertisingTimer, &QTimer::timeout, this, &BluetoothServer::onAdvertisingTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
BluetoothServer::~BluetoothServer()
|
||||||
|
{
|
||||||
|
qCDebug(dcLoopd()) << "Destroy bluetooth server.";
|
||||||
|
if (m_controller)
|
||||||
|
m_controller->stopAdvertising();
|
||||||
|
|
||||||
|
if (m_localDevice)
|
||||||
|
m_localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BluetoothServer::running() const
|
||||||
|
{
|
||||||
|
return m_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BluetoothServer::connected() const
|
||||||
|
{
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyServiceData BluetoothServer::deviceInformationServiceData()
|
||||||
|
{
|
||||||
|
QLowEnergyServiceData serviceData;
|
||||||
|
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
|
||||||
|
serviceData.setUuid(QBluetoothUuid::DeviceInformation);
|
||||||
|
|
||||||
|
// Model number string 0x2a24
|
||||||
|
QLowEnergyCharacteristicData modelNumberCharData;
|
||||||
|
modelNumberCharData.setUuid(QBluetoothUuid::ModelNumberString);
|
||||||
|
if (m_machineId.isEmpty()) {
|
||||||
|
modelNumberCharData.setValue(QString("N.A.").toUtf8());
|
||||||
|
} else {
|
||||||
|
modelNumberCharData.setValue(m_machineId.toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
modelNumberCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(modelNumberCharData);
|
||||||
|
|
||||||
|
// Firmware revision string 0x2a26
|
||||||
|
QLowEnergyCharacteristicData firmwareRevisionCharData;
|
||||||
|
firmwareRevisionCharData.setUuid(QBluetoothUuid::FirmwareRevisionString);
|
||||||
|
firmwareRevisionCharData.setValue(QString("1.0.0").toUtf8());
|
||||||
|
firmwareRevisionCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(firmwareRevisionCharData);
|
||||||
|
|
||||||
|
// Hardware revision string 0x2a27
|
||||||
|
QLowEnergyCharacteristicData hardwareRevisionCharData;
|
||||||
|
hardwareRevisionCharData.setUuid(QBluetoothUuid::HardwareRevisionString);
|
||||||
|
hardwareRevisionCharData.setValue(QString("1.0.0").toUtf8());
|
||||||
|
hardwareRevisionCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(hardwareRevisionCharData);
|
||||||
|
|
||||||
|
#ifdef SNAPPY
|
||||||
|
// Software revision string 0x2a28
|
||||||
|
QLowEnergyCharacteristicData softwareRevisionCharData;
|
||||||
|
softwareRevisionCharData.setUuid(QBluetoothUuid::SoftwareRevisionString);
|
||||||
|
softwareRevisionCharData.setValue(qgetenv("SNAP_VERSION"));
|
||||||
|
softwareRevisionCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(softwareRevisionCharData);
|
||||||
|
#else
|
||||||
|
// Software revision string 0x2a28
|
||||||
|
QLowEnergyCharacteristicData softwareRevisionCharData;
|
||||||
|
softwareRevisionCharData.setUuid(QBluetoothUuid::SoftwareRevisionString);
|
||||||
|
softwareRevisionCharData.setValue(QCoreApplication::applicationVersion().toUtf8());
|
||||||
|
softwareRevisionCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(softwareRevisionCharData);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Manufacturer name string 0x2a29
|
||||||
|
QLowEnergyCharacteristicData manufacturerNameCharData;
|
||||||
|
manufacturerNameCharData.setUuid(QBluetoothUuid::ManufacturerNameString);
|
||||||
|
manufacturerNameCharData.setValue(QString("guh GmbH").toUtf8());
|
||||||
|
manufacturerNameCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(manufacturerNameCharData);
|
||||||
|
|
||||||
|
return serviceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyServiceData BluetoothServer::genericAccessServiceData()
|
||||||
|
{
|
||||||
|
QLowEnergyServiceData serviceData;
|
||||||
|
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
|
||||||
|
serviceData.setUuid(QBluetoothUuid::GenericAccess);
|
||||||
|
|
||||||
|
// Device name 0x2a00
|
||||||
|
QLowEnergyCharacteristicData nameCharData;
|
||||||
|
nameCharData.setUuid(QBluetoothUuid::DeviceName);
|
||||||
|
nameCharData.setValue(QString("Loop-box").toUtf8());
|
||||||
|
nameCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(nameCharData);
|
||||||
|
|
||||||
|
// Appearance 0x2a01
|
||||||
|
QLowEnergyCharacteristicData appearanceCharData;
|
||||||
|
appearanceCharData.setUuid(QBluetoothUuid::Appearance);
|
||||||
|
appearanceCharData.setValue(QByteArray(4, 0));
|
||||||
|
appearanceCharData.setProperties(QLowEnergyCharacteristic::Read);
|
||||||
|
serviceData.addCharacteristic(appearanceCharData);
|
||||||
|
|
||||||
|
// Peripheral Privacy Flag 0x2a02
|
||||||
|
QLowEnergyCharacteristicData privacyFlagCharData;
|
||||||
|
privacyFlagCharData.setUuid(QBluetoothUuid::PeripheralPrivacyFlag);
|
||||||
|
privacyFlagCharData.setValue(QByteArray(2, 0));
|
||||||
|
privacyFlagCharData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Write);
|
||||||
|
serviceData.addCharacteristic(privacyFlagCharData);
|
||||||
|
|
||||||
|
// Reconnection Address 0x2a03
|
||||||
|
QLowEnergyCharacteristicData reconnectionAddressCharData;
|
||||||
|
reconnectionAddressCharData.setUuid(QBluetoothUuid::ReconnectionAddress);
|
||||||
|
reconnectionAddressCharData.setValue(QByteArray());
|
||||||
|
reconnectionAddressCharData.setProperties(QLowEnergyCharacteristic::Write);
|
||||||
|
serviceData.addCharacteristic(reconnectionAddressCharData);
|
||||||
|
|
||||||
|
return serviceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyServiceData BluetoothServer::genericAttributeServiceData()
|
||||||
|
{
|
||||||
|
QLowEnergyServiceData serviceData;
|
||||||
|
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
|
||||||
|
serviceData.setUuid(QBluetoothUuid::GenericAttribute);
|
||||||
|
|
||||||
|
QLowEnergyCharacteristicData charData;
|
||||||
|
charData.setUuid(QBluetoothUuid::ServiceChanged);
|
||||||
|
charData.setProperties(QLowEnergyCharacteristic::Indicate);
|
||||||
|
|
||||||
|
serviceData.addCharacteristic(charData);
|
||||||
|
|
||||||
|
return serviceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::setRunning(const bool &running)
|
||||||
|
{
|
||||||
|
if (m_running == running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_running = running;
|
||||||
|
emit runningChanged(m_running);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::setConnected(const bool &connected)
|
||||||
|
{
|
||||||
|
if (m_connected == connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_connected = connected;
|
||||||
|
emit connectedChanged(m_connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onHostModeStateChanged(const QBluetoothLocalDevice::HostMode mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case QBluetoothLocalDevice::HostConnectable:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Bluetooth host in connectable mode.";
|
||||||
|
break;
|
||||||
|
case QBluetoothLocalDevice::HostDiscoverable:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Bluetooth host in discoverable mode.";
|
||||||
|
break;
|
||||||
|
case QBluetoothLocalDevice::HostPoweredOff:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Bluetooth host in power off mode.";
|
||||||
|
break;
|
||||||
|
case QBluetoothLocalDevice::HostDiscoverableLimitedInquiry:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Bluetooth host in discoverable limited inquiry mode.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onDeviceConnected(const QBluetoothAddress &address)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Device connected" << address.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onDeviceDisconnected(const QBluetoothAddress &address)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Device disconnected" << address.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onError(const QLowEnergyController::Error &error)
|
||||||
|
{
|
||||||
|
qCWarning(dcBluetoothServer()) << "Bluetooth error occured:" << error << m_controller->errorString();
|
||||||
|
if (error == QLowEnergyController::AdvertisingError) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "Advertising error: enable error mode";
|
||||||
|
Loopd::instance()->hardwareManager()->ledController()->setState(LedController::LedStateBlinkingFast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onConnected()
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Client connected" << m_controller->remoteName() << m_controller->remoteAddress();
|
||||||
|
setConnected(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onDisconnected()
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Client disconnected";
|
||||||
|
setConnected(false);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onControllerStateChanged(const QLowEnergyController::ControllerState &state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case QLowEnergyController::UnconnectedState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state disonnected.";
|
||||||
|
setConnected(false);
|
||||||
|
break;
|
||||||
|
case QLowEnergyController::ConnectingState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state connecting...";
|
||||||
|
setConnected(false);
|
||||||
|
m_advertisingTimer->stop();
|
||||||
|
break;
|
||||||
|
case QLowEnergyController::ConnectedState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state connected." << m_controller->remoteName() << m_controller->remoteAddress();
|
||||||
|
setConnected(true);
|
||||||
|
m_advertisingTimer->stop();
|
||||||
|
break;
|
||||||
|
case QLowEnergyController::DiscoveringState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state discovering...";
|
||||||
|
break;
|
||||||
|
case QLowEnergyController::DiscoveredState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state discovered.";
|
||||||
|
break;
|
||||||
|
case QLowEnergyController::ClosingState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state closing...";
|
||||||
|
break;
|
||||||
|
case QLowEnergyController::AdvertisingState:
|
||||||
|
qCDebug(dcBluetoothServer()) << "Controller state advertising...";
|
||||||
|
setRunning(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::onAdvertisingTimeout()
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Advertising timeout.";
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Service characteristic changed" << characteristic.uuid() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Service characteristic read" << characteristic.uuid() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Service characteristic written" << characteristic.uuid() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Descriptor read" << descriptor.uuid() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Descriptor written" << descriptor.uuid() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::serviceError(const QLowEnergyService::ServiceError &error)
|
||||||
|
{
|
||||||
|
QString errorString;
|
||||||
|
switch (error) {
|
||||||
|
case QLowEnergyService::NoError:
|
||||||
|
errorString = "No error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::OperationError:
|
||||||
|
errorString = "Operation error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicReadError:
|
||||||
|
errorString = "Characteristic read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicWriteError:
|
||||||
|
errorString = "Characteristic write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorReadError:
|
||||||
|
errorString = "Descriptor read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorWriteError:
|
||||||
|
errorString = "Descriptor write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::UnknownError:
|
||||||
|
errorString = "Unknown error";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorString = "Unhandled error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCWarning(dcBluetoothServer()) << "Service error:" << errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::start()
|
||||||
|
{
|
||||||
|
// Check if a user is connected
|
||||||
|
if (connected()) {
|
||||||
|
qCDebug(dcBluetoothServer()) << "User is connected. Doing nothing.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running()) {
|
||||||
|
qCDebug(dcBluetoothServer()) << "Already running. Restart advertise timer." << Loopd::instance()->advertisingTimeout() << "[s].";
|
||||||
|
m_localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable);
|
||||||
|
m_advertisingTimer->stop();
|
||||||
|
m_advertisingTimer->setSingleShot(true);
|
||||||
|
m_advertisingTimer->setInterval(Loopd::instance()->advertisingTimeout() * 1000);
|
||||||
|
m_advertisingTimer->start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "-------------------------------------";
|
||||||
|
qCDebug(dcBluetoothServer()) << "Starting bluetooth server for" << Loopd::instance()->advertisingTimeout() << "[s].";
|
||||||
|
m_advertisingTimer->stop();
|
||||||
|
m_advertisingTimer->setSingleShot(true);
|
||||||
|
m_advertisingTimer->setInterval(Loopd::instance()->advertisingTimeout() * 1000);
|
||||||
|
qCDebug(dcBluetoothServer()) << "-------------------------------------";
|
||||||
|
|
||||||
|
// Local bluetooth device
|
||||||
|
m_localDevice = new QBluetoothLocalDevice(this);
|
||||||
|
if (!m_localDevice->isValid()) {
|
||||||
|
qCCritical(dcBluetoothServer()) << "Local bluetooth device is not valid.";
|
||||||
|
m_advertisingTimer->stop();
|
||||||
|
delete m_localDevice;
|
||||||
|
m_localDevice = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(m_localDevice, &QBluetoothLocalDevice::hostModeStateChanged, this, &BluetoothServer::onHostModeStateChanged);
|
||||||
|
connect(m_localDevice, &QBluetoothLocalDevice::deviceConnected, this, &BluetoothServer::onDeviceConnected);
|
||||||
|
connect(m_localDevice, &QBluetoothLocalDevice::deviceDisconnected, this, &BluetoothServer::onDeviceDisconnected);
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "Local device" << m_localDevice->name() << m_localDevice->address().toString();
|
||||||
|
m_localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable);
|
||||||
|
m_localDevice->powerOn();
|
||||||
|
|
||||||
|
|
||||||
|
// Bluetooth low energy periperal controller
|
||||||
|
m_controller = QLowEnergyController::createPeripheral(this);
|
||||||
|
connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothServer::onControllerStateChanged);
|
||||||
|
connect(m_controller, &QLowEnergyController::connected, this, &BluetoothServer::onConnected);
|
||||||
|
connect(m_controller, &QLowEnergyController::disconnected, this, &BluetoothServer::onDisconnected);
|
||||||
|
connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onError(QLowEnergyController::Error)));
|
||||||
|
|
||||||
|
// Note: https://www.bluetooth.com/specifications/gatt/services
|
||||||
|
m_deviceInfoService = m_controller->addService(deviceInformationServiceData(), m_controller);
|
||||||
|
m_genericAccessService = m_controller->addService(genericAccessServiceData(), m_controller);
|
||||||
|
m_genericAttributeService = m_controller->addService(genericAttributeServiceData(), m_controller);
|
||||||
|
|
||||||
|
// Create services
|
||||||
|
m_networkService = new NetworkService(m_controller->addService(NetworkService::serviceData(), m_controller), m_controller);
|
||||||
|
m_wirelessService = new WirelessService(m_controller->addService(WirelessService::serviceData(), m_controller), m_controller);
|
||||||
|
m_systemService = new SystemService(m_controller->addService(SystemService::serviceData(), m_controller), m_controller);
|
||||||
|
|
||||||
|
QLowEnergyAdvertisingData advertisingData;
|
||||||
|
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
|
||||||
|
advertisingData.setIncludePowerLevel(true);
|
||||||
|
advertisingData.setLocalName("Loop-box");
|
||||||
|
// TODO: set guh manufacturer SIG data
|
||||||
|
|
||||||
|
|
||||||
|
// Note: start advertising in 100 ms interval, this makes the device better discoverable on certain phones
|
||||||
|
QLowEnergyAdvertisingParameters advertisingParameters;
|
||||||
|
advertisingParameters.setInterval(100,100);
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "Start advertising loopd" << m_localDevice->address().toString();
|
||||||
|
m_controller->startAdvertising(advertisingParameters, advertisingData, advertisingData);
|
||||||
|
|
||||||
|
// Start the advertising timer
|
||||||
|
m_advertisingTimer->start();
|
||||||
|
setRunning(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothServer::stop()
|
||||||
|
{
|
||||||
|
if (connected() && m_controller) {
|
||||||
|
m_controller->disconnectFromDevice();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "-------------------------------------";
|
||||||
|
qCDebug(dcBluetoothServer()) << "Stopping bluetooth server.";
|
||||||
|
qCDebug(dcBluetoothServer()) << "-------------------------------------";
|
||||||
|
|
||||||
|
if (m_controller) {
|
||||||
|
qCDebug(dcBluetoothServer()) << "Stop advertising.";
|
||||||
|
m_controller->stopAdvertising();
|
||||||
|
delete m_controller;
|
||||||
|
m_controller = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_localDevice) {
|
||||||
|
qCDebug(dcBluetoothServer()) << "Set host mode to connectable.";
|
||||||
|
m_localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable);
|
||||||
|
delete m_localDevice;
|
||||||
|
m_localDevice = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
setConnected(false);
|
||||||
|
setRunning(false);
|
||||||
|
}
|
||||||
|
|
||||||
103
nymea-networkmanager/bluetooth/bluetoothserver.h
Normal file
103
nymea-networkmanager/bluetooth/bluetoothserver.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef BLUETOOTHSERVER_H
|
||||||
|
#define BLUETOOTHSERVER_H
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QLowEnergyHandle>
|
||||||
|
#include <QLowEnergyService>
|
||||||
|
#include <QBluetoothLocalDevice>
|
||||||
|
#include <QLowEnergyController>
|
||||||
|
#include <QLowEnergyServiceData>
|
||||||
|
#include <QLowEnergyCharacteristic>
|
||||||
|
#include <QLowEnergyDescriptorData>
|
||||||
|
#include <QLowEnergyAdvertisingData>
|
||||||
|
#include <QLowEnergyCharacteristicData>
|
||||||
|
#include <QLowEnergyConnectionParameters>
|
||||||
|
#include <QLowEnergyAdvertisingParameters>
|
||||||
|
|
||||||
|
#include "networkservice.h"
|
||||||
|
#include "wirelessservice.h"
|
||||||
|
#include "systemservice.h"
|
||||||
|
#include "networkmanager/networkmanager.h"
|
||||||
|
|
||||||
|
class BluetoothServer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit BluetoothServer(const QString &machineId, QObject *parent = 0);
|
||||||
|
~BluetoothServer();
|
||||||
|
|
||||||
|
bool running() const;
|
||||||
|
bool connected() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_machineId;
|
||||||
|
QBluetoothLocalDevice *m_localDevice = nullptr;
|
||||||
|
QLowEnergyController *m_controller = nullptr;
|
||||||
|
|
||||||
|
QLowEnergyService *m_deviceInfoService = nullptr;
|
||||||
|
QLowEnergyService *m_genericAccessService = nullptr;
|
||||||
|
QLowEnergyService *m_genericAttributeService = nullptr;
|
||||||
|
|
||||||
|
NetworkService *m_networkService = nullptr;
|
||||||
|
WirelessService *m_wirelessService = nullptr;
|
||||||
|
SystemService *m_systemService = nullptr;
|
||||||
|
|
||||||
|
QTimer *m_advertisingTimer = nullptr;
|
||||||
|
|
||||||
|
bool m_running = false;
|
||||||
|
bool m_connected = false;
|
||||||
|
|
||||||
|
QLowEnergyServiceData deviceInformationServiceData();
|
||||||
|
QLowEnergyServiceData genericAccessServiceData();
|
||||||
|
QLowEnergyServiceData genericAttributeServiceData();
|
||||||
|
|
||||||
|
void setRunning(const bool &running);
|
||||||
|
void setConnected(const bool &connected);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void runningChanged(const bool &running);
|
||||||
|
void connectedChanged(const bool &connected);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
// Local bluetooth device
|
||||||
|
void onHostModeStateChanged(const QBluetoothLocalDevice::HostMode mode);
|
||||||
|
void onDeviceConnected(const QBluetoothAddress &address);
|
||||||
|
void onDeviceDisconnected(const QBluetoothAddress &address);
|
||||||
|
void onError(const QLowEnergyController::Error &error);
|
||||||
|
|
||||||
|
// Bluetooth controller
|
||||||
|
void onConnected();
|
||||||
|
void onDisconnected();
|
||||||
|
void onControllerStateChanged(const QLowEnergyController::ControllerState &state);
|
||||||
|
|
||||||
|
void onAdvertisingTimeout();
|
||||||
|
|
||||||
|
// Services
|
||||||
|
void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void serviceError(const QLowEnergyService::ServiceError &error);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BLUETOOTHSERVER_H
|
||||||
35
nymea-networkmanager/bluetooth/bluetoothuuids.h
Normal file
35
nymea-networkmanager/bluetooth/bluetoothuuids.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef BLUETOOTHUUIDS_H
|
||||||
|
#define BLUETOOTHUUIDS_H
|
||||||
|
|
||||||
|
#include <QBluetoothUuid>
|
||||||
|
|
||||||
|
static QBluetoothUuid networkServiceUuid = QBluetoothUuid(QUuid("ef6d6610-b8af-49e0-9eca-ab343513641c"));
|
||||||
|
static QBluetoothUuid networkStatusCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6611-b8af-49e0-9eca-ab343513641c"));
|
||||||
|
static QBluetoothUuid networkCommanderCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6612-b8af-49e0-9eca-ab343513641c"));
|
||||||
|
static QBluetoothUuid networkResponseCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6613-b8af-49e0-9eca-ab343513641c"));
|
||||||
|
static QBluetoothUuid networkingEnabledCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6614-b8af-49e0-9eca-ab343513641c"));
|
||||||
|
static QBluetoothUuid wirelessEnabledCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6615-b8af-49e0-9eca-ab343513641c"));
|
||||||
|
|
||||||
|
static QBluetoothUuid wirelessServiceUuid = QBluetoothUuid(QUuid("e081fec0-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
static QBluetoothUuid wirelessCommanderCharacteristicUuid = QBluetoothUuid(QUuid("e081fec1-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
static QBluetoothUuid wirelessResponseCharacteristicUuid = QBluetoothUuid(QUuid("e081fec2-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
static QBluetoothUuid wirelessStateCharacteristicUuid = QBluetoothUuid(QUuid("e081fec3-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
|
||||||
|
static QBluetoothUuid systemServiceUuid = QBluetoothUuid(QUuid("e081fed0-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
static QBluetoothUuid systemCommanderCharacteristicUuid = QBluetoothUuid(QUuid("e081fed1-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
static QBluetoothUuid systemResponseCharacteristicUuid = QBluetoothUuid(QUuid("e081fed2-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
static QBluetoothUuid systemUpdateCharacteristicUuid = QBluetoothUuid(QUuid("e081fed3-f757-4449-b9c9-bfa83133f7fc"));
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BLUETOOTHUUIDS_H
|
||||||
340
nymea-networkmanager/bluetooth/networkservice.cpp
Normal file
340
nymea-networkmanager/bluetooth/networkservice.cpp
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "networkservice.h"
|
||||||
|
#include "bluetoothuuids.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
#include "loopd.h"
|
||||||
|
|
||||||
|
#include <QLowEnergyDescriptorData>
|
||||||
|
#include <QLowEnergyCharacteristicData>
|
||||||
|
|
||||||
|
NetworkService::NetworkService(QLowEnergyService *service, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_service(service)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Create NetworkService.";
|
||||||
|
|
||||||
|
// Service
|
||||||
|
connect(m_service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(characteristicRead(QLowEnergyCharacteristic, QByteArray)), this, SLOT(characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(characteristicWritten(QLowEnergyCharacteristic, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), this, SLOT(descriptorWritten(QLowEnergyDescriptor, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(serviceError(QLowEnergyService::ServiceError)));
|
||||||
|
|
||||||
|
// NetworkManager
|
||||||
|
connect(Loopd::instance()->networkManager(), &NetworkManager::stateChanged, this, &NetworkService::onNetworkManagerStateChanged);
|
||||||
|
connect(Loopd::instance()->networkManager(), &NetworkManager::networkingEnabledChanged, this, &NetworkService::onNetworkingEnabledChanged);
|
||||||
|
connect(Loopd::instance()->networkManager(), &NetworkManager::wirelessEnabledChanged, this, &NetworkService::onWirelessEnabledChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyService *NetworkService::service()
|
||||||
|
{
|
||||||
|
return m_service;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyServiceData NetworkService::serviceData()
|
||||||
|
{
|
||||||
|
QLowEnergyServiceData serviceData;
|
||||||
|
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
|
||||||
|
serviceData.setUuid(networkServiceUuid);
|
||||||
|
|
||||||
|
QLowEnergyDescriptorData clientConfigDescriptorData(QBluetoothUuid::ClientCharacteristicConfiguration, QByteArray(2, 0));
|
||||||
|
|
||||||
|
// Network manager status ef6d661-b8af-49e0-9eca-ab343513641c
|
||||||
|
QLowEnergyCharacteristicData networkStatusData;
|
||||||
|
networkStatusData.setUuid(networkStatusCharacteristicUuid);
|
||||||
|
networkStatusData.setValue(QByteArray(1, 0));
|
||||||
|
networkStatusData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
|
||||||
|
networkStatusData.addDescriptor(clientConfigDescriptorData);
|
||||||
|
networkStatusData.setValue(NetworkService::getNetworkManagerStateByteArray(Loopd::instance()->networkManager()->state()));
|
||||||
|
serviceData.addCharacteristic(networkStatusData);
|
||||||
|
|
||||||
|
// Network manager commander ef6d6612-b8af-49e0-9eca-ab343513641c
|
||||||
|
QLowEnergyCharacteristicData networkCommanderCharacteristicData;
|
||||||
|
networkCommanderCharacteristicData.setUuid(networkCommanderCharacteristicUuid);
|
||||||
|
networkCommanderCharacteristicData.setProperties(QLowEnergyCharacteristic::Write);
|
||||||
|
networkCommanderCharacteristicData.setValueLength(1, 1);
|
||||||
|
serviceData.addCharacteristic(networkCommanderCharacteristicData);
|
||||||
|
|
||||||
|
// Response characteristic ef6d6613-b8af-49e0-9eca-ab343513641c
|
||||||
|
QLowEnergyCharacteristicData networkResponseCharacteristicData;
|
||||||
|
networkResponseCharacteristicData.setUuid(networkResponseCharacteristicUuid);
|
||||||
|
networkResponseCharacteristicData.setProperties(QLowEnergyCharacteristic::Notify);
|
||||||
|
networkResponseCharacteristicData.addDescriptor(clientConfigDescriptorData);
|
||||||
|
networkResponseCharacteristicData.setValueLength(1, 1);
|
||||||
|
serviceData.addCharacteristic(networkResponseCharacteristicData);
|
||||||
|
|
||||||
|
// Networking enabled ef6d6614-b8af-49e0-9eca-ab343513641c
|
||||||
|
QLowEnergyCharacteristicData networkingEnabledStatusData;
|
||||||
|
networkingEnabledStatusData.setUuid(networkingEnabledCharacteristicUuid);
|
||||||
|
networkingEnabledStatusData.setValue(QByteArray(1, 0));
|
||||||
|
networkingEnabledStatusData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
|
||||||
|
networkingEnabledStatusData.setValue(QByteArray::number((int)Loopd::instance()->networkManager()->networkingEnabled()));
|
||||||
|
serviceData.addCharacteristic(networkingEnabledStatusData);
|
||||||
|
|
||||||
|
// Wireless enabled ef6d6615-b8af-49e0-9eca-ab343513641c
|
||||||
|
QLowEnergyCharacteristicData wirelessEnabledStatusData;
|
||||||
|
wirelessEnabledStatusData.setUuid(wirelessEnabledCharacteristicUuid);
|
||||||
|
wirelessEnabledStatusData.setValue(QByteArray(1, 0));
|
||||||
|
wirelessEnabledStatusData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
|
||||||
|
wirelessEnabledStatusData.setValue(QByteArray::number((int)Loopd::instance()->networkManager()->wirelessEnabled()));
|
||||||
|
serviceData.addCharacteristic(wirelessEnabledStatusData);
|
||||||
|
|
||||||
|
return serviceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray NetworkService::getNetworkManagerStateByteArray(const NetworkManager::NetworkManagerState &state)
|
||||||
|
{
|
||||||
|
QByteArray networkManagerState;
|
||||||
|
switch (state) {
|
||||||
|
case NetworkManager::NetworkManagerStateUnknown:
|
||||||
|
networkManagerState = QByteArray::fromHex("00");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateAsleep:
|
||||||
|
networkManagerState = QByteArray::fromHex("01");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateDisconnected:
|
||||||
|
networkManagerState = QByteArray::fromHex("02");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateDisconnecting:
|
||||||
|
networkManagerState = QByteArray::fromHex("03");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateConnecting:
|
||||||
|
networkManagerState = QByteArray::fromHex("04");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateConnectedLocal:
|
||||||
|
networkManagerState = QByteArray::fromHex("05");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateConnectedSite:
|
||||||
|
networkManagerState = QByteArray::fromHex("06");
|
||||||
|
break;
|
||||||
|
case NetworkManager::NetworkManagerStateConnectedGlobal:
|
||||||
|
networkManagerState = QByteArray::fromHex("07");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return networkManagerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::sendResponse(const NetworkService::NetworkServiceResponse &response)
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not send response. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(networkResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not send response. Characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (response) {
|
||||||
|
case NetworkServiceResponseSuccess:
|
||||||
|
m_service->writeCharacteristic(characteristic, QByteArray::fromHex("00"));
|
||||||
|
break;
|
||||||
|
case NetworkServiceResponseIvalidValue:
|
||||||
|
m_service->writeCharacteristic(characteristic, QByteArray::fromHex("01"));
|
||||||
|
break;
|
||||||
|
case NetworkServiceResponseNetworkManagerNotAvailable:
|
||||||
|
m_service->writeCharacteristic(characteristic, QByteArray::fromHex("02"));
|
||||||
|
break;
|
||||||
|
case NetworkServiceResponseWirelessNotAvailable:
|
||||||
|
m_service->writeCharacteristic(characteristic, QByteArray::fromHex("03"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unknown error
|
||||||
|
m_service->writeCharacteristic(characteristic, QByteArray::fromHex("04"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkService::NetworkServiceCommand NetworkService::verifyCommand(const QByteArray &commandData)
|
||||||
|
{
|
||||||
|
if (commandData.length() != 1)
|
||||||
|
return NetworkServiceCommandInvalid;
|
||||||
|
|
||||||
|
uint commandInteger = commandData.toHex().toUInt(0, 16);
|
||||||
|
switch (commandInteger) {
|
||||||
|
case NetworkServiceCommandEnableNetworking:
|
||||||
|
return NetworkServiceCommandEnableNetworking;
|
||||||
|
case NetworkServiceCommandDisableNetworking:
|
||||||
|
return NetworkServiceCommandDisableNetworking;
|
||||||
|
case NetworkServiceCommandEnableWireless:
|
||||||
|
return NetworkServiceCommandEnableWireless;
|
||||||
|
case NetworkServiceCommandDisableWireless:
|
||||||
|
return NetworkServiceCommandDisableWireless;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NetworkServiceCommandInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
if (characteristic.uuid() == networkCommanderCharacteristicUuid) {
|
||||||
|
|
||||||
|
NetworkServiceCommand command = verifyCommand(value);
|
||||||
|
if (command == NetworkServiceCommandInvalid) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: received invalid command" << command;
|
||||||
|
sendResponse(NetworkServiceResponseIvalidValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Loopd::instance()->networkManager()->available()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Networkmanager not available";
|
||||||
|
sendResponse(NetworkServiceResponseNetworkManagerNotAvailable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processCommand(command);
|
||||||
|
|
||||||
|
sendResponse(NetworkServiceResponseSuccess);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Characteristic changed" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Characteristic read" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Characteristic written" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Descriptor read" << descriptor.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Descriptor written" << descriptor.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::serviceError(const QLowEnergyService::ServiceError &error)
|
||||||
|
{
|
||||||
|
QString errorString;
|
||||||
|
switch (error) {
|
||||||
|
case QLowEnergyService::NoError:
|
||||||
|
errorString = "No error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::OperationError:
|
||||||
|
errorString = "Operation error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicReadError:
|
||||||
|
errorString = "Characteristic read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicWriteError:
|
||||||
|
errorString = "Characteristic write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorReadError:
|
||||||
|
errorString = "Descriptor read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorWriteError:
|
||||||
|
errorString = "Descriptor write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::UnknownError:
|
||||||
|
errorString = "Unknown error";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorString = "Unhandled error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Error:" << errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkService::processCommand(const NetworkServiceCommand &command)
|
||||||
|
{
|
||||||
|
switch (command) {
|
||||||
|
case NetworkServiceCommandEnableNetworking:
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: received \"Enable networking\" command";
|
||||||
|
Loopd::instance()->networkManager()->enableNetworking(true);
|
||||||
|
break;
|
||||||
|
case NetworkServiceCommandDisableNetworking:
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: received \"Disable networking\" command";
|
||||||
|
Loopd::instance()->networkManager()->enableNetworking(false);
|
||||||
|
break;
|
||||||
|
case NetworkServiceCommandEnableWireless:
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: received \"Enable wireless networking\" command";
|
||||||
|
Loopd::instance()->networkManager()->enableWireless(true);
|
||||||
|
break;
|
||||||
|
case NetworkServiceCommandDisableWireless:
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: received \"Disable wireless networking\" command";
|
||||||
|
Loopd::instance()->networkManager()->enableWireless(false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Unhandled command" << command;
|
||||||
|
sendResponse(NetworkServiceResponseIvalidValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetworkService::onNetworkManagerStateChanged()
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not updatet network manager status. Service not valid";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(networkStatusCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not update network manager status. Characteristic not valid";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Notify state changed" << NetworkService::getNetworkManagerStateByteArray(Loopd::instance()->networkManager()->state());
|
||||||
|
m_service->writeCharacteristic(characteristic, NetworkService::getNetworkManagerStateByteArray(Loopd::instance()->networkManager()->state()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetworkService::onNetworkingEnabledChanged()
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not set networking enabled. Service not valid";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(networkingEnabledCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not set networking enabled. Characteristic not valid";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Notify networking enabled changed:" << (Loopd::instance()->networkManager()->networkingEnabled() ? "enabled" : "disabled");
|
||||||
|
m_service->writeCharacteristic(characteristic, Loopd::instance()->networkManager()->networkingEnabled() ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetworkService::onWirelessEnabledChanged()
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not set wireless enabled. Service not valid";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessEnabledCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "NetworkService: Could not set wireless enabled. Characteristic not valid";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "NetworkService: Notify wireless networking enabled changed:" << (Loopd::instance()->networkManager()->wirelessEnabled() ? "enabled" : "disabled");
|
||||||
|
m_service->writeCharacteristic(characteristic, Loopd::instance()->networkManager()->wirelessEnabled() ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
78
nymea-networkmanager/bluetooth/networkservice.h
Normal file
78
nymea-networkmanager/bluetooth/networkservice.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef NETWORKSERVICE_H
|
||||||
|
#define NETWORKSERVICE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QLowEnergyService>
|
||||||
|
#include <QLowEnergyServiceData>
|
||||||
|
|
||||||
|
#include "networkmanager/networkmanager.h"
|
||||||
|
|
||||||
|
class NetworkService : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_ENUMS(NetworkServiceCommand)
|
||||||
|
Q_ENUMS(NetworkServiceResponse)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum NetworkServiceCommand {
|
||||||
|
NetworkServiceCommandInvalid = -1,
|
||||||
|
NetworkServiceCommandEnableNetworking = 0x00,
|
||||||
|
NetworkServiceCommandDisableNetworking = 0x01,
|
||||||
|
NetworkServiceCommandEnableWireless = 0x02,
|
||||||
|
NetworkServiceCommandDisableWireless = 0x03
|
||||||
|
};
|
||||||
|
Q_ENUM(NetworkServiceCommand)
|
||||||
|
|
||||||
|
enum NetworkServiceResponse {
|
||||||
|
NetworkServiceResponseSuccess = 0x00,
|
||||||
|
NetworkServiceResponseIvalidValue = 0x01,
|
||||||
|
NetworkServiceResponseNetworkManagerNotAvailable = 0x02,
|
||||||
|
NetworkServiceResponseWirelessNotAvailable = 0x03,
|
||||||
|
NetworkServiceResponseUnknownError = 0x04,
|
||||||
|
};
|
||||||
|
Q_ENUM(NetworkServiceResponse)
|
||||||
|
|
||||||
|
explicit NetworkService(QLowEnergyService *service, QObject *parent = 0);
|
||||||
|
|
||||||
|
QLowEnergyService *service();
|
||||||
|
|
||||||
|
static QLowEnergyServiceData serviceData();
|
||||||
|
static QByteArray getNetworkManagerStateByteArray(const NetworkManager::NetworkManagerState &state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLowEnergyService *m_service;
|
||||||
|
void sendResponse(const NetworkServiceResponse &response);
|
||||||
|
|
||||||
|
NetworkServiceCommand verifyCommand(const QByteArray &commandData);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
// Service
|
||||||
|
void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void serviceError(const QLowEnergyService::ServiceError &error);
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
void processCommand(const NetworkServiceCommand &command);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool onNetworkManagerStateChanged();
|
||||||
|
bool onNetworkingEnabledChanged();
|
||||||
|
bool onWirelessEnabledChanged();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NETWORKSERVICE_H
|
||||||
256
nymea-networkmanager/bluetooth/systemservice.cpp
Normal file
256
nymea-networkmanager/bluetooth/systemservice.cpp
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
#include "systemservice.h"
|
||||||
|
#include "bluetoothuuids.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
#include "loopd.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QLowEnergyDescriptorData>
|
||||||
|
#include <QLowEnergyCharacteristicData>
|
||||||
|
|
||||||
|
SystemService::SystemService(QLowEnergyService *service, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_service(service)
|
||||||
|
{
|
||||||
|
connect(m_service, &QLowEnergyService::characteristicChanged, this, &SystemService::characteristicChanged);
|
||||||
|
connect(m_service, &QLowEnergyService::characteristicRead, this, &SystemService::characteristicChanged);
|
||||||
|
connect(m_service, &QLowEnergyService::characteristicWritten, this, &SystemService::characteristicWritten);
|
||||||
|
connect(m_service, &QLowEnergyService::descriptorWritten, this, &SystemService::descriptorWritten);
|
||||||
|
connect(m_service, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(serviceError(QLowEnergyService::ServiceError)));
|
||||||
|
|
||||||
|
connect(Loopd::instance()->snapdControl(), &SnapdControl::updateRunningChanged, this, &SystemService::onUpdateRunningChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyService *SystemService::service()
|
||||||
|
{
|
||||||
|
return m_service;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyServiceData SystemService::serviceData()
|
||||||
|
{
|
||||||
|
QLowEnergyServiceData serviceData;
|
||||||
|
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
|
||||||
|
serviceData.setUuid(systemServiceUuid);
|
||||||
|
|
||||||
|
QLowEnergyDescriptorData clientConfigDescriptorData(QBluetoothUuid::ClientCharacteristicConfiguration, QByteArray(2, 0));
|
||||||
|
|
||||||
|
// System commander characterisitc e081fed1-f757-4449-b9c9-bfa83133f7fc
|
||||||
|
QLowEnergyCharacteristicData systemCommanderCharacteristicData;
|
||||||
|
systemCommanderCharacteristicData.setUuid(systemCommanderCharacteristicUuid);
|
||||||
|
systemCommanderCharacteristicData.setProperties(QLowEnergyCharacteristic::Write);
|
||||||
|
systemCommanderCharacteristicData.setValueLength(0, 20);
|
||||||
|
serviceData.addCharacteristic(systemCommanderCharacteristicData);
|
||||||
|
|
||||||
|
// Response characterisitc e081fed2-f757-4449-b9c9-bfa83133f7fc
|
||||||
|
QLowEnergyCharacteristicData systemResponseCharacteristicData;
|
||||||
|
systemResponseCharacteristicData.setUuid(systemResponseCharacteristicUuid);
|
||||||
|
systemResponseCharacteristicData.setProperties(QLowEnergyCharacteristic::Notify);
|
||||||
|
systemResponseCharacteristicData.addDescriptor(clientConfigDescriptorData);
|
||||||
|
systemResponseCharacteristicData.setValueLength(0, 20);
|
||||||
|
serviceData.addCharacteristic(systemResponseCharacteristicData);
|
||||||
|
return serviceData;
|
||||||
|
|
||||||
|
// System update indicator characterisitc e081fed3-f757-4449-b9c9-bfa83133f7fc
|
||||||
|
QLowEnergyCharacteristicData systemUpdateCharacteristicData;
|
||||||
|
systemUpdateCharacteristicData.setUuid(systemUpdateCharacteristicUuid);
|
||||||
|
systemUpdateCharacteristicData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
|
||||||
|
systemUpdateCharacteristicData.addDescriptor(clientConfigDescriptorData);
|
||||||
|
systemUpdateCharacteristicData.setValueLength(1, 1);
|
||||||
|
systemUpdateCharacteristicData.setValue(QByteArray::number((int)Loopd::instance()->snapdControl()->updateRunning()));
|
||||||
|
serviceData.addCharacteristic(systemUpdateCharacteristicData);
|
||||||
|
return serviceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::streamData(const QVariantMap &responseMap)
|
||||||
|
{
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(systemResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: System response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray data = QJsonDocument::fromVariant(responseMap).toJson(QJsonDocument::Compact) + '\n';
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Start streaming response data:" << data.count() << "bytes";
|
||||||
|
|
||||||
|
int sentDataLength = 0;
|
||||||
|
QByteArray remainingData = data;
|
||||||
|
while (!remainingData.isEmpty()) {
|
||||||
|
QByteArray package = remainingData.left(20);
|
||||||
|
sentDataLength += package.count();
|
||||||
|
m_service->writeCharacteristic(characteristic, package);
|
||||||
|
remainingData = remainingData.remove(0, package.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Finished streaming response data";
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap SystemService::createResponse(const SystemService::SystemServiceCommand &command, const SystemService::SystemServiceResponse &responseCode)
|
||||||
|
{
|
||||||
|
QVariantMap response;
|
||||||
|
response.insert("c", (int)command);
|
||||||
|
response.insert("r", (int)responseCode);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
// Command
|
||||||
|
if (characteristic.uuid() == systemCommanderCharacteristicUuid) {
|
||||||
|
// Check if currently reading
|
||||||
|
if (m_readingInputData) {
|
||||||
|
m_inputDataStream.append(value);
|
||||||
|
} else {
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = true;
|
||||||
|
m_inputDataStream.append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If command finished
|
||||||
|
if (value.endsWith('\n')) {
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(m_inputDataStream, &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Got invalid json object" << m_inputDataStream;
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Got command stream" << jsonDocument.toJson();
|
||||||
|
|
||||||
|
processCommand(jsonDocument.toVariant().toMap());
|
||||||
|
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit possible data stream to prevent overflow
|
||||||
|
if (m_inputDataStream.length() >= 20 * 1024) {
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Characteristic read" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Characteristic written" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Descriptor read" << descriptor.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Descriptor written" << descriptor.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::serviceError(const QLowEnergyService::ServiceError &error)
|
||||||
|
{
|
||||||
|
QString errorString;
|
||||||
|
switch (error) {
|
||||||
|
case QLowEnergyService::NoError:
|
||||||
|
errorString = "No error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::OperationError:
|
||||||
|
errorString = "Operation error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicReadError:
|
||||||
|
errorString = "Characteristic read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicWriteError:
|
||||||
|
errorString = "Characteristic write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorReadError:
|
||||||
|
errorString = "Descriptor read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorWriteError:
|
||||||
|
errorString = "Descriptor write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::UnknownError:
|
||||||
|
errorString = "Unknown error";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorString = "Unhandled error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Error:" << errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::processCommand(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
if (!request.contains("c")) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Invalid request. Command value missing.";
|
||||||
|
streamData(createResponse(SystemServiceCommandPushAuthentication, SystemServiceResponseInvalidValue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool commandIntOk;
|
||||||
|
int command = request.value("c").toInt(&commandIntOk);
|
||||||
|
if (!commandIntOk) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Invalid request. Could not convert method to interger.";
|
||||||
|
streamData(createResponse(SystemServiceCommandPushAuthentication, SystemServiceResponseInvalidValue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process method
|
||||||
|
switch (command) {
|
||||||
|
case SystemServiceCommandPushAuthentication:
|
||||||
|
commandPressPushButton();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Invalid request. Unknown command" << command;
|
||||||
|
streamData(createResponse(SystemServiceCommandPushAuthentication, SystemServiceResponseInvalidCommand));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::commandPressPushButton()
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Could not press push button. Service not valid.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(systemResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: System response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Loopd::instance()->nymeaService()->available()) {
|
||||||
|
streamData(createResponse(SystemServiceCommandPushAuthentication, SystemServiceResponsePushServiceUnavailable));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loopd::instance()->nymeaService()->pushButtonPressed();
|
||||||
|
|
||||||
|
streamData(createResponse(SystemServiceCommandPushAuthentication, SystemServiceResponseSuccess));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemService::onUpdateRunningChanged(const bool &running)
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Could not set system update running characteristic. Service not valid.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(systemUpdateCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "SystemService: Could not set system update running characteristic. Characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "SystemService: Notify system update running changed:" << (running ? "running" : "finished");
|
||||||
|
m_service->writeCharacteristic(characteristic, running ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
61
nymea-networkmanager/bluetooth/systemservice.h
Normal file
61
nymea-networkmanager/bluetooth/systemservice.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef SYSTEMSERVICE_H
|
||||||
|
#define SYSTEMSERVICE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QLowEnergyService>
|
||||||
|
#include <QLowEnergyServiceData>
|
||||||
|
|
||||||
|
class SystemService : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum SystemServiceCommand {
|
||||||
|
SystemServiceCommandInvalid = -1,
|
||||||
|
SystemServiceCommandPushAuthentication = 0x00
|
||||||
|
};
|
||||||
|
Q_ENUM(SystemServiceCommand)
|
||||||
|
|
||||||
|
enum SystemServiceResponse {
|
||||||
|
SystemServiceResponseSuccess = 0x00,
|
||||||
|
SystemServiceResponseUnknownError = 0x01,
|
||||||
|
SystemServiceResponseInvalidCommand = 0x02,
|
||||||
|
SystemServiceResponseInvalidValue = 0x03,
|
||||||
|
SystemServiceResponsePushServiceUnavailable = 0x04,
|
||||||
|
};
|
||||||
|
Q_ENUM(SystemServiceResponse)
|
||||||
|
|
||||||
|
explicit SystemService(QLowEnergyService *service, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QLowEnergyService *service();
|
||||||
|
|
||||||
|
static QLowEnergyServiceData serviceData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLowEnergyService *m_service = nullptr;
|
||||||
|
|
||||||
|
bool m_readingInputData = false;
|
||||||
|
QByteArray m_inputDataStream;
|
||||||
|
|
||||||
|
void streamData(const QVariantMap &responseMap);
|
||||||
|
QVariantMap createResponse(const SystemServiceCommand &command, const SystemServiceResponse &responseCode = SystemServiceResponseSuccess);
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
// Service
|
||||||
|
void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void serviceError(const QLowEnergyService::ServiceError &error);
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
void processCommand(const QVariantMap &request);
|
||||||
|
|
||||||
|
// Push button authentication
|
||||||
|
void commandPressPushButton();
|
||||||
|
|
||||||
|
void onUpdateRunningChanged(const bool &running);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYSTEMSERVICE_H
|
||||||
500
nymea-networkmanager/bluetooth/wirelessservice.cpp
Normal file
500
nymea-networkmanager/bluetooth/wirelessservice.cpp
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "wirelessservice.h"
|
||||||
|
#include "bluetoothuuids.h"
|
||||||
|
#include "loggingcategory.h"
|
||||||
|
#include "loopd.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QNetworkInterface>
|
||||||
|
#include <QLowEnergyDescriptorData>
|
||||||
|
#include <QLowEnergyCharacteristicData>
|
||||||
|
|
||||||
|
WirelessService::WirelessService(QLowEnergyService *service, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_service(service),
|
||||||
|
m_device(nullptr),
|
||||||
|
m_readingInputData(false)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "Create WirelessService.";
|
||||||
|
|
||||||
|
// Service
|
||||||
|
connect(m_service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(characteristicRead(QLowEnergyCharacteristic, QByteArray)), this, SLOT(characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(characteristicWritten(QLowEnergyCharacteristic, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), this, SLOT(descriptorWritten(QLowEnergyDescriptor, QByteArray)));
|
||||||
|
connect(m_service, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(serviceError(QLowEnergyService::ServiceError)));
|
||||||
|
|
||||||
|
// Get the wireless network device if there is any
|
||||||
|
if (!Loopd::instance()->networkManager()->wirelessAvailable()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: There is no wireless network device available";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Using" << Loopd::instance()->networkManager()->wirelessNetworkDevices().first();
|
||||||
|
m_device = Loopd::instance()->networkManager()->wirelessNetworkDevices().first();
|
||||||
|
connect(m_device, &WirelessNetworkDevice::bitRateChanged, this, &WirelessService::onWirelessDeviceBitRateChanged);
|
||||||
|
connect(m_device, &WirelessNetworkDevice::stateChanged, this, &WirelessService::onWirelessDeviceStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyService *WirelessService::service()
|
||||||
|
{
|
||||||
|
return m_service;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyServiceData WirelessService::serviceData()
|
||||||
|
{
|
||||||
|
QLowEnergyServiceData serviceData;
|
||||||
|
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
|
||||||
|
serviceData.setUuid(wirelessServiceUuid);
|
||||||
|
|
||||||
|
QLowEnergyDescriptorData clientConfigDescriptorData(QBluetoothUuid::ClientCharacteristicConfiguration, QByteArray(2, 0));
|
||||||
|
|
||||||
|
// Wifi commander characterisitc e081fec1-f757-4449-b9c9-bfa83133f7fc
|
||||||
|
QLowEnergyCharacteristicData wirelessCommanderCharacteristicData;
|
||||||
|
wirelessCommanderCharacteristicData.setUuid(wirelessCommanderCharacteristicUuid);
|
||||||
|
wirelessCommanderCharacteristicData.setProperties(QLowEnergyCharacteristic::Write);
|
||||||
|
wirelessCommanderCharacteristicData.setValueLength(0, 20);
|
||||||
|
serviceData.addCharacteristic(wirelessCommanderCharacteristicData);
|
||||||
|
|
||||||
|
// Response characterisitc e081fec2-f757-4449-b9c9-bfa83133f7fc
|
||||||
|
QLowEnergyCharacteristicData wirelessResponseCharacteristicData;
|
||||||
|
wirelessResponseCharacteristicData.setUuid(wirelessResponseCharacteristicUuid);
|
||||||
|
wirelessResponseCharacteristicData.setProperties(QLowEnergyCharacteristic::Notify);
|
||||||
|
wirelessResponseCharacteristicData.addDescriptor(clientConfigDescriptorData);
|
||||||
|
wirelessResponseCharacteristicData.setValueLength(0, 20);
|
||||||
|
serviceData.addCharacteristic(wirelessResponseCharacteristicData);
|
||||||
|
|
||||||
|
// Wireless connection status characterisitc e081fec3-f757-4449-b9c9-bfa83133f7fc
|
||||||
|
QLowEnergyCharacteristicData wirelessStatusCharacteristicData;
|
||||||
|
wirelessStatusCharacteristicData.setUuid(wirelessStateCharacteristicUuid);
|
||||||
|
wirelessStatusCharacteristicData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
|
||||||
|
wirelessStatusCharacteristicData.addDescriptor(clientConfigDescriptorData);
|
||||||
|
wirelessStatusCharacteristicData.setValueLength(1, 1);
|
||||||
|
if (!Loopd::instance()->networkManager()->wirelessAvailable()) {
|
||||||
|
wirelessStatusCharacteristicData.setValue(WirelessService::getWirelessNetworkDeviceState(NetworkDevice::NetworkDeviceStateUnavailable));
|
||||||
|
} else {
|
||||||
|
wirelessStatusCharacteristicData.setValue(WirelessService::getWirelessNetworkDeviceState(Loopd::instance()->networkManager()->wirelessNetworkDevices().first()->deviceState()));
|
||||||
|
}
|
||||||
|
serviceData.addCharacteristic(wirelessStatusCharacteristicData);
|
||||||
|
|
||||||
|
return serviceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WirelessService::WirelessServiceResponse WirelessService::checkWirelessErrors()
|
||||||
|
{
|
||||||
|
// Check possible errors
|
||||||
|
if (!Loopd::instance()->networkManager()->available()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: The networkmanager is not available.";
|
||||||
|
return WirelessServiceResponseNetworkManagerNotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_device) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: There is no wireless device available.";
|
||||||
|
return WirelessServiceResponseWirelessNotAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Loopd::instance()->networkManager()->networkingEnabled()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Networking not enabled";
|
||||||
|
return WirelessServiceResponseNetworkingNotEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Loopd::instance()->networkManager()->wirelessEnabled()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless not enabled";
|
||||||
|
return WirelessServiceResponseWirelessNotEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WirelessServiceResponseSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray WirelessService::getWirelessNetworkDeviceState(const NetworkDevice::NetworkDeviceState &state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case NetworkDevice::NetworkDeviceStateUnknown:
|
||||||
|
return QByteArray::fromHex("00");
|
||||||
|
case NetworkDevice::NetworkDeviceStateUnmanaged:
|
||||||
|
return QByteArray::fromHex("01");
|
||||||
|
case NetworkDevice::NetworkDeviceStateUnavailable:
|
||||||
|
return QByteArray::fromHex("02");
|
||||||
|
case NetworkDevice::NetworkDeviceStateDisconnected:
|
||||||
|
return QByteArray::fromHex("03");
|
||||||
|
case NetworkDevice::NetworkDeviceStatePrepare:
|
||||||
|
return QByteArray::fromHex("04");
|
||||||
|
case NetworkDevice::NetworkDeviceStateConfig:
|
||||||
|
return QByteArray::fromHex("05");
|
||||||
|
case NetworkDevice::NetworkDeviceStateNeedAuth:
|
||||||
|
return QByteArray::fromHex("06");
|
||||||
|
case NetworkDevice::NetworkDeviceStateIpConfig:
|
||||||
|
return QByteArray::fromHex("07");
|
||||||
|
case NetworkDevice::NetworkDeviceStateIpCheck:
|
||||||
|
return QByteArray::fromHex("08");
|
||||||
|
case NetworkDevice::NetworkDeviceStateSecondaries:
|
||||||
|
return QByteArray::fromHex("09");
|
||||||
|
case NetworkDevice::NetworkDeviceStateActivated:
|
||||||
|
return QByteArray::fromHex("0a");
|
||||||
|
case NetworkDevice::NetworkDeviceStateDeactivating:
|
||||||
|
return QByteArray::fromHex("0b");
|
||||||
|
case NetworkDevice::NetworkDeviceStateFailed:
|
||||||
|
return QByteArray::fromHex("0c");
|
||||||
|
default:
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Unhandled wireless network device state." << state;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
return QByteArray::fromHex("00");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WirelessService::streamData(const QVariantMap &responseMap)
|
||||||
|
{
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray data = QJsonDocument::fromVariant(responseMap).toJson(QJsonDocument::Compact) + '\n';
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Start streaming response data:" << data.count() << "bytes";
|
||||||
|
|
||||||
|
int sentDataLength = 0;
|
||||||
|
QByteArray remainingData = data;
|
||||||
|
while (!remainingData.isEmpty()) {
|
||||||
|
QByteArray package = remainingData.left(20);
|
||||||
|
sentDataLength += package.count();
|
||||||
|
m_service->writeCharacteristic(characteristic, package);
|
||||||
|
remainingData = remainingData.remove(0, package.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Finished streaming response data";
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap WirelessService::createResponse(const WirelessService::WirelessServiceCommand &command, const WirelessService::WirelessServiceResponse &responseCode)
|
||||||
|
{
|
||||||
|
QVariantMap response;
|
||||||
|
response.insert("c", (int)command);
|
||||||
|
response.insert("r", (int)responseCode);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::commandGetNetworks(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not stream wireless network list. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList accessPointVariantList;
|
||||||
|
foreach (WirelessAccessPoint *accessPoint, m_device->accessPoints()) {
|
||||||
|
QVariantMap accessPointVariantMap;
|
||||||
|
accessPointVariantMap.insert("e", accessPoint->ssid());
|
||||||
|
accessPointVariantMap.insert("m", accessPoint->macAddress());
|
||||||
|
accessPointVariantMap.insert("s", accessPoint->signalStrength());
|
||||||
|
accessPointVariantMap.insert("p", (int)accessPoint->isProtected());
|
||||||
|
accessPointVariantList.append(accessPointVariantMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap response = createResponse(WirelessServiceCommandGetNetworks);
|
||||||
|
response.insert("p", accessPointVariantList);
|
||||||
|
|
||||||
|
streamData(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::commandConnect(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not stream wireless network list. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request.contains("p")) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Connect command: Missing parameters.";
|
||||||
|
streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidParameters));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap parameters = request.value("p").toMap();
|
||||||
|
if (!parameters.contains("e") || !parameters.contains("p")) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Connect command: Invalid parameters.";
|
||||||
|
streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidParameters));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loopd::instance()->networkManager()->connectWifi(m_device->interface(), parameters.value("e").toString(), parameters.value("p").toString());
|
||||||
|
streamData(createResponse(WirelessServiceCommandConnect));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::commandConnectHidden(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
// TODO:
|
||||||
|
qCWarning(dcBluetoothServer()) << "Connect to hidden network is not implemented yet.";
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::commandDisconnect(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not stream wireless network list. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device->disconnectDevice();
|
||||||
|
streamData(createResponse(WirelessServiceCommandDisconnect));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::commandScan(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not stream wireless network list. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device->scanWirelessNetworks();
|
||||||
|
streamData(createResponse(WirelessServiceCommandScan));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::commandGetCurrentConnection(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not stream wireless network list. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Wireless response characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap connectionDataMap;
|
||||||
|
QNetworkInterface wifiInterface = QNetworkInterface::interfaceFromName(m_device->interface());
|
||||||
|
if (!m_device->activeAccessPoint() || !wifiInterface.isValid() || wifiInterface.addressEntries().isEmpty()) {
|
||||||
|
qCDebug(dcBluetoothServer()) << "There is currently no access active accesspoint";
|
||||||
|
connectionDataMap.insert("e", "");
|
||||||
|
connectionDataMap.insert("m", "");
|
||||||
|
connectionDataMap.insert("s", 0);
|
||||||
|
connectionDataMap.insert("p", 0);
|
||||||
|
connectionDataMap.insert("i", "");
|
||||||
|
} else {
|
||||||
|
QHostAddress address = wifiInterface.addressEntries().first().ip();
|
||||||
|
qCDebug(dcBluetoothServer()) << "Current connection:" << m_device->activeAccessPoint() << address.toString();
|
||||||
|
connectionDataMap.insert("e", m_device->activeAccessPoint()->ssid());
|
||||||
|
connectionDataMap.insert("m", m_device->activeAccessPoint()->macAddress());
|
||||||
|
connectionDataMap.insert("s", m_device->activeAccessPoint()->signalStrength());
|
||||||
|
connectionDataMap.insert("p", (int)m_device->activeAccessPoint()->isProtected());
|
||||||
|
connectionDataMap.insert("i", address.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap response = createResponse(WirelessServiceCommandGetCurrentConnection);
|
||||||
|
response.insert("p", connectionDataMap);
|
||||||
|
streamData(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
// Command
|
||||||
|
if (characteristic.uuid() == wirelessCommanderCharacteristicUuid) {
|
||||||
|
// Check if currently reading
|
||||||
|
if (m_readingInputData) {
|
||||||
|
m_inputDataStream.append(value);
|
||||||
|
} else {
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = true;
|
||||||
|
m_inputDataStream.append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If command finished
|
||||||
|
if (value.endsWith('\n')) {
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(m_inputDataStream, &error);
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "Got invalid json object" << m_inputDataStream;
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(dcBluetoothServer()) << "Got command stream" << jsonDocument.toJson();
|
||||||
|
|
||||||
|
processCommand(jsonDocument.toVariant().toMap());
|
||||||
|
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit possible data stream to prevent overflow
|
||||||
|
if (m_inputDataStream.length() >= 20 * 1024) {
|
||||||
|
m_inputDataStream.clear();
|
||||||
|
m_readingInputData = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Characteristic read" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Characteristic written" << characteristic.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Descriptor read" << descriptor.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Descriptor written" << descriptor.uuid().toString() << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::serviceError(const QLowEnergyService::ServiceError &error)
|
||||||
|
{
|
||||||
|
QString errorString;
|
||||||
|
switch (error) {
|
||||||
|
case QLowEnergyService::NoError:
|
||||||
|
errorString = "No error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::OperationError:
|
||||||
|
errorString = "Operation error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicReadError:
|
||||||
|
errorString = "Characteristic read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::CharacteristicWriteError:
|
||||||
|
errorString = "Characteristic write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorReadError:
|
||||||
|
errorString = "Descriptor read error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::DescriptorWriteError:
|
||||||
|
errorString = "Descriptor write error";
|
||||||
|
break;
|
||||||
|
case QLowEnergyService::UnknownError:
|
||||||
|
errorString = "Unknown error";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorString = "Unhandled error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Error:" << errorString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::processCommand(const QVariantMap &request)
|
||||||
|
{
|
||||||
|
if (!request.contains("c")) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "Invalid request. Command value missing.";
|
||||||
|
streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidCommand));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool commandIntOk;
|
||||||
|
int command = request.value("c").toInt(&commandIntOk);
|
||||||
|
if (!commandIntOk) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "Invalid request. Could not convert method to interger.";
|
||||||
|
streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidCommand));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check wireless errors
|
||||||
|
WirelessServiceResponse responseCode = checkWirelessErrors();
|
||||||
|
if (responseCode != WirelessServiceResponseSuccess) {
|
||||||
|
streamData(createResponse((WirelessServiceCommand)command, responseCode));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process method
|
||||||
|
switch (command) {
|
||||||
|
case WirelessServiceCommandGetNetworks:
|
||||||
|
commandGetNetworks(request);
|
||||||
|
break;
|
||||||
|
case WirelessServiceCommandConnect:
|
||||||
|
commandConnect(request);
|
||||||
|
break;
|
||||||
|
case WirelessServiceCommandConnectHidden:
|
||||||
|
commandConnectHidden(request);
|
||||||
|
break;
|
||||||
|
case WirelessServiceCommandDisconnect:
|
||||||
|
commandDisconnect(request);
|
||||||
|
break;
|
||||||
|
case WirelessServiceCommandScan:
|
||||||
|
commandScan(request);
|
||||||
|
break;
|
||||||
|
case WirelessServiceCommandGetCurrentConnection:
|
||||||
|
commandGetCurrentConnection(request);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCWarning(dcBluetoothServer()) << "Invalid request. Unknown command" << command;
|
||||||
|
streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidCommand));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::onWirelessDeviceBitRateChanged(const int &bitRate)
|
||||||
|
{
|
||||||
|
Q_UNUSED(bitRate)
|
||||||
|
}
|
||||||
|
|
||||||
|
void WirelessService::onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState &state)
|
||||||
|
{
|
||||||
|
qCDebug(dcBluetoothServer()) << "WirelessService: Wireless network device state changed" << state;
|
||||||
|
|
||||||
|
if (!m_service) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not update wireless network device state. Service not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessStateCharacteristicUuid);
|
||||||
|
if (!characteristic.isValid()) {
|
||||||
|
qCWarning(dcBluetoothServer()) << "WirelessService: Could not update wireless network device state. Characteristic not valid";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_service->writeCharacteristic(characteristic, WirelessService::getWirelessNetworkDeviceState(state));
|
||||||
|
}
|
||||||
101
nymea-networkmanager/bluetooth/wirelessservice.h
Normal file
101
nymea-networkmanager/bluetooth/wirelessservice.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016 Simon Stürz <simon.stuerz@guh.io> *
|
||||||
|
* *
|
||||||
|
* This file is part of loopd. *
|
||||||
|
* *
|
||||||
|
* Loopd can not be copied and/or distributed without the express *
|
||||||
|
* permission of guh GmbH. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef WIRELESSSERVICE_H
|
||||||
|
#define WIRELESSSERVICE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QVariantMap>
|
||||||
|
#include <QLowEnergyService>
|
||||||
|
#include <QLowEnergyServiceData>
|
||||||
|
|
||||||
|
#include "networkmanager/wirelessnetworkdevice.h"
|
||||||
|
#include "networkmanager/wirelessaccesspoint.h"
|
||||||
|
|
||||||
|
class WirelessService : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_ENUMS(WirelessServiceCommand)
|
||||||
|
Q_ENUMS(WirelessServiceResponse)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum WirelessServiceCommand {
|
||||||
|
WirelessServiceCommandInvalid = -1,
|
||||||
|
WirelessServiceCommandGetNetworks = 0x00,
|
||||||
|
WirelessServiceCommandConnect = 0x01,
|
||||||
|
WirelessServiceCommandConnectHidden = 0x02,
|
||||||
|
WirelessServiceCommandDisconnect = 0x03,
|
||||||
|
WirelessServiceCommandScan = 0x04,
|
||||||
|
WirelessServiceCommandGetCurrentConnection = 0x05
|
||||||
|
};
|
||||||
|
Q_ENUM(WirelessServiceCommand)
|
||||||
|
|
||||||
|
enum WirelessServiceResponse {
|
||||||
|
WirelessServiceResponseSuccess = 0x00,
|
||||||
|
WirelessServiceResponseIvalidCommand = 0x01,
|
||||||
|
WirelessServiceResponseIvalidParameters = 0x02,
|
||||||
|
WirelessServiceResponseNetworkManagerNotAvailable = 0x03,
|
||||||
|
WirelessServiceResponseWirelessNotAvailable = 0x04,
|
||||||
|
WirelessServiceResponseWirelessNotEnabled = 0x05,
|
||||||
|
WirelessServiceResponseNetworkingNotEnabled = 0x06,
|
||||||
|
WirelessServiceResponseUnknownError = 0x07
|
||||||
|
};
|
||||||
|
Q_ENUM(WirelessServiceResponse)
|
||||||
|
|
||||||
|
explicit WirelessService(QLowEnergyService *service, QObject *parent = 0);
|
||||||
|
QLowEnergyService *service();
|
||||||
|
|
||||||
|
static QLowEnergyServiceData serviceData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QLowEnergyService *m_service;
|
||||||
|
WirelessNetworkDevice *m_device;
|
||||||
|
|
||||||
|
bool m_readingInputData;
|
||||||
|
QByteArray m_inputDataStream;
|
||||||
|
|
||||||
|
WirelessServiceResponse checkWirelessErrors();
|
||||||
|
|
||||||
|
// Note: static to be available in serviceData
|
||||||
|
static QByteArray getWirelessNetworkDeviceState(const NetworkDevice::NetworkDeviceState &state);
|
||||||
|
|
||||||
|
void streamData(const QVariantMap &responseMap);
|
||||||
|
|
||||||
|
QVariantMap createResponse(const WirelessServiceCommand &command, const WirelessServiceResponse &responseCode = WirelessServiceResponseSuccess);
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
void commandGetNetworks(const QVariantMap &request);
|
||||||
|
void commandConnect(const QVariantMap &request);
|
||||||
|
void commandConnectHidden(const QVariantMap &request);
|
||||||
|
void commandDisconnect(const QVariantMap &request);
|
||||||
|
void commandScan(const QVariantMap &request);
|
||||||
|
void commandGetCurrentConnection(const QVariantMap &request);
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
// Service
|
||||||
|
void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
|
||||||
|
void descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value);
|
||||||
|
void serviceError(const QLowEnergyService::ServiceError &error);
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
void processCommand(const QVariantMap &request);
|
||||||
|
|
||||||
|
// Wireless network device
|
||||||
|
void onWirelessDeviceBitRateChanged(const int &bitRate);
|
||||||
|
void onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState &state);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIRELESSSERVICE_H
|
||||||
29
nymea-networkmanager/core.cpp
Normal file
29
nymea-networkmanager/core.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
Core* Core::s_instance = 0;
|
||||||
|
|
||||||
|
Core *Core::instance()
|
||||||
|
{
|
||||||
|
if (!s_instance)
|
||||||
|
s_instance = new Core();
|
||||||
|
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::destroy()
|
||||||
|
{
|
||||||
|
if (s_instance)
|
||||||
|
delete s_instance;
|
||||||
|
|
||||||
|
s_instance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::Core(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_networkManager = new NetworkManager(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
29
nymea-networkmanager/core.h
Normal file
29
nymea-networkmanager/core.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef CORE_H
|
||||||
|
#define CORE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "networkmanager.h"
|
||||||
|
|
||||||
|
class Core : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static Core* instance();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit Core(QObject *parent = nullptr);
|
||||||
|
static Core *s_instance;
|
||||||
|
|
||||||
|
NetworkManager *m_networkManager = nullptr;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CORE_H
|
||||||
12
nymea-networkmanager/main.cpp
Normal file
12
nymea-networkmanager/main.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
|
||||||
|
Core::instance();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
31
nymea-networkmanager/nymea-networkmanager.pro
Normal file
31
nymea-networkmanager/nymea-networkmanager.pro
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
include(../nymea-networkmanager.pri)
|
||||||
|
|
||||||
|
TARGET = nymea-networkmanager
|
||||||
|
|
||||||
|
QT += core network bluetooth dbus
|
||||||
|
QT -= gui
|
||||||
|
|
||||||
|
CONFIG += console
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
INCLUDEPATH += $$top_srcdir/libnymea-networkmanager/
|
||||||
|
LIBS += -L$$top_builddir/libnymea-networkmanager/ -lnymea-networkmanager1
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
core.h \
|
||||||
|
bluetooth/bluetoothserver.h \
|
||||||
|
bluetooth/networkservice.h \
|
||||||
|
bluetooth/bluetoothuuids.h \
|
||||||
|
bluetooth/wirelessservice.h \
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp \
|
||||||
|
core.cpp \
|
||||||
|
bluetooth/bluetoothserver.cpp \
|
||||||
|
bluetooth/networkservice.cpp \
|
||||||
|
bluetooth/wirelessservice.cpp \
|
||||||
|
|
||||||
|
target.path = /usr/bin
|
||||||
|
INSTALLS += target
|
||||||
Reference in New Issue
Block a user