diff --git a/README.md b/README.md index 501cf32..add43d9 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,6 @@ Note: Command line parameters will have higher priority than entries in the conf In order to connect to nymea-networkmanager using bluetooth low energy, once has to perform a bluetooth discovery, filter for all low energy devices and connect to the device with the name `nymea`. The remote address type for connecting to `nymea-networkmanager` is `public`. -## Behaviour - ## Notifications @@ -81,20 +79,20 @@ enabling and `0x0000` for disabling to the descriptor `0x2902` of the correspond > **W** = Write; **R** = Read; **N** = Notify -#### **S**: Generic Access +### **S**: Generic Access > Default service for Bluetooth LE GATT devices. More information can be found [here](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.generic_access.xml). -#### **S**: Generic Attribute +### **S**: Generic Attribute > Default service for Bluetooth LE GATT devices. More information can be found [here](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.generic_attribute.xml). -#### **S**: Device Information +### **S**: Device Information > Default service for Bluetooth LE GATT devices. More information can be found [here](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.device_information.xml). -#### **S**: Wireless service `e081fec0-f757-4449-b9c9-bfa83133f7fc` +### **S**: Wireless service `e081fec0-f757-4449-b9c9-bfa83133f7fc` The *Wireless Service* allows a client to configure and monitor a wireless network connection. The connection can be controlled with the *Wireless commander* characteristic. Each command sent will generate a respone on the *Comander response* characteristic containing the error code for the command. The *Wireless connection status* characteristic informs the client about the current connection status of the wireless device. @@ -105,6 +103,7 @@ The *Wireless Service* allows a client to configure and monitor a wireless netwo | Wireless commander | `e081fec1-f757-4449-b9c9-bfa83133f7fc` | **W** | Controll what the wifi manager should do. | Commander response | `e081fec2-f757-4449-b9c9-bfa83133f7fc` | **N** | This characteristic will be used to inform about the command result (error reporting). | Wireless connection status | `e081fec3-f757-4449-b9c9-bfa83133f7fc` | **RN** | Informs about the current wireless connection status. +| Wireless mode | `e081fec4-f757-4449-b9c9-bfa83133f7fc` | **RN** | Informs about the current mode of the wireless device. **Characteristic details** @@ -151,14 +150,15 @@ In following example you can find the basic structure of a command and a respons #### Methods -| Value | Name | Description -| ------ | -------------- | ---------------------------------------------------- -| `0` | GetNetworks | Get the current wifi network list on the "Wireless data stream". -| `1` | Connect | Connect to the network with the given ssid and password in **C** `e081fec4` and **C** `e081fec5`. If the network is open, set the password characteristic to an empty string. -| `2` | ConnectHidden | Connect to the hidden network using the given ssid and password in **C** `e081fec4` and **C** `e081fec5`. -| `3` | Disconnect | Disconnect from current wireless network. -| `4` | Scan | Perform a wireless accesspoint scan. -| `5` | GetConnection | Get the current connection information on the "Wireless data stream" +| Value | Name | Description +| ------ | ----------------- | ---------------------------------------------------- +| `0` | GetNetworks | Get the current wifi network list on the "Wireless data stream". +| `1` | Connect | Connect to the network with the given ssid and password in **C** `e081fec4` and **C** `e081fec5`. If the network is open, set the password characteristic to an empty string. +| `2` | ConnectHidden | Connect to the hidden network using the given ssid and password in **C** `e081fec4` and **C** `e081fec5`. +| `3` | Disconnect | Disconnect from current wireless network. +| `4` | Scan | Perform a wireless accesspoint scan. +| `5` | GetConnection | Get the current connection information on the "Wireless data stream" +| `6` | StartAccessPoint | Start a wireless access point. ##### - GetNetworks (0) @@ -192,9 +192,8 @@ In following example you can find the basic structure of a command and a respons { "c": 1, // Command: Connect "p": { - "e": "Wifi SSID" // The SSID of the wifi access point you want to connect to + "e": "Wifi SSID", // The SSID of the wifi access point you want to connect to "p": "Wifi password" // The password of the access point you want to connect to - } } @@ -213,7 +212,7 @@ In following example you can find the basic structure of a command and a respons { "c": 2, // Command: ConnectHidden "p": { - "e": "Wifi SSID" // The SSID of the wifi access point you want to connect to + "e": "Wifi SSID", // The SSID of the wifi access point you want to connect to "p": "Wifi password" // The password of the access point you want to connect to } @@ -282,6 +281,26 @@ In following example you can find the basic structure of a command and a respons } +##### - StartAccessPoint (6) + +- Request + + { + "c": 6, // Command: StartAccessPoint + "p": { + "e": "Access Point SSID", // The SSID of the wifi access point you want to create + "p": "Wireless access point password" // The password of the access point you want to create + } + } + + +- Response + + { + "c": 6, // Integer: Command: describing the method called + "r": 0 // Integer: Response error code. See list of response error codes. + } + @@ -318,7 +337,21 @@ In following example you can find the basic structure of a command and a respons | `0x0C` | Failed | The device failed to connect to the requested network and is cleaning up the connection request. -#### **S**: Network service `ef6d6610-b8af-49e0-9eca-ab343513641c` +- **C**: *Wireless mode* (RN) `e081fec4-f757-4449-b9c9-bfa83133f7fc` + + - *Description*: This characteristic represents the current state of the wireless adapter. + - *Range*: 1 Byte, Hex value + - *Possible values*: + +| Value | Name | Description +| ------ | --------------- | ---------------------------------------------------- +| `0x00` | Unknown | The device mode is unknown. +| `0x01` | Adhoc | For both devices and access point objects, indicates the object is part of an Ad-Hoc 802.11 network without a central coordinating access point. +| `0x02` | Infrastructure | The device or access point is in infrastructure mode. For devices, this indicates the device is an 802.11 client/station. +| `0x03` | AccessPoint | The device is an access point/hotspot. + + +### **S**: Network service `ef6d6610-b8af-49e0-9eca-ab343513641c` This service allows to monitor and configure the `network-manager` daemon running on the system. diff --git a/debian/changelog b/debian/changelog index ae7bf05..3ed4409 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,17 @@ -nymea-networkmanager (0.2.0) UNRELEASED; urgency=medium +nymea-networkmanager (0.3.1) UNRELEASED; urgency=medium + + * Fix modes for access-point + + -- Simon Stürz Thu, 22 Nov 2018 12:50:56 +0100 + +nymea-networkmanager (0.3.0) stretch; urgency=medium + + * Add access point mode for creating wireless access points + * Add once mode + + -- Simon Stürz Mon, 29 Oct 2018 14:46:56 +0100 + +nymea-networkmanager (0.2.0) stretch; urgency=medium * Add support for a config file diff --git a/libnymea-networkmanager/networkconnection.cpp b/libnymea-networkmanager/networkconnection.cpp index 31244ea..a81a358 100644 --- a/libnymea-networkmanager/networkconnection.cpp +++ b/libnymea-networkmanager/networkconnection.cpp @@ -30,8 +30,6 @@ NetworkConnection::NetworkConnection(const QDBusObjectPath &objectPath, QObject QObject(parent), m_objectPath(objectPath) { - qDBusRegisterMetaType(); - m_connectionInterface = new QDBusInterface(NetworkManagerUtils::networkManagerServiceString(), m_objectPath.path(), NetworkManagerUtils::connectionsInterfaceString(), QDBusConnection::systemBus(), this); if(!m_connectionInterface->isValid()) { qCWarning(dcNetworkManager()) << "Invalid connection dbus interface"; @@ -49,6 +47,10 @@ NetworkConnection::NetworkConnection(const QDBusObjectPath &objectPath, QObject const QDBusArgument &argument = query.arguments().at(0).value(); m_connectionSettings = qdbus_cast(argument); + +// foreach (const QVariant &connectionVariant, m_connectionSettings.values()) { +// qCDebug(dcNetworkManager()) << connectionVariant; +// } } /*! Delete this \l{NetworkConnection} in the \l{NetworkManager}. */ @@ -60,6 +62,12 @@ void NetworkConnection::deleteConnection() } +void NetworkConnection::registerTypes() +{ + qRegisterMetaType("ConnectionSettings"); + qDBusRegisterMetaType(); +} + /*! Returns the dbus object path of this \l{NetworkConnection}. */ QDBusObjectPath NetworkConnection::objectPath() const { diff --git a/libnymea-networkmanager/networkconnection.h b/libnymea-networkmanager/networkconnection.h index 70506f0..8da6d84 100644 --- a/libnymea-networkmanager/networkconnection.h +++ b/libnymea-networkmanager/networkconnection.h @@ -38,10 +38,12 @@ class NetworkConnection : public QObject { Q_OBJECT public: - explicit NetworkConnection(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit NetworkConnection(const QDBusObjectPath &objectPath, QObject *parent = nullptr); void deleteConnection(); + static void registerTypes(); + QDBusObjectPath objectPath() const; ConnectionSettings connectionSettings() const; @@ -60,6 +62,7 @@ private: ConnectionSettings m_connectionSettings; }; +Q_DECLARE_METATYPE(ConnectionSettings) QDebug operator<<(QDebug debug, NetworkConnection *networkConnection); #endif // NETWORKCONNECTION_H diff --git a/libnymea-networkmanager/networkdevice.h b/libnymea-networkmanager/networkdevice.h index 222f069..f381c1b 100644 --- a/libnymea-networkmanager/networkdevice.h +++ b/libnymea-networkmanager/networkdevice.h @@ -147,7 +147,7 @@ public: }; Q_ENUM(NetworkDeviceType) - explicit NetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit NetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = nullptr); QDBusObjectPath objectPath() const; diff --git a/libnymea-networkmanager/networkmanager.cpp b/libnymea-networkmanager/networkmanager.cpp index 6c2795b..18d7d1f 100644 --- a/libnymea-networkmanager/networkmanager.cpp +++ b/libnymea-networkmanager/networkmanager.cpp @@ -30,11 +30,12 @@ NetworkManager::NetworkManager(QObject *parent) : QObject(parent) { + NetworkConnection::registerTypes(); + // Get notification when network-manager appears/disappears on DBus m_serviceWatcher = new QDBusServiceWatcher(NetworkManagerUtils::networkManagerServiceString(), QDBusConnection::systemBus(), QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this); connect(m_serviceWatcher, &QDBusServiceWatcher::serviceRegistered, this, &NetworkManager::onServiceRegistered); connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &NetworkManager::onServiceUnregistered); - } NetworkManager::~NetworkManager() @@ -71,7 +72,13 @@ QList 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. */ +/*! Returns the \l{NetworkSettings} from this \l{NetworkManager}. */ +NetworkSettings *NetworkManager::networkSettings() const +{ + return m_networkSettings; +} + +/*! Returns the \l{NetworkDevice} with the given \a interface from this \l{NetworkManager}. If there is no such \a interface returns nullptr. */ NetworkDevice *NetworkManager::getNetworkDevice(const QString &interface) { foreach (NetworkDevice *device, m_networkDevices.values()) { @@ -113,10 +120,11 @@ NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &i return NetworkManagerErrorNetworkInterfaceNotFound; // Get wirelessNetworkDevice - WirelessNetworkDevice *wirelessNetworkDevice = 0; + WirelessNetworkDevice *wirelessNetworkDevice = nullptr; foreach (WirelessNetworkDevice *networkDevice, wirelessNetworkDevices()) { - if (networkDevice->interface() == interface) + if (networkDevice->interface() == interface) { wirelessNetworkDevice = networkDevice; + } } if (!wirelessNetworkDevice) @@ -129,6 +137,7 @@ NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &i // Note: https://developer.gnome.org/NetworkManager/stable/ref-settings.html + // Create network settings for this wifi QVariantMap connectionSettings; connectionSettings.insert("autoconnect", true); connectionSettings.insert("id", ssid); @@ -178,7 +187,92 @@ NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &i // Activate connection QDBusMessage query = m_networkManagerInterface->call("ActivateConnection", QVariant::fromValue(connectionObjectPath), QVariant::fromValue(wirelessNetworkDevice->objectPath()), QVariant::fromValue(accessPoint->objectPath())); - if(query.type() != QDBusMessage::ReplyMessage) { + if (query.type() != QDBusMessage::ReplyMessage) { + qCWarning(dcNetworkManager()) << query.errorName() << query.errorMessage(); + return NetworkManagerErrorWirelessConnectionFailed; + } + + return NetworkManagerErrorNoError; +} + +NetworkManager::NetworkManagerError NetworkManager::startAccessPoint(const QString &interface, const QString &ssid, const QString &password) +{ + qCDebug(dcNetworkManager()) << "Start an access point for" << interface << "SSID:" << ssid << "password:" << password; + + // Check interface + if (!getNetworkDevice(interface)) + return NetworkManagerErrorNetworkInterfaceNotFound; + + // Get wirelessNetworkDevice + WirelessNetworkDevice *wirelessNetworkDevice = nullptr; + foreach (WirelessNetworkDevice *networkDevice, wirelessNetworkDevices()) { + if (networkDevice->interface() == interface) { + wirelessNetworkDevice = networkDevice; + } + } + + if (!wirelessNetworkDevice) + return NetworkManagerErrorInvalidNetworkDeviceType; + + + // Note: https://developer.gnome.org/NetworkManager/stable/ref-settings.html + + // Create network settings for access point + QVariantMap connectionSettings; + connectionSettings.insert("id", ssid); + connectionSettings.insert("autoconnect", false); + connectionSettings.insert("uuid", QUuid::createUuid().toString().remove("{").remove("}")); + connectionSettings.insert("type", "802-11-wireless"); + + QVariantMap wirelessSettings; + wirelessSettings.insert("band", "bg"); + wirelessSettings.insert("mode", "ap"); + wirelessSettings.insert("ssid", ssid.toUtf8()); + wirelessSettings.insert("security", "802-11-wireless-security"); + // Note: disable power save mode + wirelessSettings.insert("powersave", 2); + + QVariantMap wirelessSecuritySettings; + wirelessSecuritySettings.insert("key-mgmt", "wpa-psk"); + wirelessSecuritySettings.insert("psk", password); + + QVariantMap ipv4Settings; + ipv4Settings.insert("method", "shared"); + + 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; + + + qCDebug(dcNetworkManager()) << "Connection added" << connectionObjectPath.path(); + + // + + // Activate connection + QDBusMessage query = m_networkManagerInterface->call("ActivateConnection", + QVariant::fromValue(connectionObjectPath), + QVariant::fromValue(wirelessNetworkDevice->objectPath()), + QVariant::fromValue(QDBusObjectPath("/"))); + if (query.type() != QDBusMessage::ReplyMessage) { qCWarning(dcNetworkManager()) << query.errorName() << query.errorMessage(); return NetworkManagerErrorWirelessConnectionFailed; } @@ -258,8 +352,8 @@ bool NetworkManager::init() // Init properties setVersion(m_networkManagerInterface->property("Version").toString()); - setState((NetworkManagerState)m_networkManagerInterface->property("State").toUInt()); - setConnectivityState((NetworkManagerConnectivityState)m_networkManagerInterface->property("Connectivity").toUInt()); + setState(static_cast(m_networkManagerInterface->property("State").toUInt())); + setConnectivityState(static_cast(m_networkManagerInterface->property("Connectivity").toUInt())); setNetworkingEnabled(m_networkManagerInterface->property("NetworkingEnabled").toBool()); setWirelessEnabled(m_networkManagerInterface->property("WirelessEnabled").toBool()); @@ -486,7 +580,7 @@ void NetworkManager::onPropertiesChanged(const QVariantMap &properties) setVersion(properties.value("Version").toString()); if (properties.contains("State")) - setState((NetworkManagerState)properties.value("State").toUInt()); + setState(static_cast(properties.value("State").toUInt())); if (properties.contains("Connectivity")) setConnectivityState(NetworkManagerConnectivityState(properties.value("Connectivity").toUInt())); diff --git a/libnymea-networkmanager/networkmanager.h b/libnymea-networkmanager/networkmanager.h index 12e336f..5e21a89 100644 --- a/libnymea-networkmanager/networkmanager.h +++ b/libnymea-networkmanager/networkmanager.h @@ -41,8 +41,8 @@ class NetworkManager : public QObject { Q_OBJECT Q_ENUMS(NetworkManagerState) - Q_ENUMS(NetworkManagerConnectivityState) Q_ENUMS(NetworkManagerError) + Q_ENUMS(NetworkManagerConnectivityState) public: enum NetworkManagerState { @@ -80,7 +80,7 @@ public: }; Q_ENUM(NetworkManagerError) - explicit NetworkManager(QObject *parent = 0); + explicit NetworkManager(QObject *parent = nullptr); ~NetworkManager(); bool available() const; @@ -90,6 +90,7 @@ public: QList wirelessNetworkDevices() const; QList wiredNetworkDevices() const; + NetworkSettings *networkSettings() const; NetworkDevice *getNetworkDevice(const QString &interface); // Properties @@ -99,6 +100,7 @@ public: NetworkManagerConnectivityState connectivityState() const; NetworkManagerError connectWifi(const QString &interface, const QString &ssid, const QString &password, bool hidden = false); + NetworkManagerError startAccessPoint(const QString &interface, const QString &ssid, const QString &password); // Networking bool networkingEnabled() const; diff --git a/libnymea-networkmanager/networksettings.h b/libnymea-networkmanager/networksettings.h index 05ff477..f1b56ab 100644 --- a/libnymea-networkmanager/networksettings.h +++ b/libnymea-networkmanager/networksettings.h @@ -36,7 +36,7 @@ class NetworkSettings : public QObject { Q_OBJECT public: - explicit NetworkSettings(QObject *parent = 0); + explicit NetworkSettings(QObject *parent = nullptr); QDBusObjectPath addConnection(const ConnectionSettings &settings); QList connections() const; diff --git a/libnymea-networkmanager/wirednetworkdevice.h b/libnymea-networkmanager/wirednetworkdevice.h index 02ce8d9..10d22fd 100644 --- a/libnymea-networkmanager/wirednetworkdevice.h +++ b/libnymea-networkmanager/wirednetworkdevice.h @@ -31,7 +31,7 @@ class WiredNetworkDevice : public NetworkDevice { Q_OBJECT public: - explicit WiredNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit WiredNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = nullptr); QString macAddress() const; int bitRate() const; diff --git a/libnymea-networkmanager/wirelessaccesspoint.cpp b/libnymea-networkmanager/wirelessaccesspoint.cpp index 7d5f2b4..c74e4ac 100644 --- a/libnymea-networkmanager/wirelessaccesspoint.cpp +++ b/libnymea-networkmanager/wirelessaccesspoint.cpp @@ -43,8 +43,7 @@ /*! 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) + m_objectPath(objectPath) { QDBusInterface accessPointInterface(NetworkManagerUtils::networkManagerServiceString(), m_objectPath.path(), NetworkManagerUtils::accessPointInterfaceString(), QDBusConnection::systemBus()); if(!accessPointInterface.isValid()) { @@ -56,9 +55,9 @@ WirelessAccessPoint::WirelessAccessPoint(const QDBusObjectPath &objectPath, QObj setSsid(accessPointInterface.property("Ssid").toString()); setMacAddress(accessPointInterface.property("HwAddress").toString()); setFrequency(accessPointInterface.property("Frequency").toDouble() / 1000); - setSignalStrength(accessPointInterface.property("Strength").toUInt()); + setSignalStrength(accessPointInterface.property("Strength").toInt()); setSecurityFlags(WirelessAccessPoint::ApSecurityModes(accessPointInterface.property("WpaFlags").toUInt())); - setIsProtected((bool)accessPointInterface.property("Flags").toUInt()); + setIsProtected(static_cast(accessPointInterface.property("Flags").toUInt())); QDBusConnection::systemBus().connect(NetworkManagerUtils::networkManagerServiceString(), objectPath.path(), NetworkManagerUtils::accessPointInterfaceString(), "PropertiesChanged", this, SLOT(onPropertiesChanged(QVariantMap))); } @@ -139,7 +138,7 @@ void WirelessAccessPoint::setSecurityFlags(const WirelessAccessPoint::ApSecurity void WirelessAccessPoint::onPropertiesChanged(const QVariantMap &properties) { if (properties.contains("Strength")) - setSignalStrength(properties.value("Strength").toUInt()); + setSignalStrength(properties.value("Strength").toInt()); } diff --git a/libnymea-networkmanager/wirelessaccesspoint.h b/libnymea-networkmanager/wirelessaccesspoint.h index fd0f735..7f3ce42 100644 --- a/libnymea-networkmanager/wirelessaccesspoint.h +++ b/libnymea-networkmanager/wirelessaccesspoint.h @@ -51,7 +51,7 @@ public: }; Q_DECLARE_FLAGS(ApSecurityModes, ApSecurityMode) - explicit WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent = nullptr); QDBusObjectPath objectPath() const; @@ -68,9 +68,9 @@ private: QString m_ssid; QString m_macAddress; double m_frequency; - int m_signalStrength; - bool m_isProtected; - WirelessAccessPoint::ApSecurityModes m_securityFlags; + int m_signalStrength = 0; + bool m_isProtected = false; + WirelessAccessPoint::ApSecurityModes m_securityFlags = ApSecurityModeNone; void setSsid(const QString &ssid); void setMacAddress(const QString &macAddress); diff --git a/libnymea-networkmanager/wirelessnetworkdevice.cpp b/libnymea-networkmanager/wirelessnetworkdevice.cpp index eaa5bbf..693533f 100644 --- a/libnymea-networkmanager/wirelessnetworkdevice.cpp +++ b/libnymea-networkmanager/wirelessnetworkdevice.cpp @@ -40,7 +40,7 @@ /*! 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) + m_activeAccessPoint(nullptr) { QDBusConnection systemBus = QDBusConnection::systemBus(); if (!systemBus.isConnected()) { @@ -61,6 +61,7 @@ WirelessNetworkDevice::WirelessNetworkDevice(const QDBusObjectPath &objectPath, readAccessPoints(); setMacAddress(m_wirelessInterface->property("HwAddress").toString()); + setMode(static_cast(m_wirelessInterface->property("Mode").toUInt())); setBitrate(m_wirelessInterface->property("Bitrate").toInt()); setActiveAccessPoint(qdbus_cast(m_wirelessInterface->property("ActiveAccessPoint"))); } @@ -77,6 +78,11 @@ int WirelessNetworkDevice::bitRate() const return m_bitRate; } +WirelessNetworkDevice::Mode WirelessNetworkDevice::mode() const +{ + return m_mode; +} + /*! Returns the current active \l{WirelessAccessPoint} of this \l{WirelessNetworkDevice}. */ WirelessAccessPoint *WirelessNetworkDevice::activeAccessPoint() { @@ -100,17 +106,17 @@ QList 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. */ +/*! Returns the \l{WirelessAccessPoint} with the given \a ssid. If the \l{WirelessAccessPoint} could not be found, return nullptr. */ WirelessAccessPoint *WirelessNetworkDevice::getAccessPoint(const QString &ssid) { foreach (WirelessAccessPoint *accessPoint, m_accessPointsTable.values()) { if (accessPoint->ssid() == ssid) return accessPoint; } - return Q_NULLPTR; + return nullptr; } -/*! Returns the \l{WirelessAccessPoint} with the given \a objectPath. If the \l{WirelessAccessPoint} could not be found, return Q_NULLPTR. */ +/*! Returns the \l{WirelessAccessPoint} with the given \a objectPath. If the \l{WirelessAccessPoint} could not be found, return nullptr. */ WirelessAccessPoint *WirelessNetworkDevice::getAccessPoint(const QDBusObjectPath &objectPath) { return m_accessPointsTable.value(objectPath); @@ -141,10 +147,20 @@ void WirelessNetworkDevice::setMacAddress(const QString &macAddress) m_macAddress = macAddress; } -void WirelessNetworkDevice::setBitrate(const int &bitRate) +void WirelessNetworkDevice::setMode(WirelessNetworkDevice::Mode mode) +{ + if (m_mode == mode) + return; + + m_mode = mode; + emit modeChanged(m_mode); +} + +void WirelessNetworkDevice::setBitrate(int bitRate) { if (m_bitRate != bitRate / 1000) { m_bitRate = bitRate / 1000; + emit bitRateChanged(m_bitRate); emit deviceChanged(); } } @@ -162,7 +178,7 @@ void WirelessNetworkDevice::setActiveAccessPoint(const QDBusObjectPath &activeAc // Update the device when the signalstrength changed connect(m_activeAccessPoint, &WirelessAccessPoint::signalStrengthChanged, this, &WirelessNetworkDevice::deviceChanged); } else { - m_activeAccessPoint = Q_NULLPTR; + m_activeAccessPoint = nullptr; } emit deviceChanged(); } @@ -193,7 +209,7 @@ void WirelessNetworkDevice::accessPointRemoved(const QDBusObjectPath &objectPath WirelessAccessPoint *accessPoint = m_accessPointsTable.take(objectPath); if (accessPoint == m_activeAccessPoint) - m_activeAccessPoint = Q_NULLPTR; + m_activeAccessPoint = nullptr; //qCDebug(dcNetworkManager()) << "WirelessNetworkDevice: [-]" << accessPoint; accessPoint->deleteLater(); @@ -208,6 +224,10 @@ void WirelessNetworkDevice::propertiesChanged(const QVariantMap &properties) if (properties.contains("ActiveAccessPoint")) setActiveAccessPoint(qdbus_cast(properties.value("ActiveAccessPoint"))); + + if (properties.contains("Mode")) + setMode(static_cast(m_wirelessInterface->property("Mode").toUInt())); + } /*! Writes the given \a device to the given to \a debug. \sa WirelessNetworkDevice, */ @@ -215,6 +235,7 @@ QDebug operator<<(QDebug debug, WirelessNetworkDevice *device) { debug.nospace() << "WirelessNetworkDevice(" << device->interface() << ", "; debug.nospace() << device->macAddress() << ", "; + debug.nospace() << device->mode() << ", "; debug.nospace() << device->bitRate() << " [Mb/s], "; debug.nospace() << device->deviceStateString() << ") "; return debug; diff --git a/libnymea-networkmanager/wirelessnetworkdevice.h b/libnymea-networkmanager/wirelessnetworkdevice.h index ed53380..f406ec8 100644 --- a/libnymea-networkmanager/wirelessnetworkdevice.h +++ b/libnymea-networkmanager/wirelessnetworkdevice.h @@ -37,12 +37,20 @@ class WirelessNetworkDevice : public NetworkDevice { Q_OBJECT public: + enum Mode { + ModeUnknown = 0, + ModeAdhoc = 1, + ModeInfrastructure = 2, + ModeAccessPoint = 3 + }; + Q_ENUM(Mode) - explicit WirelessNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit WirelessNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = nullptr); // Properties QString macAddress() const; int bitRate() const; + Mode mode() const; WirelessAccessPoint *activeAccessPoint(); // Accesspoints @@ -54,11 +62,12 @@ public: void scanWirelessNetworks(); private: - QDBusInterface *m_wirelessInterface; + QDBusInterface *m_wirelessInterface = nullptr; + WirelessAccessPoint *m_activeAccessPoint = nullptr; - QString m_macAddress; int m_bitRate; - WirelessAccessPoint *m_activeAccessPoint; + QString m_macAddress; + Mode m_mode = ModeUnknown; QDBusObjectPath m_activeAccessPointObjectPath; QHash m_accessPointsTable; @@ -66,7 +75,8 @@ private: void readAccessPoints(); void setMacAddress(const QString &macAddress); - void setBitrate(const int &bitRate); + void setMode(Mode mode); + void setBitrate(int bitRate); void setActiveAccessPoint(const QDBusObjectPath &activeAccessPointObjectPath); private slots: @@ -75,7 +85,8 @@ private slots: void propertiesChanged(const QVariantMap &properties); signals: - void bitRateChanged(const int &bitRate); + void bitRateChanged(int bitRate); + void modeChanged(Mode mode); }; diff --git a/nymea-networkmanager/application.cpp b/nymea-networkmanager/application.cpp index 836baf7..43c2686 100644 --- a/nymea-networkmanager/application.cpp +++ b/nymea-networkmanager/application.cpp @@ -48,6 +48,7 @@ static void catchUnixSignals(const std::vector& quitSignals, const std::vec exit(EXIT_FAILURE); } default: + qCDebug(dcApplication()) << "Cought unhandled signal" << sig; break; } diff --git a/nymea-networkmanager/bluetooth/bluetoothserver.cpp b/nymea-networkmanager/bluetooth/bluetoothserver.cpp index 57abc30..bc437be 100644 --- a/nymea-networkmanager/bluetooth/bluetoothserver.cpp +++ b/nymea-networkmanager/bluetooth/bluetoothserver.cpp @@ -221,8 +221,6 @@ void BluetoothServer::onHostModeStateChanged(const QBluetoothLocalDevice::HostMo case QBluetoothLocalDevice::HostDiscoverableLimitedInquiry: qCDebug(dcBluetoothServer()) << "Bluetooth host in discoverable limited inquiry mode."; break; - default: - break; } } @@ -283,8 +281,6 @@ void BluetoothServer::onControllerStateChanged(const QLowEnergyController::Contr qCDebug(dcBluetoothServer()) << "Controller state advertising..."; setRunning(true); break; - default: - break; } } @@ -338,9 +334,6 @@ void BluetoothServer::serviceError(const QLowEnergyService::ServiceError &error) case QLowEnergyService::UnknownError: errorString = "Unknown error"; break; - default: - errorString = "Unhandled error"; - break; } qCWarning(dcBluetoothServer()) << "Service error:" << errorString; @@ -437,7 +430,6 @@ void BluetoothServer::stop() m_localDevice = nullptr; } - setConnected(false); setRunning(false); } @@ -472,6 +464,12 @@ void BluetoothServer::onWirelessDeviceBitRateChanged(int bitRate) m_wirelessService->onWirelessDeviceBitRateChanged(bitRate); } +void BluetoothServer::onWirelessDeviceModeChanged(WirelessNetworkDevice::Mode mode) +{ + if (m_wirelessService) + m_wirelessService->onWirelessModeChanged(mode); +} + void BluetoothServer::onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState state) { if (m_wirelessService) diff --git a/nymea-networkmanager/bluetooth/bluetoothserver.h b/nymea-networkmanager/bluetooth/bluetoothserver.h index 06750b3..e996135 100644 --- a/nymea-networkmanager/bluetooth/bluetoothserver.h +++ b/nymea-networkmanager/bluetooth/bluetoothserver.h @@ -47,7 +47,7 @@ class BluetoothServer : public QObject Q_OBJECT public: - explicit BluetoothServer(QObject *parent = 0); + explicit BluetoothServer(QObject *parent = nullptr); ~BluetoothServer(); QString machineId() const; @@ -120,6 +120,7 @@ public slots: // Wireless device void onWirelessDeviceBitRateChanged(int bitRate); + void onWirelessDeviceModeChanged(WirelessNetworkDevice::Mode mode); void onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState state); }; diff --git a/nymea-networkmanager/bluetooth/bluetoothuuids.h b/nymea-networkmanager/bluetooth/bluetoothuuids.h index ada2589..92c7ab8 100644 --- a/nymea-networkmanager/bluetooth/bluetoothuuids.h +++ b/nymea-networkmanager/bluetooth/bluetoothuuids.h @@ -35,6 +35,7 @@ static QBluetoothUuid wirelessServiceUuid = QBluetoothUuid(QUuid 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 wirelessModeCharacteristicUuid = QBluetoothUuid(QUuid("e081fec4-f757-4449-b9c9-bfa83133f7fc")); static QBluetoothUuid systemServiceUuid = QBluetoothUuid(QUuid("e081fed0-f757-4449-b9c9-bfa83133f7fc")); static QBluetoothUuid systemCommanderCharacteristicUuid = QBluetoothUuid(QUuid("e081fed1-f757-4449-b9c9-bfa83133f7fc")); diff --git a/nymea-networkmanager/bluetooth/networkservice.h b/nymea-networkmanager/bluetooth/networkservice.h index 89d1cb0..c543098 100644 --- a/nymea-networkmanager/bluetooth/networkservice.h +++ b/nymea-networkmanager/bluetooth/networkservice.h @@ -53,7 +53,7 @@ public: }; Q_ENUM(NetworkServiceResponse) - explicit NetworkService(QLowEnergyService *service, QObject *parent = 0); + explicit NetworkService(QLowEnergyService *service, QObject *parent = nullptr); ~NetworkService(); QLowEnergyService *service(); diff --git a/nymea-networkmanager/bluetooth/wirelessservice.cpp b/nymea-networkmanager/bluetooth/wirelessservice.cpp index 573e6e2..da77af4 100644 --- a/nymea-networkmanager/bluetooth/wirelessservice.cpp +++ b/nymea-networkmanager/bluetooth/wirelessservice.cpp @@ -87,6 +87,15 @@ QLowEnergyServiceData WirelessService::serviceData() wirelessStatusCharacteristicData.setValue(WirelessService::getWirelessNetworkDeviceState(NetworkDevice::NetworkDeviceStateUnknown)); serviceData.addCharacteristic(wirelessStatusCharacteristicData); + // Wireless connection mode characterisitc e081fec4-f757-4449-b9c9-bfa83133f7fc + QLowEnergyCharacteristicData wirelessModeCharacteristicData; + wirelessModeCharacteristicData.setUuid(wirelessModeCharacteristicUuid); + wirelessModeCharacteristicData.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify); + wirelessModeCharacteristicData.addDescriptor(clientConfigDescriptorData); + wirelessModeCharacteristicData.setValueLength(1, 1); + wirelessModeCharacteristicData.setValue(WirelessService::getWirelessMode(WirelessNetworkDevice::ModeUnknown)); + serviceData.addCharacteristic(wirelessModeCharacteristicData); + return serviceData; } @@ -117,7 +126,7 @@ WirelessService::WirelessServiceResponse WirelessService::checkWirelessErrors() return WirelessServiceResponseSuccess; } -QByteArray WirelessService::getWirelessNetworkDeviceState(const NetworkDevice::NetworkDeviceState &state) +QByteArray WirelessService::getWirelessNetworkDeviceState(NetworkDevice::NetworkDeviceState state) { switch (state) { case NetworkDevice::NetworkDeviceStateUnknown: @@ -146,9 +155,23 @@ QByteArray WirelessService::getWirelessNetworkDeviceState(const NetworkDevice::N 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"); +} + +QByteArray WirelessService::getWirelessMode(WirelessNetworkDevice::Mode mode) +{ + switch (mode) { + case WirelessNetworkDevice::ModeUnknown: + return QByteArray::fromHex("00"); + case WirelessNetworkDevice::ModeAdhoc: + return QByteArray::fromHex("01"); + case WirelessNetworkDevice::ModeInfrastructure: + return QByteArray::fromHex("02"); + case WirelessNetworkDevice::ModeAccessPoint: + return QByteArray::fromHex("03"); } // Unknown @@ -182,8 +205,8 @@ void WirelessService::streamData(const QVariantMap &responseMap) QVariantMap WirelessService::createResponse(const WirelessService::WirelessServiceCommand &command, const WirelessService::WirelessServiceResponse &responseCode) { QVariantMap response; - response.insert("c", (int)command); - response.insert("r", (int)responseCode); + response.insert("c", static_cast(command)); + response.insert("r", static_cast(responseCode)); return response; } @@ -208,7 +231,7 @@ void WirelessService::commandGetNetworks(const QVariantMap &request) accessPointVariantMap.insert("e", accessPoint->ssid()); accessPointVariantMap.insert("m", accessPoint->macAddress()); accessPointVariantMap.insert("s", accessPoint->signalStrength()); - accessPointVariantMap.insert("p", (int)accessPoint->isProtected()); + accessPointVariantMap.insert("p", static_cast(accessPoint->isProtected())); accessPointVariantList.append(accessPointVariantMap); } @@ -328,7 +351,7 @@ void WirelessService::commandGetCurrentConnection(const QVariantMap &request) connectionDataMap.insert("e", device->activeAccessPoint()->ssid()); connectionDataMap.insert("m", device->activeAccessPoint()->macAddress()); connectionDataMap.insert("s", device->activeAccessPoint()->signalStrength()); - connectionDataMap.insert("p", (int)device->activeAccessPoint()->isProtected()); + connectionDataMap.insert("p", static_cast(device->activeAccessPoint()->isProtected())); connectionDataMap.insert("i", address.toString()); } @@ -337,6 +360,36 @@ void WirelessService::commandGetCurrentConnection(const QVariantMap &request) streamData(response); } +void WirelessService::commandStartAccessPoint(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; + } + + Core::instance()->networkManager()->startAccessPoint(Core::instance()->networkManager()->wirelessNetworkDevices().first()->interface(), parameters.value("e").toString(), parameters.value("p").toString()); + streamData(createResponse(WirelessServiceCommandStartAccessPoint)); +} + void WirelessService::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) { // Command @@ -423,9 +476,6 @@ void WirelessService::serviceError(const QLowEnergyService::ServiceError &error) case QLowEnergyService::UnknownError: errorString = "Unknown error"; break; - default: - errorString = "Unhandled error"; - break; } qCWarning(dcBluetoothServer()) << "WirelessService: Error:" << errorString; @@ -450,7 +500,7 @@ void WirelessService::processCommand(const QVariantMap &request) // Check wireless errors WirelessServiceResponse responseCode = checkWirelessErrors(); if (responseCode != WirelessServiceResponseSuccess) { - streamData(createResponse((WirelessServiceCommand)command, responseCode)); + streamData(createResponse(static_cast(command), responseCode)); return; } @@ -474,6 +524,9 @@ void WirelessService::processCommand(const QVariantMap &request) case WirelessServiceCommandGetCurrentConnection: commandGetCurrentConnection(request); break; + case WirelessServiceCommandStartAccessPoint: + commandStartAccessPoint(request); + break; default: qCWarning(dcBluetoothServer()) << "Invalid request. Unknown command" << command; streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidCommand)); @@ -481,12 +534,29 @@ void WirelessService::processCommand(const QVariantMap &request) } } -void WirelessService::onWirelessDeviceBitRateChanged(const int &bitRate) +void WirelessService::onWirelessDeviceBitRateChanged(int bitRate) { Q_UNUSED(bitRate) } -void WirelessService::onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState &state) +void WirelessService::onWirelessModeChanged(WirelessNetworkDevice::Mode mode) +{ + if (!m_service) { + qCWarning(dcBluetoothServer()) << "WirelessService: Could not update wireless device mode. Service not valid"; + return; + } + + QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessModeCharacteristicUuid); + if (!characteristic.isValid()) { + qCWarning(dcBluetoothServer()) << "WirelessService: Could not update wireless device mode. Characteristic not valid"; + return; + } + + qCDebug(dcBluetoothServer()) << "WirelessService: Notify wireless mode changed" << WirelessService::getWirelessMode(mode); + m_service->writeCharacteristic(characteristic, WirelessService::getWirelessMode(mode)); +} + +void WirelessService::onWirelessDeviceStateChanged(NetworkDevice::NetworkDeviceState state) { if (!m_service) { qCWarning(dcBluetoothServer()) << "WirelessService: Could not update wireless network device state. Service not valid"; diff --git a/nymea-networkmanager/bluetooth/wirelessservice.h b/nymea-networkmanager/bluetooth/wirelessservice.h index 8158d25..c3ba91d 100644 --- a/nymea-networkmanager/bluetooth/wirelessservice.h +++ b/nymea-networkmanager/bluetooth/wirelessservice.h @@ -45,7 +45,8 @@ public: WirelessServiceCommandConnectHidden = 0x02, WirelessServiceCommandDisconnect = 0x03, WirelessServiceCommandScan = 0x04, - WirelessServiceCommandGetCurrentConnection = 0x05 + WirelessServiceCommandGetCurrentConnection = 0x05, + WirelessServiceCommandStartAccessPoint = 0x06 }; Q_ENUM(WirelessServiceCommand) @@ -61,7 +62,7 @@ public: }; Q_ENUM(WirelessServiceResponse) - explicit WirelessService(QLowEnergyService *service, QObject *parent = 0); + explicit WirelessService(QLowEnergyService *service, QObject *parent = nullptr); ~WirelessService(); QLowEnergyService *service(); @@ -77,7 +78,8 @@ private: WirelessServiceResponse checkWirelessErrors(); // Note: static to be available in serviceData - static QByteArray getWirelessNetworkDeviceState(const NetworkDevice::NetworkDeviceState &state); + static QByteArray getWirelessNetworkDeviceState(NetworkDevice::NetworkDeviceState state); + static QByteArray getWirelessMode(WirelessNetworkDevice::Mode mode); void streamData(const QVariantMap &responseMap); @@ -90,7 +92,7 @@ private: void commandDisconnect(const QVariantMap &request); void commandScan(const QVariantMap &request); void commandGetCurrentConnection(const QVariantMap &request); - + void commandStartAccessPoint(const QVariantMap &request); private slots: // Service @@ -106,8 +108,9 @@ private slots: public slots: // Wireless network device - void onWirelessDeviceBitRateChanged(const int &bitRate); - void onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState &state); + void onWirelessDeviceBitRateChanged(int bitRate); + void onWirelessDeviceStateChanged(NetworkDevice::NetworkDeviceState state); + void onWirelessModeChanged(WirelessNetworkDevice::Mode mode); }; #endif // WIRELESSSERVICE_H diff --git a/nymea-networkmanager/core.cpp b/nymea-networkmanager/core.cpp index a339be9..30e1e33 100644 --- a/nymea-networkmanager/core.cpp +++ b/nymea-networkmanager/core.cpp @@ -105,23 +105,8 @@ void Core::run() return; } - switch (m_mode) { - case ModeAlways: - qCDebug(dcApplication()) << "Start the bluetooth service because of \"always\" mode."; - startService(); - break; - case ModeStart: - qCDebug(dcApplication()) << "Start the bluetooth service because of \"start\" mode."; - startService(); - m_advertisingTimer->start(m_advertisingTimeout * 1000); - break; - case ModeOffline: - evaluateNetworkManagerState(m_networkManager->state()); - break; - default: - break; - } - + // Note: give network-manager more time to start and get online status + QTimer::singleShot(5000, this, &Core::postRun); } Core::Core(QObject *parent) : @@ -168,6 +153,12 @@ void Core::evaluateNetworkManagerState(const NetworkManager::NetworkManagerState if (m_mode != ModeOffline) return; + // Note: if the wireless device is in the access point mode, the bluetooth server should stop + if (m_wirelessDevice && m_wirelessDevice->mode() == WirelessNetworkDevice::ModeAccessPoint) { + stopService(); + return; + } + switch (state) { case NetworkManager::NetworkManagerStateConnectedGlobal: // We are online @@ -225,10 +216,39 @@ void Core::startService() void Core::stopService() { - if (m_bluetoothServer->running()) + if (m_bluetoothServer && m_bluetoothServer->running()) { qCDebug(dcApplication()) << "Stop bluetooth service"; + m_bluetoothServer->stop(); + } +} - m_bluetoothServer->stop(); +void Core::postRun() +{ + qCDebug(dcApplication()) << "Post run service"; + m_initRunning = false; + + switch (m_mode) { + case ModeAlways: + qCDebug(dcApplication()) << "Start the bluetooth service because of \"always\" mode."; + startService(); + break; + case ModeStart: + qCDebug(dcApplication()) << "Start the bluetooth service because of \"start\" mode."; + startService(); + m_advertisingTimer->start(m_advertisingTimeout * 1000); + break; + case ModeOffline: + evaluateNetworkManagerState(m_networkManager->state()); + break; + case ModeOnce: + if (m_networkManager->networkSettings()->connections().isEmpty()) { + qCDebug(dcApplication()) << "Start the bluetooth service because of \"once\" mode and there is currenlty no network configured yet."; + startService(); + } else { + qCDebug(dcApplication()) << "Not starting the bluetooth service because of \"once\" mode. There are" << m_networkManager->networkSettings()->connections().count() << "network configurations."; + } + break; + } } void Core::onAdvertisingTimeout() @@ -259,7 +279,13 @@ void Core::onBluetoothServerRunningChanged(bool running) case ModeOffline: evaluateNetworkManagerState(m_networkManager->state()); break; - default: + case ModeOnce: + if (m_networkManager->networkSettings()->connections().isEmpty()) { + qCDebug(dcApplication()) << "Start the bluetooth service because of \"once\" mode and there is currenlty no network configured yet."; + startService(); + } else { + qCDebug(dcApplication()) << "Not starting the bluetooth service because of \"once\" mode. There are" << m_networkManager->networkSettings()->connections().count() << "network configurations."; + } break; } } @@ -275,8 +301,11 @@ void Core::onBluetoothServerConnectedChanged(bool connected) m_bluetoothServer->onNetworkManagerStateChanged(m_networkManager->state()); m_bluetoothServer->onNetworkingEnabledChanged(m_networkManager->networkingEnabled()); m_bluetoothServer->onWirelessNetworkingEnabledChanged(m_networkManager->wirelessEnabled()); - if (m_wirelessDevice) + + if (m_wirelessDevice) { m_bluetoothServer->onWirelessDeviceStateChanged(m_wirelessDevice->deviceState()); + m_bluetoothServer->onWirelessDeviceModeChanged(m_wirelessDevice->mode()); + } } else { m_advertisingTimer->stop(); @@ -292,6 +321,11 @@ void Core::onNetworkManagerAvailableChanged(const bool &available) return; } + if (m_initRunning) { + qCDebug(dcApplication()) << "Init is running"; + return; + } + qCDebug(dcApplication()) << "Networkmanager is now available."; m_bluetoothServer->onNetworkManagerAvailableChanged(available); @@ -305,7 +339,13 @@ void Core::onNetworkManagerAvailableChanged(const bool &available) case ModeOffline: evaluateNetworkManagerState(m_networkManager->state()); break; - default: + case ModeOnce: + if (m_networkManager->networkSettings()->connections().isEmpty()) { + qCDebug(dcApplication()) << "Start the bluetooth service because of \"once\" mode and there is currenlty no network configured yet."; + startService(); + } else { + qCDebug(dcApplication()) << "Not starting the bluetooth service because of \"once\" mode. There are" << m_networkManager->networkSettings()->connections().count() << "network configurations."; + } break; } } @@ -327,6 +367,9 @@ void Core::onNetworkManagerWirelessEnabledChanged(bool enabled) void Core::onNetworkManagerStateChanged(const NetworkManager::NetworkManagerState &state) { qCDebug(dcApplication()) << state; + if (!m_bluetoothServer) + return; + m_bluetoothServer->onNetworkManagerStateChanged(state); evaluateNetworkManagerState(state); } @@ -339,7 +382,8 @@ void Core::onNetworkManagerWirelessDeviceAdded(WirelessNetworkDevice *wirelessDe } m_wirelessDevice = wirelessDevice; - connect(m_wirelessDevice, &WiredNetworkDevice::stateChanged, this, &Core::onWirelessDeviceStateChanged); + connect(m_wirelessDevice, &WirelessNetworkDevice::stateChanged, this, &Core::onWirelessDeviceStateChanged); + connect(m_wirelessDevice, &WirelessNetworkDevice::modeChanged, this, &Core::onWirelessDeviceModeChanged); } void Core::onNetworkManagerWirelessDeviceRemoved(const QString &interface) @@ -350,7 +394,7 @@ void Core::onNetworkManagerWirelessDeviceRemoved(const QString &interface) } if (m_wirelessDevice->interface() == interface) { - disconnect(m_wirelessDevice, &WiredNetworkDevice::stateChanged, this, &Core::onWirelessDeviceStateChanged); + disconnect(m_wirelessDevice, &WirelessNetworkDevice::stateChanged, this, &Core::onWirelessDeviceStateChanged); m_wirelessDevice = nullptr; } } @@ -361,6 +405,15 @@ void Core::onWirelessDeviceBitRateChanged(int bitRate) m_bluetoothServer->onWirelessDeviceBitRateChanged(bitRate); } +void Core::onWirelessDeviceModeChanged(WirelessNetworkDevice::Mode mode) +{ + qCDebug(dcApplication()) << "Wireless device mode" << mode; + + // TODO: check what to do if in ap mode + + m_bluetoothServer->onWirelessDeviceModeChanged(mode); +} + void Core::onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState state) { qCDebug(dcApplication()) << state; diff --git a/nymea-networkmanager/core.h b/nymea-networkmanager/core.h index c44a6ae..e082976 100644 --- a/nymea-networkmanager/core.h +++ b/nymea-networkmanager/core.h @@ -36,6 +36,7 @@ public: enum Mode { ModeAlways, ModeOffline, + ModeOnce, ModeStart }; Q_ENUM(Mode) @@ -78,6 +79,7 @@ private: QString m_advertiseName; QString m_platformName; int m_advertisingTimeout = 60; + bool m_initRunning = true; void evaluateNetworkManagerState(const NetworkManager::NetworkManagerState &state); @@ -85,6 +87,8 @@ private: void stopService(); private slots: + void postRun(); + void onAdvertisingTimeout(); void onBluetoothServerRunningChanged(bool running); @@ -97,10 +101,9 @@ private slots: void onNetworkManagerWirelessDeviceAdded(WirelessNetworkDevice *wirelessDevice); void onNetworkManagerWirelessDeviceRemoved(const QString &interface); - - // Wireless device void onWirelessDeviceBitRateChanged(int bitRate); + void onWirelessDeviceModeChanged(WirelessNetworkDevice::Mode mode); void onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState state); void onNymeaServiceAvailableChanged(bool available); diff --git a/nymea-networkmanager/main.cpp b/nymea-networkmanager/main.cpp index 2d43d34..6320fdd 100644 --- a/nymea-networkmanager/main.cpp +++ b/nymea-networkmanager/main.cpp @@ -87,11 +87,10 @@ int main(int argc, char *argv[]) QString advertiseName = "BT WLAN setup"; QString platformName = "nymea-box"; - Application application(argc, argv); application.setApplicationName("nymea-networkmanager"); application.setOrganizationName("nymea"); - application.setApplicationVersion("0.2.0"); + application.setApplicationVersion("0.3.0"); // Command line parser QCommandLineParser parser; @@ -115,10 +114,11 @@ int main(int argc, char *argv[]) timeoutOption.setDefaultValue(QString::number(timeout)); parser.addOption(timeoutOption); - QCommandLineOption modeOption(QStringList() << "m" << "mode", "Run the daemon in a specific mode. Default \"offline\".\n\n" \ - "- offline: this mode starts the bluetooth server once the device is offline and not connected to any LAN network.\n\n" \ - "- always: this mode enables the bluetooth server as long the application is running.\n\n" \ - "- start: this mode starts the bluetooth server for 3 minutes on start and shuts down after a connection.\n\n", "offline | always | start"); + QCommandLineOption modeOption(QStringList() << "m" << "mode", "Run the daemon in a specific mode. Default is \"offline\".\n\n" \ + "- offline: this mode starts the bluetooth server once the device is offline and not connected to any LAN network.\n\n" \ + "- once: this mode starts the bluetooth server only if no network configuration exists. Once a network connection exists the server will never start again.\n\n" \ + "- always: this mode enables the bluetooth server as long the application is running.\n\n" \ + "- start: this mode starts the bluetooth server for 3 minutes on start and shuts down after a connection.\n\n", "offline | once | always | start"); parser.addOption(modeOption); parser.process(application); @@ -142,8 +142,6 @@ int main(int argc, char *argv[]) if (QFileInfo::exists(configLocation + fileName)) { qCDebug(dcApplication) << "Using configuration file from:" << configLocation + fileName; QSettings settings(configLocation + fileName, QSettings::IniFormat); - qCDebug(dcApplication()) << "Fooo" << settings.allKeys() << settings.childGroups(); - if (settings.contains("Mode")) { if (settings.value("Mode").toString().toLower() == "offline") { @@ -152,6 +150,8 @@ int main(int argc, char *argv[]) mode = Core::ModeAlways; } else if (settings.value("Mode").toString().toLower() == "start") { mode = Core::ModeStart; + } else if (settings.value("Mode").toString().toLower() == "once") { + mode = Core::ModeOnce; } else { qCWarning(dcApplication()).noquote() << QString("The config file's mode \"%1\" does not match the allowed modes.").arg(settings.value("Mode").toString()); } @@ -177,6 +177,8 @@ int main(int argc, char *argv[]) mode = Core::ModeAlways; } else if (parser.value(modeOption).toLower() == "start") { mode = Core::ModeStart; + } else if (parser.value(modeOption).toLower() == "once") { + mode = Core::ModeOnce; } else { qCWarning(dcApplication()).noquote() << QString("The given mode \"%1\" does not match the allowed modes.").arg(parser.value(modeOption)); parser.showHelp(1); diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 306b48e..51b4ef9 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -10,7 +10,7 @@ description: | is 'BT WLAN setup'. grade: stable -confinement: classic +confinement: strict apps: nymea-networkmanager: