From cd445ba31ca2f4ca4cec0ce7d451f50fa6c5fa72 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Fri, 13 Jul 2018 15:28:17 -0400 Subject: network: add network model Add the top-level network model. Supports connect, disconnect, power, and input invokables. Supports high-level WiFi enabled (powered) and connection status properties. Exposes the ConnMan-managed WiFi network list to QML. Bug-AGL: SPEC-1541 Change-Id: I623579aa6753ece4b4c0b78adef528732e1b41f3 Signed-off-by: Matt Porter --- network/CMakeLists.txt | 4 +- network/network.cpp | 324 +++++++++++++++++++++++++++++++++++++++++++++++++ network/network.h | 93 ++++++++++++++ 3 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 network/network.cpp create mode 100644 network/network.h diff --git a/network/CMakeLists.txt b/network/CMakeLists.txt index e3d4812..0a53327 100644 --- a/network/CMakeLists.txt +++ b/network/CMakeLists.txt @@ -1,2 +1,2 @@ -add_headers(networkmessage.h wifinetworkmodel.h) -add_sources(networkmessage.cpp wifinetworkmodel.cpp) +add_headers(network.h networkmessage.h wifinetworkmodel.h) +add_sources(network.cpp networkmessage.cpp wifinetworkmodel.cpp) diff --git a/network/network.cpp b/network/network.cpp new file mode 100644 index 0000000..d2a00ff --- /dev/null +++ b/network/network.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include "message.h" +#include "messageengine.h" +#include "network.h" +#include "networkmessage.h" +#include "responsemessage.h" +#include "wifinetworkmodel.h" + +Network::Network (QUrl &url, QQmlContext *context, QObject * parent) : + QObject(parent), + m_mloop(nullptr), + m_wifi(nullptr), + m_wifiConnected(false), + m_wifiEnabled(false) +{ + m_mloop = new MessageEngine(url); + m_wifi = new WifiNetworkModel(); + + context->setContextProperty("WifiNetworkModel", m_wifi); + + QObject::connect(m_mloop, &MessageEngine::connected, this, &Network::onConnected); + QObject::connect(m_mloop, &MessageEngine::disconnected, this, &Network::onDisconnected); + QObject::connect(m_mloop, &MessageEngine::messageReceived, this, &Network::onMessageReceived); +} + +Network::~Network() +{ + delete m_mloop; + delete m_wifi; +} + +void Network::connect(QString service) +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + parameter.insert("service", service); + + nmsg->createRequest("connect_service", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); +} + +void Network::disconnect(QString service) +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + parameter.insert("service", service); + + nmsg->createRequest("disconnect_service", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); +} + +void Network::input(int id, QString passphrase) +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter, fields; + + parameter.insert("id", id); + fields.insert("passphrase", passphrase); + parameter.insert("fields", fields); + + nmsg->createRequest("agent_response", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); +} + +void Network::power(bool on) +{ + if (on) + enableTechnology("wifi"); + else + disableTechnology("wifi"); +} + +void Network::enableTechnology(QString type) +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + parameter.insert("technology", type); + nmsg->createRequest("enable_technology", parameter); + m_mloop->sendMessage(nmsg); + + nmsg->deleteLater(); +} + +void Network::disableTechnology(QString type) +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + parameter.insert("technology", type); + nmsg->createRequest("disable_technology", parameter); + m_mloop->sendMessage(nmsg); + + nmsg->deleteLater(); +} + +void Network::scanServices(QString type) +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + parameter.insert("technology", type); + nmsg->createRequest("scan_services", parameter); + m_mloop->sendMessage(nmsg); + + nmsg->deleteLater(); +} + +bool Network::addService(QJsonObject service) +{ + // Ignore services that are already added + QString id = service.value("service").toString(); + if (m_wifi->getNetwork(id)) + return false; + + QJsonObject properties = service.value("properties").toObject(); + + // Ignore hidden SSIDs + QString ssid = properties.value("name").toString(); + if (ssid == "") + return false; + + // Ignore technologies other than WiFi + QString type = properties.value("type").toString(); + if (type != "wifi") + return false; + + // Initially support only IPv4 and the first security method found + QString address = properties.value("ipv4").toObject().value("address").toString(); + QString security = properties.value("security").toArray().at(0).toString(); + QString state = properties.value("state").toString(); + int strength = properties.value("strength").toInt(); + + WifiNetwork *network = new WifiNetwork(address, security, id, ssid, state, strength); + m_wifi->addNetwork(network); + + return true; +} + +void Network::removeService(QJsonObject service) +{ + QString id = service.value("service").toString(); + WifiNetwork *network = m_wifi->getNetwork(id); + + if (network) + m_wifi->removeNetwork(network); +} + +void Network::addServices(QJsonArray services) +{ + for (auto service : services) + addService(service.toObject()); +} + +void Network::getServices() +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + nmsg->createRequest("services", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); +} + +void Network::updateWifiStatus(QJsonObject properties) +{ + if (properties.contains("connected")) { + m_wifiConnected = properties.value("connected").toBool(); + emit wifiConnectedChanged(m_wifiConnected); + } + + if (properties.contains("powered")) { + m_wifiEnabled = properties.value("powered").toBool(); + emit wifiEnabledChanged(m_wifiEnabled); + if (m_wifiEnabled) + getServices(); + } +} + +void Network::parseTechnologies(QJsonArray technologies) +{ + for (auto value : technologies) { + QJsonObject technology = value.toObject(); + QJsonObject properties = technology.value("properties").toObject(); + QString type = properties.value("type").toString(); + if (type == "wifi") { + updateWifiStatus(properties); + if (m_wifiEnabled) + getServices(); + break; + } + } +} + +void Network::getTechnologies() +{ + NetworkMessage *nmsg = new NetworkMessage(); + QJsonObject parameter; + + nmsg->createRequest("technologies", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); +} + +void Network::updateServiceProperties(QJsonObject data) +{ + QString service = data.value("service").toString(); + QJsonObject properties = data.value("properties").toObject(); + m_wifi->updateProperties(service, properties); +} + +void Network::processEvent(NetworkMessage *nmsg) +{ + if (nmsg->eventName() == "agent") { + QJsonObject agent = nmsg->eventData(); + QJsonObject fields = agent.value("fields").toObject(); + QJsonObject passphrase = fields.value("passphrase").toObject(); + QString type = passphrase.value("type").toString(); + QString reqmt = passphrase.value("requirement").toString(); + if (((type == "psk") || (type == "wep")) && (reqmt == "mandatory")) { + int id = agent.value("id").toInt(); + emit inputRequest(id); + } + } else if (nmsg->eventName() == "services") { + QJsonArray services = nmsg->eventData().value("values").toArray(); + for (auto value : services) { + QJsonObject service = value.toObject(); + QString action = service.value("action").toString(); + QString id = service.value("service").toString(); + if (action == "changed") { + addService(service); + } else if (action == "removed") { + removeService(service); + } + } + } else if (nmsg->eventName() == "service_properties") { + updateServiceProperties(nmsg->eventData()); + } else if (nmsg->eventName() == "technology_properties") { + QJsonObject technology = nmsg->eventData(); + if (technology.value("technology").toString() == "wifi") { + QJsonObject properties = technology.value("properties").toObject(); + updateWifiStatus(properties); + } + } +} + +void Network::processReply(ResponseMessage *rmsg) +{ + if (rmsg->requestVerb() == "services") { + addServices(rmsg->replyData().value("values").toArray()); + } else if (rmsg->requestVerb() == "technologies") { + parseTechnologies(rmsg->replyData().value("values").toArray()); + } +} + +void Network::onMessageReceived(MessageType type, Message *msg) +{ + if (msg->isEvent() && (type == NetworkEventMessage)) { + processEvent(qobject_cast(msg)); + } else if (msg->isReply() && (type == ResponseRequestMessage)) { + processReply(qobject_cast(msg)); + } + + msg->deleteLater(); +} + +void Network::onConnected() +{ + QStringListIterator eventIterator(events); + NetworkMessage *nmsg; + + while (eventIterator.hasNext()) { + nmsg = new NetworkMessage(); + QJsonObject parameter; + parameter.insert("value", eventIterator.next()); + nmsg->createRequest("subscribe", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); + } + + getTechnologies(); +} + +void Network::onDisconnected() +{ + QStringListIterator eventIterator(events); + NetworkMessage *nmsg; + + while (eventIterator.hasNext()) { + nmsg = new NetworkMessage(); + QJsonObject parameter; + parameter.insert("value", eventIterator.next()); + nmsg->createRequest("unsubscribe", parameter); + m_mloop->sendMessage(nmsg); + nmsg->deleteLater(); + } + + m_wifi->removeAllNetworks(); +} diff --git a/network/network.h b/network/network.h new file mode 100644 index 0000000..dc52dd2 --- /dev/null +++ b/network/network.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETWORK_H +#define NETWORK_H + +#include +#include +#include +#include +#include + +#include "messageengine.h" +#include "networkmessage.h" +#include "responsemessage.h" +#include "wifinetworkmodel.h" + +class Network : public QObject +{ + Q_OBJECT + + public: + explicit Network(QUrl &url, QQmlContext *context, QObject * parent = Q_NULLPTR); + virtual ~Network(); + + Q_INVOKABLE void connect(QString service); + Q_INVOKABLE void disconnect(QString service); + Q_INVOKABLE void power(bool on); + Q_INVOKABLE void input(int id, QString passphrase); + + Q_PROPERTY(bool wifiConnected READ wifiConnected NOTIFY wifiConnectedChanged) + Q_PROPERTY(bool wifiEnabled READ wifiEnabled NOTIFY wifiEnabledChanged) + + bool wifiConnected() const { return m_wifiConnected; } + bool wifiEnabled() const { return m_wifiEnabled; } + + signals: + void inputRequest(int id); + void searchResults(QString name); + void statusChanged(bool connected); + void wifiConnectedChanged(bool connected); + void wifiEnabledChanged(bool enabled); + + private: + MessageEngine *m_mloop; + QQmlContext *m_context; + WifiNetworkModel *m_wifi; + bool m_wifiConnected; + bool m_wifiEnabled; + + void updateWifiStatus(QJsonObject properties); + void updateServiceProperties(QJsonObject data); + bool addService(QJsonObject service); + void removeService(QJsonObject remove); + void addServices(QJsonArray services); + void getServices(); + void scanServices(QString type); + void disableTechnology(QString type); + void enableTechnology(QString type); + void parseTechnologies(QJsonArray technologies); + void getTechnologies(); + void processEvent(NetworkMessage *nmsg); + void processReply(ResponseMessage *rmsg); + + // slots + void onConnected(); + void onDisconnected(); + void onMessageReceived(MessageType, Message*); + + const QStringList events { + "agent", + "global_state", + "services", + "service_properties", + "technologies", + "technology_properties", + }; +}; + +#endif // NETWORK_H -- cgit 1.2.3-korg