Project: Update and bug fix.
1. Optimize static build. 2. Fix Config couldn't be used in QML. 3. Fix RibbonMessageListView's slide lag bug. 4. Add FrameChooser to let user customize DataFrame. 5. Fix EventHistoryList display bug. 6. Add Slider for ListTable.
This commit is contained in:
parent
cc08435a3a
commit
93c11e7ecf
|
@ -1 +1 @@
|
|||
Subproject commit 43240eab1f351a90afdc843119743b0aca4d311c
|
||||
Subproject commit 18edf9f0fdf0f11663d328a8166486226246e656
|
|
@ -2,13 +2,23 @@ cmake_minimum_required(VERSION 3.21)
|
|||
|
||||
project(ProtocolParser VERSION ${CMAKE_PROJECT_VERSION} LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.3")
|
||||
qt_standard_project_setup()
|
||||
qt_policy(SET QTP0001 NEW)
|
||||
else()
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/app_source CACHE STRING "Qt Creator extra QML import paths" FORCE)
|
||||
|
||||
set(PROJECT_COMPANY "Mentalflow's Lab")
|
||||
set(PROJECT_COPYRIGHT "Copyright (c) 2023 Mentalflow's Lab. All rights reserved.")
|
||||
set(PROJECT_DOMAIN "dev.ourdocs.cn.protocolparser")
|
||||
|
@ -36,7 +46,7 @@ set(
|
|||
qml/components/ZigBeeMessage.qml qml/components/SerialPortAssistant.qml
|
||||
qml/components/ZigBeeDataView.qml qml/components/TabBar.qml qml/components/CenterView.qml
|
||||
qml/components/ListTable.qml qml/components/DeviceList.qml qml/components/KeysList.qml
|
||||
qml/components/EventsHistoryList.qml
|
||||
qml/components/EventsHistoryList.qml qml/components/FrameChooser.qml
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(dlln3x include)
|
||||
|
|
|
@ -9,17 +9,18 @@ class Config : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
QML_NAMED_ELEMENT(Config)
|
||||
public:
|
||||
static Config* instance();
|
||||
static Config* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();}
|
||||
Q_INVOKABLE void Set(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue);
|
||||
Q_INVOKABLE void SetArray(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue);
|
||||
Q_INVOKABLE QVariant Get(QString qstrnodename,QString qstrkeyname);
|
||||
Q_INVOKABLE QVariant GetArray(QString qstrnodename,QString qstrkeyname);
|
||||
Q_INVOKABLE void set(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue);
|
||||
Q_INVOKABLE void setArray(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue);
|
||||
Q_INVOKABLE QVariant get(QString qstrnodename,QString qstrkeyname);
|
||||
Q_INVOKABLE QVariant getArray(QString qstrnodename,QString qstrkeyname);
|
||||
void Clear();
|
||||
private:
|
||||
Config(QString qstrfilename = "");
|
||||
explicit Config(QString qstrfilename = "");
|
||||
~Config(void);
|
||||
Q_DISABLE_COPY_MOVE(Config)
|
||||
QString m_qstrFileName;
|
||||
|
|
|
@ -24,6 +24,7 @@ private:
|
|||
void src_port_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo = false);
|
||||
void des_port_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo = false);
|
||||
void remote_addr_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo = false);
|
||||
QString sensor_data_reader(void **data,QString type);
|
||||
zigbee_protocol::Protocol* _protocol = nullptr;
|
||||
QString _self_addr;
|
||||
QMap<uint16_t, QPair<device,device>> nodes;
|
||||
|
|
|
@ -33,9 +33,9 @@ public:
|
|||
QList<uint16_t> wait_queue(){if(!_resolver)_resolver=ZigBeeDataResolver::instance();return _resolver->get_wait_queue();};
|
||||
void setWait_queue(QList<uint16_t> wait_queue){if(!_resolver)_resolver=ZigBeeDataResolver::instance();QList<uint16_t> &a=_resolver->get_wait_queue();a=wait_queue;emit wait_queueChanged();};
|
||||
QString hmac_verify_key(){ return _protocol->hmac_verify_key;};
|
||||
void setHmac_verify_key(QString key){ _config->Set("Protocol","hmac_verify_key",key); _protocol->hmac_verify_key = key;emit hmac_verify_keyChanged();};
|
||||
void setHmac_verify_key(QString key){ _config->set("Protocol","hmac_verify_key",key); _protocol->hmac_verify_key = key;emit hmac_verify_keyChanged();};
|
||||
QStringList pre_hmac_verify_key(){ return _protocol->pre_hmac_verify_key;};
|
||||
void setPre_hmac_verify_key(QStringList keys){ _config->SetArray("Protocol","pre_hmac_verify_key",keys); _protocol->pre_hmac_verify_key = keys;emit pre_hmac_verify_keyChanged();};
|
||||
void setPre_hmac_verify_key(QStringList keys){ _config->setArray("Protocol","pre_hmac_verify_key",keys); _protocol->pre_hmac_verify_key = keys;emit pre_hmac_verify_keyChanged();};
|
||||
static ZigBeeParser* instance();
|
||||
static ZigBeeParser* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();}
|
||||
void message_parser(QJsonObject message);
|
||||
|
|
|
@ -10,7 +10,9 @@ import "components"
|
|||
RibbonWindow {
|
||||
id:root
|
||||
width: 1200
|
||||
minimumWidth: 1200
|
||||
height: 800
|
||||
minimumHeight: 800
|
||||
title: qsTr("Protocol Parser") + ` V${PPAPP_Version}`
|
||||
|
||||
TabBar{
|
||||
|
|
|
@ -7,7 +7,7 @@ import ProtocolParser
|
|||
Item {
|
||||
id:obj
|
||||
property var header_items: ["序号","事件"]
|
||||
property var header_items_width: [100,400]
|
||||
property var header_items_width: [100,700]
|
||||
property var data_source: []
|
||||
implicitHeight: list_layout.height
|
||||
implicitWidth: list_layout.width
|
||||
|
@ -21,7 +21,7 @@ Item {
|
|||
var data = []
|
||||
for (var i = 0; i < EventsBus.event_history.length; i++)
|
||||
{
|
||||
data.push({"序号":i+1,"事件":JSON.stringify(EventsBus.event_history)})
|
||||
data.push({"序号":i+1,"事件":JSON.stringify(EventsBus.event_history[i])})
|
||||
}
|
||||
data_source = data
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ Item {
|
|||
var data = []
|
||||
for (var i = 0; i < EventsBus.event_history.length; i++)
|
||||
{
|
||||
data.push({"序号":i+1,"事件":JSON.stringify(EventsBus.event_history)})
|
||||
data.push({"序号":i+1,"事件":JSON.stringify(EventsBus.event_history[i])})
|
||||
}
|
||||
data_source = data
|
||||
}
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import RibbonUI
|
||||
import ProtocolParser
|
||||
|
||||
Item {
|
||||
clip: true
|
||||
id: root
|
||||
implicitWidth: layout.width + margins*2
|
||||
implicitHeight: layout.height + margins*2
|
||||
property double margins: 30
|
||||
property int object_width: 30
|
||||
|
||||
ListModel{
|
||||
id: frame_model
|
||||
ListElement{
|
||||
name:"温度"
|
||||
type:"float"
|
||||
}
|
||||
ListElement{
|
||||
name:"湿度"
|
||||
type:"float"
|
||||
}
|
||||
ListElement{
|
||||
name:"气体浓度"
|
||||
type:"float"
|
||||
}
|
||||
ListElement{
|
||||
name:"火焰指数"
|
||||
type:"float"
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
let result = Config.getArray('Protocol', 'data_frame_name')
|
||||
if (result)
|
||||
{
|
||||
frame_model.clear()
|
||||
var name_array=[],type_array=[]
|
||||
name_array = Config.getArray('Protocol', 'data_frame_name')
|
||||
type_array = Config.getArray('Protocol', 'data_frame_type')
|
||||
for (var i=0;i<name_array.length;i++)
|
||||
{
|
||||
frame_model.append({
|
||||
name:name_array[i],
|
||||
type:type_array[i]
|
||||
})
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let name_array=[],type_array=[]
|
||||
for (let i=0;i<frame_model.count;i++)
|
||||
{
|
||||
name_array[i] = frame_model.get(i).name
|
||||
type_array[i] = frame_model.get(i).type
|
||||
}
|
||||
Config.setArray('Protocol', 'data_frame_name', name_array)
|
||||
Config.setArray('Protocol', 'data_frame_type', type_array)
|
||||
}
|
||||
}
|
||||
|
||||
RibbonButton{
|
||||
anchors{
|
||||
top:parent.top
|
||||
margins: 4
|
||||
right:parent.right
|
||||
}
|
||||
show_bg: false
|
||||
show_hovered_bg: false
|
||||
icon_source: RibbonIcons.Dismiss
|
||||
onClicked: window_popup.close()
|
||||
}
|
||||
|
||||
ColumnLayout{
|
||||
id:layout
|
||||
anchors{
|
||||
top:parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
margins: margins
|
||||
}
|
||||
RibbonText{
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
width: implicitWidth > parent.width ? parent.width : implicitWidth
|
||||
text: qsTr("自定义传感器数据结构")
|
||||
font.pixelSize: 20
|
||||
wrapMode: RibbonText.WordWrap
|
||||
view_only: true
|
||||
}
|
||||
RibbonText{
|
||||
Layout.topMargin: margins/2
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
width: implicitWidth > parent.width ? parent.width : implicitWidth
|
||||
text: qsTr("传感器数据帧结构组成:")
|
||||
wrapMode: RibbonText.WordWrap
|
||||
view_only: true
|
||||
}
|
||||
Rectangle{
|
||||
id: frame_bg
|
||||
radius: 5
|
||||
Layout.preferredHeight: object_width + frame.anchors.leftMargin*2
|
||||
Layout.preferredWidth: object_width * 16 + frame.anchors.leftMargin*2
|
||||
color: RibbonTheme.dark_mode ? '#2A2C31' : '#F2F4F7'
|
||||
ListView{
|
||||
id: frame
|
||||
property int current_size: 0
|
||||
property bool is_full: current_size === 16
|
||||
property int has_selected: 0
|
||||
clip: true
|
||||
model: frame_model
|
||||
orientation: ListView.Horizontal
|
||||
implicitHeight: object_width
|
||||
implicitWidth: contentWidth
|
||||
anchors{
|
||||
leftMargin: 2
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
delegate:RibbonRectangle{
|
||||
id: bg
|
||||
topLeftRadius: index === 0 ? 5 : 0
|
||||
bottomLeftRadius: topLeftRadius
|
||||
topRightRadius: frame.current_size === 16 && (index + 1) === frame.count ? 5 : 0
|
||||
bottomRightRadius: topRightRadius
|
||||
implicitHeight: object_width
|
||||
implicitWidth: object_width
|
||||
color: bg.selected || mouse.containsMouse ? "#506BBD" : RibbonTheme.dark_mode ? '#3A4045' : "white"
|
||||
property bool selected: false
|
||||
property bool is_focused: frame.currentIndex === index
|
||||
onIs_focusedChanged: {
|
||||
if (!is_focused && selected)
|
||||
bg.selected = !bg.selected
|
||||
}
|
||||
onSelectedChanged: frame.has_selected += bg.selected ? 1 : -1
|
||||
property string type: model.type
|
||||
property int data_size
|
||||
onTypeChanged: {
|
||||
data_size = cal_size(model.type)
|
||||
implicitWidth = object_width * data_size
|
||||
}
|
||||
RibbonText{
|
||||
anchors.centerIn: parent
|
||||
width: implicitWidth > parent.width ? parent.width : implicitWidth
|
||||
text: model.name
|
||||
wrapMode: RibbonText.WordWrap
|
||||
view_only: true
|
||||
color:{
|
||||
if(!RibbonTheme.dark_mode)
|
||||
{
|
||||
if(mouse.containsMouse&&!bg.selected)
|
||||
return 'black'
|
||||
else if(mouse.containsMouse&&bg.selected)
|
||||
return 'white'
|
||||
else if(!mouse.containsMouse&&bg.selected)
|
||||
return 'black'
|
||||
else
|
||||
return 'black'
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mouse.containsMouse&&!bg.selected)
|
||||
return 'white'
|
||||
else if(mouse.containsMouse&&bg.selected)
|
||||
return 'black'
|
||||
else if(!mouse.containsMouse&&bg.selected)
|
||||
return 'white'
|
||||
else
|
||||
return 'white'
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
width: 1
|
||||
height: parent.height - frame.anchors.leftMargin * 2
|
||||
visible: index + 1 !== frame.count
|
||||
color: RibbonTheme.dark_mode ? "#525252" : "#D4D4D4"
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: 60
|
||||
easing.type: Easing.OutSine
|
||||
}
|
||||
}
|
||||
}
|
||||
RibbonToolTip{
|
||||
text: qsTr(`类型:${bg.type}, 长度:${bg.data_size}B`)
|
||||
visible: text && mouse.containsMouse
|
||||
}
|
||||
|
||||
MouseArea{
|
||||
id: mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked:
|
||||
{
|
||||
frame.currentIndex = index
|
||||
bg.selected = !bg.selected
|
||||
}
|
||||
}
|
||||
ListView.onRemove: cal_size(type,true)
|
||||
function cal_size(type,is_remove)
|
||||
{
|
||||
let size = frame.judge_size(type);
|
||||
if(!is_remove)
|
||||
frame.current_size += size
|
||||
else
|
||||
frame.current_size -= size
|
||||
return size
|
||||
}
|
||||
}
|
||||
function judge_size(type)
|
||||
{
|
||||
let size = 0
|
||||
switch(type)
|
||||
{
|
||||
case "float":
|
||||
size = 4
|
||||
break
|
||||
case "double":
|
||||
size = 8
|
||||
break
|
||||
case "int64_t":
|
||||
size = 8
|
||||
break
|
||||
case "int32_t":
|
||||
size = 4
|
||||
break
|
||||
case "int16_t":
|
||||
size = 2
|
||||
break
|
||||
case "int8_t":
|
||||
size = 1
|
||||
break
|
||||
case "uint64_t":
|
||||
size = 8
|
||||
break
|
||||
case "uint32_t":
|
||||
size = 4
|
||||
break
|
||||
case "uint16_t":
|
||||
size = 2
|
||||
break
|
||||
case "uint8_t":
|
||||
size = 1
|
||||
break
|
||||
}
|
||||
return size
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.topMargin: margins/2
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: margins/3
|
||||
RibbonText{
|
||||
text: qsTr("类型:")
|
||||
view_only: true
|
||||
}
|
||||
RibbonComboBox{
|
||||
id: type_combo
|
||||
Layout.preferredWidth: 100
|
||||
model: ListModel {
|
||||
ListElement { text: "float" }
|
||||
ListElement { text: "double" }
|
||||
ListElement { text: "int64_t" }
|
||||
ListElement { text: "int32_t" }
|
||||
ListElement { text: "int16_t" }
|
||||
ListElement { text: "int8_t" }
|
||||
ListElement { text: "uint64_t" }
|
||||
ListElement { text: "uint32_t" }
|
||||
ListElement { text: "uint16_t" }
|
||||
ListElement { text: "uint8_t" }
|
||||
}
|
||||
enabled: frame.current_size !==16
|
||||
}
|
||||
RibbonText{
|
||||
text: qsTr("名称:")
|
||||
view_only: true
|
||||
}
|
||||
RibbonLineEdit{
|
||||
id: name_edit
|
||||
Layout.preferredWidth: 120
|
||||
placeholderText: qsTr("请输入数据名称")
|
||||
onCommit: save_btn.clicked()
|
||||
enabled: frame.current_size !==16
|
||||
}
|
||||
RibbonButton{
|
||||
id: add_btn
|
||||
icon_source: RibbonIcons.Add
|
||||
text: qsTr("添加")
|
||||
show_tooltip: false
|
||||
enabled: {
|
||||
if (frame.judge_size(type_combo.currentText)+frame.current_size>16)
|
||||
return false
|
||||
else
|
||||
return true
|
||||
}
|
||||
onClicked: {
|
||||
frame_model.append({
|
||||
type:type_combo.currentText,
|
||||
name:name_edit.text
|
||||
})
|
||||
}
|
||||
}
|
||||
RibbonButton{
|
||||
id: delete_btn
|
||||
icon_source: RibbonIcons.Delete
|
||||
text: qsTr("删除")
|
||||
show_tooltip: false
|
||||
enabled: frame.has_selected !== 0
|
||||
onClicked: {
|
||||
frame_model.remove(frame.currentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
RowLayout{
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: margins/2
|
||||
spacing: margins
|
||||
RibbonButton{
|
||||
id: save_btn
|
||||
Layout.preferredWidth: 150
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
icon_source: RibbonIcons.Save
|
||||
text: qsTr("保存")
|
||||
show_tooltip: false
|
||||
onClicked: {
|
||||
if (!type_combo.enabled && !name_edit.enabled && frame.current_size > 0)
|
||||
{
|
||||
let name_array=[],type_array=[]
|
||||
for (let i=0;i<frame_model.count;i++)
|
||||
{
|
||||
name_array[i] = frame_model.get(i).name
|
||||
type_array[i] = frame_model.get(i).type
|
||||
}
|
||||
Config.setArray('Protocol', 'data_frame_name', name_array)
|
||||
Config.setArray('Protocol', 'data_frame_type', type_array)
|
||||
}
|
||||
else
|
||||
{
|
||||
name_edit.text = qsTr("请检查数据长度")
|
||||
}
|
||||
}
|
||||
}
|
||||
RibbonButton{
|
||||
id: reset_btn
|
||||
Layout.preferredWidth: 150
|
||||
icon_source: RibbonIcons.ArrowReset
|
||||
text: qsTr("还原默认值")
|
||||
show_tooltip: false
|
||||
onClicked: {
|
||||
frame_model.clear()
|
||||
frame_model.append([{
|
||||
name:"温度",
|
||||
type:"float"
|
||||
},{
|
||||
name:"湿度",
|
||||
type:"float"
|
||||
},{
|
||||
name:"气体浓度",
|
||||
type:"float"
|
||||
},{
|
||||
name:"火焰指数",
|
||||
type:"float"
|
||||
}])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -93,7 +93,30 @@ Item {
|
|||
view_only: true
|
||||
text: modelData.data
|
||||
wrapMode: RibbonText.WordWrap
|
||||
color: RibbonTheme.dark_mode ? mouse.containsMouse ? 'black' : 'white' : mouse.containsMouse ? 'white':'black'
|
||||
color: {
|
||||
if(RibbonTheme.dark_mode)
|
||||
{
|
||||
if(mouse.containsMouse&&!row_bg.selected)
|
||||
return 'black'
|
||||
else if(mouse.containsMouse&&row_bg.selected)
|
||||
return 'white'
|
||||
else if(!mouse.containsMouse&&row_bg.selected)
|
||||
return 'black'
|
||||
else
|
||||
return 'white'
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mouse.containsMouse&&!row_bg.selected)
|
||||
return 'white'
|
||||
else if(mouse.containsMouse&&row_bg.selected)
|
||||
return 'black'
|
||||
else if(!mouse.containsMouse&&row_bg.selected)
|
||||
return 'white'
|
||||
else
|
||||
return 'black'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +137,11 @@ Item {
|
|||
add: Transition {
|
||||
NumberAnimation { properties: "y"; from: list_table.height; duration: 200 }
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
anchors.right: list_table.right
|
||||
anchors.rightMargin: 2
|
||||
}
|
||||
}
|
||||
|
||||
function getRowValues(index) {
|
||||
|
|
|
@ -8,11 +8,12 @@ Rectangle{
|
|||
color: "transparent"
|
||||
property double padding: 10
|
||||
default property alias content: message_layout.data
|
||||
property var data_model:model
|
||||
property var data_model: model
|
||||
property int font_size: 13
|
||||
property string sender_text: "sender"
|
||||
width: ListView.view.width
|
||||
height: bubble_layout.height + padding*2
|
||||
|
||||
ColumnLayout{
|
||||
id: bubble_layout
|
||||
anchors{
|
||||
|
|
|
@ -12,80 +12,53 @@ RibbonView{
|
|||
spacing: 0
|
||||
|
||||
property int max_msg_num: 10
|
||||
property bool auto_scroll_to_bottom: false
|
||||
property int animation_time: 200
|
||||
property alias delegate: message_list.delegate
|
||||
property alias message_model: message_model
|
||||
property alias view: message_list
|
||||
|
||||
ListModel{
|
||||
id: message_model
|
||||
property int begin_index: 0
|
||||
property int end_index: 0
|
||||
onCountChanged: {
|
||||
if (end_index == count - 2 || begin_index == end_index)
|
||||
{
|
||||
while(show_model.count > max_msg_num)
|
||||
{
|
||||
show_model.remove(0)
|
||||
begin_index++
|
||||
}
|
||||
show_model.append(message_model.get(count - 1))
|
||||
end_index = count-1
|
||||
//console.log('append:',begin_index,end_index)
|
||||
}
|
||||
if(count===0)
|
||||
show_model.clear()
|
||||
}
|
||||
onCountChanged: auto_scroll_btn_timer.restart()
|
||||
}
|
||||
ListModel{
|
||||
id: show_model
|
||||
|
||||
Timer{
|
||||
id: auto_scroll_btn_timer
|
||||
interval: animation_time
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if(view.auto_scroll_to_bottom)
|
||||
view.scroll_to_bottom()
|
||||
}
|
||||
}
|
||||
|
||||
ListView{
|
||||
id: message_list
|
||||
cacheBuffer: message_list.height * 2
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredHeight: contentHeight
|
||||
Layout.preferredHeight: parent.height
|
||||
Layout.preferredWidth: parent.width
|
||||
interactive: false
|
||||
model: show_model
|
||||
model: message_model
|
||||
add: Transition {
|
||||
NumberAnimation { properties: "y"; from: message_list.height; duration: 100 }
|
||||
NumberAnimation {
|
||||
properties: "y"
|
||||
from: message_list.height
|
||||
duration: animation_time
|
||||
}
|
||||
}
|
||||
displaced: Transition {
|
||||
NumberAnimation { properties: "y"; duration: 100 }
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
anchors.right: message_list.right
|
||||
anchors.rightMargin: 2
|
||||
}
|
||||
}
|
||||
Connections{
|
||||
target: view
|
||||
function onPull_up_triggered()
|
||||
{
|
||||
for(let i = message_model.begin_index - 1, count = 0;
|
||||
i >= 0 && count < max_msg_num; i--,count++ )
|
||||
{
|
||||
show_model.insert(0,message_model.get(i))
|
||||
message_model.begin_index = i
|
||||
if (show_model.count > max_msg_num + 2)
|
||||
{
|
||||
show_model.remove(show_model.count - 1)
|
||||
message_model.end_index--
|
||||
}
|
||||
}
|
||||
//console.log('up:',message_model.begin_index,message_model.end_index)
|
||||
}
|
||||
function onPull_down_triggered()
|
||||
{
|
||||
for(let i = message_model.end_index + 1, count = 0;
|
||||
i < message_model.count && count < max_msg_num; i++,count++ )
|
||||
{
|
||||
show_model.append(message_model.get(i))
|
||||
message_model.end_index = i
|
||||
if (show_model.count > max_msg_num)
|
||||
{
|
||||
show_model.remove(0)
|
||||
message_model.begin_index++
|
||||
}
|
||||
}
|
||||
//console.log('down:',message_model.begin_index,message_model.end_index)
|
||||
}
|
||||
|
||||
function scroll_to_up(){
|
||||
message_list.positionViewAtBeginning()
|
||||
}
|
||||
|
||||
function scroll_to_bottom(){
|
||||
message_list.positionViewAtEnd()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,22 +14,23 @@ Item{
|
|||
property double bottom_padding: 0
|
||||
property bool handle_serial: true
|
||||
|
||||
onAuto_scroll_to_bottomChanged: if(auto_scroll_to_bottom) serial_view.scroll_to_bottom()
|
||||
onAuto_scroll_to_bottomChanged: {
|
||||
serial_view.auto_scroll_to_bottom = auto_scroll_to_bottom
|
||||
if(auto_scroll_to_bottom)
|
||||
serial_view.scroll_to_bottom()
|
||||
}
|
||||
|
||||
RibbonMessageListView{
|
||||
id: serial_view
|
||||
anchors.fill: parent
|
||||
top_padding: serial_title_bar.height + control.top_padding + (!RibbonTheme.modern_style ? 10 : 0)
|
||||
bottom_padding: message_sender.height + control.bottom_padding
|
||||
auto_scroll_to_bottom: control.auto_scroll_to_bottom
|
||||
delegate: ZigBeeMessage{
|
||||
sender_text: `${model.time} ${model.recieved ? '收' : '发'}`
|
||||
show_tooltip: control.show_tooltip
|
||||
component_width: serial_view.width / 2
|
||||
}
|
||||
view.onHeightChanged: {
|
||||
if (control.auto_scroll_to_bottom)
|
||||
scroll_to_bottom()
|
||||
}
|
||||
Connections{
|
||||
target: SerialPortManager
|
||||
function onRecved(data)
|
||||
|
|
|
@ -404,8 +404,8 @@ RibbonTabBar {
|
|||
}
|
||||
|
||||
let repeat_count = 16
|
||||
let t = `FF 29 ${get_rand_byte()}${get_rand_byte()} 83 56 56 `+
|
||||
`AA AD 56 56 52 48 23 32 01 00 17 00 00 00 AA AA 01 10 00 FF FF `
|
||||
let t = `FF 2B ${get_rand_byte()}${get_rand_byte()} 83 56 56 `+
|
||||
`AA AD 56 56 EE EE 56 56 01 00 26 00 00 00 AA AA 01 FF 10 00 FF FF `
|
||||
for (let j=0;j<repeat_count;j++){
|
||||
t+=` ${get_rand_byte()}${get_rand_byte()}`
|
||||
}
|
||||
|
@ -458,5 +458,27 @@ RibbonTabBar {
|
|||
}
|
||||
}
|
||||
}
|
||||
RibbonTabGroup{
|
||||
text: qsTr("数据结构自定义")
|
||||
width: frame_custom_layout.width + 30
|
||||
RowLayout{
|
||||
id: frame_custom_layout
|
||||
anchors.centerIn: parent
|
||||
height: parent.height
|
||||
spacing: 10
|
||||
ColumnLayout{
|
||||
spacing: 10
|
||||
RibbonButton{
|
||||
Layout.fillWidth: true
|
||||
icon_source: RibbonIcons.CodeTextEdit
|
||||
text: qsTr("自定义数据帧")
|
||||
tip_text: qsTr("自定义传感器数据帧结构")
|
||||
onClicked: {
|
||||
show_popup("components/FrameChooser.qml")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,10 @@ Item{
|
|||
identify_view.scroll_to_bottom()
|
||||
data_view.scroll_to_bottom()
|
||||
}
|
||||
identify_view.auto_scroll_to_bottom = auto_scroll_to_bottom
|
||||
data_view.auto_scroll_to_bottom = auto_scroll_to_bottom
|
||||
}
|
||||
|
||||
Item{
|
||||
anchors{
|
||||
top:parent.top
|
||||
|
@ -56,14 +59,11 @@ Item{
|
|||
anchors.fill: parent
|
||||
top_padding: control.top_padding + identify_title_bar.height + (!RibbonTheme.modern_style ? 10 : 0)
|
||||
bottom_padding: control.bottom_padding
|
||||
auto_scroll_to_bottom: control.auto_scroll_to_bottom
|
||||
delegate: ZigBeeMessage{
|
||||
show_tooltip: control.show_tooltip
|
||||
component_width: identify_view.width / 2
|
||||
}
|
||||
view.onHeightChanged: {
|
||||
if (control.auto_scroll_to_bottom)
|
||||
scroll_to_bottom()
|
||||
}
|
||||
Event{
|
||||
id:identify_view_event
|
||||
type: "zigbee_identify_data_view"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
project(sm_crypto VERSION 1.0.0.0)
|
||||
project(sm_crypto VERSION 1.0.0)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
|
|
@ -35,12 +35,12 @@ Config* Config::instance()
|
|||
return singleton;
|
||||
}
|
||||
|
||||
void Config::Set(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue)
|
||||
void Config::set(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue)
|
||||
{
|
||||
m_psetting->setValue(QString("/%1/%2").arg(qstrnodename).arg(qstrkeyname), qvarvalue);
|
||||
}
|
||||
|
||||
void Config::SetArray(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue)
|
||||
void Config::setArray(QString qstrnodename,QString qstrkeyname,QVariant qvarvalue)
|
||||
{
|
||||
m_psetting->beginWriteArray(QString("/%1/%2").arg(qstrnodename).arg(qstrkeyname));
|
||||
QList<QVariant> list = qvarvalue.toList();
|
||||
|
@ -52,13 +52,13 @@ void Config::SetArray(QString qstrnodename,QString qstrkeyname,QVariant qvarvalu
|
|||
m_psetting->endArray();
|
||||
}
|
||||
|
||||
QVariant Config::Get(QString qstrnodename,QString qstrkeyname)
|
||||
QVariant Config::get(QString qstrnodename,QString qstrkeyname)
|
||||
{
|
||||
QVariant qvar = m_psetting->value(QString("/%1/%2").arg(qstrnodename).arg(qstrkeyname));
|
||||
return qvar;
|
||||
}
|
||||
|
||||
QVariant Config::GetArray(QString qstrnodename,QString qstrkeyname)
|
||||
QVariant Config::getArray(QString qstrnodename,QString qstrkeyname)
|
||||
{
|
||||
QList<QVariant> list;
|
||||
int size = m_psetting->beginReadArray(QString("/%1/%2").arg(qstrnodename).arg(qstrkeyname));
|
||||
|
|
|
@ -31,9 +31,6 @@ int main(int argc, char *argv[])
|
|||
QList<int> verl = {PROTOCOLPARSER_VERSION};
|
||||
QString version = QString::number(verl[0])+'.'+QString::number(verl[1])+'.'+QString::number(verl[2]);
|
||||
engine.rootContext()->setContextProperty("PPAPP_Version",version);
|
||||
#ifdef RIBBONUI_BUILD_STATIC_LIB
|
||||
engine.addImportPath("qrc:/");
|
||||
#endif
|
||||
const QUrl url(u"qrc:/qt/qml/ProtocolParser/Main.qml"_qs);
|
||||
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
|
||||
&app, [url](QObject *obj, const QUrl &objUrl) {
|
||||
|
|
|
@ -5,20 +5,18 @@ using namespace zigbee_protocol;
|
|||
|
||||
Protocol::Protocol(){
|
||||
_config = Config::instance();
|
||||
if (_config->Get("Protocol","hmac_verify_key").toString().isEmpty())
|
||||
_config->Set("Protocol","hmac_verify_key",hmac_verify_key);
|
||||
if (_config->get("Protocol","hmac_verify_key").toString().isEmpty())
|
||||
_config->set("Protocol","hmac_verify_key",hmac_verify_key);
|
||||
else
|
||||
hmac_verify_key = _config->Get("Protocol","hmac_verify_key").toString();
|
||||
if (_config->GetArray("Protocol","pre_hmac_verify_key").toStringList().isEmpty())
|
||||
_config->SetArray("Protocol","pre_hmac_verify_key",pre_hmac_verify_key);
|
||||
hmac_verify_key = _config->get("Protocol","hmac_verify_key").toString();
|
||||
if (_config->getArray("Protocol","pre_hmac_verify_key").toStringList().isEmpty())
|
||||
_config->setArray("Protocol","pre_hmac_verify_key",pre_hmac_verify_key);
|
||||
else
|
||||
pre_hmac_verify_key = _config->GetArray("Protocol","pre_hmac_verify_key").toStringList();
|
||||
pre_hmac_verify_key = _config->getArray("Protocol","pre_hmac_verify_key").toStringList();
|
||||
}
|
||||
|
||||
Protocol::~Protocol()
|
||||
{
|
||||
_config->Set("Protocol","hmac_verify_key",hmac_verify_key);
|
||||
_config->SetArray("Protocol","pre_hmac_verify_key",pre_hmac_verify_key);
|
||||
}
|
||||
|
||||
Protocol* Protocol::getInstance()
|
||||
|
|
|
@ -221,6 +221,7 @@ void ZigBeeDataResolver::des_port_parser(zigbee_protocol::ZigbeeFrame &zframe, b
|
|||
QJsonObject object;
|
||||
if (node->first.verified)
|
||||
{
|
||||
QString note_text;
|
||||
new_data_frame(72) ndata;
|
||||
uint8_t data_len = 0;
|
||||
memset(&ndata,0,sizeof(ndata));
|
||||
|
@ -231,7 +232,7 @@ void ZigBeeDataResolver::des_port_parser(zigbee_protocol::ZigbeeFrame &zframe, b
|
|||
object.insert("type","zigbee_recv_data");
|
||||
if (*(u16 *)frame == CRYPTO_ZDATA_FRAME_HEAD)
|
||||
{
|
||||
QString note_text = "解密数据为按照未加密传输重新打包的原始数据,因此数据长度会有差异\n";
|
||||
note_text = "解密数据为按照未加密传输重新打包的原始数据,因此数据长度会有差异\n";
|
||||
new_base_frame(sizeof(ndata)) nbframe;
|
||||
memcpy(&nbframe, bframe, BASE_FRAME_PREFIX_LEN);
|
||||
zigbee_protocol::ZigbeeFrame nzframe = zframe;
|
||||
|
@ -242,22 +243,29 @@ void ZigBeeDataResolver::des_port_parser(zigbee_protocol::ZigbeeFrame &zframe, b
|
|||
nzframe.setData((char*)&nbframe,nbframe.length);
|
||||
zdata = QByteArray((char *)nzframe.data(), nzframe.size());
|
||||
object.insert("decrypted_text", QJsonValue(QString(zdata.toHex(' ').toUpper())));
|
||||
switch (ndata.type) {
|
||||
case SENSOR_DATA_TYPE:
|
||||
{
|
||||
note_text += "传感器数据:";
|
||||
sensor_data* sdata = (sensor_data*)ndata.data;
|
||||
note_text += "PPM:" + QString::number(sdata->ppm) + ' ';
|
||||
note_text += "Temperature:" + QString::number(sdata->temp) + ' ';
|
||||
note_text += "Humidity:" + QString::number(sdata->humi) + ' ';
|
||||
note_text += "Flare:" + QString::number(sdata->flare) + ' ';
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
object.insert("note_text",QJsonValue(note_text));
|
||||
ddata = (data_frame*)&ndata;
|
||||
}
|
||||
else{
|
||||
ddata = (data_frame*)frame;
|
||||
}
|
||||
switch (ddata->type) {
|
||||
case SENSOR_DATA_TYPE:
|
||||
{
|
||||
QStringList name_list, type_list;
|
||||
name_list = Config::instance()->getArray("Protocol", "data_frame_name").toStringList();
|
||||
type_list = Config::instance()->getArray("Protocol", "data_frame_type").toStringList();
|
||||
note_text += "传感器数据:";
|
||||
void* pdata = (void *)ddata->data;
|
||||
for (uint8_t i = 0; i < name_list.length(); i++)
|
||||
{
|
||||
note_text += name_list[i]+ ":" + sensor_data_reader(&pdata,type_list[i]) + ' ';
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
object.insert("note_text",QJsonValue(note_text));
|
||||
if (QRandomGenerator::global()->bounded(2)!=0 && is_demo)
|
||||
object.insert("decrypted_text", QJsonValue(QString(zdata.toHex(' ').toUpper())));
|
||||
emit data_send("zigbee_recv_data_view",object);
|
||||
|
@ -353,3 +361,59 @@ void ZigBeeDataResolver::message_parser(QJsonObject message, QString self_addr)
|
|||
data_parser(zf, message["type"] == "demo_recv_data");
|
||||
}
|
||||
}
|
||||
|
||||
QString ZigBeeDataResolver::sensor_data_reader(void **data,QString type)
|
||||
{
|
||||
QString d;
|
||||
uint8_t** pdata = (uint8_t**)(data);
|
||||
if (type.contains("64"))
|
||||
{
|
||||
if(type.contains("u"))
|
||||
d = QString::number(*(uint64_t*)(*data));
|
||||
else
|
||||
d = QString::number(*(int64_t*)(*data));
|
||||
*pdata += sizeof(uint64_t);
|
||||
return d;
|
||||
}
|
||||
else if (type.contains("32"))
|
||||
{
|
||||
if(type.contains("u"))
|
||||
d = QString::number(*(uint32_t*)(*data));
|
||||
else
|
||||
d = QString::number(*(int32_t*)(*data));
|
||||
*pdata += sizeof(uint32_t);
|
||||
return d;
|
||||
}
|
||||
else if (type.contains("16"))
|
||||
{
|
||||
if(type.contains("u"))
|
||||
d = QString::number(*(uint16_t*)(*data));
|
||||
else
|
||||
d = QString::number(*(int16_t*)(*data));
|
||||
*pdata += sizeof(uint16_t);
|
||||
return d;
|
||||
}
|
||||
else if (type.contains("8"))
|
||||
{
|
||||
if(type.contains("u"))
|
||||
d = QString::number(*(uint8_t*)(*data));
|
||||
else
|
||||
d = QString::number(*(int8_t*)(*data));
|
||||
*pdata += sizeof(uint8_t);
|
||||
return d;
|
||||
}
|
||||
else if (type=="float")
|
||||
{
|
||||
d = QString::number(*(float*)(*data), 'g', 1);
|
||||
*pdata += sizeof(float);
|
||||
return d;
|
||||
}
|
||||
else if (type=="double")
|
||||
{
|
||||
d = QString::number(*(double*)(*data), 'g', 1);
|
||||
*pdata += sizeof(double);
|
||||
return d;
|
||||
}
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue