diff --git a/libnymea-networkmanager/bluetooth/bluetoothserver.cpp b/libnymea-networkmanager/bluetooth/bluetoothserver.cpp index 22e7844..2f45e94 100644 --- a/libnymea-networkmanager/bluetooth/bluetoothserver.cpp +++ b/libnymea-networkmanager/bluetooth/bluetoothserver.cpp @@ -136,7 +136,7 @@ QLowEnergyServiceData BluetoothServer::deviceInformationServiceData() serialNumberCharData.setUuid(QBluetoothUuid::SerialNumberString); if (m_serialNumber.isNull()) { // Note: if no serialnumber specified use the system uuid from /etc/machine-id - qCWarning(dcNetworkManagerBluetoothServer()) << "Serial number not specified. Using system uuid from /etc/machine-id as serialnumber."; + qCDebug(dcNetworkManagerBluetoothServer()) << "Serial number not specified. Using system uuid from /etc/machine-id as serialnumber."; m_serialNumber = readMachineId().toString(); } serialNumberCharData.setValue(m_serialNumber.toUtf8()); @@ -260,7 +260,7 @@ QUuid BluetoothServer::readMachineId() tmpId.insert(23, "-"); systemUuid = QUuid(tmpId); } else { - qWarning(dcNetworkManagerBluetoothServer()) << "Failed to open /etc/machine-id for reading the system uuid as device information serialnumber."; + qCWarning(dcNetworkManagerBluetoothServer()) << "Failed to open /etc/machine-id for reading the system uuid as device information serialnumber."; } systemUuidFile.close(); @@ -401,13 +401,13 @@ void BluetoothServer::serviceError(QLowEnergyService::ServiceError error) void BluetoothServer::start() { - if (connected()) { - qCDebug(dcNetworkManagerBluetoothServer()) << "Start Bluetooth server called but the server is running and a client is connected. Doing nothing."; + if (running()) { + qCDebug(dcNetworkManagerBluetoothServer()) << "Start Bluetooth server called but the server is already running. Doing nothing."; return; } - if (running()) { - qCDebug(dcNetworkManagerBluetoothServer()) << "Start Bluetooth server called but the server is already running. Doing nothing."; + if (connected()) { + qCDebug(dcNetworkManagerBluetoothServer()) << "Start Bluetooth server called but the server is running and a client is connected. Doing nothing."; return; } @@ -432,7 +432,6 @@ void BluetoothServer::start() m_localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable); m_localDevice->powerOn(); - // Bluetooth low energy periperal controller m_controller = QLowEnergyController::createPeripheral(this); connect(m_controller, &QLowEnergyController::stateChanged, this, &BluetoothServer::onControllerStateChanged); @@ -455,37 +454,23 @@ void BluetoothServer::start() advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); advertisingData.setIncludePowerLevel(true); advertisingData.setLocalName(m_advertiseName); - // FIXME: set guh manufacturer SIG data once available // Note: start advertising in 100 ms interval, this makes the device better discoverable on certain phones QLowEnergyAdvertisingParameters advertisingParameters; - advertisingParameters.setInterval(100,100); + advertisingParameters.setInterval(100, 100); qCDebug(dcNetworkManagerBluetoothServer()) << "Start advertising" << m_advertiseName << m_localDevice->address().toString(); m_controller->startAdvertising(advertisingParameters, advertisingData, advertisingData); - // Note: setRunning(true) will be called when the service is really advertising, see onControllerStateChanged() } void BluetoothServer::stop() { - if (connected() && m_controller) { - m_controller->disconnectFromDevice(); - return; - } - qCDebug(dcNetworkManagerBluetoothServer()) << "-------------------------------------"; qCDebug(dcNetworkManagerBluetoothServer()) << "Stopping bluetooth server."; qCDebug(dcNetworkManagerBluetoothServer()) << "-------------------------------------"; - if (m_controller) { - qCDebug(dcNetworkManagerBluetoothServer()) << "Stop advertising."; - m_controller->stopAdvertising(); - delete m_controller; - m_controller = nullptr; - } - if (m_localDevice) { qCDebug(dcNetworkManagerBluetoothServer()) << "Set host mode to connectable."; m_localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable); @@ -493,6 +478,13 @@ void BluetoothServer::stop() m_localDevice = nullptr; } + if (m_controller) { + qCDebug(dcNetworkManagerBluetoothServer()) << "Stop advertising."; + m_controller->stopAdvertising(); + delete m_controller; + m_controller = nullptr; + } + setConnected(false); setRunning(false); } diff --git a/libnymea-networkmanager/bluetooth/bluetoothuuids.h b/libnymea-networkmanager/bluetooth/bluetoothuuids.h index 3d32643..a8dd659 100644 --- a/libnymea-networkmanager/bluetooth/bluetoothuuids.h +++ b/libnymea-networkmanager/bluetooth/bluetoothuuids.h @@ -36,5 +36,6 @@ 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")); #endif // BLUETOOTHUUIDS_H diff --git a/libnymea-networkmanager/bluetooth/wirelessservice.cpp b/libnymea-networkmanager/bluetooth/wirelessservice.cpp index 7e124e7..f1d6345 100644 --- a/libnymea-networkmanager/bluetooth/wirelessservice.cpp +++ b/libnymea-networkmanager/bluetooth/wirelessservice.cpp @@ -60,6 +60,7 @@ WirelessService::WirelessService(QLowEnergyService *service, NetworkManager *net m_device = m_networkManager->wirelessNetworkDevices().first(); connect(m_device, &WirelessNetworkDevice::bitRateChanged, this, &WirelessService::onWirelessDeviceBitRateChanged); connect(m_device, &WirelessNetworkDevice::stateChanged, this, &WirelessService::onWirelessDeviceStateChanged); + connect(m_device, &WirelessNetworkDevice::modeChanged, this, &WirelessService::onWirelessModeChanged); } QLowEnergyService *WirelessService::service() @@ -103,6 +104,19 @@ QLowEnergyServiceData WirelessService::serviceData(NetworkManager *networkManage } serviceData.addCharacteristic(wirelessStatusCharacteristicData); + // Wireless 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); + if (networkManager->wirelessNetworkDevices().isEmpty()) { + wirelessModeCharacteristicData.setValue(WirelessService::getWirelessMode(WirelessNetworkDevice::ModeUnknown)); + } else { + wirelessModeCharacteristicData.setValue(WirelessService::getWirelessMode(networkManager->wirelessNetworkDevices().first()->mode())); + } + serviceData.addCharacteristic(wirelessModeCharacteristicData); + return serviceData; } @@ -168,6 +182,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) { @@ -359,6 +390,36 @@ void WirelessService::commandGetCurrentConnection(const QVariantMap &request) streamData(response); } +void WirelessService::commandStartAccessPoint(const QVariantMap &request) +{ + if (!m_service) { + qCWarning(dcNetworkManagerBluetoothServer()) << "WirelessService: Could not start access point. Service is not valid."; + return; + } + + QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessResponseCharacteristicUuid); + if (!characteristic.isValid()) { + qCWarning(dcNetworkManagerBluetoothServer()) << "WirelessService: Wireless response characteristic not valid"; + return; + } + + if (!request.contains("p")) { + qCWarning(dcNetworkManagerBluetoothServer()) << "WirelessService: Start access point command: Missing parameters."; + streamData(createResponse(WirelessServiceCommandStartAccessPoint, WirelessServiceResponseIvalidParameters)); + return; + } + + QVariantMap parameters = request.value("p").toMap(); + if (!parameters.contains("e") || !parameters.contains("p")) { + qCWarning(dcNetworkManagerBluetoothServer()) << "WirelessService: Start access point command: Invalid parameters."; + streamData(createResponse(WirelessServiceCommandStartAccessPoint, WirelessServiceResponseIvalidParameters)); + return; + } + + m_networkManager->startAccessPoint(m_device->interface(), parameters.value("e").toString(), parameters.value("p").toString()); + streamData(createResponse(WirelessServiceCommandStartAccessPoint)); +} + void WirelessService::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) { // Command @@ -493,6 +554,9 @@ void WirelessService::processCommand(const QVariantMap &request) case WirelessServiceCommandGetCurrentConnection: commandGetCurrentConnection(request); break; + case WirelessServiceCommandStartAccessPoint: + commandStartAccessPoint(request); + break; default: qCWarning(dcNetworkManagerBluetoothServer()) << "Invalid request. Unknown command" << command; streamData(createResponse(WirelessServiceCommandConnect, WirelessServiceResponseIvalidCommand)); @@ -522,3 +586,20 @@ void WirelessService::onWirelessDeviceStateChanged(const NetworkDevice::NetworkD m_service->writeCharacteristic(characteristic, WirelessService::getWirelessNetworkDeviceState(state)); } + +void WirelessService::onWirelessModeChanged(WirelessNetworkDevice::Mode mode) +{ + if (!m_service) { + qCWarning(dcNetworkManagerBluetoothServer()) << "WirelessService: Could not update wireless device mode. Service not valid"; + return; + } + + QLowEnergyCharacteristic characteristic = m_service->characteristic(wirelessModeCharacteristicUuid); + if (!characteristic.isValid()) { + qCWarning(dcNetworkManagerBluetoothServer()) << "WirelessService: Could not update wireless device mode. Characteristic not valid"; + return; + } + + qCDebug(dcNetworkManagerBluetoothServer()) << "WirelessService: Notify wireless mode changed" << WirelessService::getWirelessMode(mode); + m_service->writeCharacteristic(characteristic, WirelessService::getWirelessMode(mode)); +} diff --git a/libnymea-networkmanager/bluetooth/wirelessservice.h b/libnymea-networkmanager/bluetooth/wirelessservice.h index 6cacae3..8511ad5 100644 --- a/libnymea-networkmanager/bluetooth/wirelessservice.h +++ b/libnymea-networkmanager/bluetooth/wirelessservice.h @@ -44,7 +44,8 @@ public: WirelessServiceCommandConnectHidden = 0x02, WirelessServiceCommandDisconnect = 0x03, WirelessServiceCommandScan = 0x04, - WirelessServiceCommandGetCurrentConnection = 0x05 + WirelessServiceCommandGetCurrentConnection = 0x05, + WirelessServiceCommandStartAccessPoint = 0x06 }; Q_ENUM(WirelessServiceCommand) @@ -77,6 +78,7 @@ private: // Note: static to be available in serviceData static QByteArray getWirelessNetworkDeviceState(const NetworkDevice::NetworkDeviceState &state); + static QByteArray getWirelessMode(WirelessNetworkDevice::Mode mode); void streamData(const QVariantMap &responseMap); @@ -89,6 +91,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 @@ -105,6 +108,8 @@ private slots: // Wireless network device void onWirelessDeviceBitRateChanged(const int &bitRate); void onWirelessDeviceStateChanged(const NetworkDevice::NetworkDeviceState &state); + void onWirelessModeChanged(WirelessNetworkDevice::Mode mode); + }; #endif // WIRELESSSERVICE_H