First version of automatic network-manager bluetooth service

This commit is contained in:
Simon Stürz 2018-03-12 15:47:04 +01:00
parent bf509677eb
commit e0ca87ef39
11 changed files with 142 additions and 64 deletions

View File

@ -55,6 +55,7 @@ public:
NetworkDeviceStateDeactivating = 110,
NetworkDeviceStateFailed = 120
};
Q_ENUM(NetworkDeviceState)
enum NetworkDeviceStateReason {
NetworkDeviceStateReasonNone = 0,
@ -121,6 +122,7 @@ public:
NetworkDeviceStateReasonParentChanged = 61,
NetworkDeviceStateReasonParentManagedChanged = 62
};
Q_ENUM(NetworkDeviceStateReason)
enum NetworkDeviceType {
NetworkDeviceTypeUnknown = 0,
@ -143,6 +145,7 @@ public:
NetworkDeviceTypeVXLan = 19,
NetworkDeviceTypeVEth = 20,
};
Q_ENUM(NetworkDeviceType)
explicit NetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0);

View File

@ -127,7 +127,7 @@ NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &i
QVariantMap connectionSettings;
connectionSettings.insert("autoconnect", true);
connectionSettings.insert("id", ssid + " (loop)");
connectionSettings.insert("id", ssid);
connectionSettings.insert("uuid", QUuid::createUuid().toString().remove("{").remove("}"));
connectionSettings.insert("type", "802-11-wireless");
@ -229,25 +229,6 @@ bool NetworkManager::enableWireless(bool enabled)
return m_networkManagerInterface->setProperty("WirelessEnabled", enabled);
}
bool NetworkManager::isConnectedToLan() const
{
// Check all wireless devices if one is connected
foreach (WirelessNetworkDevice *wirelessDevice, wirelessNetworkDevices()) {
if (wirelessDevice->deviceState() == NetworkDevice::NetworkDeviceStateActivated) {
return true;
}
}
// Check all wired devices if one is connected
foreach (WiredNetworkDevice *wiredDevice, wiredNetworkDevices()) {
if (wiredDevice->deviceState() == NetworkDevice::NetworkDeviceStateActivated) {
return true;
}
}
return false;
}
void NetworkManager::loadDevices()
{
// Get network devices
@ -312,7 +293,7 @@ void NetworkManager::setWirelessEnabled(bool enabled)
qCDebug(dcNetworkManager()) << "Wireless networking" << (enabled ? "enabled" : "disabled");
m_wirelessEnabled = enabled;
emit wirelessEnabledChanged();
emit wirelessEnabledChanged(m_wirelessEnabled);
}
void NetworkManager::setConnectivityState(const NetworkManager::NetworkManagerConnectivityState &connectivityState)
@ -322,7 +303,7 @@ void NetworkManager::setConnectivityState(const NetworkManager::NetworkManagerCo
qCDebug(dcNetworkManager()) << "Connectivity state changed:" << networkManagerConnectivityStateToString(connectivityState);
m_connectivityState = connectivityState;
emit connectivityStateChanged();
emit connectivityStateChanged(m_connectivityState);
}
void NetworkManager::setState(const NetworkManager::NetworkManagerState &state)
@ -332,7 +313,7 @@ void NetworkManager::setState(const NetworkManager::NetworkManagerState &state)
qCDebug(dcNetworkManager()) << "State changed:" << networkManagerStateToString(state);
m_state = state;
emit stateChanged();
emit stateChanged(m_state);
}
void NetworkManager::onServiceRegistered()
@ -408,7 +389,7 @@ void NetworkManager::onDeviceRemoved(const QDBusObjectPath &deviceObjectPath)
qCDebug(dcNetworkManager()) << "[-]" << m_wirelessNetworkDevices.value(deviceObjectPath);
m_wirelessNetworkDevices.remove(deviceObjectPath);
if (!wirelessAvailable())
emit wirelessAvailableChanged();
emit wirelessAvailableChanged(wirelessAvailable());
emit wirelessDeviceRemoved(networkDevice->interface());
} else {

View File

@ -55,14 +55,16 @@ public:
NetworkManagerStateConnectedSite = 60,
NetworkManagerStateConnectedGlobal = 70
};
Q_ENUM(NetworkManagerState)
enum NetworkManagerConnectivityState {
NetworkManagerConnectivityStateUnknown = 1,
NetworkManagerConnectivityStateNone = 2,
NetworkManagerConnectivityStatePortal = 3,
NetworkManagerConnectivityStateLimited = 4,
NetworkManagerConnectivityStateFull = 5
NetworkManagerConnectivityStateUnknown = 0,
NetworkManagerConnectivityStateNone = 1,
NetworkManagerConnectivityStatePortal = 2,
NetworkManagerConnectivityStateLimited = 3,
NetworkManagerConnectivityStateFull = 4
};
Q_ENUM(NetworkManagerConnectivityState)
enum NetworkManagerError {
NetworkManagerErrorNoError,
@ -76,6 +78,7 @@ public:
NetworkManagerErrorNetworkingDisabled,
NetworkManagerErrorNetworkManagerNotAvailable
};
Q_ENUM(NetworkManagerError)
explicit NetworkManager(QObject *parent = 0);
~NetworkManager();
@ -105,10 +108,6 @@ public:
bool wirelessEnabled() const;
bool enableWireless(bool enabled);
// Status methods
bool isConnectedToLan() const;
bool isOnline() const;
private:
QDBusServiceWatcher *m_serviceWatcher = nullptr;
QDBusInterface *m_networkManagerInterface = nullptr;
@ -119,9 +118,7 @@ private:
QHash<QDBusObjectPath, WiredNetworkDevice *> m_wiredNetworkDevices;
bool m_available = false;
QString m_version;
NetworkManagerState m_state = NetworkManagerStateUnknown;
NetworkManagerConnectivityState m_connectivityState = NetworkManagerConnectivityStateUnknown;
bool m_networkingEnabled = false;
@ -143,10 +140,10 @@ signals:
void availableChanged(bool available);
void versionChanged(const QString &version);
void networkingEnabledChanged(bool enabled);
void wirelessEnabledChanged();
void wirelessAvailableChanged();
void stateChanged();
void connectivityStateChanged();
void wirelessEnabledChanged(bool enabled);
void wirelessAvailableChanged(bool available);
void stateChanged(const NetworkManagerState &state);
void connectivityStateChanged(const NetworkManagerConnectivityState &state);
void wirelessDeviceAdded(WirelessNetworkDevice *wirelessDevice);
void wirelessDeviceRemoved(const QString &interface);

View File

@ -36,7 +36,7 @@ class WirelessAccessPoint : public QObject
Q_FLAGS(ApSecurityModes)
public:
enum ApSecurityMode{
enum ApSecurityMode {
ApSecurityModeNone = 0x000,
ApSecurityModePairWep40 = 0x001,
ApSecurityModePairWep104 = 0x002,
@ -51,7 +51,6 @@ public:
};
Q_DECLARE_FLAGS(ApSecurityModes, ApSecurityMode)
explicit WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent = 0);
QDBusObjectPath objectPath() const;

View File

@ -155,7 +155,7 @@ QLowEnergyServiceData BluetoothServer::genericAttributeServiceData()
return serviceData;
}
void BluetoothServer::setRunning(const bool &running)
void BluetoothServer::setRunning(bool running)
{
if (m_running == running)
return;
@ -164,7 +164,7 @@ void BluetoothServer::setRunning(const bool &running)
emit runningChanged(m_running);
}
void BluetoothServer::setConnected(const bool &connected)
void BluetoothServer::setConnected(bool connected)
{
if (m_connected == connected)
return;
@ -218,7 +218,6 @@ void BluetoothServer::onDisconnected()
{
qCDebug(dcBluetoothServer()) << "Client disconnected";
setConnected(false);
stop();
}
void BluetoothServer::onControllerStateChanged(const QLowEnergyController::ControllerState &state)
@ -367,14 +366,14 @@ void BluetoothServer::start(WirelessNetworkDevice *wirelessDevice)
QLowEnergyAdvertisingData advertisingData;
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setIncludePowerLevel(true);
advertisingData.setLocalName("Loop-box");
advertisingData.setLocalName("nymea");
// 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();
qCDebug(dcBluetoothServer()) << "Start advertising" << advertisingData.localName() << m_localDevice->address().toString();
m_controller->startAdvertising(advertisingParameters, advertisingData, advertisingData);
}
@ -385,6 +384,9 @@ void BluetoothServer::stop()
return;
}
if (!running())
return;
qCDebug(dcBluetoothServer()) << "-------------------------------------";
qCDebug(dcBluetoothServer()) << "Stopping bluetooth server.";
qCDebug(dcBluetoothServer()) << "-------------------------------------";

View File

@ -72,12 +72,12 @@ private:
QLowEnergyServiceData genericAccessServiceData();
QLowEnergyServiceData genericAttributeServiceData();
void setRunning(const bool &running);
void setConnected(const bool &connected);
void setRunning(bool running);
void setConnected(bool connected);
signals:
void runningChanged(const bool &running);
void connectedChanged(const bool &connected);
void runningChanged(bool running);
void connectedChanged(bool connected);
private slots:
// Local bluetooth device

View File

@ -45,23 +45,40 @@ NetworkManager *Core::networkManager() const
return m_networkManager;
}
BluetoothServer *Core::bluetoothServer() const
{
return m_bluetoothServer;
}
NymeadService *Core::nymeaService() const
{
return m_nymeaService;
}
Core::Core(QObject *parent) :
QObject(parent)
{
m_networkManager = new NetworkManager(this);
connect(m_networkManager, &NetworkManager::availableChanged, this, &Core::onNetworkManagerAvailableChanged);
connect(m_networkManager, &NetworkManager::stateChanged, this, &Core::onNetworkManagerStateChanged);
m_bluetoothServer = new BluetoothServer("nymea", this);
m_bluetoothServer = new BluetoothServer("nymea-box", this);
connect(m_bluetoothServer, &BluetoothServer::runningChanged, this, &Core::onBluetoothServerRunningChanged);
connect(m_bluetoothServer, &BluetoothServer::connectedChanged, this, &Core::onBluetoothServerConnectedChanged);
m_nymeaService = new NymeadService(false, this);
// Start the networkmanager service
if (!m_networkManager->start()) {
qCWarning(dcApplication()) << "Could not start network manager.";
qCWarning(dcApplication()) << "Could not start network manager. The service is not available. Make sure the network-manager is installed and running.";
}
}
Core::~Core()
{
delete m_nymeaService;
m_nymeaService = nullptr;
delete m_networkManager;
m_networkManager = nullptr;
@ -69,12 +86,80 @@ Core::~Core()
m_bluetoothServer = nullptr;
}
void Core::evaluateNetworkManagerState(const NetworkManager::NetworkManagerState &state)
{
switch (state) {
case NetworkManager::NetworkManagerStateConnectedGlobal:
// We are online
stopService();
break;
case NetworkManager::NetworkManagerStateConnectedSite:
// We somehow in the network
stopService();
break;
default:
// Everything else is not connected, start the service
startService();
break;
}
}
void Core::startService()
{
if (!m_networkManager->available())
return;
// Verify if we have a wireless network available
if (!m_networkManager->wirelessAvailable()) {
qCWarning(dcApplication()) << "Could not start services. There is no wireless device available.";
return;
}
// Disable bluetooth on nymea in order to not crash with client connections
m_nymeaService->enableBluetooth(false);
// Start the bluetooth server for this wireless device
qCDebug(dcApplication()) << "Start bluetooth service";
m_bluetoothServer->start(m_networkManager->wirelessNetworkDevices().first());
}
void Core::stopService()
{
if (m_bluetoothServer->running())
qCDebug(dcApplication()) << "Stop bluetooth service";
m_bluetoothServer->stop();
}
void Core::onBluetoothServerRunningChanged(bool running)
{
qCDebug(dcApplication()) << "Bluetooth server" << (running ? "started" : "stopped");
if (!running) {
// Enable bluetooth on nymea
m_nymeaService->enableBluetooth(true);
}
}
void Core::onBluetoothServerConnectedChanged(bool connected)
{
qCDebug(dcApplication()) << "Bluetooth client" << (connected ? "connected" : "disconnected");
}
void Core::onNetworkManagerAvailableChanged(const bool &available)
{
if (!available) {
qCWarning(dcApplication()) << "Networkmanager is not available any more.";
} else {
qCDebug(dcApplication()) << "Networkmanager is now available.";
stopService();
return;
}
qCDebug(dcApplication()) << "Networkmanager is now available.";
evaluateNetworkManagerState(m_networkManager->state());
}
void Core::onNetworkManagerStateChanged(const NetworkManager::NetworkManagerState &state)
{
qCDebug(dcApplication()) << state;
evaluateNetworkManagerState(state);
}

View File

@ -36,6 +36,8 @@ public:
void destroy();
NetworkManager *networkManager() const;
BluetoothServer *bluetoothServer() const;
NymeadService *nymeaService() const;
private:
explicit Core(QObject *parent = nullptr);
@ -47,8 +49,17 @@ private:
BluetoothServer *m_bluetoothServer = nullptr;
NymeadService *m_nymeaService = nullptr;
void evaluateNetworkManagerState(const NetworkManager::NetworkManagerState &state);
void startService();
void stopService();
private slots:
void onBluetoothServerRunningChanged(bool running);
void onBluetoothServerConnectedChanged(bool connected);
void onNetworkManagerAvailableChanged(const bool &available);
void onNetworkManagerStateChanged(const NetworkManager::NetworkManagerState &state);
};

View File

@ -88,15 +88,15 @@ int main(int argc, char *argv[])
parser.addVersionOption();
parser.setApplicationDescription(QString("\nThis daemon allows to configure a wifi network using a bluetooth low energy connection.\n\nCopyright %1 2018 Simon Stürz <simon.stuerz@guh.io>").arg(QChar(0xA9)));
// TODO: set options
QCommandLineOption debugOption(QStringList() << "d" << "debug", "Enable more debug output.");
parser.addOption(debugOption);
parser.process(application);
// Enable debug categories
s_loggingFilters.insert("Application", true);
s_loggingFilters.insert("BluetoothServer", true);
s_loggingFilters.insert("NetworkManager", true);
s_loggingFilters.insert("NymeaService", true);
s_loggingFilters.insert("BluetoothServer", parser.isSet(debugOption));
s_loggingFilters.insert("NetworkManager", parser.isSet(debugOption) );
s_loggingFilters.insert("NymeaService", parser.isSet(debugOption));
QLoggingCategory::installFilter(loggingCategoryFilter);

View File

@ -32,7 +32,7 @@ bool NymeadService::available() const
void NymeadService::enableBluetooth(const bool &enable)
{
if (!m_nymeadHardwareInterface) {
qCCritical(dcNymeaService()) << "Could not enable/disable bluetooth hardware resource. D-Bus interface not available.";
qCWarning(dcNymeaService()) << "Could not enable/disable bluetooth hardware resource. D-Bus interface not available.";
return;
}
@ -48,7 +48,7 @@ void NymeadService::enableBluetooth(const bool &enable)
void NymeadService::pushButtonPressed()
{
if (!m_pushButtonAgent) {
qCCritical(dcNymeaService()) << "Could not press pushbutton. Pushbutton agent not available.";
qCWarning(dcNymeaService()) << "Could not press pushbutton. Pushbutton agent not available.";
return;
}

View File

@ -14,14 +14,14 @@ bool PushButtonAgent::init(QDBusConnection::BusType busType)
{
QDBusConnection bus = busType == QDBusConnection::SessionBus ? QDBusConnection::sessionBus() : QDBusConnection::systemBus();
bool result = bus.registerObject("/io/guh/loopd/pushbutton", this, QDBusConnection::ExportScriptableContents);
bool result = bus.registerObject("/io/nymea/nymea-networkmanager/pushbutton", this, QDBusConnection::ExportScriptableContents);
if (!result) {
qCWarning(dcNymeaService()) << "PushButtonAgent: Error registering PushButton agent on D-Bus.";
return false;
}
QDBusMessage message = QDBusMessage::createMethodCall("io.guh.nymead", "/io/guh/nymead/UserManager", QString(), "RegisterButtonAgent");
message << qVariantFromValue(QDBusObjectPath("/io/guh/loopd/pushbutton"));
message << qVariantFromValue(QDBusObjectPath("/io/nymea/nymea-networkmanager/pushbutton"));
QDBusMessage reply = bus.call(message);
if (!reply.errorName().isEmpty()) {
qCWarning(dcNymeaService()) << "PushButtonAgent: Error registering PushButton agent:" << reply.errorMessage();