From 2debe4b265a1bf33e9c155d3f2ebb63923b590a9 Mon Sep 17 00:00:00 2001 From: impressionyang Date: Fri, 20 Dec 2024 11:11:59 +0800 Subject: [PATCH] =?UTF-8?q?update=E2=9C=A8:=20=E9=98=B6=E6=AE=B5=E6=80=A7?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=EF=BC=8C=E6=9B=B4=E6=96=B0=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0C++=20=E6=96=87=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=B2=E5=8F=A3=E5=88=B7=E6=96=B0=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 13 +++- Main.qml | 23 +++++++ QML/components/HomePageConnectStateInfo.qml | 68 +++++++++++++++++---- QML/components/IconInfoLabel.qml | 6 +- QML/components/LeftMenu.qml | 40 ++++++------ QML/models/GlobalProperties.qml | 42 ++++++------- QML/pages/HomePage.qml | 12 ++-- QML/pages/MainPage.qml | 18 +++++- main.cpp | 3 + src/components/serialportcomp.cpp | 45 ++++++++++++++ src/components/serialportcomp.h | 26 ++++++++ src/services/esp32upperextservice.cpp | 27 ++++++++ src/services/esp32upperextservice.h | 26 ++++++++ src/wrapper/esp32uperwrapper.cpp | 30 +++++++++ src/wrapper/esp32uperwrapper.h | 26 ++++++++ 15 files changed, 341 insertions(+), 64 deletions(-) create mode 100644 src/components/serialportcomp.cpp create mode 100644 src/components/serialportcomp.h create mode 100644 src/services/esp32upperextservice.cpp create mode 100644 src/services/esp32upperextservice.h create mode 100644 src/wrapper/esp32uperwrapper.cpp create mode 100644 src/wrapper/esp32uperwrapper.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ece2c2..c377a66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_AUTORCC ON) find_package(Qt6 6.5 REQUIRED COMPONENTS Quick) -find_package(Qt6 COMPONENTS Core Gui Svg Core5Compat REQUIRED) +find_package(Qt6 COMPONENTS Core Gui Svg Core5Compat SerialPort REQUIRED) qt_standard_project_setup(REQUIRES 6.5) @@ -15,6 +15,12 @@ qt_add_executable(appESP32_upper main.cpp ) +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/src/components + ${CMAKE_CURRENT_SOURCE_DIR}/src/services + ${CMAKE_CURRENT_SOURCE_DIR}/src/wrapper +) + qt_add_qml_module(appESP32_upper URI ESP32_upper VERSION 1.0 @@ -33,6 +39,9 @@ qt_add_qml_module(appESP32_upper QML_FILES QML/components/IconInfoLabel.qml QML_FILES QML/components/HomePageConnectStateInfo.qml QML_FILES + SOURCES src/wrapper/esp32uperwrapper.h src/wrapper/esp32uperwrapper.cpp + SOURCES src/services/esp32upperextservice.h src/services/esp32upperextservice.cpp + SOURCES src/components/serialportcomp.h src/components/serialportcomp.cpp ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. @@ -47,7 +56,7 @@ set_target_properties(appESP32_upper PROPERTIES ) target_link_libraries(appESP32_upper - PRIVATE Qt6::Quick Qt6::Core Qt6::Gui Qt6::Svg Qt6::Core5Compat + PRIVATE Qt6::Quick Qt6::Core Qt6::Gui Qt6::Svg Qt6::Core5Compat Qt6::SerialPort ) include(GNUInstallDirs) diff --git a/Main.qml b/Main.qml index a36f189..8c347c7 100644 --- a/Main.qml +++ b/Main.qml @@ -11,7 +11,30 @@ Window { minimumWidth: 800 // color: "green" + property var sharedData: ({ + counter: 0 , + gp_inited: 0, + global_banner: "Hello World", + left_menu_index_now: 0, + left_menu_index_last: 255, + left_menu_lighlight_color: "#FF00FF", + left_menu_non_lighlight_color: "#00FF00", + left_menu_focus_color: "#FAFA00", + left_menu_icon_color: "#0d4e8b", + font_info_pixel_size: 20, + btn_normalBackground: "#FFFFFF", // 白色// 正常状态的背景 + btn_hoverBackground: "#F0F0F0", // 浅灰色// hover 状态的背景 + btn_pressedBackground: "#D0D0D0", // 深灰色// pressed 状态的背景 + btn_borderColor: "#000000", // 深灰色// pressed 状态的背景 + port_name_list_model: ListModel + }) + MainPage { id: id_home_page } + + Component.onCompleted: { + console.log(sharedData.counter); // 输出初始值 + sharedData.gp_inited = 1 + } } diff --git a/QML/components/HomePageConnectStateInfo.qml b/QML/components/HomePageConnectStateInfo.qml index ccc2d65..69d6c4f 100644 --- a/QML/components/HomePageConnectStateInfo.qml +++ b/QML/components/HomePageConnectStateInfo.qml @@ -16,7 +16,7 @@ Item { Text { Layout.preferredWidth: 100 text: "连接状态:" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } @@ -24,7 +24,7 @@ Item { Layout.preferredWidth: 100 id: id_text_home_page_connet_state text: "未连接" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } Rectangle { @@ -33,16 +33,16 @@ Item { } Button { - id: button - text: "重新连接" + id: id_button_refresh_portlist + text: "shuaxin" Layout.preferredWidth: 100 - Layout.preferredHeight: 50 - font.pixelSize: id_gp.font_info_pixel_size + Layout.preferredHeight: 40 + font.pixelSize: sharedData.font_info_pixel_size background: Rectangle { - color: button.down ? id_gp.btn_pressedBackground : - button.hovered ? id_gp.btn_hoverBackground : id_gp.btn_normalBackground - border.color: id_gp.btn_borderColor + color: id_button_refresh_portlist.down ? sharedData.btn_pressedBackground : + id_button_refresh_portlist.hovered ? sharedData.btn_hoverBackground : sharedData.btn_normalBackground + border.color: sharedData.btn_borderColor radius: 10 } @@ -52,9 +52,53 @@ Item { // MouseArea 用于处理按下和松开事件 MouseArea { anchors.fill: parent - onPressed: button.background.color = id_gp.btn_pressedBackground - onReleased: button.background.color = button.hovered ? id_gp.btn_hoverBackground : id_gp.btn_normalBackground - onExited: button.background.color = id_gp.btn_normalBackground + onPressed: id_button_refresh_portlist.background.color = sharedData.btn_pressedBackground + onReleased: id_button_refresh_portlist.background.color = id_button_refresh_portlist.hovered ? sharedData.btn_hoverBackground : sharedData.btn_normalBackground + onExited: id_button_refresh_portlist.background.color = sharedData.btn_normalBackground + onClicked: { + console.log("clear all port") + id_combox_port_list.model.clear() + id_esp32upperwaper.GetPortNameList(); + } + } + } + + ComboBox { + id:id_combox_port_list + model: protname_list_model + Layout.preferredWidth: 100 + Layout.preferredHeight: 40 + background: Rectangle { + color: sharedData.btn_normalBackground + border.color: sharedData.btn_borderColor + radius: 10 + } + font.pixelSize: sharedData.font_info_pixel_size + } + + Button { + id: button + text: "重新连接" + Layout.preferredWidth: 100 + Layout.preferredHeight: 40 + font.pixelSize: sharedData.font_info_pixel_size + + background: Rectangle { + color: button.down ? sharedData.btn_pressedBackground : + button.hovered ? sharedData.btn_hoverBackground : sharedData.btn_normalBackground + border.color: sharedData.btn_borderColor + radius: 10 + } + + // 使 Button 支持 hover 事件 + hoverEnabled: true + + // MouseArea 用于处理按下和松开事件 + MouseArea { + anchors.fill: parent + onPressed: button.background.color = sharedData.btn_pressedBackground + onReleased: button.background.color = button.hovered ? sharedData.btn_hoverBackground : sharedData.btn_normalBackground + onExited: button.background.color = sharedData.btn_normalBackground } onClicked: { diff --git a/QML/components/IconInfoLabel.qml b/QML/components/IconInfoLabel.qml index 8bc9b13..b199df9 100644 --- a/QML/components/IconInfoLabel.qml +++ b/QML/components/IconInfoLabel.qml @@ -24,7 +24,7 @@ Item { ColorOverlay { anchors.fill: parent source: parent - color: id_gp.left_menu_non_lighlight_color // 修改后的 SVG 图片颜色 + color: sharedData.left_menu_non_lighlight_color // 修改后的 SVG 图片颜色 } } @@ -32,13 +32,13 @@ Item { Text { text: "芯片类型:" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } Text { id: id_comp_ico_info_lb text: "未确认" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } } } diff --git a/QML/components/LeftMenu.qml b/QML/components/LeftMenu.qml index d217e5d..b7ac380 100644 --- a/QML/components/LeftMenu.qml +++ b/QML/components/LeftMenu.qml @@ -11,31 +11,31 @@ Item { Rectangle { width: 60; height: 60 radius: 5 - color: id_gp.left_menu_non_lighlight_color + color: sharedData.left_menu_non_lighlight_color MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true onClicked: { // id_view.view.currentIndex = index - id_gp.left_menu_index_last = id_gp.left_menu_index_now - id_gp.left_menu_index_now = index + sharedData.left_menu_index_last = sharedData.left_menu_index_now + sharedData.left_menu_index_now = index id_view.currentIndex = index id_layout_right_panel.currentIndex = index - // console.log("left_menu_index", id_gp.left_menu_index_now) + // console.log("left_menu_index", sharedData.left_menu_index_now) } onEntered: { - if (index != id_gp.left_menu_index_now) { - id_view.itemAtIndex(index).color = id_gp.left_menu_focus_color + if (index != sharedData.left_menu_index_now) { + id_view.itemAtIndex(index).color = sharedData.left_menu_focus_color } id_lm_tooltip_text.text = name; id_lm_tooltip.visible = true; } onExited: { - if (index != id_gp.left_menu_index_now) { - id_view.itemAtIndex(index).color = id_gp.left_menu_non_lighlight_color + if (index != sharedData.left_menu_index_now) { + id_view.itemAtIndex(index).color = sharedData.left_menu_non_lighlight_color } id_lm_tooltip.visible = false; } @@ -57,7 +57,7 @@ Item { ColorOverlay { anchors.fill: svgIMG source: svgIMG - color: id_gp.left_menu_icon_color // 修改后的 SVG 图片颜色 + color: sharedData.left_menu_icon_color // 修改后的 SVG 图片颜色 } } @@ -105,13 +105,17 @@ Item { clip : true snapMode: ListView.SnapToItem onCurrentIndexChanged: { - // console.log("2 left_menu_index", id_gp.left_menu_index_now) - itemAtIndex(id_gp.left_menu_index_last).color = id_gp.left_menu_non_lighlight_color - itemAtIndex(id_gp.left_menu_index_now).color = id_gp.left_menu_lighlight_color + // console.log("2 left_menu_index", sharedData.left_menu_index_now) + if (sharedData.gp_inited == 1) { + itemAtIndex(sharedData.left_menu_index_last).color = sharedData.left_menu_non_lighlight_color + itemAtIndex(sharedData.left_menu_index_now).color = sharedData.left_menu_lighlight_color + } + + } Component.onCompleted: { - console.log("complete at ", id_gp.left_menu_index_now) + console.log("complete at ", sharedData.left_menu_index_now) id_timer_leftmenu.start() } } @@ -127,14 +131,14 @@ Item { onTriggered: { // 这里执行你的轮询逻辑,比如调用一个函数来获取数据 - if (id_gp.gp_inited == 1) { + if (sharedData.gp_inited == 1) { running = false; - id_gp.left_menu_index_last = id_view.count - id_gp.left_menu_index_now = 0 - id_view.itemAtIndex(id_gp.left_menu_index_now).color = id_gp.left_menu_lighlight_color + sharedData.left_menu_index_last = id_view.count + sharedData.left_menu_index_now = 0 + id_view.itemAtIndex(sharedData.left_menu_index_now).color = sharedData.left_menu_lighlight_color } else { pollForData(); - console.log("id gp ini : " , id_gp.gp_inited ) + console.log("id gp ini : " , sharedData.gp_inited ) } } } diff --git a/QML/models/GlobalProperties.qml b/QML/models/GlobalProperties.qml index b29a632..78671cf 100644 --- a/QML/models/GlobalProperties.qml +++ b/QML/models/GlobalProperties.qml @@ -2,27 +2,27 @@ import QtQuick 2.15 import ESP32_upper Item { - property int gp_inited: 0 - property string global_banner: "Hello World" - property int left_menu_index_now: 0 - property int left_menu_index_last: 255 - property color left_menu_lighlight_color: "#FF00FF" - property color left_menu_non_lighlight_color: "#00FF00" - property color left_menu_focus_color: "#FAFA00" - property color left_menu_icon_color: "#0d4e8b" - property int font_info_pixel_size: 20 - // 正常状态的背景 - property color btn_normalBackground: "#FFFFFF" // 白色 - // hover 状态的背景 - property color btn_hoverBackground: "#F0F0F0" // 浅灰色 - // pressed 状态的背景 - property color btn_pressedBackground: "#D0D0D0" // 深灰色 - // pressed 状态的背景 - property color btn_borderColor: "#000000" // 深灰色 + // property int gp_inited: 0 + // property string global_banner: "Hello World" + // property int left_menu_index_now: 0 + // property int left_menu_index_last: 255 + // property color left_menu_lighlight_color: "#FF00FF" + // property color left_menu_non_lighlight_color: "#00FF00" + // property color left_menu_focus_color: "#FAFA00" + // property color left_menu_icon_color: "#0d4e8b" + // property int font_info_pixel_size: 20 + // // 正常状态的背景 + // property color btn_normalBackground: "#FFFFFF" // 白色 + // // hover 状态的背景 + // property color btn_hoverBackground: "#F0F0F0" // 浅灰色 + // // pressed 状态的背景 + // property color btn_pressedBackground: "#D0D0D0" // 深灰色 + // // pressed 状态的背景 + // property color btn_borderColor: "#000000" // 深灰色 - Component.onCompleted: { - console.log("global property has been initialized"); - gp_inited = 1; - } + // Component.onCompleted: { + // console.log("global property has been initialized"); + // gp_inited = 1; + // } } diff --git a/QML/pages/HomePage.qml b/QML/pages/HomePage.qml index 41ebcf2..659fdf1 100644 --- a/QML/pages/HomePage.qml +++ b/QML/pages/HomePage.qml @@ -26,21 +26,21 @@ Item { spacing: 10 Text { text: "版本号: 软件版本->" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } Text { id: id_text_soft_ver text: "未获取" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } Text { text: " 硬件版本->" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } Text { id: id_text_hard_ver text: "未获取" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } } } @@ -55,12 +55,12 @@ Item { spacing: 10 Text { text: "固件编译时间:" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } Text { id: id_text_firm_build_time text: "未获取" - font.pixelSize: id_gp.font_info_pixel_size + font.pixelSize: sharedData.font_info_pixel_size } } } diff --git a/QML/pages/MainPage.qml b/QML/pages/MainPage.qml index 429e5bf..6487b09 100644 --- a/QML/pages/MainPage.qml +++ b/QML/pages/MainPage.qml @@ -2,12 +2,23 @@ import QtQuick 2.15 import QtQuick.Controls import QtQuick.Layouts import ESP32_upper 1.0 +import com.esp32upper 1.0 Item { id: root - GlobalProperties { - id: id_gp + // GlobalProperties { + // id: id_gp + // } + ListModel { + id: protname_list_model + } + + ESP32UperWrapper { + id: id_esp32upperwaper + onPortNameListChange: (port_name_list) => { + protname_list_model.append({text: qsTr(port_name_list)}) + } } RowLayout { @@ -48,5 +59,8 @@ Item { } } } + Component.onCompleted: { + id_esp32upperwaper.GetPortNameList(); + } } diff --git a/main.cpp b/main.cpp index 9cd2425..734a1c7 100644 --- a/main.cpp +++ b/main.cpp @@ -1,12 +1,15 @@ #include #include #include +#include "esp32uperwrapper.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); app.setWindowIcon(QIcon(":/assets/img/esp32_upper.png")); // 设置应用窗口图标 + qmlRegisterType("com.esp32upper", 1, 0, "ESP32UperWrapper"); + QQmlApplicationEngine engine; QObject::connect( &engine, diff --git a/src/components/serialportcomp.cpp b/src/components/serialportcomp.cpp new file mode 100644 index 0000000..96f608e --- /dev/null +++ b/src/components/serialportcomp.cpp @@ -0,0 +1,45 @@ +#include "serialportcomp.h" + +SerialPortComp::SerialPortComp(QObject *parent) + : QObject{parent} +{} + +void SerialPortComp::RefreshPorts() +{ + this->ports = QSerialPortInfo::availablePorts(); +} + +int SerialPortComp::OpenPort(int index) +{ + serialPort.setPort(ports.at(index)); + if (serialPort.open(QIODevice::ReadWrite)) { // 打开串口进行读写 + serialPort.setBaudRate(QSerialPort::Baud9600); // 设置波特率 + serialPort.setDataBits(QSerialPort::Data8); // 设置数据位 + serialPort.setParity(QSerialPort::NoParity); // 设置校验位 + serialPort.setStopBits(QSerialPort::OneStop); // 设置停止位 + serialPort.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制 + } else { + + } + return 0; +} + +QByteArray SerialPortComp::PortRead() +{ + QByteArray read_data; + if (serialPort.isOpen()) { + read_data = serialPort.readAll(); + } + return read_data; +} + +int SerialPortComp::PortWrite(QByteArray data) +{ + if (serialPort.isOpen()) { + serialPort.write(data); + serialPort.flush(); + }else { + return 1; + } + return 0; +} diff --git a/src/components/serialportcomp.h b/src/components/serialportcomp.h new file mode 100644 index 0000000..1c16d6f --- /dev/null +++ b/src/components/serialportcomp.h @@ -0,0 +1,26 @@ +#ifndef SERIALPORTCOMP_H +#define SERIALPORTCOMP_H + +#include +#include +#include +#include + +class SerialPortComp : public QObject +{ + Q_OBJECT +public: + QList ports; + + explicit SerialPortComp(QObject *parent = nullptr); + void RefreshPorts(); + int OpenPort(int index); + QByteArray PortRead(); + int PortWrite(QByteArray date); + +signals: +private: + QSerialPort serialPort; +}; + +#endif // SERIALPORTCOMP_H diff --git a/src/services/esp32upperextservice.cpp b/src/services/esp32upperextservice.cpp new file mode 100644 index 0000000..5f77e37 --- /dev/null +++ b/src/services/esp32upperextservice.cpp @@ -0,0 +1,27 @@ +#include "esp32upperextservice.h" +#include + +ESP32UpperExtService::ESP32UpperExtService(QObject *parent) + : QThread{parent} +{ + serial_comp.RefreshPorts(); +} + +QList ESP32UpperExtService::GetPortNameList() +{ + serial_comp.RefreshPorts(); + this->port_name_list.clear();; + foreach (QSerialPortInfo item, serial_comp.ports) { + item.portName(); + this->port_name_list.append(item.portName()); + } + return this->port_name_list; +} + +void ESP32UpperExtService::run() +{ + while (thread_alive) { + // do sth + msleep(1); + } +} diff --git a/src/services/esp32upperextservice.h b/src/services/esp32upperextservice.h new file mode 100644 index 0000000..b33819c --- /dev/null +++ b/src/services/esp32upperextservice.h @@ -0,0 +1,26 @@ +#ifndef ESP32UPPEREXTSERVICE_H +#define ESP32UPPEREXTSERVICE_H + +#include +#include "serialportcomp.h" +#include +#include + +class ESP32UpperExtService : public QThread +{ + Q_OBJECT +public: + explicit ESP32UpperExtService(QObject *parent = nullptr); + QList GetPortNameList(); + +protected: + void run() override; + +signals: +private: + QList port_name_list; + SerialPortComp serial_comp; + int thread_alive = 1; +}; + +#endif // ESP32UPPEREXTSERVICE_H diff --git a/src/wrapper/esp32uperwrapper.cpp b/src/wrapper/esp32uperwrapper.cpp new file mode 100644 index 0000000..383e288 --- /dev/null +++ b/src/wrapper/esp32uperwrapper.cpp @@ -0,0 +1,30 @@ +#include "esp32uperwrapper.h" +#include + +ESP32UperWrapper::ESP32UperWrapper(QObject *parent) + : QObject{parent} +{ + qDebug("init ESP32UperWrapper OK\r\n"); +} + +void ESP32UperWrapper::OutPortWriteData(QByteArray &data) +{ + +} + +void ESP32UperWrapper::GetPortNameList() +{ + serial_comp.RefreshPorts(); + this->port_name_list.clear();; + foreach (QSerialPortInfo item, serial_comp.ports) { + item.portName(); + this->port_name_list.append(item.portName()); + emit portNameListChange(item.portName()); + } + +} + +void ESP32UperWrapper::OpenPort(int index) +{ + this->serial_comp.OpenPort(index); +} diff --git a/src/wrapper/esp32uperwrapper.h b/src/wrapper/esp32uperwrapper.h new file mode 100644 index 0000000..3931577 --- /dev/null +++ b/src/wrapper/esp32uperwrapper.h @@ -0,0 +1,26 @@ +#ifndef ESP32UPERWRAPPER_H +#define ESP32UPERWRAPPER_H + +#include +#include +#include "serialportcomp.h" +#include + +class ESP32UperWrapper : public QObject +{ + Q_OBJECT +public: + explicit ESP32UperWrapper(QObject *parent = nullptr); + Q_INVOKABLE void OutPortWriteData(QByteArray &data); + Q_INVOKABLE void GetPortNameList(); + Q_INVOKABLE void OpenPort(int index); + +signals: + void outPortDataRecv(QByteArray data); + void portNameListChange(QString port_name_list); +private: + QList port_name_list; + SerialPortComp serial_comp; +}; + +#endif // ESP32UPERWRAPPER_H