Initial structure

This commit is contained in:
Simon Stürz 2018-03-05 20:37:40 +01:00
commit d6db317347
32 changed files with 4230 additions and 0 deletions

73
.gitignore vendored Normal file
View 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

View 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

View 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})
}

View 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;
}

View 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

View 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;
}

View 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

View 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);
}

View 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

View 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;
}

View 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

View 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;
}

View 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

View 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" ) << ")";
}

View 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

View 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;
}

View 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
View 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
View File

@ -0,0 +1,5 @@
TEMPLATE=subdirs
networkmanager.depends = libnymea-networkmanager
SUBDIRS += libnymea-networkmanager nymea-networkmanager

View 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);
}

View 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

View 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

View 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;
}

View 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

View 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;
}

View 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

View 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));
}

View 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

View 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);
}

View 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

View 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();
}

View 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