diff --git a/CMakeLists.txt b/CMakeLists.txt index 0140ed5..9aeb966 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,17 +20,17 @@ find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick WebSockets LinguistTools) qt_standard_project_setup(REQUIRES 6.6 I18N_TRANSLATED_LANGUAGES de) qt_add_executable(evcharger-app WIN32 MACOSX_BUNDLE -apikeyvaluehelper.cpp -apikeyvaluehelper.h -appsettings.cpp -appsettings.h -deviceconnection.cpp -deviceconnection.h -devicesmodel.cpp -devicesmodel.h -main.cpp -sendmessagehelper.cpp -sendmessagehelper.h + apikeyvaluehelper.cpp + apikeyvaluehelper.h + appsettings.cpp + appsettings.h + deviceconnection.cpp + deviceconnection.h + devicesmodel.cpp + devicesmodel.h + main.cpp + sendmessagehelper.cpp + sendmessagehelper.h ) qt6_add_translations(evcharger-app @@ -121,6 +121,7 @@ qt_add_qml_module(evcharger-app WiFiErrorsPage.qml WiFiOnOffSwitch.qml WiFiPage.qml + WiFiScanPage.qml RESOURCES icons/Charger.svg icons/ChargerV3.svg diff --git a/ChargerTabPage.qml b/ChargerTabPage.qml index 07e99ea..ab7abd5 100644 --- a/ChargerTabPage.qml +++ b/ChargerTabPage.qml @@ -126,19 +126,19 @@ StackView { } source: { - if (devicetype.value == 'go-eCharger_V5' || - devicetype.value == 'go-eCharger_V4') + if (devicetype.value == "go-eCharger_V5" || + devicetype.value == "go-eCharger_V4") { if (isgo.value) return "images/geminiFlex.png" else return "images/geminiFix.png" - } else if (devicetype.value == 'wattpilot_V2') { + } else if (devicetype.value == "wattpilot_V2") { return "images/wattpilot.png" - } else if (devicetype.value == 'go-eCharger' || - devicetype.value == 'wattpilot') { + } else if (devicetype.value == "go-eCharger" || + devicetype.value == "wattpilot") { return "images/homeFix.png" - } else if (devicetype.value == 'go-eCharger_Phoenix') { + } else if (devicetype.value == "go-eCharger_Phoenix") { return "images/phoenix.png" } diff --git a/DeviceListScreen.qml b/DeviceListScreen.qml index cf2fd5c..26ddee5 100644 --- a/DeviceListScreen.qml +++ b/DeviceListScreen.qml @@ -170,17 +170,17 @@ StackView { height: parent.height //Layout.fillHeight: true source: { - if (delegate.deviceType == 'go-eCharger_V5' || - delegate.deviceType == 'go-eCharger_V4' || - delegate.deviceType == 'wattpilot_V2') + if (delegate.deviceType == "go-eCharger_V5" || + delegate.deviceType == "go-eCharger_V4" || + delegate.deviceType == "wattpilot_V2") { return "icons/ChargerV4.svg" - } else if (delegate.deviceType == 'go-eCharger' || - delegate.deviceType == 'wattpilot') { + } else if (delegate.deviceType == "go-eCharger" || + delegate.deviceType == "wattpilot") { return "icons/ChargerV3.svg" - } else if (delegate.deviceType == 'go-eCharger_Phoenix') { + } else if (delegate.deviceType == "go-eCharger_Phoenix") { return "icons/Charger.svg" - } else if (delegate.deviceType.includes('controller')) { + } else if (delegate.deviceType.includes("controller")) { return "icons/Controller.svg" } } @@ -293,6 +293,7 @@ StackView { Button { Layout.fillWidth: true text: qsTr("Solala") + onClicked: deviceSelected("wss://solalaweb.com/" + delegate.serial, delegate.password) visible: theSettings.showSolalaweb } } diff --git a/FirmwarePage.qml b/FirmwarePage.qml index dbbcaf8..60eb170 100644 --- a/FirmwarePage.qml +++ b/FirmwarePage.qml @@ -180,12 +180,12 @@ NavigationPage { text: { switch (updateStatus.value) { - case 0: return 'Idle' - case 1: return 'Updating' - case 2: return 'Failed' - case 3: return 'Succeeded' - case 4: return 'NotReady' - case 5: return 'Verifying' + case 0: return "Idle" + case 1: return "Updating" + case 2: return "Failed" + case 3: return "Succeeded" + case 4: return "NotReady" + case 5: return "Verifying" default: return updateStatus.value } } @@ -212,7 +212,7 @@ NavigationPage { apiKey: "ocl" } - text: updateProgress.value + ' / ' + updateLength.value + text: updateProgress.value + " / " + updateLength.value } ProgressBar { diff --git a/MainScreen.qml b/MainScreen.qml index d70e30e..4f008cb 100644 --- a/MainScreen.qml +++ b/MainScreen.qml @@ -47,12 +47,12 @@ ColumnLayout { const hours = duration%24; - return (wasNegative ? qsTr('%0 ago') : qsTr('in %0')) + return (wasNegative ? qsTr("%0 ago") : qsTr("in %0")) .arg( - (hours < 10 ? '0' : '') + hours + ':' + - (minutes < 10 ? '0' : '') + minutes + ':' + - (seconds < 10 ? '0' : '') + seconds + '.' + - (milliseconds < 100 ? '0' : '') + (milliseconds < 10 ? '0' : '') + milliseconds) + (hours < 10 ? "0" : "") + hours + ":" + + (minutes < 10 ? "0" : "") + minutes + ":" + + (seconds < 10 ? "0" : "") + seconds + "." + + (milliseconds < 100 ? "0" : "") + (milliseconds < 10 ? "0" : "") + milliseconds) ; } diff --git a/NavigationItem.qml b/NavigationItem.qml index 872c0fe..041c2b8 100644 --- a/NavigationItem.qml +++ b/NavigationItem.qml @@ -17,7 +17,7 @@ ItemDelegate { Component.onCompleted: { background.radius = 5 - background.color = 'white' + background.color = "white" } onClicked: stackView.push(navigationItem.component) diff --git a/RequestStatusText.qml b/RequestStatusText.qml index 2db4326..5559ea9 100644 --- a/RequestStatusText.qml +++ b/RequestStatusText.qml @@ -16,7 +16,7 @@ Text { if (request.response.type == "response") { if (request.response.success) return "OK" - if ('message' in request.response) + if ("message" in request.response) return request.response.message } return JSON.stringify(request.response) diff --git a/SetPriceLimitPage.qml b/SetPriceLimitPage.qml index f6d0a45..dd1ce95 100644 --- a/SetPriceLimitPage.qml +++ b/SetPriceLimitPage.qml @@ -31,7 +31,7 @@ NavigationPage { } Text { - text: '>' + text: ">" } } } diff --git a/SimpleNavigationItem.qml b/SimpleNavigationItem.qml index e9c250d..ee204df 100644 --- a/SimpleNavigationItem.qml +++ b/SimpleNavigationItem.qml @@ -13,7 +13,7 @@ ItemDelegate { Component.onCompleted: { background.radius = 5 - background.color = 'white' + background.color = "white" contentItem.children[0].color = navigationItem.color } diff --git a/WiFiPage.qml b/WiFiPage.qml index 6b0c19a..bb39e84 100644 --- a/WiFiPage.qml +++ b/WiFiPage.qml @@ -29,23 +29,35 @@ NavigationPage { text: { switch (staStatus.value) { - case 0: return 'IDLE_STATUS' - case 1: return 'NO_SSID_AVAIL' - case 2: return 'SCAN_COMPLETED' - case 3: return 'CONNECTED' - case 4: return 'CONNECT_FAILED' - case 5: return 'CONNECTION_LOST' - case 6: return 'DISCONNECTED' - case 7: return 'CONNECTING' - case 8: return 'DISCONNECTING' - case 9: return 'NO_SHIELD' - case 10: return 'WAITING_FOR_IP' + case 0: return "IDLE_STATUS" + case 1: return "NO_SSID_AVAIL" + case 2: return "SCAN_COMPLETED" + case 3: return "CONNECTED" + case 4: return "CONNECT_FAILED" + case 5: return "CONNECTION_LOST" + case 6: return "DISCONNECTED" + case 7: return "CONNECTING" + case 8: return "DISCONNECTING" + case 9: return "NO_SHIELD" + case 10: return "WAITING_FOR_IP" default: return staStatus.value } } } } + Button { + ApiKeyValueHelper { + id: wifiScanResult + deviceConnection: mainScreen.deviceConnection + apiKey: "scan" + } + + text: qsTr("(%0) Wi-Fi Scan").arg(wifiScanResult.value == null ? 0 : wifiScanResult.value.length) + onClicked: stackView.push("WiFiScanPage.qml", {wifiScanResult} ) + enabled: wifiScanResult.value != null + } + Button { ApiKeyValueHelper { id: wifiErrorLog diff --git a/WiFiScanPage.qml b/WiFiScanPage.qml new file mode 100644 index 0000000..48d860c --- /dev/null +++ b/WiFiScanPage.qml @@ -0,0 +1,122 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import EVChargerApp + +BaseNavigationPage { + property ApiKeyValueHelper wifiScanResult + + title: qsTr("Wi-Fi Scan Result") + + ListView { + id: listView + Layout.fillWidth: true + Layout.fillHeight: true + + model: wifiScanResult.value + spacing: 5 + clip: true + + delegate: WhiteBox { + required property var modelData + property var theModelData: modelData + + width: listView.width + + GridLayout { + anchors.fill: parent + columns: 2 + + Text { + text: qsTr("SSID:") + font.bold: true + } + + Text { + text: modelData.ssid + } + + Text { + text: qsTr("Authmode:") + font.bold: true + } + + Text { + text: { + switch (modelData.encryptionType) + { + case 0: return qsTr("OPEN") + case 1: return qsTr("WEP") + case 2: return qsTr("WPA_PSK") + case 3: return qsTr("WPA2_PSK") + case 4: return qsTr("WPA_WPA2_PSK") + case 5: return qsTr("WPA2_ENTERPRISE") + case 6: return qsTr("WPA3_PSK") + case 7: return qsTr("WPA2_WPA3_PSK") + case 8: return qsTr("WAPI_PSK") + case 9: return qsTr("OWE") + case 10: return qsTr("WPA3_ENT_192") + case 11: return qsTr("WPA3_EXT_PSK") + case 12: return qsTr("WPA3_EXT_PSK_MIXED_MODE") + } + return modelData.encryptionType + } + } + + function wiFiCipherToString(cipher) { + const names = ['NONE', 'WEP40', 'WEP104', 'TKIP', 'CCMP', 'TKIP_CCMP', 'AES_CMAC128', 'SMS4', 'GCMP', 'GCMP256', 'AES_GMAC128', 'AES_GMAC256', 'UNKNOWN']; + + if (cipher >= 0 && cipher < names.length) + return names[cipher]; + + return cipher; + } + + Text { + text: qsTr("Pairwise cipher:") + font.bold: true + } + + Text { + text: parent.wiFiCipherToString("f" in modelData ? modelData.f[0] : modelData.pairwiseCipher) + } + + Text { + text: qsTr("Group cipher:") + font.bold: true + } + + Text { + text: parent.wiFiCipherToString("f" in modelData ? modelData.f[1] : modelData.groupCipher) + } + + Text { + text: qsTr("RSSI:") + font.bold: true + } + + Text { + text: modelData.rssi + } + + Text { + text: qsTr("Channel:") + font.bold: true + } + + Text { + text: modelData.channel + } + + Text { + text: qsTr("BSSID:") + font.bold: true + } + + Text { + text: modelData.bssid + } + } + } + } +} diff --git a/qmldir b/qmldir index c0d4666..30abcbb 100644 --- a/qmldir +++ b/qmldir @@ -71,3 +71,4 @@ EVChargerApp 1.0 WhiteBox.qml EVChargerApp 1.0 WiFiErrorsPage.qml EVChargerApp 1.0 WiFiOnOffSwitch.qml EVChargerApp 1.0 WiFiPage.qml +EVChargerApp 1.0 WiFiScanPage.qml