1029 lines
38 KiB
C++
1029 lines
38 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* Copyright 2013 - 2020, nymea GmbH
|
|
* Contact: contact@nymea.io
|
|
*
|
|
* This file is part of nymea.
|
|
* This project including source code and documentation is protected by
|
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
|
* reproduction, publication, editing and translation, are reserved. The use of
|
|
* this project is subject to the terms of a license agreement to be concluded
|
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
|
* under https://nymea.io/license
|
|
*
|
|
* GNU General Public License Usage
|
|
* Alternatively, this project may be redistributed and/or modified under the
|
|
* terms of the GNU General Public License as published by the Free Software
|
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* For any further details and any questions please contact us under
|
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
|
* https://nymea.io/license/faq
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "wirelesssetupmanager.h"
|
|
#include "types/wirelessaccesspoint.h"
|
|
#include "types/wirelessaccesspoints.h"
|
|
#include "models/wirelessaccesspointsproxy.h"
|
|
|
|
#include <QJsonDocument>
|
|
|
|
static QBluetoothUuid wifiServiceUuid = QBluetoothUuid(QUuid("e081fec0-f757-4449-b9c9-bfa83133f7fc"));
|
|
static QBluetoothUuid wifiCommanderCharacteristicUuid = QBluetoothUuid(QUuid("e081fec1-f757-4449-b9c9-bfa83133f7fc"));
|
|
static QBluetoothUuid wifiResponseCharacteristicUuid = QBluetoothUuid(QUuid("e081fec2-f757-4449-b9c9-bfa83133f7fc"));
|
|
static QBluetoothUuid wifiStatusCharacteristicUuid = QBluetoothUuid(QUuid("e081fec3-f757-4449-b9c9-bfa83133f7fc"));
|
|
|
|
static QBluetoothUuid networkServiceUuid = QBluetoothUuid(QUuid("ef6d6610-b8af-49e0-9eca-ab343513641c"));
|
|
static QBluetoothUuid networkStatusCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6611-b8af-49e0-9eca-ab343513641c"));
|
|
static QBluetoothUuid networkCommanderCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6612-b8af-49e0-9eca-ab343513641c"));
|
|
static QBluetoothUuid networkResponseCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6613-b8af-49e0-9eca-ab343513641c"));
|
|
static QBluetoothUuid networkingEnabledCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6614-b8af-49e0-9eca-ab343513641c"));
|
|
static QBluetoothUuid wirelessEnabledCharacteristicUuid = QBluetoothUuid(QUuid("ef6d6615-b8af-49e0-9eca-ab343513641c"));
|
|
|
|
static QBluetoothUuid systemServiceUuid = QBluetoothUuid(QUuid("e081fed0-f757-4449-b9c9-bfa83133f7fc"));
|
|
static QBluetoothUuid systemCommanderCharacteristicUuid = QBluetoothUuid(QUuid("e081fed1-f757-4449-b9c9-bfa83133f7fc"));
|
|
static QBluetoothUuid systemResponseCharacteristicUuid = QBluetoothUuid(QUuid("e081fed2-f757-4449-b9c9-bfa83133f7fc"));
|
|
|
|
|
|
WirelessSetupManager::WirelessSetupManager(const QBluetoothDeviceInfo &deviceInfo, QObject *parent) :
|
|
BluetoothDevice(deviceInfo, parent),
|
|
m_accessPoints(new WirelessAccessPoints(this))
|
|
{
|
|
connect(this, &WirelessSetupManager::connectedChanged, this, &WirelessSetupManager::onConnectedChanged);
|
|
connect(this, &WirelessSetupManager::serviceDiscoveryFinished, this, &WirelessSetupManager::onServiceDiscoveryFinished);
|
|
}
|
|
|
|
QString WirelessSetupManager::modelNumber() const
|
|
{
|
|
return m_modelNumber;
|
|
}
|
|
|
|
QString WirelessSetupManager::manufacturer() const
|
|
{
|
|
return m_manufacturer;
|
|
}
|
|
|
|
QString WirelessSetupManager::softwareRevision() const
|
|
{
|
|
return m_softwareRevision;
|
|
}
|
|
|
|
QString WirelessSetupManager::firmwareRevision() const
|
|
{
|
|
return m_firmwareRevision;
|
|
}
|
|
|
|
QString WirelessSetupManager::hardwareRevision() const
|
|
{
|
|
return m_hardwareRevision;
|
|
}
|
|
|
|
bool WirelessSetupManager::initialized() const
|
|
{
|
|
return m_initialized;
|
|
}
|
|
|
|
bool WirelessSetupManager::working() const
|
|
{
|
|
return m_working;
|
|
}
|
|
|
|
WirelessSetupManager::NetworkStatus WirelessSetupManager::networkStatus() const
|
|
{
|
|
return m_networkStatus;
|
|
}
|
|
|
|
WirelessSetupManager::WirelessStatus WirelessSetupManager::wirelessStatus() const
|
|
{
|
|
return m_wirelessStatus;
|
|
}
|
|
|
|
bool WirelessSetupManager::networkingEnabled() const
|
|
{
|
|
return m_networkingEnabled;
|
|
}
|
|
|
|
bool WirelessSetupManager::wirelessEnabled() const
|
|
{
|
|
return m_wirelessEnabled;
|
|
}
|
|
|
|
WirelessAccessPoints *WirelessSetupManager::accessPoints() const
|
|
{
|
|
return m_accessPoints;
|
|
}
|
|
|
|
WirelessAccessPoint *WirelessSetupManager::currentConnection() const
|
|
{
|
|
return m_currentConnection;
|
|
}
|
|
|
|
void WirelessSetupManager::reloadData()
|
|
{
|
|
loadNetworks();
|
|
}
|
|
|
|
void WirelessSetupManager::loadNetworks()
|
|
{
|
|
qDebug() << "WifiSetupManager: Start loading wifi networks";
|
|
|
|
if (!m_wifiService) {
|
|
qWarning() << "WifiSetupManager: Could not send command. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic characteristic = m_wifiService->characteristic(wifiCommanderCharacteristicUuid);
|
|
if (!characteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not send command. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
m_readingResponse = true;
|
|
m_inputDataStream.clear();
|
|
|
|
setStatusText("Loading wifi network list...");
|
|
m_working = true;
|
|
emit workingChanged();
|
|
|
|
QVariantMap request;
|
|
request.insert("c", (int)WirelessServiceCommandGetNetworks);
|
|
streamData(request);
|
|
}
|
|
|
|
void WirelessSetupManager::loadCurrentConnection()
|
|
{
|
|
qDebug() << "WifiSetupManager: Start loading current connection data";
|
|
|
|
if (!m_wifiService) {
|
|
qWarning() << "WifiSetupManager: Could not send command. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic characteristic = m_wifiService->characteristic(wifiCommanderCharacteristicUuid);
|
|
if (!characteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not send command. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
m_readingResponse = false;
|
|
m_inputDataStream.clear();
|
|
|
|
setStatusText("Loading current connection data");
|
|
m_working = true;
|
|
emit workingChanged();
|
|
|
|
QVariantMap request;
|
|
request.insert("c", (int)WirelessServiceCommandGetCurrentConnection);
|
|
streamData(request);
|
|
}
|
|
|
|
void WirelessSetupManager::performWifiScan()
|
|
{
|
|
qDebug() << "WifiSetupManager: Start loading wifi networks";
|
|
|
|
if (!m_wifiService) {
|
|
qWarning() << "WifiSetupManager: Could not send command. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic characteristic = m_wifiService->characteristic(wifiCommanderCharacteristicUuid);
|
|
if (!characteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not send command. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
setStatusText("Perform refresh...");
|
|
m_working = true;
|
|
emit workingChanged();
|
|
|
|
QVariantMap request;
|
|
request.insert("c", (int)WirelessServiceCommandScan);
|
|
streamData(request);
|
|
}
|
|
|
|
void WirelessSetupManager::enableNetworking(bool enable)
|
|
{
|
|
qDebug() << "WifiSetupManager: Send networking" << enable;
|
|
|
|
if (!m_netwokService) {
|
|
qWarning() << "WifiSetupManager: Could not set networking. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic characteristic = m_netwokService->characteristic(networkCommanderCharacteristicUuid);
|
|
if (!characteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not set networking. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
m_netwokService->writeCharacteristic(characteristic, enable ? QByteArray::fromHex("00") : QByteArray::fromHex("01"));
|
|
}
|
|
|
|
void WirelessSetupManager::enableWireless(bool enable)
|
|
{
|
|
qDebug() << "WifiSetupManager: Send wireless networking" << enable;
|
|
|
|
if (!m_netwokService) {
|
|
qWarning() << "WifiSetupManager: Could not enable/disable wireless. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic characteristic = m_netwokService->characteristic(networkCommanderCharacteristicUuid);
|
|
if (!characteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not enable/disable wireless. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
m_netwokService->writeCharacteristic(characteristic, enable ? QByteArray::fromHex("02") : QByteArray::fromHex("03"));
|
|
}
|
|
|
|
void WirelessSetupManager::connectWirelessNetwork(const QString &ssid, const QString &password)
|
|
{
|
|
qDebug() << "WifiSetupManager: Connect wireless network" << ssid << password;
|
|
|
|
m_ssid = ssid;
|
|
m_password = password;
|
|
|
|
if (!m_wifiService) {
|
|
qWarning() << "WifiSetupManager: Could not set wireless network. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic ssidCharacteristic = m_wifiService->characteristic(wifiCommanderCharacteristicUuid);
|
|
if (!ssidCharacteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not connect. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
QVariantMap request;
|
|
request.insert("c", (int)WirelessServiceCommandConnect);
|
|
QVariantMap parameters;
|
|
parameters.insert("e", ssid);
|
|
parameters.insert("p", password);
|
|
request.insert("p", parameters);
|
|
|
|
streamData(request);
|
|
}
|
|
|
|
void WirelessSetupManager::disconnectWirelessNetwork()
|
|
{
|
|
qDebug() << "WifiSetupManager: Disconnect wireless network";
|
|
|
|
if (!m_wifiService) {
|
|
qWarning() << "WifiSetupManager: Could not disconnect wireless network. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic ssidCharacteristic = m_wifiService->characteristic(wifiCommanderCharacteristicUuid);
|
|
if (!ssidCharacteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not disconnect wireless ssid. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
QVariantMap request;
|
|
request.insert("c", (int)WirelessServiceCommandDisconnect);
|
|
streamData(request);
|
|
}
|
|
|
|
void WirelessSetupManager::pressPushButton()
|
|
{
|
|
qDebug() << "WifiSetupManager: Press push button";
|
|
|
|
if (!m_systemService) {
|
|
qWarning() << "WifiSetupManager: Could not press push button. Service not valid";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic commanderCharacteristic = m_systemService->characteristic(systemCommanderCharacteristicUuid);
|
|
if (!commanderCharacteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: Could not press push button. Characteristic is not valid";
|
|
return;
|
|
}
|
|
|
|
QVariantMap request;
|
|
request.insert("c", (int)SystemServiceCommandPushAuthentication);
|
|
|
|
QByteArray data = QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + '\n';
|
|
qDebug() << "WifiSetupManager: SystemService: Start streaming response data:" << data.count() << "bytes";
|
|
|
|
int sentDataLength = 0;
|
|
QByteArray remainingData = data;
|
|
while (!remainingData.isEmpty()) {
|
|
QByteArray package = remainingData.left(20);
|
|
sentDataLength += package.count();
|
|
m_systemService->writeCharacteristic(commanderCharacteristic, package);
|
|
remainingData = remainingData.remove(0, package.count());
|
|
}
|
|
|
|
qDebug() << "WifiSetupManager: SystemService: Finished streaming request data";
|
|
}
|
|
|
|
void WirelessSetupManager::checkInitialized()
|
|
{
|
|
bool initialized = false;
|
|
|
|
if (m_systemService) {
|
|
initialized = m_deviceInformationService->state() == QLowEnergyService::ServiceDiscovered
|
|
&& m_netwokService->state() == QLowEnergyService::ServiceDiscovered
|
|
&& m_wifiService->state() == QLowEnergyService::ServiceDiscovered
|
|
&& m_systemService->state() == QLowEnergyService::ServiceDiscovered;
|
|
} else {
|
|
initialized = m_deviceInformationService->state() == QLowEnergyService::ServiceDiscovered
|
|
&& m_netwokService->state() == QLowEnergyService::ServiceDiscovered
|
|
&& m_wifiService->state() == QLowEnergyService::ServiceDiscovered;
|
|
}
|
|
|
|
if (initialized && m_wirelessEnabled && m_networkingEnabled) {
|
|
loadNetworks();
|
|
}
|
|
}
|
|
|
|
void WirelessSetupManager::setModelNumber(const QString &modelNumber)
|
|
{
|
|
m_modelNumber = modelNumber;
|
|
emit modelNumberChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setManufacturer(const QString &manufacturer)
|
|
{
|
|
m_manufacturer = manufacturer;
|
|
emit manufacturerChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setSoftwareRevision(const QString &softwareRevision)
|
|
{
|
|
m_softwareRevision = softwareRevision;
|
|
emit softwareRevisionChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setFirmwareRevision(const QString &firmwareRevision)
|
|
{
|
|
m_firmwareRevision = firmwareRevision;
|
|
emit firmwareRevisionChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setHardwareRevision(const QString &hardwareRevision)
|
|
{
|
|
m_hardwareRevision = hardwareRevision;
|
|
emit hardwareRevisionChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setNetworkStatus(int networkStatus)
|
|
{
|
|
if (m_networkStatus == networkStatus)
|
|
return;
|
|
|
|
m_networkStatus = static_cast<NetworkStatus>(networkStatus);
|
|
qDebug() << "-->" << m_networkStatus;
|
|
emit networkStatusChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setWirelessStatus(int wirelessStatus)
|
|
{
|
|
if (m_wirelessStatus == wirelessStatus)
|
|
return;
|
|
|
|
m_wirelessStatus = static_cast<WirelessStatus>(wirelessStatus);
|
|
qDebug() << "-->" << m_wirelessStatus;
|
|
emit wirelessStatusChanged();
|
|
}
|
|
|
|
void WirelessSetupManager::setNetworkingEnabled(bool networkingEnabled)
|
|
{
|
|
if (m_networkingEnabled == networkingEnabled)
|
|
return;
|
|
|
|
qDebug() << "WifiSetupManager: Networking enabled changed" << networkingEnabled;
|
|
m_networkingEnabled = networkingEnabled;
|
|
emit networkingEnabledChanged();
|
|
|
|
if (!m_networkingEnabled)
|
|
m_accessPoints->clearModel();
|
|
|
|
}
|
|
|
|
void WirelessSetupManager::setWirelessEnabled(bool wirelessEnabled)
|
|
{
|
|
if (m_wirelessEnabled == wirelessEnabled)
|
|
return;
|
|
|
|
qDebug() << "WifiSetupManager: Wireless enabled changed" << wirelessEnabled;
|
|
m_wirelessEnabled = wirelessEnabled;
|
|
emit wirelessEnabledChanged();
|
|
|
|
if (!m_wirelessEnabled)
|
|
m_accessPoints->clearModel();
|
|
|
|
}
|
|
|
|
void WirelessSetupManager::streamData(const QVariantMap &request)
|
|
{
|
|
QLowEnergyCharacteristic characteristic = m_wifiService->characteristic(wifiCommanderCharacteristicUuid);
|
|
if (!characteristic.isValid()) {
|
|
qWarning() << "WifiSetupManager: WirelessService: Wireless commander characteristic not valid";
|
|
return;
|
|
}
|
|
|
|
QByteArray data = QJsonDocument::fromVariant(request).toJson(QJsonDocument::Compact) + '\n';
|
|
qDebug() << "WifiSetupManager: WirelessService: Start streaming response data:" << data.count() << "bytes";
|
|
|
|
int sentDataLength = 0;
|
|
QByteArray remainingData = data;
|
|
while (!remainingData.isEmpty()) {
|
|
QByteArray package = remainingData.left(20);
|
|
sentDataLength += package.count();
|
|
m_wifiService->writeCharacteristic(characteristic, package);
|
|
remainingData = remainingData.remove(0, package.count());
|
|
}
|
|
|
|
qDebug() << "WifiSetupManager: WirelessService: Finished streaming request data";
|
|
}
|
|
|
|
void WirelessSetupManager::processNetworkResponse(const QVariantMap &response)
|
|
{
|
|
if (!response.contains("c") || !response.contains("r")) {
|
|
qWarning() << "WifiSetupManager: Got invalid response map.";
|
|
return;
|
|
}
|
|
|
|
NetworkServiceCommand command = (NetworkServiceCommand)response.value("c").toInt();
|
|
NetworkServiceResponse responseCode = (NetworkServiceResponse)response.value("r").toInt();
|
|
|
|
if (responseCode != NetworkServiceResponseSuccess) {
|
|
qWarning() << "WifiSetupManager: Got error for command" << command << responseCode;
|
|
|
|
|
|
switch (responseCode) {
|
|
case NetworkServiceResponseIvalidValue:
|
|
emit errorOccurred(tr("Invalid value."));
|
|
break;
|
|
case NetworkServiceResponseNetworkManagerNotAvailable:
|
|
emit errorOccurred(tr("There is no networkmanager available on the device."));
|
|
break;
|
|
case NetworkServiceResponseWirelessNotAvailable:
|
|
emit errorOccurred(tr("There is no wireless device available on the device."));
|
|
break;
|
|
default:
|
|
emit errorOccurred(tr("Unknown error occured."));
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
qDebug() << "WifiSetupManager: Network command response" << command << responseCode;
|
|
}
|
|
|
|
void WirelessSetupManager::processWifiResponse(const QVariantMap &response)
|
|
{
|
|
m_working = false;
|
|
emit workingChanged();
|
|
|
|
if (!response.contains("c") || !response.contains("r")) {
|
|
qWarning() << "WifiSetupManager: Got invalid response map.";
|
|
return;
|
|
}
|
|
|
|
WirelessServiceCommand command = (WirelessServiceCommand)response.value("c").toInt();
|
|
WirelessServiceResponse responseCode = (WirelessServiceResponse)response.value("r").toInt();
|
|
|
|
if (responseCode != WirelessServiceResponseSuccess) {
|
|
qWarning() << "WifiSetupManager: Got error for command" << command << responseCode;
|
|
|
|
switch (responseCode) {
|
|
case WirelessServiceResponseIvalidCommand:
|
|
emit errorOccurred(tr("Invalid command."));
|
|
break;
|
|
case WirelessServiceResponseIvalidParameters:
|
|
emit errorOccurred(tr("Invalid parameters."));
|
|
break;
|
|
case WirelessServiceResponseNetworkManagerNotAvailable:
|
|
emit errorOccurred(tr("There is no networkmanager available on the device."));
|
|
break;
|
|
case WirelessServiceResponseWirelessNotAvailable:
|
|
emit errorOccurred(tr("There is no wireless device available on the device."));
|
|
break;
|
|
case WirelessServiceResponseWirelessNotEnabled:
|
|
emit errorOccurred(tr("The wireless networking is disabled on the device."));
|
|
break;
|
|
case WirelessServiceResponseNetworkingNotEnabled:
|
|
emit errorOccurred(tr("The networking is disabled on the device."));
|
|
break;
|
|
default:
|
|
emit errorOccurred(tr("Unknown error occured."));
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
switch (command) {
|
|
case WirelessServiceCommandGetNetworks: {
|
|
if (!response.contains("p")) {
|
|
qWarning() << "WifiSetupManager: Missing parameters in response.";
|
|
return;
|
|
}
|
|
|
|
m_accessPointsVariantList = response.value("p").toList();
|
|
m_accessPoints->clearModel();
|
|
|
|
foreach (const QVariant &accessPointVariant, m_accessPointsVariantList) {
|
|
QVariantMap accessPointVariantMap = accessPointVariant.toMap();
|
|
WirelessAccessPoint *accessPoint = new WirelessAccessPoint(this);
|
|
accessPoint->setSsid(accessPointVariantMap.value("e").toString());
|
|
accessPoint->setMacAddress(accessPointVariantMap.value("m").toString());
|
|
accessPoint->setSignalStrength(accessPointVariantMap.value("s").toInt());
|
|
accessPoint->setProtected(accessPointVariantMap.value("p").toBool());
|
|
accessPoint->setHostAddress("");
|
|
|
|
m_accessPoints->addWirelessAccessPoint(accessPoint);
|
|
}
|
|
|
|
loadCurrentConnection();
|
|
|
|
break;
|
|
}
|
|
case WirelessServiceCommandConnect:
|
|
|
|
break;
|
|
case WirelessServiceCommandConnectHidden:
|
|
|
|
break;
|
|
case WirelessServiceCommandDisconnect:
|
|
|
|
break;
|
|
case WirelessServiceCommandGetCurrentConnection: {
|
|
|
|
qDebug() << "Current network connection" << response;
|
|
QVariantMap currentConnection = response.value("p").toMap();;
|
|
|
|
// Find current network
|
|
m_currentConnection = nullptr;
|
|
QString macAddress = currentConnection.value("m").toString();
|
|
foreach (WirelessAccessPoint *accessPoint, m_accessPoints->wirelessAccessPoints()) {
|
|
if (accessPoint->macAddress() == macAddress) {
|
|
// Set the current network
|
|
m_currentConnection = accessPoint;
|
|
accessPoint->setHostAddress(currentConnection.value("i").toString());
|
|
}
|
|
}
|
|
qDebug() << "current connection is:" << m_currentConnection;
|
|
emit currentConnectionChanged();
|
|
|
|
m_initialized = true;
|
|
emit initializedChanged();
|
|
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WirelessSetupManager::processSystemResponse(const QVariantMap &response)
|
|
{
|
|
m_working = false;
|
|
emit workingChanged();
|
|
|
|
if (!response.contains("c") || !response.contains("r")) {
|
|
qWarning() << "WifiSetupManager: Got invalid response map.";
|
|
return;
|
|
}
|
|
|
|
SystemServiceCommand command = (SystemServiceCommand)response.value("c").toInt();
|
|
SystemServiceResponse responseCode = (SystemServiceResponse)response.value("r").toInt();
|
|
|
|
if (responseCode != SystemServiceResponseSuccess) {
|
|
qWarning() << "WifiSetupManager: Got error for command" << command << responseCode;
|
|
return;
|
|
}
|
|
|
|
qDebug() << "WifiSetupManager: System command response" << command << responseCode;
|
|
}
|
|
|
|
void WirelessSetupManager::onConnectedChanged()
|
|
{
|
|
if (!connected()) {
|
|
// Clean up
|
|
qDebug() << "WifiSetupManager: Clean up services";
|
|
if (m_deviceInformationService) {
|
|
m_deviceInformationService->deleteLater();
|
|
}
|
|
if (m_netwokService) {
|
|
m_netwokService->deleteLater();
|
|
}
|
|
if (m_wifiService) {
|
|
m_wifiService->deleteLater();
|
|
}
|
|
if (m_systemService) {
|
|
m_systemService->deleteLater();
|
|
}
|
|
|
|
m_deviceInformationService = nullptr;
|
|
m_netwokService = nullptr;
|
|
m_wifiService = nullptr;
|
|
m_systemService = nullptr;
|
|
|
|
m_accessPoints->clearModel();
|
|
|
|
m_initialized = false;
|
|
emit initializedChanged();
|
|
m_working = false;
|
|
emit workingChanged();
|
|
|
|
setManufacturer("");
|
|
setModelNumber("");
|
|
setSoftwareRevision("");
|
|
setFirmwareRevision("");
|
|
setHardwareRevision("");
|
|
}
|
|
}
|
|
|
|
void WirelessSetupManager::onServiceDiscoveryFinished()
|
|
{
|
|
foreach (const QBluetoothUuid &serviceUuid, controller()->services()) {
|
|
qDebug() << "WifiSetupManager: -->" << serviceUuid.toString();
|
|
}
|
|
|
|
if (!controller()->services().contains(QBluetoothUuid::DeviceInformation)) {
|
|
qWarning() << "WifiSetupManager: Could not find device information service";
|
|
controller()->disconnectFromDevice();
|
|
return;
|
|
}
|
|
|
|
if (!controller()->services().contains(networkServiceUuid)) {
|
|
qWarning() << "WifiSetupManager: Could not find network service";
|
|
controller()->disconnectFromDevice();
|
|
return;
|
|
}
|
|
|
|
if (!controller()->services().contains(wifiServiceUuid)) {
|
|
qWarning() << "WifiSetupManager: Could not find wifi service";
|
|
controller()->disconnectFromDevice();
|
|
return;
|
|
}
|
|
|
|
// Device Informantion service
|
|
if (!m_deviceInformationService) {
|
|
m_deviceInformationService = controller()->createServiceObject(QBluetoothUuid::DeviceInformation, this);
|
|
if (!m_deviceInformationService) {
|
|
qWarning() << "WifiSetupManager: Could not create temperature service.";
|
|
controller()->disconnectFromDevice();
|
|
return;
|
|
}
|
|
|
|
connect(m_deviceInformationService, &QLowEnergyService::stateChanged, this, &WirelessSetupManager::onDeviceInformationStateChanged);
|
|
connect(m_deviceInformationService, &QLowEnergyService::characteristicChanged, this, &WirelessSetupManager::onDeviceInformationCharacteristicChanged);
|
|
connect(m_deviceInformationService, &QLowEnergyService::characteristicRead, this, &WirelessSetupManager::onDeviceInformationCharacteristicChanged);
|
|
|
|
if (m_deviceInformationService->state() == QLowEnergyService::DiscoveryRequired) {
|
|
qDebug() << "WifiSetupManager: start discovering device information service...";
|
|
m_deviceInformationService->discoverDetails();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void WirelessSetupManager::onDeviceInformationStateChanged(const QLowEnergyService::ServiceState &state)
|
|
{
|
|
|
|
if (state != QLowEnergyService::ServiceDiscovered)
|
|
return;
|
|
|
|
qDebug() << "WifiSetupManager: Device information service discovered.";
|
|
|
|
foreach (const QLowEnergyCharacteristic &characteristic, m_deviceInformationService->characteristics()) {
|
|
qDebug() << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
|
|
foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
|
qDebug() << " -->" << descriptor.name() << descriptor.uuid().toString() << descriptor.value();
|
|
}
|
|
}
|
|
|
|
setManufacturer(QString::fromUtf8(m_deviceInformationService->characteristic(QBluetoothUuid::ManufacturerNameString).value()));
|
|
setModelNumber(QString::fromUtf8(m_deviceInformationService->characteristic(QBluetoothUuid::ModelNumberString).value()));
|
|
setSoftwareRevision(QString::fromUtf8(m_deviceInformationService->characteristic(QBluetoothUuid::SoftwareRevisionString).value()));
|
|
setFirmwareRevision(QString::fromUtf8(m_deviceInformationService->characteristic(QBluetoothUuid::FirmwareRevisionString).value()));
|
|
setHardwareRevision(QString::fromUtf8(m_deviceInformationService->characteristic(QBluetoothUuid::HardwareRevisionString).value()));
|
|
|
|
// Network service
|
|
if (!m_netwokService) {
|
|
m_netwokService = controller()->createServiceObject(networkServiceUuid, this);
|
|
if (!m_netwokService) {
|
|
qWarning() << "WifiSetupManager: Could not create network service.";
|
|
controller()->disconnectFromDevice();
|
|
return;
|
|
}
|
|
|
|
connect(m_netwokService, &QLowEnergyService::stateChanged, this, &WirelessSetupManager::onNetworkServiceStateChanged);
|
|
connect(m_netwokService, &QLowEnergyService::characteristicChanged, this, &WirelessSetupManager::onNetworkServiceCharacteristicChanged);
|
|
connect(m_netwokService, &QLowEnergyService::characteristicRead, this, &WirelessSetupManager::onNetworkServiceReadFinished);
|
|
|
|
if (m_netwokService->state() == QLowEnergyService::DiscoveryRequired) {
|
|
qDebug() << "WifiSetupManager: start discovering network service...";
|
|
m_netwokService->discoverDetails();
|
|
}
|
|
}
|
|
checkInitialized();
|
|
}
|
|
|
|
void WirelessSetupManager::onDeviceInformationCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
Q_UNUSED(value)
|
|
}
|
|
|
|
void WirelessSetupManager::onDeviceInformationReadFinished(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
Q_UNUSED(value)
|
|
}
|
|
|
|
void WirelessSetupManager::onNetworkServiceStateChanged(const QLowEnergyService::ServiceState &state)
|
|
{
|
|
if (state != QLowEnergyService::ServiceDiscovered)
|
|
return;
|
|
|
|
qDebug() << "WifiSetupManager: Network service discovered.";
|
|
|
|
foreach (const QLowEnergyCharacteristic &characteristic, m_netwokService->characteristics()) {
|
|
qDebug() << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
|
|
foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
|
qDebug() << " -->" << descriptor.name() << descriptor.uuid().toString() << descriptor.value();
|
|
}
|
|
}
|
|
|
|
QLowEnergyCharacteristic networkCharacteristic = m_netwokService->characteristic(networkStatusCharacteristicUuid);
|
|
if (!networkCharacteristic.isValid()) {
|
|
qWarning() << "Invalud networking status characteristic";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic networkingEnabledCharacteristic = m_netwokService->characteristic(networkingEnabledCharacteristicUuid);
|
|
if (!networkingEnabledCharacteristic.isValid()) {
|
|
qWarning() << "Invalud networking enabled characteristic";
|
|
return;
|
|
}
|
|
|
|
QLowEnergyCharacteristic wirelessEnabledCharacteristic = m_netwokService->characteristic(wirelessEnabledCharacteristicUuid);
|
|
if (!wirelessEnabledCharacteristic.isValid()) {
|
|
qWarning() << "Invalud wireless enabled characteristic";
|
|
return;
|
|
}
|
|
|
|
|
|
// Enable notifications
|
|
qDebug() << "Enable notifications of network service";
|
|
m_netwokService->writeDescriptor(networkCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), QByteArray::fromHex("0100"));
|
|
m_netwokService->writeDescriptor(networkingEnabledCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), QByteArray::fromHex("0100"));
|
|
m_netwokService->writeDescriptor(wirelessEnabledCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), QByteArray::fromHex("0100"));
|
|
|
|
setStatusText("Connected and ready");
|
|
m_working = false;
|
|
emit workingChanged();
|
|
|
|
// Done with discovery
|
|
setNetworkStatus(networkCharacteristic.value().toHex().toUInt(0, 16));
|
|
setNetworkingEnabled((bool)networkingEnabledCharacteristic.value().toHex().toUInt(0, 16));
|
|
setWirelessEnabled((bool)wirelessEnabledCharacteristic.value().toHex().toUInt(0, 16));
|
|
|
|
// Wifi service
|
|
if (!m_wifiService) {
|
|
m_wifiService = controller()->createServiceObject(wifiServiceUuid, this);
|
|
if (!m_wifiService) {
|
|
qWarning() << "WifiSetupManager: Could not create wifi service.";
|
|
controller()->disconnectFromDevice();
|
|
return;
|
|
}
|
|
|
|
connect(m_wifiService, &QLowEnergyService::stateChanged, this, &WirelessSetupManager::onWifiServiceStateChanged);
|
|
connect(m_wifiService, &QLowEnergyService::characteristicChanged, this, &WirelessSetupManager::onWifiServiceCharacteristicChanged);
|
|
connect(m_wifiService, &QLowEnergyService::characteristicRead, this, &WirelessSetupManager::onWifiServiceReadFinished);
|
|
|
|
if (m_wifiService->state() == QLowEnergyService::DiscoveryRequired) {
|
|
qDebug() << "WifiSetupManager: start discovering wifi service...";
|
|
m_wifiService->discoverDetails();
|
|
}
|
|
|
|
}
|
|
|
|
checkInitialized();
|
|
}
|
|
|
|
void WirelessSetupManager::onNetworkServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
if (characteristic.uuid() == networkStatusCharacteristicUuid) {
|
|
qDebug() << "Network status changed:" << value;
|
|
setNetworkStatus(value.toHex().toInt(nullptr, 16));
|
|
if (m_networkStatus == NetworkStatusGlobal) {
|
|
loadCurrentConnection();
|
|
}
|
|
return;
|
|
} else if (characteristic.uuid() == networkResponseCharacteristicUuid) {
|
|
// Check if currently reading
|
|
if (m_readingResponse) {
|
|
m_inputDataStream.append(value);
|
|
} else {
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = true;
|
|
m_inputDataStream.append(value);
|
|
}
|
|
|
|
// If command finished
|
|
if (value.endsWith('\n')) {
|
|
QJsonParseError error;
|
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(m_inputDataStream, &error);
|
|
if (error.error != QJsonParseError::NoError) {
|
|
qWarning() << "Got invalid json object" << m_inputDataStream;
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = false;
|
|
return;
|
|
}
|
|
|
|
qDebug() << "Got command stream" << qUtf8Printable(jsonDocument.toJson());
|
|
|
|
processNetworkResponse(jsonDocument.toVariant().toMap());
|
|
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = false;
|
|
return;
|
|
}
|
|
} else if (characteristic.uuid() == networkingEnabledCharacteristicUuid) {
|
|
qDebug() << "Networking enabled changed" << (bool)value.toHex().toUInt(0, 16);
|
|
setNetworkingEnabled((bool)value.toHex().toUInt(0, 16));
|
|
return;
|
|
} else if (characteristic.uuid() == wirelessEnabledCharacteristicUuid) {
|
|
qDebug() << "Wireless enabled changed" << (bool)value.toHex().toUInt(0, 16);
|
|
setWirelessEnabled((bool)value.toHex().toUInt(0, 16));
|
|
return;
|
|
}
|
|
|
|
qWarning() << "Bluetooth: Unhandled service characteristic changed" << characteristic.uuid() << value;
|
|
}
|
|
|
|
void WirelessSetupManager::onNetworkServiceReadFinished(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
Q_UNUSED(value)
|
|
}
|
|
|
|
void WirelessSetupManager::onWifiServiceStateChanged(const QLowEnergyService::ServiceState &state)
|
|
{
|
|
if (state != QLowEnergyService::ServiceDiscovered)
|
|
return;
|
|
|
|
qDebug() << "WifiSetupManager: Wifi service discovered.";
|
|
|
|
foreach (const QLowEnergyCharacteristic &characteristic, m_wifiService->characteristics()) {
|
|
qDebug() << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
|
|
foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
|
qDebug() << " -->" << descriptor.name() << descriptor.uuid().toString() << descriptor.value();
|
|
}
|
|
}
|
|
|
|
// Enable notifications
|
|
m_wifiService->writeDescriptor(m_wifiService->characteristic(wifiResponseCharacteristicUuid).descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), QByteArray::fromHex("0100"));
|
|
m_wifiService->writeDescriptor(m_wifiService->characteristic(wifiStatusCharacteristicUuid).descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), QByteArray::fromHex("0100"));
|
|
|
|
setWirelessStatus(m_wifiService->characteristic(wifiStatusCharacteristicUuid).value().toHex().toUInt(0, 16));
|
|
|
|
// System service
|
|
if (!m_systemService) {
|
|
m_systemService = controller()->createServiceObject(systemServiceUuid, this);
|
|
if (!m_systemService) {
|
|
qWarning() << "WifiSetupManager: Could not create system service. Looks like this networkmanager has not implemented that.";
|
|
//controller()->disconnectFromDevice();
|
|
} else {
|
|
connect(m_systemService, &QLowEnergyService::stateChanged, this, &WirelessSetupManager::onSystemServiceStateChanged);
|
|
connect(m_systemService, &QLowEnergyService::characteristicChanged, this, &WirelessSetupManager::onSystemServiceCharacteristicChanged);
|
|
connect(m_systemService, &QLowEnergyService::characteristicRead, this, &WirelessSetupManager::onSystemServiceReadFinished);
|
|
|
|
if (m_systemService->state() == QLowEnergyService::DiscoveryRequired) {
|
|
qDebug() << "WifiSetupManager: start discovering system service...";
|
|
m_systemService->discoverDetails();
|
|
}
|
|
}
|
|
}
|
|
|
|
checkInitialized();
|
|
}
|
|
|
|
void WirelessSetupManager::onWifiServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
|
|
if (characteristic.uuid() == wifiResponseCharacteristicUuid) {
|
|
// Check if currently reading
|
|
if (m_readingResponse) {
|
|
m_inputDataStream.append(value);
|
|
} else {
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = true;
|
|
m_inputDataStream.append(value);
|
|
}
|
|
|
|
// If command finished
|
|
if (value.endsWith('\n')) {
|
|
QJsonParseError error;
|
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(m_inputDataStream, &error);
|
|
if (error.error != QJsonParseError::NoError) {
|
|
qWarning() << "Got invalid json object" << m_inputDataStream;
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = false;
|
|
return;
|
|
}
|
|
|
|
qDebug() << "Got command stream" << qUtf8Printable(jsonDocument.toJson());
|
|
|
|
processWifiResponse(jsonDocument.toVariant().toMap());
|
|
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = false;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (characteristic.uuid() == wifiStatusCharacteristicUuid) {
|
|
qDebug() << "Wireless status changed:" << value.toHex().toUInt(nullptr, 16) << "Old status:" << m_wirelessStatus;
|
|
setWirelessStatus(value.toHex().toInt(nullptr, 16));
|
|
if (m_wirelessStatus == WirelessStatusActivated) {
|
|
loadCurrentConnection();
|
|
}
|
|
return;
|
|
}
|
|
|
|
qWarning() << "Bluetooth: Unhandled service characteristic changed" << characteristic.uuid() << value;
|
|
|
|
}
|
|
|
|
void WirelessSetupManager::onWifiServiceReadFinished(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
Q_UNUSED(value)
|
|
}
|
|
|
|
void WirelessSetupManager::onSystemServiceStateChanged(const QLowEnergyService::ServiceState &state)
|
|
{
|
|
if (state != QLowEnergyService::ServiceDiscovered)
|
|
return;
|
|
|
|
qDebug() << "WifiSetupManager: System service discovered.";
|
|
|
|
foreach (const QLowEnergyCharacteristic &characteristic, m_systemService->characteristics()) {
|
|
qDebug() << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
|
|
foreach (const QLowEnergyDescriptor &descriptor, characteristic.descriptors()) {
|
|
qDebug() << " -->" << descriptor.name() << descriptor.uuid().toString() << descriptor.value();
|
|
}
|
|
}
|
|
|
|
// Enable notifications
|
|
m_systemService->writeDescriptor(m_systemService->characteristic(systemResponseCharacteristicUuid).descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), QByteArray::fromHex("0100"));
|
|
|
|
checkInitialized();
|
|
}
|
|
|
|
void WirelessSetupManager::onSystemServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
|
|
// Check if currently reading
|
|
if (m_readingResponse) {
|
|
m_inputDataStream.append(value);
|
|
} else {
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = true;
|
|
m_inputDataStream.append(value);
|
|
}
|
|
|
|
// If command finished
|
|
if (value.endsWith('\n')) {
|
|
QJsonParseError error;
|
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(m_inputDataStream, &error);
|
|
if (error.error != QJsonParseError::NoError) {
|
|
qWarning() << "Got invalid json object" << m_inputDataStream;
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = false;
|
|
return;
|
|
}
|
|
|
|
qDebug() << "Got command stream" << qUtf8Printable(jsonDocument.toJson());
|
|
|
|
processSystemResponse(jsonDocument.toVariant().toMap());
|
|
|
|
m_inputDataStream.clear();
|
|
m_readingResponse = false;
|
|
}
|
|
}
|
|
|
|
void WirelessSetupManager::onSystemServiceReadFinished(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
|
|
{
|
|
Q_UNUSED(characteristic)
|
|
Q_UNUSED(value)
|
|
}
|