From 217007154c38390e5de20920b8d0ec279978bd1e Mon Sep 17 00:00:00 2001 From: 0xFEEDC0DE64 Date: Thu, 6 Nov 2025 16:07:19 +0100 Subject: [PATCH] Remove flotten-updater --- CMakeLists.txt | 11 +- flotten-updater/CMakeLists.txt | 60 -- flotten-updater/addserialsrangedialog.cpp | 61 -- flotten-updater/addserialsrangedialog.h | 27 - flotten-updater/addserialsrangedialog.ui | 109 --- flotten-updater/deviceconnection.cpp | 656 ------------------- flotten-updater/deviceconnection.h | 135 ---- flotten-updater/devicesmodel.cpp | 523 --------------- flotten-updater/devicesmodel.h | 74 --- flotten-updater/flottenupdatersettings.cpp | 41 -- flotten-updater/flottenupdatersettings.h | 23 - flotten-updater/goe-root-ca.pem | 32 - flotten-updater/importcredentialsdialog.cpp | 89 --- flotten-updater/importcredentialsdialog.h | 35 - flotten-updater/importcredentialsdialog.ui | 114 ---- flotten-updater/main.cpp | 63 -- flotten-updater/mainwindow.cpp | 321 --------- flotten-updater/mainwindow.h | 40 -- flotten-updater/mainwindow.ui | 92 --- flotten-updater/requestdialog.cpp | 19 - flotten-updater/requestdialog.h | 24 - flotten-updater/requestdialog.ui | 71 -- flotten-updater/requestmodel.cpp | 177 ----- flotten-updater/requestmodel.h | 37 -- flotten-updater/setarbitraryapikeydialog.cpp | 61 -- flotten-updater/setarbitraryapikeydialog.h | 28 - flotten-updater/setarbitraryapikeydialog.ui | 127 ---- 27 files changed, 4 insertions(+), 3046 deletions(-) delete mode 100644 flotten-updater/CMakeLists.txt delete mode 100644 flotten-updater/addserialsrangedialog.cpp delete mode 100644 flotten-updater/addserialsrangedialog.h delete mode 100644 flotten-updater/addserialsrangedialog.ui delete mode 100644 flotten-updater/deviceconnection.cpp delete mode 100644 flotten-updater/deviceconnection.h delete mode 100644 flotten-updater/devicesmodel.cpp delete mode 100644 flotten-updater/devicesmodel.h delete mode 100644 flotten-updater/flottenupdatersettings.cpp delete mode 100644 flotten-updater/flottenupdatersettings.h delete mode 100644 flotten-updater/goe-root-ca.pem delete mode 100644 flotten-updater/importcredentialsdialog.cpp delete mode 100644 flotten-updater/importcredentialsdialog.h delete mode 100644 flotten-updater/importcredentialsdialog.ui delete mode 100644 flotten-updater/main.cpp delete mode 100644 flotten-updater/mainwindow.cpp delete mode 100644 flotten-updater/mainwindow.h delete mode 100644 flotten-updater/mainwindow.ui delete mode 100644 flotten-updater/requestdialog.cpp delete mode 100644 flotten-updater/requestdialog.h delete mode 100644 flotten-updater/requestdialog.ui delete mode 100644 flotten-updater/requestmodel.cpp delete mode 100644 flotten-updater/requestmodel.h delete mode 100644 flotten-updater/setarbitraryapikeydialog.cpp delete mode 100644 flotten-updater/setarbitraryapikeydialog.h delete mode 100644 flotten-updater/setarbitraryapikeydialog.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index bf38f94..5da2708 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.16) project(evcharger-app LANGUAGES CXX) set(CMAKE_AUTOMOC ON) -#set(CMAKE_CXX_STANDARD 23) -#set(CMAKE_CXX_STANDARD_REQUIRED ON) -#set(CMAKE_CXX_EXTENSIONS ON) -add_compile_options(-std=c++2b) +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) +#add_compile_options(-std=c++2b) find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) @@ -16,7 +16,4 @@ add_definitions(-DQT_GUI_LIB) add_subdirectory(3rdparty) add_subdirectory(evcharger-app) -if (NOT ANDROID) -add_subdirectory(flotten-updater) -endif() add_subdirectory(goecommon) diff --git a/flotten-updater/CMakeLists.txt b/flotten-updater/CMakeLists.txt deleted file mode 100644 index e0f7238..0000000 --- a/flotten-updater/CMakeLists.txt +++ /dev/null @@ -1,60 +0,0 @@ -find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Quick WebSockets LinguistTools) - -qt_standard_project_setup(REQUIRES 6.6 I18N_TRANSLATED_LANGUAGES de) - -qt_add_executable(flotten-updater WIN32 MACOSX_BUNDLE - addserialsrangedialog.h - addserialsrangedialog.cpp - addserialsrangedialog.ui - deviceconnection.cpp - deviceconnection.h - devicesmodel.cpp - devicesmodel.h - flottenupdatersettings.cpp - flottenupdatersettings.h - importcredentialsdialog.cpp - importcredentialsdialog.h - importcredentialsdialog.ui - main.cpp - mainwindow.cpp - mainwindow.h - mainwindow.ui - requestdialog.cpp - requestdialog.h - requestdialog.ui - requestmodel.cpp - requestmodel.h - setarbitraryapikeydialog.cpp - setarbitraryapikeydialog.h - setarbitraryapikeydialog.ui -) - -qt_add_resources(flotten-updater - PREFIX / - FILES - goe-root-ca.pem -) - -find_package(OpenSSL) -if (OpenSSL_Found) - target_compile_definitions(flotten-updater HAS_OPENSSL) - target_link_libraries(flotten-updater PUBLIC - OpenSSL::SSL - OpenSSL::Crypto - ) -endif() - -target_link_libraries(flotten-updater PUBLIC - Qt6::Core - Qt6::Gui - Qt6::Widgets - Qt6::Quick - Qt6::WebSockets - goecommon -) - -install(TARGETS flotten-updater - BUNDLE DESTINATION . - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) diff --git a/flotten-updater/addserialsrangedialog.cpp b/flotten-updater/addserialsrangedialog.cpp deleted file mode 100644 index d9e7e03..0000000 --- a/flotten-updater/addserialsrangedialog.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "addserialsrangedialog.h" -#include "ui_addserialsrangedialog.h" - -AddSerialsRangeDialog::AddSerialsRangeDialog(QWidget *parent) : - QDialog{parent}, - m_ui{std::make_unique()} -{ - m_ui->setupUi(this); - - connect(m_ui->spinBoxFrom, &QSpinBox::valueChanged, - this, &AddSerialsRangeDialog::updatePreview); - connect(m_ui->spinBoxTo, &QSpinBox::valueChanged, - this, &AddSerialsRangeDialog::updatePreview); - updatePreview(); -} - -AddSerialsRangeDialog::~AddSerialsRangeDialog() = default; - -void AddSerialsRangeDialog::accept() -{ - if (from() > to()) - return; - QDialog::accept(); -} - -int AddSerialsRangeDialog::from() const -{ - return m_ui->spinBoxFrom->value(); -} - -int AddSerialsRangeDialog::to() const -{ - return m_ui->spinBoxTo->value(); -} - -void AddSerialsRangeDialog::updatePreview() -{ - const auto from = this->from(); - const auto to = this->to(); - - QString text; - QColor color; - if (from > to) - { - text = tr("???"); - color = Qt::red; - } - else - { - const auto count = to - from + 1; - text = tr("%0 serials").arg(count); - color = count > 100 ? Qt::yellow : Qt::green; - } - - m_ui->labelCountDisplay->setText(text); - - QPalette palette = m_ui->labelCountDisplay->palette(); - palette.setColor(m_ui->labelCountDisplay->backgroundRole(), color); - palette.setColor(m_ui->labelCountDisplay->foregroundRole(), color); - m_ui->labelCountDisplay->setPalette(palette); -} diff --git a/flotten-updater/addserialsrangedialog.h b/flotten-updater/addserialsrangedialog.h deleted file mode 100644 index 0067aa5..0000000 --- a/flotten-updater/addserialsrangedialog.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -#include - -namespace Ui { class AddSerialsRangeDialog; } - -class AddSerialsRangeDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AddSerialsRangeDialog(QWidget *parent = nullptr); - ~AddSerialsRangeDialog(); - - void accept() override; - - int from() const; - int to() const; - -private: - void updatePreview(); - -private: - const std::unique_ptr m_ui; -}; diff --git a/flotten-updater/addserialsrangedialog.ui b/flotten-updater/addserialsrangedialog.ui deleted file mode 100644 index c64c5b0..0000000 --- a/flotten-updater/addserialsrangedialog.ui +++ /dev/null @@ -1,109 +0,0 @@ - - - AddSerialsRangeDialog - - - - 0 - 0 - 194 - 140 - - - - Add serials range - - - - - - - - From: - - - - - - - To: - - - - - - - Count: - - - - - - - - - - 2147483647 - - - 999930 - - - - - - - 2147483647 - - - 999940 - - - - - - - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - - - - - - - buttonBox - accepted() - AddSerialsRangeDialog - accept() - - - 96 - 118 - - - 96 - 69 - - - - - buttonBox - rejected() - AddSerialsRangeDialog - reject() - - - 96 - 118 - - - 96 - 69 - - - - - diff --git a/flotten-updater/deviceconnection.cpp b/flotten-updater/deviceconnection.cpp deleted file mode 100644 index 98e3ace..0000000 --- a/flotten-updater/deviceconnection.cpp +++ /dev/null @@ -1,656 +0,0 @@ -#include "deviceconnection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "devicesmodel.h" - -namespace { -const constexpr QColor red{255, 150, 150}; -const constexpr QColor yellow{255, 255, 150}; -const constexpr QColor green{150, 255, 150}; -const constexpr QColor cyan{150, 255, 255}; -const constexpr QColor blue{150, 150, 255}; -const constexpr QColor magenta{255, 150, 255}; -} - -DeviceConnection::DeviceConnection(const QByteArray &username, const QByteArray &password, QString &&serial, QObject *parent) : - QObject{parent}, - m_serial(std::move(serial)), - m_username{username}, - m_password{password} -{ - init(); -} - -DeviceConnection::DeviceConnection(const QByteArray &username, const QByteArray &password, const QString &serial, QObject *parent) : - QObject{parent}, - m_serial(serial), - m_username{username}, - m_password{password} -{ - init(); -} - -void DeviceConnection::start() -{ - QNetworkRequest request{QString("wss://solalaweb.com/%0").arg(m_serial)}; - QString credentials = m_username + ':' + m_password; - QString base64 = credentials.toUtf8().toBase64(); - request.setRawHeader("Authorization", "Basic " + base64.toUtf8()); - m_websocket.open(request); -} - -void DeviceConnection::stop() -{ - m_websocket.close(); -} - -QString DeviceConnection::wsStatusText() const -{ - return QMetaEnum::fromType().valueToKey(m_websocket.state()); -} - -QBrush DeviceConnection::wsStatusBackground() const -{ - switch (m_websocket.state()) - { - case QAbstractSocket::UnconnectedState: return red; - case QAbstractSocket::HostLookupState: - case QAbstractSocket::ConnectingState: return yellow; - case QAbstractSocket::ConnectedState: return green; - case QAbstractSocket::ClosingState: return red; - } - return {}; -} - -QString DeviceConnection::statusText() const -{ - switch (m_status) - { - case Status::Unknown: return tr("Unknown"); - case Status::Ok: return tr("Ok"); - case Status::Offline: return tr("Offline"); - } - - return QString::number(std::to_underlying(m_status)); -} - -QBrush DeviceConnection::statusBackground() const -{ - switch (m_status) - { - case Status::Unknown: return yellow; - case Status::Ok: return green; - case Status::Offline: return red; - } - return {}; -} - -QString DeviceConnection::variantText() const -{ - if (!m_fullStatus.contains("var")) - return {}; - - return m_fullStatus.value("var").toString(); -} - -QBrush DeviceConnection::variantBackground() const -{ - if (!m_fullStatus.contains("var")) - return {}; - - switch (m_fullStatus.value("var").toInt()) - { - case 11: return blue; - case 22: return yellow; - } - return red; -} - -QString DeviceConnection::isGoText() const -{ - if (!m_fullStatus.contains("isgo")) - return {}; - - return m_fullStatus.value("isgo").toBool() ? "yes" : "no"; -} - -QBrush DeviceConnection::isGoBackground() const -{ - if (!m_fullStatus.contains("isgo")) - return {}; - - return m_fullStatus.value("isgo").toBool() ? blue : yellow; -} - -QString DeviceConnection::isAustralienText() const -{ - if (!m_fullStatus.contains("aus")) - return {}; - - return m_fullStatus.value("aus").toBool() ? "yes" : "no"; -} - -QBrush DeviceConnection::isAustralienBackground() const -{ - if (!m_fullStatus.contains("aus")) - return {}; - - return m_fullStatus.value("aus").toBool() ? yellow : blue; -} - -QString DeviceConnection::resetCardText() const -{ - if (!m_fullStatus.contains("frci")) - return {}; - - return m_fullStatus.value("frci").toBool() ? "yes" : "no"; -} - -QBrush DeviceConnection::resetCardBackground() const -{ - if (!m_fullStatus.contains("frci")) - return {}; - - return m_fullStatus.value("frci").toBool() ? green : red; -} - -QString DeviceConnection::connectedWifiText() const -{ - if (!m_fullStatus.contains("ccw")) - return {}; - - const auto &apd = m_fullStatus.value("ccw").toJsonObject(); - if (!apd.contains("ssid")) - return {}; - - return apd.value("ssid").toString(); -} - -QString DeviceConnection::projectText() const -{ - if (!m_fullStatus.contains("apd")) - return {}; - - const auto &apd = m_fullStatus.value("apd").toJsonObject(); - if (!apd.contains("project_name")) - return {}; - - return apd.value("project_name").toString(); -} - -QString DeviceConnection::versionText() const -{ - if (!m_fullStatus.contains("apd")) - return {}; - - const auto &apd = m_fullStatus.value("apd").toJsonObject(); - if (!apd.contains("version")) - return {}; - - return apd.value("version").toString(); -} - -QString DeviceConnection::idfVersionText() const -{ - if (!m_fullStatus.contains("apd")) - return {}; - - const auto &apd = m_fullStatus.value("apd").toJsonObject(); - if (!apd.contains("idf_ver")) - return {}; - - return apd.value("idf_ver").toString(); -} - -QString DeviceConnection::updateText() const -{ - if (!m_fullStatus.contains("ocs")) - return {}; - - const QStringList updateStates { tr("Idle"), tr("Updating"), tr("Failed"), tr("Succeeded"), tr("NotReady"), tr("Verifying") }; - const auto ocs = m_fullStatus.value("ocs").toInt(); - if (ocs >= 0 && ocs < updateStates.size()) - { - if (ocs == 1) - { - std::optional progress; - if (m_fullStatus.contains("ocp")) - progress = m_fullStatus.value("ocp").toInt(); - std::optional total; - if (m_fullStatus.contains("ocl")) - total = m_fullStatus.value("ocl").toInt(); - if (progress && total) - return (tr("%0 %1%").arg(updateStates.at(ocs)).arg(*progress ? *progress * 100 / *total : 0)); - else if (progress) - return tr("%0 %1/?").arg(updateStates.at(ocs)).arg(*progress); - else if (total) - return tr("%0 ?/%1").arg(updateStates.at(ocs)).arg(*total); - } - return updateStates.at(ocs); - } - return QString::number(ocs); -} - -QBrush DeviceConnection::updateBackground() const -{ - if (!m_fullStatus.contains("ocs")) - return {}; - - const auto ocs = m_fullStatus.value("ocs").toInt(); - switch (ocs) - { - case 1: return yellow; - case 2: return red; - case 3: return green; - case 4: return red; - case 5: return yellow; - } - - return {}; -} - -std::optional DeviceConnection::uptime() const -{ - if (!m_fullStatus.contains("rbt")) - return {}; - - return m_fullStatus.value("rbt").toULongLong(); -} - -QString DeviceConnection::uptimeText() const -{ - if (!m_fullStatus.contains("rbt")) - return {}; - - return QString::number(m_fullStatus.value("rbt").toULongLong()); -} - -QString DeviceConnection::currentPartition() const -{ - if (!m_fullStatus.contains("otap")) - return {}; - - const auto &otap = m_fullStatus.value("otap").toJsonObject(); - if (!otap.contains("label")) - return {}; - - return otap.value("label").toString(); -} - -std::optional DeviceConnection::reboots() const -{ - if (!m_fullStatus.contains("rbc")) - return {}; - - return m_fullStatus.value("rbc").toInt(); -} - -QString DeviceConnection::rebootsText() const -{ - if (!m_fullStatus.contains("rbc")) - return {}; - - return QString::number(m_fullStatus.value("rbc").toInt()); -} - -QString DeviceConnection::carStateText() const -{ - if (!m_fullStatus.contains("car")) - return {}; - - const QStringList carStates { tr("Unknown"), tr("Idle"), tr("Charging"), tr("WaitCar"), tr("Complete"), tr("Error") }; - const auto car = m_fullStatus.value("car").toInt(); - if (car >= 0 && car < carStates.size()) - return carStates.at(car); - return QString::number(car); -} - -std::optional DeviceConnection::energy() const -{ - if (!m_fullStatus.contains("eto")) - return {}; - - return m_fullStatus.value("eto").toDouble(); -} - -QString DeviceConnection::energyText() const -{ - if (!m_fullStatus.contains("eto")) - return {}; - - return QString("%0kWh").arg(m_fullStatus.value("eto").toDouble() / 1000.); -} - -QString DeviceConnection::livedataText() const -{ - if (!m_fullStatus.contains("nrg")) - return {}; - - const auto nrg = m_fullStatus.value("nrg").toList(); - if (nrg.size() > 3) - return QString{"%0V %1V %2V %3V"} - .arg(nrg.at(0).toDouble()) - .arg(nrg.at(1).toDouble()) - .arg(nrg.at(2).toDouble()) - .arg(nrg.at(3).toDouble()); - return {}; -} - -QVariant DeviceConnection::getApiKey(const QString &apiKey) const -{ - return m_fullStatus.value(apiKey); -} - -void DeviceConnection::sendMessage(const QJsonDocument &doc) -{ - sendMessage(QString::fromUtf8(doc.toJson())); -} - -void DeviceConnection::sendMessage(const QJsonObject &obj) -{ - sendMessage(QJsonDocument{obj}); -} - -void DeviceConnection::sendMessage(const QString &msg) -{ - qDebug() << msg << m_websocket.errorString(); - if (const auto written = m_websocket.sendTextMessage(msg); written != msg.size()) - qCritical() << "sending message failed" << written << "(expected:" << msg.size() << ')'; -} - -QString DeviceConnection::errorString() const -{ - return m_websocket.errorString(); -} - -void DeviceConnection::init() -{ - if (auto model = qobject_cast(parent())) - { - connect(this, &DeviceConnection::wsStatusChanged, model, &DevicesModel::wsStatusChanged); - connect(this, &DeviceConnection::statusChanged, model, &DevicesModel::statusChanged); - connect(this, &DeviceConnection::variantChanged, model, &DevicesModel::variantChanged); - connect(this, &DeviceConnection::isGoChanged, model, &DevicesModel::isGoChanged); - connect(this, &DeviceConnection::isAustralienChanged, model, &DevicesModel::isAustralienChanged); - connect(this, &DeviceConnection::resetCardChanged, model, &DevicesModel::resetCardChanged); - connect(this, &DeviceConnection::connectedWifiChanged, model, &DevicesModel::connectedWifiChanged); - connect(this, &DeviceConnection::projectChanged, model, &DevicesModel::projectChanged); - connect(this, &DeviceConnection::versionChanged, model, &DevicesModel::versionChanged); - connect(this, &DeviceConnection::idfVersionChanged, model, &DevicesModel::idfVersionChanged); - connect(this, &DeviceConnection::updateChanged, model, &DevicesModel::updateChanged); - connect(this, &DeviceConnection::uptimeChanged, model, &DevicesModel::uptimeChanged); - connect(this, &DeviceConnection::currentPartitionChanged, model, &DevicesModel::currentPartitionChanged); - connect(this, &DeviceConnection::rebootsChanged, model, &DevicesModel::rebootsChanged); - connect(this, &DeviceConnection::carStateChanged, model, &DevicesModel::carStateChanged); - connect(this, &DeviceConnection::energyChanged, model, &DevicesModel::energyChanged); - connect(this, &DeviceConnection::livedataChanged, model, &DevicesModel::livedataChanged); - connect(this, &DeviceConnection::apiKeyChanged, model, &DevicesModel::apiKeyChanged); - } - else - qWarning() << "unexpected parent"; - - //{ - // auto sslConfig = m_websocket.sslConfiguration(); - // sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone); - // //sslConfig.setPeerVerifyMode(QSslSocket::VerifyPeer); - // { - // auto caCerts = QSslCertificate::fromPath(":/goe-root-ca.pem"); - // if (caCerts.empty()) - // qFatal("could not parse root ca"); - // for (const auto &caCert : std::as_const(caCerts)) - // qDebug() << caCert.issuerDisplayName(); - // sslConfig.setCaCertificates(std::move(caCerts)); - // } - // sslConfig.setPrivateKey(m_key); - // sslConfig.setLocalCertificate(m_cert); - // m_websocket.setSslConfiguration(sslConfig); - // m_websocket.ignoreSslErrors(); - //} - - connect(&m_websocket, &QWebSocket::connected, this, &DeviceConnection::connectedSignal); - connect(&m_websocket, &QWebSocket::disconnected, this, &DeviceConnection::disconnectedSignal); - connect(&m_websocket, &QWebSocket::errorOccurred, this, &DeviceConnection::errorOccurredSignal); - - connect(&m_websocket, &QWebSocket::connected, this, &DeviceConnection::connected); - connect(&m_websocket, &QWebSocket::disconnected, this, &DeviceConnection::disconnected); - connect(&m_websocket, &QWebSocket::stateChanged, this, &DeviceConnection::stateChanged); - connect(&m_websocket, &QWebSocket::textMessageReceived, this, &DeviceConnection::textMessageReceived); - connect(&m_websocket, &QWebSocket::binaryMessageReceived, this, &DeviceConnection::binaryMessageReceived); - connect(&m_websocket, &QWebSocket::errorOccurred, this, &DeviceConnection::errorOccurred); - connect(&m_websocket, &QWebSocket::peerVerifyError, this, &DeviceConnection::peerVerifyError); - connect(&m_websocket, &QWebSocket::sslErrors, this, &DeviceConnection::sslErrors); - connect(&m_websocket, &QWebSocket::alertReceived, this, &DeviceConnection::alertReceived); - connect(&m_websocket, &QWebSocket::handshakeInterruptedOnError, this, &DeviceConnection::handshakeInterruptedOnError); -} - -void DeviceConnection::maintainStatus(const QJsonObject &msg, bool forceChange) -{ - bool variantChanged{forceChange}; - bool isGoChanged{forceChange}; - bool isAustralienChanged{forceChange}; - bool resetCardChanged{forceChange}; - bool connectedWifiChanged{forceChange}; - bool versionChanged{forceChange}; - bool updateChanged{forceChange}; - bool uptimeChanged{forceChange}; - bool currentPartitionChanged{forceChange}; - bool rebootsChanged{forceChange}; - bool carStateChanged{forceChange}; - bool energyChanged{forceChange}; - bool livedataChanged{forceChange}; - - const auto status = msg.value("status").toObject(); - for (auto iter = std::cbegin(status); iter != std::cend(status); iter++) - { - m_fullStatus[iter.key()] = iter.value().toVariant(); - - if (iter.key() == "var") - variantChanged = true; - else if (iter.key() == "isgo") - isGoChanged = true; - else if (iter.key() == "aus") - isAustralienChanged = true; - else if (iter.key() == "frci") - resetCardChanged = true; - else if (iter.key() == "ccw") - connectedWifiChanged = true; - else if (iter.key() == "apd") - versionChanged = true; - else if (iter.key() == "ocs" || iter.key() == "ocp" || iter.key() == "ocl") - updateChanged = true; - else if (iter.key() == "rbt") - uptimeChanged = true; - else if (iter.key() == "otap") - currentPartitionChanged = true; - else if (iter.key() == "rbc") - rebootsChanged = true; - else if (iter.key() == "car") - carStateChanged = true; - else if (iter.key() == "eto") - energyChanged = true; - else if (iter.key() == "nrg") - livedataChanged = true; - - emit apiKeyChanged(iter.key()); - } - - if (variantChanged) - emit this->variantChanged(); - if (isGoChanged) - emit this->isGoChanged(); - if (isAustralienChanged) - emit this->isAustralienChanged(); - if (resetCardChanged) - emit this->resetCardChanged(); - if (connectedWifiChanged) - emit this->connectedWifiChanged(); - if (versionChanged) - { - emit this->projectChanged(); - emit this->versionChanged(); - emit this->idfVersionChanged(); - } - if (updateChanged) - emit this->updateChanged(); - if (uptimeChanged) - emit this->uptimeChanged(); - if (currentPartitionChanged) - emit this->currentPartitionChanged(); - if (rebootsChanged) - emit this->rebootsChanged(); - if (carStateChanged) - emit this->carStateChanged(); - if (energyChanged) - emit this->energyChanged(); - if (livedataChanged) - emit this->livedataChanged(); -} - -void DeviceConnection::connected() -{ - qDebug() << "called"; -} - -void DeviceConnection::disconnected() -{ - qDebug() << "called"; -} - -void DeviceConnection::stateChanged(QAbstractSocket::SocketState state) -{ -// qDebug() << "called" << state; - - if (state != QAbstractSocket::ConnectedState) - { - if (m_status != Status::Unknown) - { - m_status = Status::Unknown; - emit statusChanged(); - } - } - - emit wsStatusChanged(); -} - -void DeviceConnection::textMessageReceived(const QString &message) -{ -// qDebug() << "called" << message; - - QJsonParseError error; - const auto doc = QJsonDocument::fromJson(message.toUtf8(), &error); - if (error.error != QJsonParseError::NoError) - { - qWarning() << m_serial << "could not parse json:" << error.errorString(); - return; - } - - if (!doc.isObject()) - { - qWarning() << m_serial << "json is not an object"; - return; - } - - const auto msgObj = doc.object(); - - if (!msgObj.contains("type")) - { - qWarning() << "msg does not contain a type"; - return; - } - - const auto typeVal = msgObj.value("type"); - - if (!typeVal.isString()) - { - qWarning() << "msg type is not a string"; - return; - } - - const auto type = typeVal.toString(); - - bool response{}; - if (msgObj.contains("requestId")) - { - response = true; - - qDebug() << "response to a request" << message; - - emit responseReceived(msgObj.value("requestId").toString(), msgObj); - } - - if (type == "hello") - { -// qDebug() << "hello received" << msgObj; - m_status = Status::Ok; - emit statusChanged(); - } - else if (type == "offline") - { -// qDebug() << "offline received" << msgObj; - m_status = Status::Offline; - emit statusChanged(); - } - else if (type == "fullStatus") - { - bool forceChange{false}; - - if (m_receivedDelta) - { - m_receivedDelta = false; - m_fullStatus.clear(); - forceChange = true; - } - - maintainStatus(msgObj, forceChange); - } - else if (type == "deltaStatus") - { - m_receivedDelta = true; - - maintainStatus(msgObj, false); - } - else if (!response) - qWarning() << "unknown message type" << msgObj; -} - -void DeviceConnection::binaryMessageReceived(const QByteArray &message) -{ - qDebug() << "called" << message; -} - -void DeviceConnection::errorOccurred(QAbstractSocket::SocketError error) -{ - qDebug() << "called" << QMetaEnum::fromType().valueToKey(error) << m_websocket.errorString(); -} - -void DeviceConnection::peerVerifyError(const QSslError &error) -{ - qDebug() << "called" << error; -} - -void DeviceConnection::sslErrors(const QList &errors) -{ - qDebug() << "called" << errors; -} - -void DeviceConnection::alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description) -{ - qDebug() << "called" << std::to_underlying(level) << std::to_underlying(type) << description; -} - -void DeviceConnection::handshakeInterruptedOnError(const QSslError &error) -{ - qDebug() << "called" << error; -} diff --git a/flotten-updater/deviceconnection.h b/flotten-updater/deviceconnection.h deleted file mode 100644 index 5dd5469..0000000 --- a/flotten-updater/deviceconnection.h +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class QSslKey; -class QSslCertificate; -class QJsonObject; - -class DeviceConnection : public QObject -{ - Q_OBJECT - -public: - explicit DeviceConnection(const QByteArray &username, const QByteArray &password, QString &&serial, QObject *parent = nullptr); - explicit DeviceConnection(const QByteArray &username, const QByteArray &password, const QString &serial, QObject *parent = nullptr); - - void start(); - void stop(); - - const QString &serial() const { return m_serial; } - - QString wsStatusText() const; - QBrush wsStatusBackground() const; - - QString statusText() const; - QBrush statusBackground() const; - - QString variantText() const; - QBrush variantBackground() const; - - QString isGoText() const; - QBrush isGoBackground() const; - - QString isAustralienText() const; - QBrush isAustralienBackground() const; - - QString resetCardText() const; - QBrush resetCardBackground() const; - - QString connectedWifiText() const; - - QString projectText() const; - - QString versionText() const; - - QString idfVersionText() const; - - QString updateText() const; - QBrush updateBackground() const; - - std::optional uptime() const; - QString uptimeText() const; - - QString currentPartition() const; - - std::optional reboots() const; - QString rebootsText() const; - - QString carStateText() const; - - std::optional energy() const; - QString energyText() const; - - QString livedataText() const; - - QVariant getApiKey(const QString &apiKey) const; - - void sendMessage(const QJsonDocument &doc); - void sendMessage(const QJsonObject &obj); - void sendMessage(const QString &msg); - - QString errorString() const; - -signals: - void connectedSignal(); - void disconnectedSignal(); - void errorOccurredSignal(QAbstractSocket::SocketError error); - - void responseReceived(const QString &requestId, const QJsonObject &msg); - - void wsStatusChanged(); - void statusChanged(); - void variantChanged(); - void isGoChanged(); - void isAustralienChanged(); - void resetCardChanged(); - void connectedWifiChanged(); - void projectChanged(); - void versionChanged(); - void idfVersionChanged(); - void updateChanged(); - void uptimeChanged(); - void currentPartitionChanged(); - void rebootsChanged(); - void carStateChanged(); - void energyChanged(); - void livedataChanged(); - void apiKeyChanged(const QString &apiKey); - -private: - void init(); - void maintainStatus(const QJsonObject &msg, bool forceChange); - -private slots: - void connected(); - void disconnected(); - void stateChanged(QAbstractSocket::SocketState state); - void textMessageReceived(const QString &message); - void binaryMessageReceived(const QByteArray &message); - void errorOccurred(QAbstractSocket::SocketError error); - void peerVerifyError(const QSslError &error); - void sslErrors(const QList &errors); - void alertReceived(QSsl::AlertLevel level, QSsl::AlertType type, const QString &description); - void handshakeInterruptedOnError(const QSslError &error); - -private: - const QString m_serial; - const QByteArray m_username; - const QByteArray m_password; - - enum Status { - Unknown, - Ok, - Offline - }; - Status m_status{Status::Unknown}; - - QWebSocket m_websocket; - - QVariantMap m_fullStatus; - bool m_receivedDelta{false}; -}; diff --git a/flotten-updater/devicesmodel.cpp b/flotten-updater/devicesmodel.cpp deleted file mode 100644 index 9394592..0000000 --- a/flotten-updater/devicesmodel.cpp +++ /dev/null @@ -1,523 +0,0 @@ -#include "devicesmodel.h" - -#include -#include -#include - -#include -#include - -#include "deviceconnection.h" -#include "flottenupdatersettings.h" - -namespace { -enum { - ColumnSerial, - ColumnWsStatus, - ColumnStatus, - ColumnVariant, - ColumnIsGo, - ColumnIsAustralien, - ColumnResetCard, - ColumnConnectedWifi, - ColumnProject, - ColumnVersion, - ColumnIdfVersion, - ColumnUpdate, - ColumnReboots, - ColumnUptime, - ColumnCurrentPartition, - ColumnCarState, - ColumnEnergy, - ColumnLivedata, - NumberOfColumns -}; -} - -DevicesModel::DevicesModel(FlottenUpdaterSettings &settings, const QByteArray &username, - const QByteArray &password, QObject *parent) : - QAbstractTableModel{parent}, - m_settings{settings}, - m_username{username}, - m_password{password}, - m_customColumns{settings.customColumns()} -{ - for (const auto &serial : m_settings.serials()) - { - if (std::none_of(std::cbegin(m_devices), std::cend(m_devices), [&serial](auto &ptr){ - return ptr->serial() == serial; - })) - m_devices.emplace_back(std::make_shared(m_username, m_password, serial, this)); - } -} - -DevicesModel::~DevicesModel() = default; - -int DevicesModel::rowCount(const QModelIndex &parent) const -{ - return m_devices.size(); -} - -int DevicesModel::columnCount(const QModelIndex &parent) const -{ - return NumberOfColumns + m_customColumns.size(); -} - -QVariant DevicesModel::data(const QModelIndex &index, int role) const -{ - if (index.row() < 0 || index.row() >= m_devices.size()) - { - qWarning() << "row out of bounds"; - return {}; - } - - const DeviceConnection &device = **std::next(std::begin(m_devices), index.row()); - - switch (index.column()) - { - case ColumnSerial: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.serial(); - } - return {}; - case ColumnWsStatus: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.wsStatusText(); - case Qt::BackgroundRole: - return device.wsStatusBackground(); - } - return {}; - case ColumnStatus: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.statusText(); - case Qt::BackgroundRole: - return device.statusBackground(); - } - return {}; - case ColumnVariant: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.variantText(); - case Qt::BackgroundRole: - return device.variantBackground(); - } - return {}; - case ColumnIsGo: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.isGoText(); - case Qt::BackgroundRole: - return device.isGoBackground(); - } - return {}; - case ColumnIsAustralien: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.isAustralienText(); - case Qt::BackgroundRole: - return device.isAustralienBackground(); - } - return {}; - case ColumnResetCard: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.resetCardText(); - case Qt::BackgroundRole: - return device.resetCardBackground(); - } - return {}; - case ColumnConnectedWifi: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.connectedWifiText(); - } - return {}; - case ColumnProject: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.projectText(); - } - return {}; - case ColumnVersion: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.versionText(); - } - return {}; - case ColumnIdfVersion: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.idfVersionText(); - } - return {}; - case ColumnUpdate: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.updateText(); - case Qt::BackgroundRole: - return device.updateBackground(); - } - return {}; - case ColumnUptime: - switch (role) - { - case Qt::DisplayRole: - return device.uptimeText(); - case Qt::EditRole: - if (const auto uptime = device.uptime(); uptime) - return *uptime; - } - return {}; - case ColumnCurrentPartition: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.currentPartition(); - } - return {}; - case ColumnReboots: - switch (role) - { - case Qt::DisplayRole: - return device.rebootsText(); - case Qt::EditRole: - if (const auto reboots = device.reboots(); reboots) - return *reboots; - } - return {}; - case ColumnCarState: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.carStateText(); - } - return {}; - case ColumnEnergy: - switch (role) - { - case Qt::DisplayRole: - return device.energyText(); - case Qt::EditRole: - if (const auto energy = device.energy(); energy) - return *energy; - } - return {}; - case ColumnLivedata: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return device.livedataText(); - } - return {}; - } - - if (index.column() >= NumberOfColumns && index.column() - NumberOfColumns < m_customColumns.size()) - switch (role) - { - case Qt::DisplayRole: - { - auto variant = device.getApiKey(m_customColumns.at(index.column() - NumberOfColumns)); - auto str = variant.toString(); - if (str.isEmpty()) - str = QJsonDocument::fromVariant(variant).toJson(QJsonDocument::Compact); - return str; - } - case Qt::EditRole: - return device.getApiKey(m_customColumns.at(index.column() - NumberOfColumns)); - } - - return {}; -} - -QVariant DevicesModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole && role != Qt::EditRole) - return {}; - - switch (orientation) - { - case Qt::Horizontal: - switch (section) - { - case ColumnSerial: return tr("Serial"); - case ColumnWsStatus: return tr("WS Status"); - case ColumnStatus: return tr("Status"); - case ColumnVariant: return tr("Variant"); - case ColumnIsGo: return tr("IsGo"); - case ColumnIsAustralien: return tr("IsAustralien"); - case ColumnResetCard: return tr("ResetCard"); - case ColumnConnectedWifi: return tr("ConnectedWifi"); - case ColumnProject: return tr("Project"); - case ColumnVersion: return tr("Version"); - case ColumnIdfVersion: return tr("IDF Version"); - case ColumnUpdate: return tr("Update"); - case ColumnReboots: return tr("Reboots"); - case ColumnUptime: return tr("Uptime"); - case ColumnCurrentPartition: return tr("Current Partition"); - case ColumnCarState: return tr("Car state"); - case ColumnEnergy: return tr("Energy"); - case ColumnLivedata: return tr("Livedata"); - } - - if (section >= NumberOfColumns && section - NumberOfColumns < m_customColumns.size()) - return m_customColumns[section - NumberOfColumns]; - - return {}; - } - - return {}; -} - -bool DevicesModel::removeRows(int row, int count, const QModelIndex &parent) -{ - if (row < 0 || std::size_t(row) >= m_devices.size()) - { - qWarning() << "unexpected row" << row; - return false; - } - - if (count < 0 || std::size_t(count) > m_devices.size() - row) - { - qWarning() << "unexpected row+count" << count << row; - return false; - } - - beginRemoveRows({}, row, row + count - 1); - auto begin = std::next(std::begin(m_devices), row); - auto end = std::next(begin, count); - m_devices.erase(begin, end); - endRemoveRows(); - - return true; -} - -bool DevicesModel::addClient(const QString &serial) -{ - if (std::any_of(std::cbegin(m_devices), std::cend(m_devices), - [&](const auto &device){ return device->serial() == serial; })) - { - qWarning() << "duplicate serial"; - return false; - } - - beginInsertRows({}, m_devices.size(), m_devices.size()); - - auto clientPtr = std::make_shared(m_username, m_password, serial, this); - auto client = clientPtr.get(); - m_devices.emplace_back(std::move(clientPtr)); - - endInsertRows(); - - client->start(); - - return true; -} - -std::shared_ptr DevicesModel::getDevice(QModelIndex index) -{ - Q_ASSERT(!index.parent().isValid()); - Q_ASSERT(index.row() >= 0 && index.row() < m_devices.size()); - auto device = m_devices.at(index.row()); - Q_ASSERT(device); - return device; -} - -std::shared_ptr DevicesModel::getDevice(QModelIndex index) const -{ - Q_ASSERT(!index.parent().isValid()); - return m_devices.at(index.row()); -} - -void DevicesModel::addCustomColumn(const QString &apiKey) -{ - beginInsertColumns({}, NumberOfColumns + m_customColumns.size(), NumberOfColumns + m_customColumns.size()); - m_customColumns.push_back(apiKey); - endInsertColumns(); - m_settings.setCustomColumns(m_customColumns); -} - -bool DevicesModel::customColumnRemovable(int section) -{ - return section >= NumberOfColumns && section - NumberOfColumns < m_customColumns.size(); -} - -void DevicesModel::removeCustomColumn(int section) -{ - if (section < NumberOfColumns || section - NumberOfColumns >= m_customColumns.size()) - return; - - beginRemoveColumns({}, section, section); - m_customColumns.erase(std::next(std::begin(m_customColumns), section - NumberOfColumns)); - endRemoveColumns(); - m_settings.setCustomColumns(m_customColumns); -} - -QStringList DevicesModel::serials() const -{ - QStringList serials; - - serials.resize(m_devices.size()); - - std::transform(std::cbegin(m_devices), std::cend(m_devices), - std::begin(serials), [](const auto &device){ return device->serial(); }); - - return serials; -} - -void DevicesModel::connectAll() -{ - for (auto &device : m_devices) - device->start(); -} - -void DevicesModel::disconnectAll() -{ - for (auto &device : m_devices) - device->stop(); -} - -void DevicesModel::wsStatusChanged() -{ - columnChanged(ColumnWsStatus, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::statusChanged() -{ - columnChanged(ColumnStatus, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::variantChanged() -{ - columnChanged(ColumnVariant, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::isGoChanged() -{ - columnChanged(ColumnIsGo, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::isAustralienChanged() -{ - columnChanged(ColumnIsAustralien, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::resetCardChanged() -{ - columnChanged(ColumnResetCard, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::connectedWifiChanged() -{ - columnChanged(ColumnConnectedWifi, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::projectChanged() -{ - columnChanged(ColumnProject, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::versionChanged() -{ - columnChanged(ColumnVersion, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::idfVersionChanged() -{ - columnChanged(ColumnIdfVersion, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::updateChanged() -{ - columnChanged(ColumnUpdate, {Qt::DisplayRole, Qt::EditRole, Qt::BackgroundRole}); -} - -void DevicesModel::uptimeChanged() -{ - columnChanged(ColumnUptime, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::currentPartitionChanged() -{ - columnChanged(ColumnCurrentPartition, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::rebootsChanged() -{ - columnChanged(ColumnReboots, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::carStateChanged() -{ - columnChanged(ColumnCarState, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::energyChanged() -{ - columnChanged(ColumnEnergy, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::livedataChanged() -{ - columnChanged(ColumnLivedata, {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::apiKeyChanged(const QString &apiKey) -{ - for (auto iter = std::cbegin(m_customColumns); iter != std::cend(m_customColumns); iter++) - if (*iter == apiKey) - columnChanged(NumberOfColumns + std::distance(std::cbegin(m_customColumns), iter), {Qt::DisplayRole, Qt::EditRole}); -} - -void DevicesModel::columnChanged(int column, const QList &roles) -{ - auto device = qobject_cast(sender()); - if (!device) - { - qWarning() << "unknown sender" << sender(); - return; - } - - auto iter = std::find_if(std::cbegin(m_devices), std::cend(m_devices), [&device](const std::shared_ptr &ptr){ return device == ptr.get(); }); - if (iter == std::cend(m_devices)) - { - qWarning() << "unknown sender" << device; - for (const auto &device : m_devices) - qDebug() << device.get(); - return; - } - - auto row = std::distance(std::cbegin(m_devices), iter); - - auto index = createIndex(row, column); - emit dataChanged(index, index, roles); -} diff --git a/flotten-updater/devicesmodel.h b/flotten-updater/devicesmodel.h deleted file mode 100644 index 8d0566f..0000000 --- a/flotten-updater/devicesmodel.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include - -#include -#include - -class QSslKey; -class QSslCertificate; - -class FlottenUpdaterSettings; -class DeviceConnection; - -class DevicesModel : public QAbstractTableModel -{ - Q_OBJECT - - using base = QAbstractTableModel; - -public: - explicit DevicesModel(FlottenUpdaterSettings &settings, const QByteArray &username, - const QByteArray &password, QObject *parent = nullptr); - ~DevicesModel() override; - - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - bool removeRows(int row, int count, const QModelIndex &parent) override; - - bool addClient(const QString &serial); - - std::shared_ptr getDevice(QModelIndex index); - std::shared_ptr getDevice(QModelIndex index) const; - - void addCustomColumn(const QString &apiKey); - bool customColumnRemovable(int section); - void removeCustomColumn(int section); - - QStringList serials() const; - -public slots: - void connectAll(); - void disconnectAll(); - - void wsStatusChanged(); - void statusChanged(); - void variantChanged(); - void isGoChanged(); - void isAustralienChanged(); - void resetCardChanged(); - void connectedWifiChanged(); - void projectChanged(); - void versionChanged(); - void idfVersionChanged(); - void updateChanged(); - void uptimeChanged(); - void currentPartitionChanged(); - void rebootsChanged(); - void carStateChanged(); - void energyChanged(); - void livedataChanged(); - void apiKeyChanged(const QString &apiKey); - -private: - FlottenUpdaterSettings &m_settings; - const QByteArray m_username; - const QByteArray m_password; - void columnChanged(int column, const QList &roles = QList()); - - std::vector> m_devices; - - QStringList m_customColumns; -}; diff --git a/flotten-updater/flottenupdatersettings.cpp b/flotten-updater/flottenupdatersettings.cpp deleted file mode 100644 index 2f5bd0a..0000000 --- a/flotten-updater/flottenupdatersettings.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "flottenupdatersettings.h" - -QByteArray FlottenUpdaterSettings::username() const -{ - return value("username").toByteArray(); -} - -void FlottenUpdaterSettings::setUsername(const QByteArray &username) -{ - setValue("username", username); -} - -QByteArray FlottenUpdaterSettings::password() const -{ - return value("password").toByteArray(); -} - -void FlottenUpdaterSettings::setPassword(const QByteArray &password) -{ - setValue("password", password); -} - -QStringList FlottenUpdaterSettings::customColumns() const -{ - return value("customColumns").toStringList(); -} - -void FlottenUpdaterSettings::setCustomColumns(const QStringList &customColumns) -{ - setValue("customColumns", customColumns); -} - -QStringList FlottenUpdaterSettings::serials() const -{ - return value("serials").toStringList(); -} - -void FlottenUpdaterSettings::setSerials(const QStringList &serials) -{ - setValue("serials", serials); -} diff --git a/flotten-updater/flottenupdatersettings.h b/flotten-updater/flottenupdatersettings.h deleted file mode 100644 index 3111076..0000000 --- a/flotten-updater/flottenupdatersettings.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -class FlottenUpdaterSettings : public QSettings -{ - Q_OBJECT - -public: - using QSettings::QSettings; - - QByteArray username() const; - void setUsername(const QByteArray &key); - - QByteArray password() const; - void setPassword(const QByteArray &cert); - - QStringList customColumns() const; - void setCustomColumns(const QStringList &customColumns); - - QStringList serials() const; - void setSerials(const QStringList &serials); -}; diff --git a/flotten-updater/goe-root-ca.pem b/flotten-updater/goe-root-ca.pem deleted file mode 100644 index e752706..0000000 --- a/flotten-updater/goe-root-ca.pem +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFlTCCA32gAwIBAgIUcZ/DDQS4/ix7lYlys+2zMAZnHwowDQYJKoZIhvcNAQEN -BQAwZTELMAkGA1UEBhMCQVQxETAPBgNVBAgMCEthZXJudGVuMRQwEgYDVQQHDAtG -ZWxka2lyY2hlbjESMBAGA1UECgwJZ28tZSBHbWJIMRkwFwYDVQQDDBBnby1lIElP -VCBST09UIENBMCAXDTIwMTEyOTE5MTU0MFoYDzIwOTAxMTEyMTkxNTQwWjBlMQsw -CQYDVQQGEwJBVDERMA8GA1UECAwIS2Flcm50ZW4xFDASBgNVBAcMC0ZlbGRraXJj -aGVuMRIwEAYDVQQKDAlnby1lIEdtYkgxGTAXBgNVBAMMEGdvLWUgSU9UIFJPT1Qg -Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIPhF0MflVFuGUtyI0 -UjyQpjAQStP9k4Wlx+czab6vPXbDbdVEXxXPhoHBeW0oT0g8UuOtMsdfGy3RsNCd -MLR8KiwqysaYeDmHWvVG2Bmpc8+BUm3p2zg63MMCrjp4Syfytgg4hORZjAvbRgDv -Jmh+EgjtD0nakyhBWwCkbDqQN0AXumvSaWRgvcDppI94i4aFGeg8xUBRLzsHbdHY -CuP4hCM/75FqIbOvUuXAMC/FfUxGAt/evxrQRoqyLzF0MrPvzQUTWaOuVH4WPxRM -zDm7kEBUmFL/nYcxkVjLoGqhDAjiMX1Xo4IgsUA0zUVHNHPOKyc7P2E2jgeVDe7o -WCjifoO0OQXiS/uaJmz+33dFe5hBQmKPFEit45ijrsieo1hBasUWHToaa/o/iArp -iSjKTy7YzLFKhvFVZs5iBOOc0K2KglYSBii7d7cT2wArfGpTtuA+eBthIPvM432a -KuW0IGl1BwzjlqIwnSCNd43s4KXg3sUgzW4GtIYSjI897nLlBeJ8Y5zsuEWPRaDG -FVLQJQ1lEwo740CFRSCEkGKdmKMT5TmuA4aApAT0xl8R06lbri9mY0BFWyLrGf3q -rrJO8LDcgGm5fIch+XlNb6H7nf6nP2AJOJRNha9ziNkjDI8jaKlBGveEzw6a+O4X -npsTdKS6hGJ8V74PvlDsZg5nUwIDAQABozswOTAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBhjAWBgNVHREEDzANggtpb3QuZ28tZS5jbzANBgkqhkiG9w0B -AQ0FAAOCAgEAsuGAB7wTy3+9/7/DfBWUkPHvLmR2MmkfBljt/cxFz6pFAVe+QDnb -9EmUWOmWjw7i2rvs5mvcErynj2/R+VDFyorufXMnfm7BXGl/68xIvRszpJe2snPq -cfhC48R7JX7jJcm5xMHkAg8oc3ziRH634/Lo/KXkRhSfxbbujpdAeEhO68ekLKuq -1V8RuJ+MNspLsIrn366kN6pPAQWUM0TUTAs2W0cIDgVx4pnRQd31ccBiCoRcNaer -5mA85KdTkzF0E3/jLuvB4BZRKI0apTg+/hO2a3XQhjbdAKw8C8rYu3Db+t6KRnsa -tyl2Nxeh7nfmfQgdgKZ0zA4osjREzObycZYdUgBFQOf67pU7TCxpzk3iflLSGL92 -AXRpcf3oSw3DLm+fAgaNVVHeSQ3ipB0YLGmf4l/105DAL6o4jTGFcsbPkkrtC8rT -E5+lJYyTQzvb6gLsBLKBTrpcC2BNli5f5tmZJdKOrpY9lb8XFO3W31OTl71FdwlE -KtJrht8K/9xvAUzYHXeTORl0gR7B/yNzSg4p8nJOhSJD9ktUrXErFLu4S2GMqcBM -U/YOJkFc93cSZf0TKM3TaUUslHYFKruBKH8sd15UhijnixED111F63Kwcar87QES -8ipCcGWUtufRHKaUhmswP7lbR5hbQJwIpyBg+FfzcrPUAFrXdllxe4A= ------END CERTIFICATE----- diff --git a/flotten-updater/importcredentialsdialog.cpp b/flotten-updater/importcredentialsdialog.cpp deleted file mode 100644 index aa80eed..0000000 --- a/flotten-updater/importcredentialsdialog.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "importcredentialsdialog.h" -#include "ui_importcredentialsdialog.h" - -#include -#include - -#include "deviceconnection.h" - -ImportCredentialsDialog::ImportCredentialsDialog(QWidget *parent) : - QDialog{parent}, - m_ui{std::make_unique()} -{ - m_ui->setupUi(this); -} - -ImportCredentialsDialog::~ImportCredentialsDialog() = default; - -QByteArray ImportCredentialsDialog::username() const -{ - return m_ui->lineEditUsername->text().toUtf8(); -} - -QByteArray ImportCredentialsDialog::password() const -{ - return m_ui->lineEditPassword->text().toUtf8(); -} - -void ImportCredentialsDialog::accept() -{ - if (username().isEmpty() || - password().isEmpty()) - { - QMessageBox::warning(this, tr("Please fill out all fields!"), tr("Please fill out all fields!")); - return; - } - - m_ui->lineEditUsername->setEnabled(false); - m_ui->lineEditPassword->setEnabled(false); - if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Save)) - button->setEnabled(false); - - m_testConnection = std::make_unique(username(), password(), "123456"); - connect(m_testConnection.get(), &DeviceConnection::connectedSignal, - this, &ImportCredentialsDialog::connected); - connect(m_testConnection.get(), &DeviceConnection::disconnectedSignal, - this, &ImportCredentialsDialog::disconnected); - connect(m_testConnection.get(), &DeviceConnection::errorOccurredSignal, - this, &ImportCredentialsDialog::errorOccurred); - m_testConnection->start(); -} - -void ImportCredentialsDialog::connected() -{ - qDebug() << "called"; - - QDialog::accept(); - - finishTestConnection(); -} - -void ImportCredentialsDialog::disconnected() -{ - qDebug() << "called"; - - finishTestConnection(); -} - -void ImportCredentialsDialog::errorOccurred(QAbstractSocket::SocketError error) -{ - Q_ASSERT(m_testConnection); - QMessageBox::warning(this, - tr("Problem verifying credentials!"), - QString("%0\n\n%1") - .arg(QMetaEnum::fromType().valueToKey(error)) - .arg(m_testConnection->errorString()) - ); -} - -void ImportCredentialsDialog::finishTestConnection() -{ - Q_ASSERT(m_testConnection); - - m_ui->lineEditUsername->setEnabled(true); - m_ui->lineEditPassword->setEnabled(true); - if (auto button = m_ui->buttonBox->button(QDialogButtonBox::Save)) - button->setEnabled(true); - - m_testConnection.release()->deleteLater(); -} diff --git a/flotten-updater/importcredentialsdialog.h b/flotten-updater/importcredentialsdialog.h deleted file mode 100644 index 568c554..0000000 --- a/flotten-updater/importcredentialsdialog.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace Ui { class ImportCredentialsDialog; } -class DeviceConnection; - -class ImportCredentialsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ImportCredentialsDialog(QWidget *parent = nullptr); - ~ImportCredentialsDialog(); - - QByteArray username() const; - QByteArray password() const; - -public slots: - void accept() override; - -private slots: - void connected(); - void disconnected(); - void errorOccurred(QAbstractSocket::SocketError error); - -private: - void finishTestConnection(); - - const std::unique_ptr m_ui; - std::unique_ptr m_testConnection; -}; diff --git a/flotten-updater/importcredentialsdialog.ui b/flotten-updater/importcredentialsdialog.ui deleted file mode 100644 index 37b7297..0000000 --- a/flotten-updater/importcredentialsdialog.ui +++ /dev/null @@ -1,114 +0,0 @@ - - - ImportCredentialsDialog - - - - 0 - 0 - 442 - 164 - - - - Import Credentials - - - - - - Please enter your credentials to access solalaweb.com: - - - - - - - Please create an app password in <a href="https://auth.go-e.com/if/user/#/settings;{%22page%22:%22page-tokens%22}">our SSO</a>. - - - true - - - Qt::TextInteractionFlag::TextBrowserInteraction - - - - - - - - - Username: - - - lineEditUsername - - - - - - - App-Password: - - - lineEditPassword - - - - - - - - - - - - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Save - - - - - - - - - buttonBox - accepted() - ImportCredentialsDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ImportCredentialsDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/flotten-updater/main.cpp b/flotten-updater/main.cpp deleted file mode 100644 index fa2340b..0000000 --- a/flotten-updater/main.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include - -#include "flottenupdatersettings.h" -#include "importcredentialsdialog.h" -#include "mainwindow.h" - -int main(int argc, char *argv[]) -{ - qSetMessagePattern(QStringLiteral("%{time dd.MM.yyyy HH:mm:ss.zzz} " - "[" - "%{if-debug}D%{endif}" - "%{if-info}I%{endif}" - "%{if-warning}W%{endif}" - "%{if-critical}C%{endif}" - "%{if-fatal}F%{endif}" - "] " - "%{function}(): " - "%{message}")); - - QApplication app{argc, argv}; - - QCoreApplication::setOrganizationName("feedc0de"); - QCoreApplication::setOrganizationDomain("brunner.ninja"); - QCoreApplication::setApplicationName("flotten-updater"); - -#ifdef Q_OS_WIN - if (QSslSocket::availableBackends().contains("schannel")) - QSslSocket::setActiveBackend("schannel"); -#endif - - FlottenUpdaterSettings settings; - QByteArray username = settings.username(); - QByteArray password = settings.password(); - - if (username.isEmpty()) - goto loadCredentials; - - if (password.isEmpty()) - goto loadCredentials; - - goto showMainWindow; - - { - loadCredentials: - ImportCredentialsDialog dialog; - if (dialog.exec() != QDialog::Accepted) - return 0; - - username = dialog.username(); - password = dialog.password(); - settings.setUsername(username); - settings.setPassword(password); - } - - showMainWindow: - - MainWindow mainWindow{settings, username, password}; - mainWindow.show(); - - return app.exec(); -} diff --git a/flotten-updater/mainwindow.cpp b/flotten-updater/mainwindow.cpp deleted file mode 100644 index 83d08d6..0000000 --- a/flotten-updater/mainwindow.cpp +++ /dev/null @@ -1,321 +0,0 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "flottenupdatersettings.h" -#include "devicesmodel.h" -#include "requestdialog.h" -#include "setarbitraryapikeydialog.h" -#include "addserialsrangedialog.h" - -MainWindow::MainWindow(FlottenUpdaterSettings &settings, const QByteArray &username, - const QByteArray &password, QWidget *parent) : - QMainWindow{parent}, - m_ui{std::make_unique()}, - m_settings{settings}, - m_model{std::make_unique(settings, username, password, this)}, - m_proxyModel{std::make_unique(this)} -{ - m_ui->setupUi(this); - - m_proxyModel->setSourceModel(m_model.get()); - m_proxyModel->setSortRole(Qt::EditRole); - m_ui->treeView->setModel(m_proxyModel.get()); - - connect(m_ui->pushButtonConnectAll, &QAbstractButton::pressed, m_model.get(), &DevicesModel::connectAll); - connect(m_ui->pushButtonDisconnectAll, &QAbstractButton::pressed, m_model.get(), &DevicesModel::disconnectAll); - connect(m_ui->pushButtonAdd, &QAbstractButton::pressed, this, &MainWindow::doAdd); - connect(m_ui->pushButtonRemove, &QAbstractButton::pressed, this, &MainWindow::doRemove); - connect(m_ui->pushButtonAddRange, &QAbstractButton::pressed, this, &MainWindow::doAddRange); - connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::selectionChanged); - m_ui->treeView->header()->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_ui->treeView->header(), &QTreeView::customContextMenuRequested, this, &MainWindow::headerContextMenuRequested); - connect(m_ui->treeView, &QTreeView::customContextMenuRequested, this, &MainWindow::contextMenuRequested); - selectionChanged(); -} - -MainWindow::~MainWindow() = default; - -void MainWindow::doAdd() -{ - bool ok{}; - const auto serial = QInputDialog::getText(this, tr("Serial"), tr("Serial"), QLineEdit::Normal, {}, &ok); - if (!ok) - return; - if (m_model->addClient(serial)) - m_settings.setSerials(m_model->serials()); - else - QMessageBox::warning(this, tr("Error while adding serial!"), tr("Error while adding serial!")); -} - -void MainWindow::doRemove() -{ - auto selectedRows = m_ui->treeView->selectionModel()->selectedRows(); - if (selectedRows.isEmpty()) - return; - - // map proxied indices to those from the model - std::transform(std::begin(selectedRows), std::end(selectedRows), std::begin(selectedRows), - [&](const QModelIndex &index){ return m_proxyModel->mapToSource(index); }); - - removeRows(std::move(selectedRows)); -} - -void MainWindow::doAddRange() -{ - AddSerialsRangeDialog dialog{this}; - if (dialog.exec() != QDialog::Accepted) - return; - - int succeeded{}, failed{}; - - for (auto serial = dialog.from(); serial <= dialog.to(); serial++) - { - if (m_model->addClient(QString::number(serial))) - succeeded++; - else - { - qWarning() << "adding serial" << serial << "failed"; - failed++; - } - } - - if (succeeded > 0) - m_settings.setSerials(m_model->serials()); - - if (failed > 0) - QMessageBox::warning(this, tr("Error while adding!"), tr("%0 rows could not be adding!").arg(failed)); -} - -void MainWindow::selectionChanged() -{ - auto count = m_ui->treeView->selectionModel()->selectedRows().count(); - m_ui->pushButtonRemove->setEnabled(count > 0); - m_ui->statusbar->showMessage(tr("%0 selected").arg(m_ui->treeView->selectionModel()->selectedRows().count())); -} - -void MainWindow::headerContextMenuRequested(const QPoint &pos) -{ - QMenu menu; - - auto addColumnAction = menu.addAction(tr("Add new column...")); - - QAction *removeColumnAction{}; - auto header = m_ui->treeView->header(); - const auto section = header->logicalIndexAt(pos); - if (section >= 0) - { - removeColumnAction = menu.addAction(tr("Remove column %0").arg(header->model()->headerData(section, Qt::Horizontal).toString())); - if (!m_model->customColumnRemovable(section)) - removeColumnAction->setEnabled(false); - } - - if (auto selectedAction = menu.exec(header->mapToGlobal(pos)); selectedAction == addColumnAction) - { - bool ok{}; - auto apiKey = QInputDialog::getText(this, tr("Enter api key"), tr("Api key:"), QLineEdit::Normal, {}, &ok); - if (!ok) - return; - - m_model->addCustomColumn(apiKey); - } - else if (removeColumnAction && selectedAction == removeColumnAction) - { - m_model->removeCustomColumn(section); - } -} - -void MainWindow::contextMenuRequested(const QPoint &pos) -{ - auto selectedRows = m_ui->treeView->selectionModel()->selectedRows(); - if (selectedRows.isEmpty()) - return; - - // map proxied indices to those from the model - std::transform(std::begin(selectedRows), std::end(selectedRows), std::begin(selectedRows), - [&](const QModelIndex &index){ return m_proxyModel->mapToSource(index); }); - - // get all the devices for selected indices - std::vector> devices; - devices.reserve(selectedRows.size()); - std::transform(std::begin(selectedRows), std::end(selectedRows), std::back_inserter(devices), - [&](const QModelIndex &index){ auto device = m_model->getDevice(index); Q_ASSERT(device); return device; }); - - Q_ASSERT(std::all_of(std::begin(devices), std::end(devices), [](const auto &device)->bool{ return device.get(); })); - - QMenu menu; - auto actionSetUpdateUrl = menu.addAction(tr("Set update url...")); - auto actionStartUpdate = menu.addAction(tr("Start update...")); - auto actionReboot = menu.addAction(tr("Reboot...")); - auto actionSetChargectrlOverride = menu.addAction(tr("Set chargectrl override...")); - auto actionSetAbitraryApiKey = menu.addAction(tr("Set abitrary api key...")); - auto resetNvsKey = menu.addAction(tr("Reset nvs key...")); - auto actionOpenApps = menu.addAction(tr("Open app(s)...")); - auto actionRemove = menu.addAction(tr("Remove...")); - if (const auto selected = menu.exec(m_ui->treeView->viewport()->mapToGlobal(pos)); selected == actionSetUpdateUrl) - { - bool ok{}; - const auto url = QInputDialog::getText(this, tr("Enter update url..."), tr("Update url:"), QLineEdit::Normal, {}, &ok); - if (!ok) - return; - QJsonObject msg { - { "type", "setValue" }, - { "key", "ocu" }, - { "value", url }, - { "sudo", true } - }; - RequestDialog{std::move(msg), std::move(devices), this}.exec(); - } - else if (selected == actionStartUpdate) - { - QString branch; - { - QInputDialog dialog{this}; - dialog.setWindowTitle(tr("Select update release...")); - dialog.setInputMode(QInputDialog::TextInput); - dialog.setLabelText(tr("Update release")); - dialog.setComboBoxEditable(true); - dialog.setComboBoxItems({QStringLiteral("__default")}); - if (dialog.exec() != QDialog::Accepted) - return; - branch = dialog.textValue(); - } - QJsonObject msg { - { "type", "setValue" }, - { "key", "oct" }, - { "value", branch }, - { "sudo", true } - }; - RequestDialog{std::move(msg), std::move(devices), this}.exec(); - } - else if (selected == actionReboot) - { - if (const auto result = QMessageBox::question(this, tr("Are you sure?"), tr("Do you really want to reboot selected devices?")); result == QMessageBox::Yes) - { - QJsonObject msg { - { "type", "setValue" }, - { "key", "rst" }, - { "value", 1 }, - { "sudo", true } - }; - RequestDialog{std::move(msg), std::move(devices), this}.exec(); - } - } - else if (selected == actionSetChargectrlOverride) - { - QJsonObject msg { - { "type", "setValue" }, - { "key", "stao" }, - { "value", QJsonObject { - { "car", 2 }, - { "error", 0 }, - { "phases", QJsonArray { - true, - true, - true, - true, - true, - true - } }, - { "temperature", 30 }, - { "voltageL1", 230 }, - { "voltageL2", 230 }, - { "voltageL3", 230 }, - { "voltageN", 0 }, - { "ampereL1", 32 }, - { "ampereL2", 32 }, - { "ampereL3", 32 }, - { "powerL1", 7360 }, - { "powerL2", 7360 }, - { "powerL3", 7360 }, - { "powerN", 0 }, - { "powerTotal", 22080 }, - { "powerFactorL1", 90 }, - { "powerFactorL2", 90 }, - { "powerFactorL3", 90 }, - { "powerFactorN", 0 } - } }, - { "sudo", true } - }; - RequestDialog{std::move(msg), std::move(devices), this}.exec(); - } - else if (selected == actionSetAbitraryApiKey) - { - SetArbitraryApiKeyDialog dialog{this}; - if (dialog.exec() == QDialog::Accepted) - { - QJsonObject msg { - { "type", "setValue" }, - { "key", dialog.apiKey() }, - { "value", dialog.value() } - }; - if (dialog.sudo()) - msg["sudo"] = true; - RequestDialog{std::move(msg), std::move(devices), this}.exec(); - } - } - else if (selected == resetNvsKey) - { - bool ok{}; - auto nvsKey = QInputDialog::getText(this, tr("Please input nvs key to be reset"), tr("Nvs key"), QLineEdit::Normal, {}, &ok); - if (!ok) - return; - - QJsonObject msg { - { "type", "nvsReset" }, - { "key", nvsKey }, - { "sudo", true } - }; - RequestDialog{std::move(msg), std::move(devices), this}.exec(); - } - else if (selected == actionOpenApps) - { - - } - else if (selected == actionRemove) - { - removeRows(std::move(selectedRows)); - } -} - -void MainWindow::removeRows(QModelIndexList &&indexes) -{ - if (QMessageBox::question( - this, - tr("Confirm deletion of devices"), - tr("Do you really want to remove %0 devices?").arg(indexes.count()) - ) != QMessageBox::Yes) - return; - - int succeeded{}, failed{}; - - std::sort(indexes.begin(), indexes.end(), - [](const QModelIndex &a, const QModelIndex &b) { - return a.row() > b.row(); - }); - - for (const QModelIndex &index : std::as_const(indexes)) - if (m_model->removeRows(index.row(), 1, index.parent())) - succeeded++; - else - { - failed++; - qWarning() << "removing row" << index.row() << "failed"; - } - - if (succeeded > 0) - m_settings.setSerials(m_model->serials()); - - if (failed > 0) - QMessageBox::warning(this, tr("Error while removing!"), tr("%0 rows could not be removed!").arg(failed)); -} diff --git a/flotten-updater/mainwindow.h b/flotten-updater/mainwindow.h deleted file mode 100644 index 610e80d..0000000 --- a/flotten-updater/mainwindow.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace Ui { class MainWindow; } -class QSslKey; -class QSslCertificate; -class QItemSelection; -class DevicesModel; -class QSortFilterProxyModel; -class FlottenUpdaterSettings; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - explicit MainWindow(FlottenUpdaterSettings &settings, const QByteArray &username, - const QByteArray &password, QWidget *parent = nullptr); - ~MainWindow() override; - -private slots: - void doAdd(); - void doRemove(); - void doAddRange(); - void selectionChanged(); - void headerContextMenuRequested(const QPoint &pos); - void contextMenuRequested(const QPoint &pos); - -private: - void removeRows(QModelIndexList &&indexes); - - const std::unique_ptr m_ui; - FlottenUpdaterSettings &m_settings; - const std::unique_ptr m_model; - const std::unique_ptr m_proxyModel; -}; diff --git a/flotten-updater/mainwindow.ui b/flotten-updater/mainwindow.ui deleted file mode 100644 index 69b0266..0000000 --- a/flotten-updater/mainwindow.ui +++ /dev/null @@ -1,92 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - MainWindow - - - - - - - - - Connect All - - - - - - - Disconnect All - - - - - - - Add - - - - - - - Remove - - - - - - - Add range - - - - - - - - - Qt::ContextMenuPolicy::CustomContextMenu - - - QAbstractItemView::SelectionMode::ExtendedSelection - - - false - - - true - - - true - - - - - - - - - 0 - 0 - 800 - 22 - - - - - - - - diff --git a/flotten-updater/requestdialog.cpp b/flotten-updater/requestdialog.cpp deleted file mode 100644 index 00cac5a..0000000 --- a/flotten-updater/requestdialog.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "requestdialog.h" -#include "ui_requestdialog.h" - -#include -#include - -#include "deviceconnection.h" -#include "requestmodel.h" - -RequestDialog::RequestDialog(QJsonObject &&msg, std::vector> &&devices, QWidget *parent) : - QDialog{parent}, - m_ui{std::make_unique()}, - m_model{std::make_unique(std::move(msg), std::move(devices), this)} -{ - m_ui->setupUi(this); - m_ui->treeView->setModel(m_model.get()); -} - -RequestDialog::~RequestDialog() = default; diff --git a/flotten-updater/requestdialog.h b/flotten-updater/requestdialog.h deleted file mode 100644 index 5e424e5..0000000 --- a/flotten-updater/requestdialog.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include - -class QJsonObject; -class DeviceConnection; -class RequestModel; - -namespace Ui { class RequestDialog; } - -class RequestDialog : public QDialog -{ - Q_OBJECT - -public: - explicit RequestDialog(QJsonObject &&msg, std::vector> &&devices, QWidget *parent = nullptr); - ~RequestDialog(); - -private: - const std::unique_ptr m_ui; - const std::unique_ptr m_model; -}; diff --git a/flotten-updater/requestdialog.ui b/flotten-updater/requestdialog.ui deleted file mode 100644 index 07091c3..0000000 --- a/flotten-updater/requestdialog.ui +++ /dev/null @@ -1,71 +0,0 @@ - - - RequestDialog - - - - 0 - 0 - 400 - 300 - - - - Pending requests... - - - - - - false - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - RequestDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - RequestDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/flotten-updater/requestmodel.cpp b/flotten-updater/requestmodel.cpp deleted file mode 100644 index f1564a4..0000000 --- a/flotten-updater/requestmodel.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "requestmodel.h" - -#include -#include -#include - -#include -#include - -#include "deviceconnection.h" - -namespace { -enum { - ColumnSerial, - ColumnRequestId, - ColumnStatus, - ColumnMessage, - NumberOfColumns -}; - -QString getRandomString(); -} - -RequestModel::RequestModel(QJsonObject &&msg, std::vector> &&devices, QObject *parent) : - QAbstractTableModel{parent} -{ - m_requests.reserve(devices.size()); - - for (auto &device : devices) - { - Request request { - .device = std::move(device), - .requestId = getRandomString() - }; - - connect(request.device.get(), &DeviceConnection::responseReceived, this, &RequestModel::responseReceived); - - { - QJsonObject msg2 = msg; - msg2["requestId"] = request.requestId; - request.device->sendMessage(msg2); - } - - m_requests.emplace_back(std::move(request)); - } -} - -RequestModel::~RequestModel() = default; - -int RequestModel::rowCount(const QModelIndex &parent) const -{ - return m_requests.size(); -} - -int RequestModel::columnCount(const QModelIndex &parent) const -{ - return NumberOfColumns; -} - -QVariant RequestModel::data(const QModelIndex &index, int role) const -{ - if (index.row() < 0 || index.row() >= m_requests.size()) - { - qWarning() << "row out of bounds"; - return {}; - } - - const Request &request = *std::next(std::begin(m_requests), index.row()); - - switch (index.column()) - { - case ColumnSerial: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return request.device->serial(); - } - return {}; - case ColumnRequestId: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return request.requestId; - } - return {}; - case ColumnStatus: - switch (role) - { - case Qt::DisplayRole: - switch (request.status) - { - case Request::Status::Pending: return tr("Pending"); - case Request::Status::Failed: return tr("Failed"); - case Request::Status::Succeeded: return tr("Succeeded"); - } - return QString::number(std::to_underlying(request.status)); - case Qt::EditRole: - return std::to_underlying(request.status); - } - return {}; - case ColumnMessage: - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return request.message; - } - return {}; - } - return {}; -} - -QVariant RequestModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole && role != Qt::EditRole) - return {}; - - switch (orientation) - { - case Qt::Horizontal: - switch (section) - { - case ColumnSerial: return tr("Serial"); - case ColumnRequestId: return tr("RequestId"); - case ColumnStatus: return tr("Status"); - case ColumnMessage: return tr("Message"); - } - return {}; - } - - return {}; -} - -void RequestModel::responseReceived(const QString &requestId, const QJsonObject &msg) -{ - qDebug() << requestId << msg; - - auto iter = std::find_if(std::begin(m_requests), std::end(m_requests), - [&requestId](const auto &request){ return request.requestId == requestId; }); - if (iter == std::end(m_requests)) - { - qWarning() << "unknown request id" << requestId; - return; - } - - const auto row = std::distance(std::begin(m_requests), iter); - if (msg.value("success").toBool()) - { - iter->status = Request::Status::Succeeded; - emit dataChanged(index(row, ColumnStatus), index(row, ColumnStatus), { Qt::DisplayRole, Qt::EditRole }); - } - else - { - iter->status = Request::Status::Failed; - iter->message = msg.value("message").toString(); - emit dataChanged(index(row, ColumnStatus), index(row, ColumnMessage), { Qt::DisplayRole, Qt::EditRole }); - } -} - -namespace { -QString getRandomString() -{ - const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); - const int randomStringLength = 12; // assuming you want random strings of 12 characters - - QString randomString; - for(int i = 0; ibounded(possibleCharacters.length()); - QChar nextChar = possibleCharacters.at(index); - randomString.append(nextChar); - } - return randomString; -} -} diff --git a/flotten-updater/requestmodel.h b/flotten-updater/requestmodel.h deleted file mode 100644 index d685fbb..0000000 --- a/flotten-updater/requestmodel.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include - -#include - -class QJsonObject; -class DeviceConnection; - -class RequestModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - explicit RequestModel(QJsonObject &&msg, std::vector> &&devices, QObject *parent = nullptr); - ~RequestModel() override; - - // QAbstractItemModel interface - int rowCount(const QModelIndex &parent) const override; - int columnCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - -private slots: - void responseReceived(const QString &requestId, const QJsonObject &msg); - -private: - struct Request { - std::shared_ptr device; - QString requestId; - enum class Status { Pending, Failed, Succeeded }; - Status status{Status::Pending}; - QString message; - }; - std::vector m_requests; -}; diff --git a/flotten-updater/setarbitraryapikeydialog.cpp b/flotten-updater/setarbitraryapikeydialog.cpp deleted file mode 100644 index b3be469..0000000 --- a/flotten-updater/setarbitraryapikeydialog.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "setarbitraryapikeydialog.h" -#include "ui_setarbitraryapikeydialog.h" - -#include -#include -#include -#include -#include - -SetArbitraryApiKeyDialog::SetArbitraryApiKeyDialog(QWidget *parent) : - QDialog{parent}, - m_ui{std::make_unique()} -{ - m_ui->setupUi(this); -} - -SetArbitraryApiKeyDialog::~SetArbitraryApiKeyDialog() = default; - -QString SetArbitraryApiKeyDialog::apiKey() const -{ - return m_ui->lineEditApiKey->text(); -} - -QJsonValue SetArbitraryApiKeyDialog::value() const -{ - return m_value; -} - -bool SetArbitraryApiKeyDialog::sudo() const -{ - return m_ui->checkBoxSudo->isChecked(); -} - -void SetArbitraryApiKeyDialog::accept() -{ - QJsonParseError error; - const auto doc = QJsonDocument::fromJson("[" + m_ui->plainTextEditValue->toPlainText().toUtf8() + "]", &error); - if (error.error != QJsonParseError::NoError) - { - QMessageBox::warning(this, tr("Could not parse JSON"), tr("Could not parse JSON") + "\n\n" + error.errorString()); - return; - } - - if (!doc.isArray()) - { - QMessageBox::warning(this, tr("Unexpected not array!"), tr("Unexpected not array!")); - return; - } - - const auto array = doc.array(); - - if (array.size() != 1) - { - QMessageBox::warning(this, tr("Unexpected array length!"), tr("Unexpected array length: %0!").arg(array.size())); - return; - } - - m_value = array.first(); - - QDialog::accept(); -} diff --git a/flotten-updater/setarbitraryapikeydialog.h b/flotten-updater/setarbitraryapikeydialog.h deleted file mode 100644 index 10c7d24..0000000 --- a/flotten-updater/setarbitraryapikeydialog.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace Ui { class SetArbitraryApiKeyDialog; } - -class SetArbitraryApiKeyDialog : public QDialog -{ - Q_OBJECT - -public: - explicit SetArbitraryApiKeyDialog(QWidget *parent = nullptr); - ~SetArbitraryApiKeyDialog() override; - - QString apiKey() const; - QJsonValue value() const; - bool sudo() const; - -protected: - void accept() override; - -private: - const std::unique_ptr m_ui; - - QJsonValue m_value; -}; diff --git a/flotten-updater/setarbitraryapikeydialog.ui b/flotten-updater/setarbitraryapikeydialog.ui deleted file mode 100644 index 5f4cdf7..0000000 --- a/flotten-updater/setarbitraryapikeydialog.ui +++ /dev/null @@ -1,127 +0,0 @@ - - - SetArbitraryApiKeyDialog - - - - 0 - 0 - 285 - 224 - - - - Dialog - - - - - - - - ApiKey: - - - lineEditApiKey - - - - - - - Value: - - - plainTextEditValue - - - - - - - - - - - - - Sudo: - - - checkBoxSudo - - - - - - - Enabled - - - true - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - SetArbitraryApiKeyDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - SetArbitraryApiKeyDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -