This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
2020-01-09 22:43:38 +01:00

235 lines
7.3 KiB
C++

#include "nymeadiscovery.h"
#include "upnpdiscovery.h"
#include "zeroconfdiscovery.h"
#include "bluetoothservicediscovery.h"
#include "connection/awsclient.h"
#include "../nymeahost.h"
#include <QUuid>
#include <QBluetoothUuid>
#include <QUrlQuery>
#include <QSettings>
#include <QNetworkConfigurationManager>
#include <QNetworkSession>
NymeaDiscovery::NymeaDiscovery(QObject *parent) : QObject(parent)
{
m_nymeaHosts = new NymeaHosts(this);
loadFromDisk();
m_upnp = new UpnpDiscovery(m_nymeaHosts, this);
m_zeroConf = new ZeroconfDiscovery(m_nymeaHosts, this);
#ifndef Q_OS_IOS
m_bluetooth = new BluetoothServiceDiscovery(m_nymeaHosts, this);
#endif
m_cloudPollTimer.setInterval(5000);
connect(&m_cloudPollTimer, &QTimer::timeout, this, [this](){
if (m_awsClient && m_awsClient->isLoggedIn()) {
m_awsClient->fetchDevices();
}
});
}
NymeaDiscovery::~NymeaDiscovery()
{
}
bool NymeaDiscovery::discovering() const
{
return m_discovering;
}
void NymeaDiscovery::setDiscovering(bool discovering)
{
if (m_discovering == discovering)
return;
m_discovering = discovering;
// If we have zeroconf skip upnp. ZeroConf will not do an active discovery and if it's available it'll always have good data
if (!m_zeroConf->available()) {
if (discovering) {
m_upnp->discover();
} else {
m_upnp->stopDiscovery();
}
}
if (discovering) {
// If there's no Zeroconf, use UPnP instead
if (!m_zeroConf->available()) {
m_upnp->discover();
}
// Always start Bluetooth discovery if HW is available
if (m_bluetooth) {
m_bluetooth->discover();
}
// start polling cloud
m_cloudPollTimer.start();
// If we're logged in, poll right away
if (m_awsClient && m_awsClient->isLoggedIn()) {
m_awsClient->fetchDevices();
}
} else {
if (!m_zeroConf->available()) {
m_upnp->stopDiscovery();
}
if (m_bluetooth) {
m_bluetooth->stopDiscovery();
}
m_cloudPollTimer.stop();
}
emit discoveringChanged();
}
NymeaHosts *NymeaDiscovery::nymeaHosts() const
{
return m_nymeaHosts;
}
AWSClient *NymeaDiscovery::awsClient() const
{
return m_awsClient;
}
void NymeaDiscovery::setAwsClient(AWSClient *awsClient)
{
if (m_awsClient != awsClient) {
m_awsClient = awsClient;
emit awsClientChanged();
}
if (m_awsClient) {
connect(m_awsClient, &AWSClient::devicesFetched, this, &NymeaDiscovery::syncCloudDevices);
}
}
void NymeaDiscovery::cacheHost(NymeaHost *host)
{
QSettings settings;
settings.beginGroup("HostCache");
settings.remove(host->uuid().toString());
settings.beginGroup(host->uuid().toString());
settings.setValue("name", host->name());
QList<Connection*> connections;
Connection *remoteConnection = host->connections()->bestMatch(Connection::BearerTypeCloud);
if (remoteConnection) {
connections.append(remoteConnection);
}
Connection *loopbackConnection = host->connections()->bestMatch(Connection::BearerTypeLoopback);
if (loopbackConnection) {
connections.append(loopbackConnection);
}
Connection *lanConnection = host->connections()->bestMatch(Connection::BearerTypeLan);
if (lanConnection) {
connections.append(lanConnection);
}
Connection *wanConnection = host->connections()->bestMatch(Connection::BearerTypeWan);
if (wanConnection) {
connections.append(wanConnection);
}
Connection *btConnection = host->connections()->bestMatch(Connection::BearerTypeBluetooth);
if (btConnection) {
connections.append(btConnection);
}
int i = 0;
foreach (Connection *connection, connections) {
settings.beginGroup(QString::number(i++));
settings.setValue("url", connection->url());
settings.setValue("bearerType", connection->bearerType());
settings.value("secure", connection->secure());
settings.setValue("displayName", connection->displayName());
settings.endGroup();
}
settings.endGroup();
}
void NymeaDiscovery::syncCloudDevices()
{
for (int i = 0; i < m_awsClient->awsDevices()->rowCount(); i++) {
AWSDevice *d = m_awsClient->awsDevices()->get(i);
NymeaHost *host = m_nymeaHosts->find(d->id());
if (!host) {
host = new NymeaHost();
host->setUuid(d->id());
qDebug() << "CloudDiscovery: Adding new host:" << host->name() << host->uuid().toString();
m_nymeaHosts->addHost(host);
}
host->setName(d->name());
QUrl url;
url.setScheme("cloud");
url.setHost(d->id());
Connection *conn = host->connections()->find(url);
if (!conn) {
conn = new Connection(url, Connection::BearerTypeCloud, true, d->id());
qDebug() << "CloudDiscovery: Adding new connection to host:" << host->name() << conn->url().toString();
host->connections()->addConnection(conn);
}
conn->setOnline(d->online());
}
QList<NymeaHost*> hostsToRemove;
for (int i = 0; i < m_nymeaHosts->rowCount(); i++) {
NymeaHost *host = m_nymeaHosts->get(i);
for (int j = 0; j < host->connections()->rowCount(); j++) {
if (host->connections()->get(j)->bearerType() == Connection::BearerTypeCloud) {
if (m_awsClient->awsDevices()->getDevice(host->uuid().toString()) == nullptr) {
host->connections()->removeConnection(j);
break;
}
}
}
if (host->connections()->rowCount() == 0) {
hostsToRemove.append(host);
}
}
while (!hostsToRemove.isEmpty()) {
m_nymeaHosts->removeHost(hostsToRemove.takeFirst());
}
}
void NymeaDiscovery::loadFromDisk()
{
QSettings settings;
settings.beginGroup("HostCache");
foreach (const QString &serverUuid, settings.childGroups()) {
settings.beginGroup(serverUuid);
NymeaHost* host = m_nymeaHosts->find(QUuid(serverUuid));
if (!host) {
host = new NymeaHost(m_nymeaHosts);
host->setName(settings.value("name").toString());
host->setUuid(QUuid(serverUuid));
m_nymeaHosts->addHost(host);
}
qDebug() << "Loaded Host from cache" << host->name() << host->uuid();
foreach (const QString &group, settings.childGroups()) {
settings.beginGroup(group);
QString url = settings.value("url").toString();
Connection* connection = host->connections()->find(url);
if (!connection) {
Connection::BearerType bearerType = static_cast<Connection::BearerType>(settings.value("bearerType").toInt());
bool secure = settings.value("secure").toBool();
QString displayName = settings.value("displayName").toString();
connection = new Connection(url, bearerType, secure, displayName, host);
host->connections()->addConnection(connection);
qDebug() << "|- Connection:" << group << connection->url() << connection->bearerType() << "secure:" << connection->secure();
}
settings.endGroup();
}
settings.endGroup();
}
}
void NymeaDiscovery::updateActiveBearers()
{
}