diff --git a/CMakeLists.txt b/CMakeLists.txt index eff65b6..55fd9f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,38 +5,58 @@ project(WaterLevelRewrite VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTORCC ON) -find_package(Qt6 REQUIRED COMPONENTS Quick Multimedia) +find_package(Qt6 REQUIRED COMPONENTS Gui Core Quick Multimedia) qt_standard_project_setup(REQUIRES 6.10) +if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/importedcontent/CMakeLists.txt") + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/importedcontent) +endif() + qt_add_executable(appWaterLevelRewrite main.cpp - media.qrc ) qt_add_qml_module(appWaterLevelRewrite URI WaterLevelRewrite QML_FILES Main.qml - QML_FILES WaterTank.qml - QML_FILES SettingsBarIcon.qml - QML_FILES SettingsPopup.qml - SOURCES configinterface.h configinterface.cpp - QML_FILES ConnectButton.qml - SOURCES requestworker.h requestworker.cpp - RESOURCES media.qrc + WaterTank.qml + SettingsBarIcon.qml + SettingsPopup.qml + ConnectButton.qml + SOURCES + configinterface.h + configinterface.cpp + requestworker.h + requestworker.cpp + wifihelper.h + wifihelper.cpp + RESOURCES + media.qrc ) +if(APPLE) + set_target_properties(appWaterLevelRewrite PROPERTIES + # MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appWaterLevelRewrite + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACOSX_BUNDLE TRUE + ) +endif() + +if(WIN32) + set_target_properties(appWaterLevelRewrite PROPERTIES + WIN32_EXECUTABLE TRUE + ) +endif() + set_target_properties(appWaterLevelRewrite PROPERTIES -# MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appWaterLevelRewrite - MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} - MACOSX_BUNDLE TRUE - WIN32_EXECUTABLE TRUE + QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android" ) target_link_libraries(appWaterLevelRewrite - PRIVATE Qt6::Quick Qt6::Multimedia + PRIVATE Qt6::Quick Qt6::Multimedia Qt6::Gui Qt6::Core ) install(TARGETS appWaterLevelRewrite diff --git a/Main.qml b/Main.qml index 8c2a35f..b3be173 100644 --- a/Main.qml +++ b/Main.qml @@ -14,6 +14,7 @@ Window { property color dark_accent_color: "#FF5F7F5F" property color danger_color: "#F0AF2F1F" property color water_color: "#F00F7FAF" + property color water_color_above_alert: "#F00FAF0F" property color background_color: "#1F1F1F" Material.accent: root.accent_color property int font_enlarged_text_size: 20 @@ -21,6 +22,7 @@ Window { property int distance_count_thres: 3 property string mode: "http" property string status: "Initializing" + property string connection_text_string: "Reading WiFi Status..." property string alarm_status_text: "" property var root_config: ({}) @@ -73,6 +75,19 @@ Window { } } + Text { + id: connection_text + anchors { + top: top_bar.bottom + topMargin: 20 + bottom: tank.top + horizontalCenter: parent.horizontalCenter + } + text: root.connection_text_string + color: root.accent_color + font.pointSize: root.font_normal_text_size + } + WaterTank { id: tank anchors { @@ -207,6 +222,16 @@ Window { onRequestFailed: () => { status.color = root.danger_color; } + + onConnectionText: (text, error) => { + root.connection_text_string = text + if(!error) { + connection_text.color = root.accent_color + } + else { + connection_text.color = root.danger_color + } + } } ConfigInterface { diff --git a/SettingsPopup.qml b/SettingsPopup.qml index 41f5cc7..b62624f 100644 --- a/SettingsPopup.qml +++ b/SettingsPopup.qml @@ -107,7 +107,7 @@ Popup { Text { id: alert_thres_label - text: "Alert Percentage: " + text: "Alert Threshold: " anchors { topMargin: 20 top: min_thres_label.bottom diff --git a/WaterTank.qml b/WaterTank.qml index dc264f1..6e20cb1 100644 --- a/WaterTank.qml +++ b/WaterTank.qml @@ -9,6 +9,7 @@ Item { property color tank_lid_color: "#F0121212" property color tank_base_color: "#00FFFFFF" property color water_level_color: "#F00F7FAF" + property color water_color_above_alert: "#F00FAF0F" property color tank_base_border_color: "#F0121212" property color text_color: "#F05FAF5F" property double height_max: tank_base.height - 10 @@ -19,6 +20,7 @@ Item { property double max_thres_input: 0 property double rate_of_fill: 0 property double expected_to_fill: 0 + property double alert_threshold: 0 Rectangle { id: base @@ -137,6 +139,7 @@ Item { function setConfig(config: var) { min_thres_input = config.min; max_thres_input = config.max; + alert_threshold = config.alert; } function setDistance(distance) { @@ -156,8 +159,17 @@ Item { console.log("Current reading is: " + current_reading) console.log("Normalized height is: " + normalized_height) console.log("Percentage filled is: " + percentage_filled) + console.log("Alert threshold is: " + root.alert_threshold) + console.log("Is level above alert threshold: " + (distance_f <= root.alert_threshold)) root.current_level = normalized_height; root.percentage_filled = percentage_filled; + + if(distance_f <= root.alert_threshold) { + water_level.color = water_color_above_alert + } + else { + water_level.color = water_level_color + } } } diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml new file mode 100644 index 0000000..2598885 --- /dev/null +++ b/android/AndroidManifest.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main.cpp b/main.cpp index 87ac2c0..ecedbf4 100644 --- a/main.cpp +++ b/main.cpp @@ -4,7 +4,7 @@ int main(int argc, char *argv[]) { qputenv("QT_SCALE_FACTOR", "1.0"); - qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "Round");qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "Round"); + qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "Round"); QGuiApplication app(argc, argv); diff --git a/requestworker.cpp b/requestworker.cpp index 983c554..c13d223 100644 --- a/requestworker.cpp +++ b/requestworker.cpp @@ -8,7 +8,16 @@ RequestWorker::RequestWorker(QObject *parent) : QObject{parent} { - +#ifdef Q_OS_ANDROID + wifi = new WiFiHelper(this); + connect(wifi, &WiFiHelper::ssidRetrieved, this, &RequestWorker::gotWiFiSSID); + poll_wifi = new QTimer(this); + poll_wifi->setInterval(3000); + poll_wifi->setSingleShot(false); + connect(poll_wifi, &QTimer::timeout, this, &RequestWorker::pollWiFi); + wifi->requestPermissionsAndFetch(); + poll_wifi->start(); +#endif } void RequestWorker::setConfig(QJsonObject config) @@ -54,6 +63,31 @@ void RequestWorker::stop() qDebug() << "Stopping" << timer->isActive(); } +void RequestWorker::pollWiFi() +{ +#ifdef Q_OS_ANDROID + if(wifi) { + wifi->requestPermissionsAndFetch(); + } +#endif +} + +void RequestWorker::gotWiFiSSID(QString ssid) +{ + if(ssid.length() > 0 && ssid != "Permission Denied" && ssid != "") { + emit connectionText("WiFi connected: " + ssid); + } + else if(ssid.length() == 0) { + emit connectionText("WiFi might not be connected", true); + } + else if(ssid != "") { + emit connectionText("Failed to query wifi info", true); + } + else { + emit connectionText("WiFi disconnected", true); + } +} + void RequestWorker::playAlarm() { if(player_started) diff --git a/requestworker.h b/requestworker.h index f78e3a6..6a87bbb 100644 --- a/requestworker.h +++ b/requestworker.h @@ -11,6 +11,9 @@ #include #include #include +#ifdef Q_OS_ANDROID +#include "wifihelper.h" +#endif class RequestWorker : public QObject { @@ -31,6 +34,10 @@ class RequestWorker : public QObject bool player_started = false; QMediaPlayer *player = nullptr; QAudioOutput *audioOutput = nullptr; +#ifdef Q_OS_ANDROID + WiFiHelper *wifi = nullptr; + QTimer *poll_wifi = nullptr; +#endif std::chrono::time_point prev_time; public: explicit RequestWorker(QObject *parent = nullptr); @@ -42,6 +49,7 @@ signals: void networkReply(int distance, float rate_of_fill, int expected_to_fill); void statusChanged(); void playMedia(); + void connectionText(QString text, bool errored = false); public slots: void startAlarm(); void stopAlarm(); @@ -49,6 +57,8 @@ public slots: void start(); void stop(); private slots: + void pollWiFi(); + void gotWiFiSSID(QString ssid); void playAlarm(); void makeRequest(); void requestFinished(QNetworkReply *rep); diff --git a/wifihelper.cpp b/wifihelper.cpp new file mode 100644 index 0000000..739a9dd --- /dev/null +++ b/wifihelper.cpp @@ -0,0 +1,70 @@ +#include "wifihelper.h" +#include +#include +#include +#include + +WiFiHelper::WiFiHelper(QObject *parent) + : QObject{parent} +{ + +} + +QString WiFiHelper::getWifiSsid() { + // Get Android application context in Qt 6 + QJniObject context = QNativeInterface::QAndroidApplication::context(); + if (!context.isValid()) return QString(); + + // Get WifiManager service + QJniObject wifiService = QJniObject::fromString("wifi"); + QJniObject wifiManager = context.callObjectMethod( + "getSystemService", + "(Ljava/lang/String;)Ljava/lang/Object;", + wifiService.object() + ); + if (!wifiManager.isValid()) return QString(); + + // Fetch WifiInfo + QJniObject wifiInfo = wifiManager.callObjectMethod( + "getConnectionInfo", + "()Landroid/net/wifi/WifiInfo;" + ); + if (!wifiInfo.isValid()) return QString(); + + // Get SSID string + QJniObject ssidJni = wifiInfo.callObjectMethod( + "getSSID", + "()Ljava/lang/String;" + ); + if (!ssidJni.isValid()) return QString(); + + QString ssid = ssidJni.toString(); + + // Android returns SSIDs wrapped in double quotes (e.g., "\"MyWiFi\"") + if (ssid.startsWith('"') && ssid.endsWith('"') && ssid.length() > 1) { + ssid = ssid.mid(1, ssid.length() - 2); + } + + return ssid; +} + +void WiFiHelper::requestPermissionsAndFetch() { + QLocationPermission locationPermission; + locationPermission.setAccuracy(QLocationPermission::Accuracy::Precise); + Qt::PermissionStatus status = qApp->checkPermission(locationPermission); + + if (status == Qt::PermissionStatus::Granted) { + emit ssidRetrieved(getWifiSsid()); + } else { + qDebug() << "Requesting permission."; + qApp->requestPermission(locationPermission, this, [this](const QPermission &permission) { + if (permission.status() == Qt::PermissionStatus::Granted) { + qDebug() << "Requested permission and got ssid"; + emit ssidRetrieved(getWifiSsid()); + } else { + qDebug() << "Failed to get WiFi SSID due to denied permission."; + emit ssidRetrieved("Permission Denied"); + } + }); + } +} diff --git a/wifihelper.h b/wifihelper.h new file mode 100644 index 0000000..ab10632 --- /dev/null +++ b/wifihelper.h @@ -0,0 +1,17 @@ +#ifndef WIFIHELPER_H +#define WIFIHELPER_H + +#include + +class WiFiHelper : public QObject +{ + Q_OBJECT +public: + explicit WiFiHelper(QObject *parent = nullptr); + Q_INVOKABLE QString getWifiSsid(); + Q_INVOKABLE void requestPermissionsAndFetch(); + +signals: + void ssidRetrieved(const QString &ssid); +}; +#endif // WIFIHELPER_H