From c603acdb446267666fa3b6ae991e30895c9ea7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Mon, 29 Oct 2018 18:37:55 +0100 Subject: [PATCH] Add wireless mode characteristic and implement start access point method --- README.md | 69 ++++++++++---- debian/changelog | 8 +- libnymea-networkmanager/networkconnection.cpp | 4 + libnymea-networkmanager/networkmanager.cpp | 93 ++++++++++++++++++- libnymea-networkmanager/networkmanager.h | 1 + .../wirelessnetworkdevice.cpp | 31 +++++-- .../wirelessnetworkdevice.h | 15 ++- .../bluetooth/bluetoothuuids.h | 1 + .../bluetooth/wirelessservice.cpp | 86 ++++++++++++++++- .../bluetooth/wirelessservice.h | 13 ++- 10 files changed, 280 insertions(+), 41 deletions(-) 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..523ce1b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,10 @@ -nymea-networkmanager (0.2.0) UNRELEASED; urgency=medium +nymea-networkmanager (0.3.0) stretch; urgency=medium + + * Add access point mode for creating wireless access points + + -- 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..3d00fed 100644 --- a/libnymea-networkmanager/networkconnection.cpp +++ b/libnymea-networkmanager/networkconnection.cpp @@ -49,6 +49,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}. */ diff --git a/libnymea-networkmanager/networkmanager.cpp b/libnymea-networkmanager/networkmanager.cpp index e4d0928..709ef23 100644 --- a/libnymea-networkmanager/networkmanager.cpp +++ b/libnymea-networkmanager/networkmanager.cpp @@ -71,7 +71,7 @@ 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{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()) { @@ -115,8 +115,9 @@ NetworkManager::NetworkManagerError NetworkManager::connectWifi(const QString &i // Get wirelessNetworkDevice WirelessNetworkDevice *wirelessNetworkDevice = nullptr; foreach (WirelessNetworkDevice *networkDevice, wirelessNetworkDevices()) { - if (networkDevice->interface() == interface) + if (networkDevice->interface() == interface) { wirelessNetworkDevice = networkDevice; + } } if (!wirelessNetworkDevice) @@ -129,6 +130,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 +180,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; } diff --git a/libnymea-networkmanager/networkmanager.h b/libnymea-networkmanager/networkmanager.h index 8758228..212c725 100644 --- a/libnymea-networkmanager/networkmanager.h +++ b/libnymea-networkmanager/networkmanager.h @@ -99,6 +99,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/wirelessnetworkdevice.cpp b/libnymea-networkmanager/wirelessnetworkdevice.cpp index eaa5bbf..dc247ce 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(); @@ -215,6 +231,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 54b0cab..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 = nullptr); // Properties QString macAddress() const; int bitRate() const; + Mode mode() const; WirelessAccessPoint *activeAccessPoint(); // Accesspoints @@ -59,6 +67,7 @@ private: int m_bitRate; 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/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/wirelessservice.cpp b/nymea-networkmanager/bluetooth/wirelessservice.cpp index 248d710..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: @@ -152,6 +161,23 @@ QByteArray WirelessService::getWirelessNetworkDeviceState(const NetworkDevice::N 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 + return QByteArray::fromHex("00"); +} + void WirelessService::streamData(const QVariantMap &responseMap) { @@ -205,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); } @@ -334,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 @@ -444,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; } @@ -468,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)); @@ -475,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 6244fc5..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) @@ -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