SerialPort and ZigBee: Use QThread and bump to 1.0.2.

This commit is contained in:
Mentalflow 2024-03-03 18:43:26 +08:00
parent 75bee1a451
commit 7bda54063c
Signed by: Mentalflow
GPG Key ID: 5AE68D4401A2EE71
21 changed files with 814 additions and 629 deletions

2
3rdparty/RibbonUI vendored

@ -1 +1 @@
Subproject commit aa3604579b8864efe9e777c7dec96209d7b8ee72
Subproject commit 43240eab1f351a90afdc843119743b0aca4d311c

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
project(ProtocolParser_APP VERSION 0.1 LANGUAGES CXX)
project(ProtocolParser_APP VERSION 1.0.2 LANGUAGES CXX)
add_definitions(-DFRAMELESSHELPER_CORE_NO_DEBUG_OUTPUT)
add_definitions(-DFRAMELESSHELPER_QUICK_NO_DEBUG_OUTPUT)

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.21)
project(ProtocolParser VERSION 1.0.1 LANGUAGES CXX)
project(ProtocolParser VERSION ${CMAKE_PROJECT_VERSION} LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -13,8 +13,8 @@ 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")
set(PROJECT_BUNDLE_NAME ${PROJECT_NAME})
add_definitions(-DPROTOCOLPARSER_VERSION=1,0,1)
set(version_str "${CMAKE_PROJECT_VERSION_MAJOR},${CMAKE_PROJECT_VERSION_MINOR},${CMAKE_PROJECT_VERSION_PATCH}")
add_definitions(-DPROTOCOLPARSER_VERSION=${version_str})
find_package(Qt6 COMPONENTS Quick SerialPort LinguistTools REQUIRED)
@ -24,8 +24,18 @@ set(
include/zigbeeparser.h source/zigbeeparser.cpp source/crypto.cpp include/crypto.h
include/protocol.h source/protocol.cpp include/protocol_data.h
include/config.h source/config.cpp
include/serialdataresolver.h source/serialdataresolver.cpp
include/zigbeedataresolver.h source/zigbeedataresolver.cpp
languages/zh_CN.ts languages/en_US.ts
# dlln3x_handler.h dlln3x_handler.cpp
)
set(
qml_files qml/Main.qml qml/components/RibbonWindow.qml qml/components/ZigBeeFrame.qml
qml/components/RibbonMessageListView.qml qml/components/RibbonMessage.qml
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
)
INCLUDE_DIRECTORIES(dlln3x include)
@ -71,15 +81,16 @@ else ()
)
endif ()
foreach(qmlfile ${qml_files})
string(REPLACE "qml/" "" fixedfile ${qmlfile})
set_source_files_properties(${qmlfile} PROPERTIES QT_RESOURCE_ALIAS ${fixedfile})
endforeach(qmlfile)
qt_add_qml_module(${PROJECT_NAME}
URI ${PROJECT_NAME}
VERSION 1.0
QML_FILES qml/Main.qml qml/components/RibbonWindow.qml qml/components/ZigBeeFrame.qml
qml/components/RibbonMessageListView.qml qml/components/RibbonMessage.qml
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_FILES ${qml_files}
RESOURCE_PREFIX "/qt/qml/"
VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}
)
set_target_properties(${PROJECT_NAME} PROPERTIES

View File

@ -7,7 +7,6 @@ using namespace zigbee_protocol;
DLLN3X::DLLN3X(QObject *parent)
: QObject{parent}
{
}
DLLN3X* DLLN3X::instance(){
@ -60,6 +59,8 @@ ZigbeeFrame DLLN3X::recv(bool non_blocked)
bool DLLN3X::send(ZigbeeFrame zf)
{
if(!_DSerial->isOpen())
return false;
bool status = false;
uint8_t len = zf.size();
if (zf.getSrcPort() < 0x80 || len > 66)
@ -281,7 +282,7 @@ enum DLLN3X::PIN_CONTROL DLLN3X::pin_control(PIN pin, PIN_CONTROL cmd)
void DLLN3X::loop()
{
if (_DSerial->bytesAvailable() > 7 && !_recv_lock) {
if (_DSerial && _DSerial->bytesAvailable() > 7 && !_recv_lock) {
ZigbeeFrame zf = recv();
printf("Message: ");
for (int i = 0; i < zf.size(); i++) {
@ -303,7 +304,8 @@ int DLLN3X::readBytesUntil(uint8_t delimiter, uint8_t* buffer, qint64 maxSize)
{
QByteArray data;
qint64 bytesRead = 0;
if(!_DSerial->isOpen())
return bytesRead;
if (_DSerial->bytesAvailable() || _DSerial->waitForReadyRead(2000))
while (bytesRead < maxSize)
{

View File

@ -17,6 +17,8 @@ private:
const QSerialPort::BaudRate _baud_rate_list[7] = {QSerialPort::Baud2400, QSerialPort::Baud4800, QSerialPort::Baud9600,
QSerialPort::Baud19200, QSerialPort::Baud38400, QSerialPort::Baud57600, QSerialPort::Baud115200};
QSerialPort* _DSerial;
explicit DLLN3X(QObject *parent = nullptr);
Q_DISABLE_COPY_MOVE(DLLN3X)
void (*_callback)(ZigbeeFrame& zf) = nullptr;
int readBytesUntil(uint8_t delimiter, uint8_t* buf, qint64 maxSize);
void _sleep(int msec);
@ -33,7 +35,6 @@ public:
};
enum PIN_CONTROL{ OUT_HIGH = 0x11, OUT_LOW = 0x10, READ_PIN = 0x12};
enum PIN{ DLLN3X_PIN4 = 0x44, DLLN3X_PIN5 = 0x45};
explicit DLLN3X(QObject *parent = nullptr);
static DLLN3X* instance();
void init(QSerialPort* DSerial, uint32_t baudrate = 115200);
ZigbeeFrame recv(bool non_blocked = true);

View File

@ -21,6 +21,7 @@ public:
private:
Config(QString qstrfilename = "");
~Config(void);
Q_DISABLE_COPY_MOVE(Config)
QString m_qstrFileName;
QSettings *m_psetting=nullptr;
};

View File

@ -1,31 +0,0 @@
#ifndef DLLN3X_HANDLER_H
#define DLLN3X_HANDLER_H
#include <QObject>
#include <QQmlEngine>
#include <QSerialPort>
#include "DLLN3X.h"
#include "3rdparty/RibbonUI/lib_source/definitions.h"
class DLLN3X_Handler : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
QML_NAMED_ELEMENT(DLLN3XHandler)
Q_PROPERTY_RW(bool, handle_serial);
Q_PROPERTY_RW(QSerialPort*, serial);
public:
explicit DLLN3X_Handler(QObject *parent = nullptr);
Q_INVOKABLE bool send(QString data);
signals:
void zigbee_recved(QByteArray data, QByteArray sender);
private:
zigbee_protocol::DLLN3X* _zigbee=nullptr;
void zigbee_callback(zigbee_protocol::ZigbeeFrame zframe);
void close();
};
#endif // DLLN3X_HANDLER_H

View File

@ -33,6 +33,7 @@ public:
Q_INVOKABLE void unreg_event(Event* event);
private:
explicit EventsBus(QObject *parent = nullptr);
Q_DISABLE_COPY_MOVE(EventsBus);
QList<Event*> _events;
};

View File

@ -35,6 +35,7 @@ public:
private:
Protocol();
~Protocol();
Q_DISABLE_COPY_MOVE(Protocol)
Config* _config = nullptr;
};
}

View File

@ -0,0 +1,53 @@
#ifndef SERIALDATARESOLVER_H
#define SERIALDATARESOLVER_H
#include <QObject>
#include <QMutex>
#include <QSerialPort>
#include "DLLN3X.h"
class SerialDataResolver : public QObject
{
Q_OBJECT
public:
enum class SendType{
Blank=0,
WithCarriageEnter=1,
WithLineFeed=2,
WithCarriageEnterAndLineFeed=3
};
Q_ENUM(SendType)
void open(QString port_name, QString baudrate, QString databits,
QString parity, QString stopbits);
void close();
bool handled_by_manager();
void handled_by_manager(bool handled_by_manager);
bool recv_hex();
void recv_hex(bool recv_hex);
bool serial_opened();
static SerialDataResolver* instance();
public slots:
void write_data(QString data, SendType type, bool send_hex);
private:
explicit SerialDataResolver(QObject *parent = nullptr);
~SerialDataResolver();
Q_DISABLE_COPY_MOVE(SerialDataResolver)
void readHandler();
void zigbee_callback(zigbee_protocol::ZigbeeFrame zframe);
void serial_opened(bool serial_opened);
zigbee_protocol::DLLN3X* _zigbee=nullptr;
QSerialPort* _serial=nullptr;
bool _quit = false, _handled_by_manager = false, _recv_hex = false,
_serial_opened = false,_serial_want_open = false;
signals:
void error(const QString &s);
void recved(const QByteArray &data);
void recved_zframe(zigbee_protocol::ZigbeeFrame zframe);
void handled_by_managerChanged();
void recv_hexChanged();
void serial_openedChanged();
};
#endif // SERIALDATARESOLVER_H

View File

@ -5,9 +5,9 @@
#include <QQmlEngine>
#include <QTimer>
#include <QSerialPort>
#include "DLLN3X.h"
#include <QThread>
#include "serialdataresolver.h"
#include "../3rdparty/RibbonUI/lib_source/definitions.h"
#include "zigbeeparser.h"
#include "eventsbus.h"
class SerialPortManager : public QObject
@ -27,10 +27,8 @@ public:
WithCarriageEnterAndLineFeed=3
};
Q_ENUM(SendType)
Q_PROPERTY_RW(int, available_ports_count)
Q_PROPERTY_RW(bool, opened)
Q_PROPERTY_RW(bool, closed)
Q_PROPERTY_RW(bool, readyRead)
Q_PROPERTY_RW(bool, handledBymanager)
Q_PROPERTY_RW(bool, recv_hex)
@ -41,25 +39,30 @@ public:
static SerialPortManager* instance();
static SerialPortManager* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();}
QList<QString> available_ports();
Q_INVOKABLE bool open(QString port_name, QString baudrate, QString databits,
Q_INVOKABLE void open(QString port_name, QString baudrate, QString databits,
QString parity, QString stopbits);
Q_INVOKABLE void close();
Q_INVOKABLE QByteArray read();
Q_INVOKABLE bool write(QString data);
Q_INVOKABLE QSerialPort* get_serial();
Q_INVOKABLE void write(QString data);
signals:
void available_portsChanged(QList<QString> ports);
void recved(QString data);
void serial_open(QString port_name, QString baudrate, QString databits,
QString parity, QString stopbits);
void serial_close();
void serial_write(QString data, SerialDataResolver::SendType type, bool send_hex);
private:
explicit SerialPortManager(QObject *parent = nullptr);
~SerialPortManager();
Q_DISABLE_COPY_MOVE(SerialPortManager)
QTimer _serial_port_scanner;
QSerialPort _serial_port;
zigbee_protocol::DLLN3X* _zigbee=nullptr;
void _ready_for_read();
void zigbee_callback(zigbee_protocol::ZigbeeFrame zframe);
Event _event;
EventsBus* _bus = nullptr;
SerialDataResolver* _resolver = nullptr;
QThread* _thread = nullptr;
private slots:
void zigbee_callback(zigbee_protocol::ZigbeeFrame zframe);
};
#endif // SERIALPORTMANAGER_H

View File

@ -0,0 +1,32 @@
#ifndef ZIGBEEDATARESOLVER_H
#define ZIGBEEDATARESOLVER_H
#include <QObject>
#include <QJsonObject>
#include "zigbeeframe.h"
#include "protocol.h"
class ZigBeeDataResolver : public QObject
{
Q_OBJECT
public:
static ZigBeeDataResolver* instance();
public slots:
void message_parser(QJsonObject message, QString self_addr, QList<uint16_t> allow_list, QList<uint16_t> deny_list, QList<uint16_t> wait_queue);
private:
explicit ZigBeeDataResolver(QObject *parent = nullptr);
~ZigBeeDataResolver();
Q_DISABLE_COPY_MOVE(ZigBeeDataResolver)
void data_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo = false);
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);
zigbee_protocol::Protocol* _protocol = nullptr;
QString _self_addr;
QMap<uint16_t, QPair<device,device>> nodes;
QList<uint16_t> _allow_list,_deny_list,_wait_queue;
signals:
void data_send(QString type, QJsonObject data, QList<uint16_t> allow_list, QList<uint16_t> deny_list, QList<uint16_t> wait_queue);
};
#endif // ZIGBEEDATARESOLVER_H

View File

@ -11,6 +11,7 @@
#include "protocol.h"
#include "eventsbus.h"
#include "config.h"
#include "zigbeedataresolver.h"
class ZigBeeParser : public QObject
{
@ -30,24 +31,25 @@ public:
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 data_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo = false);
void message_parser(QJsonObject message);
static ZigBeeParser* instance();
static ZigBeeParser* create(QQmlEngine *qmlEngine, QJSEngine *jsEngine){return instance();}
void message_parser(QJsonObject message);
signals:
void hmac_verify_keyChanged();
void pre_hmac_verify_keyChanged();
void message_recved(QJsonObject message, QString self_addr, QList<uint16_t> allow_list, QList<uint16_t> deny_list, QList<uint16_t> wait_queue);
private:
explicit ZigBeeParser(QObject *parent = nullptr);
~ZigBeeParser();
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);
QMap<uint16_t, QPair<device,device>> nodes;
Q_DISABLE_COPY_MOVE(ZigBeeParser)
Event _event;
EventsBus *_bus = nullptr;
zigbee_protocol::Protocol* _protocol = nullptr;
QString _self_addr = QString::number(DEFAULT_SELF_ADDR,16).toUpper();
Config* _config = nullptr;
ZigBeeDataResolver* _resolver = nullptr;
QThread *_thread = nullptr;
private slots:
void bus_data_send(QString type, QJsonObject data, QList<uint16_t> allow_list, QList<uint16_t> deny_list, QList<uint16_t> wait_queue);
};
#endif // ZIGBEEPARSER_H

View File

@ -32,17 +32,14 @@ Item{
}
Connections{
target: SerialPortManager
function onReadyReadChanged(){
if (control.handle_serial && SerialPortManager.readyRead)
function onRecved(data)
{
var d = SerialPortManager.read()
serial_view.message_model.append({
note_text: d.toString(),
time: Qt.formatDateTime(new Date(), "yyyy-MM-dd hh:mm:ss.zzz"),
note_text: data.toString(),
recieved: true,
})
}
}
}
}
RibbonRectangle{
@ -192,6 +189,7 @@ Item{
: SerialPortManager.WithCarriageEnterAndLineFeed
SerialPortManager.write(message_sender_textbox.text)
serial_view.message_model.append({
time: Qt.formatDateTime(new Date(), "yyyy-MM-dd hh:mm:ss.zzz"),
note_text: message_sender_textbox.text,
recieved: false,
})

View File

@ -37,7 +37,7 @@ RibbonTabBar {
}
icon_source: RibbonIcons.SerialPort
currentIndex: 0
enabled: SerialPortManager.closed
enabled: !SerialPortManager.opened
Connections{
target: SerialPortManager
function onAvailable_portsChanged(ports){
@ -70,7 +70,7 @@ RibbonTabBar {
ListElement { text: "57600" }
ListElement { text: "115200" }
}
enabled: SerialPortManager.closed
enabled: !SerialPortManager.opened
currentIndex: 6
icon_source: RibbonIcons.NumberSymbol
}
@ -91,7 +91,7 @@ RibbonTabBar {
ListElement { text: "7" }
ListElement { text: "8" }
}
enabled: SerialPortManager.closed
enabled: !SerialPortManager.opened
currentIndex: 3
icon_source: RibbonIcons.DataWhisker
}
@ -121,7 +121,7 @@ RibbonTabBar {
ListElement { text: qsTr("EVEN") }
ListElement { text: qsTr("ODD") }
}
enabled: SerialPortManager.closed
enabled: !SerialPortManager.opened
icon_source: RibbonIcons.DataWhisker
}
}
@ -140,7 +140,7 @@ RibbonTabBar {
ListElement { text: "1.5" }
ListElement { text: "2" }
}
enabled: SerialPortManager.closed
enabled: !SerialPortManager.opened
icon_source: RibbonIcons.DataWhisker
}
}
@ -150,12 +150,13 @@ RibbonTabBar {
Layout.alignment: Qt.AlignVCenter
icon_source: RibbonIcons.Open
show_tooltip: false
text: SerialPortManager.closed ? qsTr("打开串口") : qsTr("关闭串口")
onClicked: SerialPortManager.open(serial_port_combo.currentText,
text: SerialPortManager.opened ? qsTr("关闭串口") : qsTr("打开串口")
onClicked: !SerialPortManager.opened ? SerialPortManager.open(serial_port_combo.currentText,
serial_baudrate_combo.currentText,
serial_databits_combo.currentText,
serial_parity_combo.currentText,
serial_stopbits_combo.currentText)
serial_stopbits_combo.currentText) :
SerialPortManager.close()
}
}
}

View File

@ -1,56 +0,0 @@
#include "dlln3x_handler.h"
DLLN3X_Handler::DLLN3X_Handler(QObject *parent)
: QObject{parent}
{
_zigbee = zigbee_protocol::DLLN3X::instance();
handle_serial(false);
serial(nullptr);
connect(this, &DLLN3X_Handler::handle_serialChanged, this, [=](){
if (_handle_serial&&_serial!=nullptr)
{
_zigbee->init(_serial, _serial->baudRate());
connect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &DLLN3X_Handler::zigbee_callback);
connect(_serial, &QSerialPort::readyRead, _zigbee, &zigbee_protocol::DLLN3X::loop);
connect(_serial, &QSerialPort::aboutToClose, this, &DLLN3X_Handler::close);
}
else
{
close();
}
});
}
void DLLN3X_Handler::zigbee_callback(zigbee_protocol::ZigbeeFrame zframe)
{
QByteArray zf = QByteArray((char *)zframe.data(),zframe.size());
QByteArray hex = zf.toHex(' ');
QByteArray data = hex.toUpper();
QByteArray num = QByteArray::number(zframe.getRemoteAddr(),16);
QByteArray sender = num.toUpper();
emit zigbee_recved(data, sender);
}
void DLLN3X_Handler::close()
{
disconnect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &DLLN3X_Handler::zigbee_callback);
disconnect(_serial, &QSerialPort::readyRead, _zigbee, &zigbee_protocol::DLLN3X::loop);
disconnect(_serial, &QSerialPort::aboutToClose, this, &DLLN3X_Handler::close);
}
bool DLLN3X_Handler::send(QString data)
{
if (_handle_serial)
{
QByteArray bdata;
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
zigbee_protocol::ZigbeeFrame zf(bdata.data(),bdata.length());
return _zigbee->send(zf);
}
else
return false;
}

View File

@ -35,7 +35,7 @@ int main(int argc, char *argv[])
#ifdef RIBBONUI_BUILD_STATIC_LIB
engine.addImportPath("qrc:/");
#endif
const QUrl url(u"qrc:/ProtocolParser/qml/Main.qml"_qs);
const QUrl url(u"qrc:/qt/qml/ProtocolParser/Main.qml"_qs);
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)

View File

@ -0,0 +1,246 @@
#include "serialdataresolver.h"
#include "protocol.h"
#include <QThread>
SerialDataResolver::SerialDataResolver(QObject *parent)
: QObject{parent}
{
//qDebug()<<__FUNCTION__<<"Thread: "<<QThread::currentThread();
_serial = new QSerialPort(this);
_zigbee = zigbee_protocol::DLLN3X::instance();
recv_hex(false);
handled_by_manager(true);
connect(this, &SerialDataResolver::handled_by_managerChanged, this, [=](){
if (!_handled_by_manager && _serial->isOpen())
{
_zigbee->init(_serial, _serial->baudRate());
zigbee_protocol::Protocol::getInstance()->self_addr = _zigbee->read_addr();
connect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialDataResolver::zigbee_callback);
}
else
{
disconnect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialDataResolver::zigbee_callback);
}
});
}
SerialDataResolver::~SerialDataResolver()
{
close();
delete _serial;
}
SerialDataResolver* SerialDataResolver::instance()
{
//qDebug()<<__FUNCTION__<<"Thread: "<<QThread::currentThread();
static QMutex mutex;
QMutexLocker locker(&mutex);
static SerialDataResolver *singleton = nullptr;
if (!singleton) {
singleton = new SerialDataResolver();
}
return singleton;
}
void SerialDataResolver::open(QString port_name, QString baudrate, QString databits,
QString parity, QString stopbits)
{
//qDebug()<<__FUNCTION__<<"Thread: "<<QThread::currentThread();
QMutex mutex;
const QMutexLocker locker(&mutex);
_serial->setPortName(port_name);
if (!_serial->open(QIODevice::ReadWrite))
{
emit error(tr("串口%1打开失败, 错误代码:%2")
.arg(port_name).arg(_serial->error()));
return;
}
else
{
serial_opened(true);
_serial->setBaudRate(baudrate.toInt());
switch (databits.toInt())
{
case 5:
_serial->setDataBits( QSerialPort::Data5 ); // 设置数据位(数据位为5位)
break;
case 6:
_serial->setDataBits( QSerialPort::Data6 ); // 设置数据位(数据位为6位)
break;
case 7:
_serial->setDataBits( QSerialPort::Data7 ); // 设置数据位(数据位为7位)
break;
case 8:
_serial->setDataBits( QSerialPort::Data8 ); // 设置数据位(数据位为8位)
break;
default:
break;
}
if (parity=="NONE")
{
_serial->setParity( QSerialPort::NoParity ); // 设置校验位(无校验位)
}
else if (parity=="EVEN")
{
_serial->setParity( QSerialPort::EvenParity ); // 设置校验位(奇校验位)
}
else
{
_serial->setParity( QSerialPort::OddParity ); // 设置校验位(偶校验位)
}
if (stopbits=="1")
{
_serial->setStopBits( QSerialPort::OneStop ); // 设置停止位(停止位为1)
}
else if (stopbits=="1.5")
{
_serial->setStopBits( QSerialPort::OneAndHalfStop ); // 设置停止位(停止位为1.5)
}
else
{
_serial->setStopBits( QSerialPort::TwoStop ); // 设置停止位(停止位为2)
}
_serial->setFlowControl( QSerialPort::NoFlowControl ); // 设置流控制(无数据流控制)
connect(_serial,&QSerialPort::aboutToClose, this, &SerialDataResolver::close);
connect(_serial,&QSerialPort::readyRead, this, &SerialDataResolver::readHandler);
if (!_handled_by_manager)
{
_zigbee->init(_serial, _serial->baudRate());
zigbee_protocol::Protocol::getInstance()->self_addr = _zigbee->read_addr();
connect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialDataResolver::zigbee_callback);
}
}
}
bool SerialDataResolver::handled_by_manager()
{
return _handled_by_manager;
}
void SerialDataResolver::handled_by_manager(bool handled_by_manager)
{
QMutex mutex;
const QMutexLocker locker(&mutex);
_handled_by_manager = handled_by_manager;
emit handled_by_managerChanged();
}
bool SerialDataResolver::recv_hex()
{
return _recv_hex;
}
void SerialDataResolver::recv_hex(bool recv_hex)
{
QMutex mutex;
const QMutexLocker locker(&mutex);
_recv_hex = recv_hex;
emit recv_hexChanged();
}
bool SerialDataResolver::serial_opened()
{
return _serial_opened;
}
void SerialDataResolver::serial_opened(bool serial_opened)
{
QMutex mutex;
const QMutexLocker locker(&mutex);
_serial_opened = serial_opened;
emit serial_openedChanged();
}
void SerialDataResolver::readHandler()
{
//qDebug()<<__FUNCTION__<<"Thread: "<<QThread::currentThread();
if (_handled_by_manager)
{
QByteArray bdata;
if (_serial->isOpen() && _handled_by_manager)
{
while(true){
bdata += _serial->readAll();
if (!_serial->waitForReadyRead(20))
break;
}
if (_recv_hex)
{
emit recved(bdata.toHex(' ').toUpper());
}
else
emit recved(bdata);
}
else
emit recved(bdata);
}
else
_zigbee->loop();
}
void SerialDataResolver::close()
{
//qDebug()<<__FUNCTION__<<"Thread: "<<QThread::currentThread();
serial_opened(false);
disconnect(_serial,&QSerialPort::aboutToClose,this,&SerialDataResolver::close);
disconnect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialDataResolver::zigbee_callback);
if(_serial->isOpen())
{
_serial->clear();
_serial->close();
}
}
void SerialDataResolver::write_data(QString data, SendType type, bool send_hex)
{
//qDebug()<<__FUNCTION__<<"Thread: "<<QThread::currentThread();
QByteArray bdata;
if (!_serial->isOpen())
return;
if (!_handled_by_manager)
{
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
zigbee_protocol::ZigbeeFrame zf;
zf.load_package((uint8_t*)bdata.data(),bdata.length());
_zigbee->send(zf);
return;
}
if(send_hex)
{
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
}
else
bdata = data.toUtf8();
switch(type)
{
case SendType::WithCarriageEnter:
bdata += "\n";
break;
case SendType::WithLineFeed:
bdata += "\r";
break;
case SendType::WithCarriageEnterAndLineFeed:
bdata += "\r\n";
break;
case SendType::Blank:
default:
break;
}
_serial->write(bdata);
_serial->flush();
return;
}
void SerialDataResolver::zigbee_callback(zigbee_protocol::ZigbeeFrame zframe)
{
emit recved_zframe(zframe);
}

View File

@ -1,48 +1,62 @@
#include "serialportmanager.h"
#include <QSerialPortInfo>
#include <QMutex>
#include "zigbeeparser.h"
SerialPortManager::SerialPortManager(QObject *parent)
: QObject{parent}
{
_zigbee = zigbee_protocol::DLLN3X::instance();
_resolver = SerialDataResolver::instance();
_thread = new QThread();
_resolver->moveToThread(_thread);
_bus = EventsBus::instance();
ZigBeeParser::instance(); // 让ZigBeeParser在QML引擎中实例化
_event.type("serial_port");
_bus->reg_event(&_event);
closed(true);
opened(false);
handledBymanager(true);
recv_hex(false);
send_hex(false);
send_type(SendType::Blank);
_serial_port_scanner.setInterval(1000);
_serial_port_scanner.start();
connect(&_serial_port_scanner, &QTimer::timeout, this, [=](){
available_ports();
});
connect(this, &SerialPortManager::handledBymanagerChanged, this, [=](){
if (!_handledBymanager && _serial_port.isOpen())
{
_zigbee->init(&_serial_port, _serial_port.baudRate());
zigbee_protocol::Protocol::getInstance()->self_addr = _zigbee->read_addr();
connect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialPortManager::zigbee_callback);
}
else
{
disconnect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialPortManager::zigbee_callback);
}
});
connect(&_event, &Event::triggered, this, [=](QJsonObject data){
write(data["text"].toString());
});
connect(_resolver,&SerialDataResolver::recved, this, [=](const QByteArray &data){
emit recved(data);
});
connect(_resolver,&SerialDataResolver::recved_zframe, this, &SerialPortManager::zigbee_callback);
connect(this, &SerialPortManager::recv_hexChanged, this, [=](){
_resolver->recv_hex(recv_hex());
});
connect(this, &SerialPortManager::handledBymanagerChanged, this, [=](){
_resolver->handled_by_manager(handledBymanager());
});
connect(_resolver,&SerialDataResolver::serial_openedChanged, this, [=](){
opened(_resolver->serial_opened());
});
connect(this, &SerialPortManager::serial_close, _resolver, &SerialDataResolver::close);
connect(this, &SerialPortManager::serial_open, _resolver, &SerialDataResolver::open);
connect(this, &SerialPortManager::serial_write, _resolver, &SerialDataResolver::write_data);
connect(_thread, &QThread::finished, this, [=](){
_thread->deleteLater();
_resolver->deleteLater();
});
_serial_port_scanner.setInterval(1000);
_serial_port_scanner.start();
_thread->start();
}
SerialPortManager::~SerialPortManager()
{
close();
_bus->unreg_event(&_event);
if(_thread->isRunning())
{
_thread->quit();
}
}
SerialPortManager* SerialPortManager::instance(){
@ -68,164 +82,20 @@ QList<QString> SerialPortManager::available_ports(){
return newPortStringList;
}
bool SerialPortManager::open(QString port_name, QString baudrate, QString databits,
void SerialPortManager::open(QString port_name, QString baudrate, QString databits,
QString parity, QString stopbits)
{
_serial_port.setPortName(port_name);
if (_serial_port.isOpen())
{
close();
return false;
}
else
{
if (_serial_port.open(QIODevice::ReadWrite))
{
_serial_port.setBaudRate(baudrate.toInt());
switch (databits.toInt())
{
case 5:
_serial_port.setDataBits( QSerialPort::Data5 ); // 设置数据位(数据位为5位)
break;
case 6:
_serial_port.setDataBits( QSerialPort::Data6 ); // 设置数据位(数据位为6位)
break;
case 7:
_serial_port.setDataBits( QSerialPort::Data7 ); // 设置数据位(数据位为7位)
break;
case 8:
_serial_port.setDataBits( QSerialPort::Data8 ); // 设置数据位(数据位为8位)
break;
default:
return false;
}
if (parity=="NONE")
{
_serial_port.setParity( QSerialPort::NoParity ); // 设置校验位(无校验位)
}
else if (parity=="EVEN")
{
_serial_port.setParity( QSerialPort::EvenParity ); // 设置校验位(奇校验位)
}
else
{
_serial_port.setParity( QSerialPort::OddParity ); // 设置校验位(偶校验位)
}
if (stopbits=="1")
{
_serial_port.setStopBits( QSerialPort::OneStop ); // 设置停止位(停止位为1)
}
else if (stopbits=="1.5")
{
_serial_port.setStopBits( QSerialPort::OneAndHalfStop ); // 设置停止位(停止位为1.5)
}
else
{
_serial_port.setStopBits( QSerialPort::TwoStop ); // 设置停止位(停止位为2)
}
_serial_port.setFlowControl( QSerialPort::NoFlowControl ); // 设置流控制(无数据流控制)
// 当下位机中有数据发送过来时就会响应这个槽函数
connect(&_serial_port,&QSerialPort::readyRead,this,&SerialPortManager::_ready_for_read);
connect(&_serial_port,&QSerialPort::aboutToClose,this,&SerialPortManager::close);
opened(true);
closed(false);
return true;
}
else
return false;
}
emit serial_open(port_name,baudrate,databits,parity,stopbits);
}
void SerialPortManager::close()
{
disconnect(&_serial_port,&QSerialPort::aboutToClose,this,&SerialPortManager::close);
disconnect(&_serial_port,&QSerialPort::readyRead,this,&SerialPortManager::_ready_for_read);
disconnect(_zigbee, &zigbee_protocol::DLLN3X::recved, this, &SerialPortManager::zigbee_callback);
if(_opened)
{
_serial_port.clear();
_serial_port.close();
}
readyRead(false);
closed(true);
opened(false);
emit serial_close();
}
QByteArray SerialPortManager::read()
void SerialPortManager::write(QString data)
{
QByteArray bdata;
if (_opened && _handledBymanager)
{
readyRead(false);
while(true){
bdata += _serial_port.readAll();
if (!_serial_port.waitForReadyRead(20))
break;
}
if (_recv_hex)
{
return bdata.toHex(' ').toUpper();
}
else
return bdata;
}
else
return bdata;
}
void SerialPortManager::_ready_for_read()
{
if (_handledBymanager)
readyRead(true);
if (!_handledBymanager)
_zigbee->loop();
}
bool SerialPortManager::write(QString data)
{
if (_closed)
return false;
if ( !_handledBymanager)
{
QByteArray bdata;
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
zigbee_protocol::ZigbeeFrame zf;
zf.load_package((uint8_t*)bdata.data(),bdata.length());
return _zigbee->send(zf);
}
QByteArray bdata;
if(_send_hex)
{
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
}
else
bdata = data.toUtf8();
switch(_send_type)
{
case SendType::WithCarriageEnter:
bdata += "\n";
break;
case SendType::WithLineFeed:
bdata += "\r";
break;
case SendType::WithCarriageEnterAndLineFeed:
bdata += "\r\n";
break;
case SendType::Blank:
default:
break;
}
bool status = _serial_port.write(bdata);
status = _serial_port.flush();
return status;
emit serial_write(data,static_cast<SerialDataResolver::SendType>(send_type()),send_hex());
}
void SerialPortManager::zigbee_callback(zigbee_protocol::ZigbeeFrame zframe)
@ -234,16 +104,7 @@ void SerialPortManager::zigbee_callback(zigbee_protocol::ZigbeeFrame zframe)
QByteArray zf = QByteArray((char *)zframe.data(),zframe.size());
QByteArray hex = zf.toHex(' ');
QByteArray data = hex.toUpper();
readyRead(false);
object.insert("data_hex", QJsonValue(QString(data)));
object.insert("type","zigbee_raw_data");
_bus->push_data("zigbee_parser", object);
}
QSerialPort* SerialPortManager::get_serial()
{
if (!_handledBymanager)
return &_serial_port;
else
return nullptr;
}

View File

@ -0,0 +1,325 @@
#include "zigbeedataresolver.h"
#include "crypto.h"
#include <QRandomGenerator>
#include <QMutex>
ZigBeeDataResolver::ZigBeeDataResolver(QObject *parent)
: QObject{parent}
{
_protocol = zigbee_protocol::Protocol::getInstance();
}
ZigBeeDataResolver::~ZigBeeDataResolver()
{
}
ZigBeeDataResolver* ZigBeeDataResolver::instance()
{
static QMutex mutex;
QMutexLocker locker(&mutex);
static ZigBeeDataResolver *singleton = nullptr;
if (!singleton) {
singleton = new ZigBeeDataResolver();
}
return singleton;
}
void ZigBeeDataResolver::data_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
src_port_parser(zframe,is_demo);
des_port_parser(zframe, is_demo);
remote_addr_parser(zframe, is_demo);
}
void ZigBeeDataResolver::src_port_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
switch (zframe.getSrcPort()) {
case 0x81:
break;
default:
break;
}
}
void ZigBeeDataResolver::des_port_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
if (zframe.size() <= 7)
{
qDebug()<<"ZigBee: recved package is corrupted, dropped.";
return;
}
void *frame = nullptr;
base_frame *bframe=nullptr;
hmac_frame *hframe=nullptr;
crypto_zdata_frame *czdata = nullptr;
data_frame *ddata = nullptr;
QByteArray zdata((char *)zframe.data(), zframe.size());
QString sender = QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper();
device temp,self;
QPair<device,device>* node = nullptr;
memset(&temp,0,sizeof(temp));
memset(&temp,0,sizeof(self));
self.addr = _protocol->self_addr;
if (!nodes.contains(((base_frame *)zframe.getData().data())->ori_addr))
{
temp.addr=((base_frame *)zframe.getData().data())->ori_addr;
temp.id = 0;
temp.online = 1;
temp.rand_num = 0;
temp.verified = 0;
nodes.insert(temp.addr,qMakePair(temp,self));
}
node = &nodes[((base_frame *)zframe.getData().data())->ori_addr];
bframe = (base_frame*)zframe.getData().data();
if (is_demo || bframe->des_addr == _protocol->self_addr && (node->first.id == 0||bframe->reset_num==0xDD||((bframe->id > node->first.id && bframe->id<=BASE_FRAME_RESET_NUM))))
{
node->first.addr = bframe->ori_addr;
node->first.id = bframe->id;
node->first.rand_num = bframe->rand_num;
frame = (void*)bframe->data;
}
else
{
QJsonObject object;
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("请注意节点0x"+QString::number(node->first.addr,16).toUpper()+"发送的该数据包损坏"));
object.insert("recieved", true);
object.insert("sender", sender);
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
return;
}
switch (zframe.getDesPort()) {
case 0x81:
{
hframe = (hmac_frame*)frame;
QJsonObject object;
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("sender", sender);
object.insert("note_text",QJsonValue("收到节点0x"+ sender +"发送的验证信息"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
if (_allow_list.contains(node->first.addr))
{
u8 hmac[33]="";
QByteArray key = QByteArray::fromHex(_protocol->hmac_verify_key.toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(),16,&hframe->value,1,hmac);
if (_protocol->bytecmp(hframe->hmac,hmac,32))
{
new_data_frame(15) data;
memset(&data, 0, sizeof(data));
_protocol->protocal_wrapper((data_frame *)&data, 0, 10, (u8 *)"Identified", 0);
node->first.verified = 1;
new_base_frame(15 + DATA_FRAME_PREFIX_LEN + BASE_FRAME_PREFIX_LEN) bframe;
memset(&bframe, 0, sizeof(bframe));
_protocol->base_frame_maker(&data, (base_frame *)&bframe, node->first.addr,&node->second);
zigbee_protocol::ZigbeeFrame zf(zframe.getSrcPort(),zframe.getDesPort(),zframe.getRemoteAddr(),(uint8_t *)&bframe,bframe.length);
QByteArray bdata((char *)&bframe, bframe.length);
QByteArray zdata((char *)zf.data(), zf.size());
QJsonObject object;
object.insert("baseframe_data",QJsonValue(QString(bdata.toHex(' ').toUpper())));
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("向0x"+QString::number(node->first.addr,16).toUpper()+"节点发送验证通过回复信息"));
object.insert("recieved", false);
object.insert("sender", QString::number(_protocol->self_addr,16).toUpper());
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
if(!is_demo)
emit data_send("serial_port",object,_allow_list,_deny_list,_wait_queue);
}
else
{
u8 hmac[33]="";
QJsonObject object;
QByteArray latest_key = QByteArray::fromHex(_protocol->hmac_verify_key.toLatin1());
for (auto key_str : _protocol->pre_hmac_verify_key)
{
QByteArray key = QByteArray::fromHex(key_str.toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(),16,&hframe->value,1,hmac);
if (_protocol->bytecmp(hframe->hmac,hmac,32))
{
zigbee_protocol::ZigbeeFrame zf(0x82,0x82,node->first.addr);
new_crypto_zdata_frame(32) zdata;
memset(&zdata, 0, sizeof(zdata));
_protocol->zigbee_data_encrypt((u8*)latest_key.data(), 16, (crypto_zdata_frame *)&zdata, Crypto::SM4_encrypt, key_str);
new_base_frame(sizeof(zdata) + BASE_FRAME_PREFIX_LEN) bframe;
memset(&bframe, 0, sizeof(bframe));
_protocol->base_frame_maker(&zdata, (base_frame *)&bframe, node->first.addr, &node->second);
zf.setData((u8 *)&bframe, bframe.length);
QByteArray bdata((char *)&bframe, bframe.length);
QByteArray zfdata((char *)zf.data(), zf.size());
object.insert("baseframe_data",QJsonValue(QString(bdata.toHex(' ').toUpper())));
object.insert("text",QJsonValue(QString(zfdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("节点0x"+QString::number(node->first.addr,16).toUpper()+"正在使用旧密钥,发送密钥更新指令"));
object.insert("recieved", false);
object.insert("sender", QString::number(_protocol->self_addr,16).toUpper());
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
if(!is_demo)
emit data_send("serial_port",object,_allow_list,_deny_list,_wait_queue);
return;
}
}
object.insert("note_text",QJsonValue("节点0x"+QString::number(node->first.addr,16).toUpper()+"验证不通过,请考虑移出认证列表"));
object.insert("recieved", true);
object.insert("sender", sender);
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
}
}
else if(_deny_list.contains(node->first.addr))
{
object.insert("sender", sender);
object.insert("text","");
object.insert("note_text",QJsonValue("节点0x"+QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper()+"被禁止接入"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
}
else {
if (!_wait_queue.contains(node->first.addr))
{
_wait_queue.append(node->first.addr);
object.insert("sender", sender);
object.insert("text","");
object.insert("note_text",QJsonValue("节点0x"+QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper()+"进入等待队列"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
}
else
{
object.insert("sender", sender);
object.insert("text","");
object.insert("note_text",QJsonValue("节点0x"+QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper()+"已在等待队列"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
emit data_send("zigbee_identify_data_view",object,_allow_list,_deny_list,_wait_queue);
}
}
break;
}
case 0x82:
{
}
case 0x83:
{
QJsonObject object;
if (node->first.verified)
{
zigbee_protocol::ZigbeeFrame dzf = zframe;
new_data_frame(72) ndata;
uint8_t data_len = 0;
memset(&ndata,0,sizeof(ndata));
if (*(u16 *)frame == CRYPTO_ZDATA_FRAME_HEAD)
{
czdata = (crypto_zdata_frame*)frame;
_protocol->zigbee_data_dectypt((uint8_t*)&ndata, &data_len, czdata, Crypto::SM4_decrypt);
dzf.setData((char*)&ndata,ndata.data_length + DATA_FRAME_PREFIX_LEN);
zdata = QByteArray((char *)dzf.data(), dzf.size());
object.insert("decrypted_text", QJsonValue(QString(zdata.toHex(' ').toUpper())));
}
object.insert("sender", sender);
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("收到节点0x"+sender+"发送的数据"));
object.insert("recieved", true);
object.insert("type","zigbee_recv_data");
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,_allow_list,_deny_list,_wait_queue);
}
else
{
object.insert("sender", sender);
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("收到节点0x"+sender+"发送的数据,但节点并未认证"));
object.insert("recieved", true);
object.insert("type","zigbee_recv_data");
emit data_send("zigbee_recv_data_view",object,_allow_list,_deny_list,_wait_queue);
node->second.id=0;
new_data_frame(5) dframe;
memset(&dframe,0,sizeof (dframe));
_protocol->protocal_wrapper((data_frame *)&dframe, 0, 5, (u8 *)"RESET", false);
new_base_frame(5 + DATA_FRAME_PREFIX_LEN + BASE_FRAME_PREFIX_LEN) bframe;
memset(&bframe, 0, sizeof(bframe));
_protocol->base_frame_maker(&dframe, (base_frame *)&bframe, node->first.addr,&node->second);
zigbee_protocol::ZigbeeFrame zf(0x83,0x83,node->first.addr,(char *)&bframe,bframe.length);
QByteArray zfdata((char *)zf.data(),zf.size());
QJsonObject object;
object.insert("sender", QString::number(_protocol->self_addr,16).toUpper());
object.insert("text",QJsonValue(QString(zfdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("向节点0x"+sender+"发送重置命令"));
object.insert("recieved", false);
object.insert("type","zigbee_recv_data");
emit data_send("zigbee_recv_data_view",object,_allow_list,_deny_list,_wait_queue);
}
}
default:
break;
}
}
void ZigBeeDataResolver::remote_addr_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
switch (zframe.getRemoteAddr()) {
case 0xAAAA:
break;
default:
break;
}
}
void ZigBeeDataResolver::message_parser(QJsonObject message, QString self_addr, QList<uint16_t> allow_list, QList<uint16_t> deny_list, QList<uint16_t> wait_queue)
{
_self_addr = self_addr;
_allow_list = allow_list;
_deny_list = deny_list;
_wait_queue = wait_queue;
if (message["type"] == "demo_verify_request")
{
hmac_frame frame;
frame.value = QRandomGenerator::global()->bounded(256);
frame.head = HMAC_FRAME_HEAD;
frame.length = 32 + HMAC_FRAME_PREFIX_LEN;
QByteArray key = QByteArray::fromHex(_protocol->hmac_verify_key.toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(), 16, &frame.value, 1, frame.hmac);
new_base_frame(50 + BASE_FRAME_PREFIX_LEN) bframe;
device test;
test.addr = 0x5656;
_protocol->base_frame_maker(&frame, (base_frame *)&bframe, _protocol->self_addr, &test);
zigbee_protocol::ZigbeeFrame zf(0x81,0x81,0x5656,(char*)&bframe,bframe.length);
data_parser(zf, true);
}
if (message["type"] == "demo_verify_key_update")
{
hmac_frame frame;
frame.value = QRandomGenerator::global()->bounded(256);
frame.head = HMAC_FRAME_HEAD;
frame.length = 32 + HMAC_FRAME_PREFIX_LEN;
QByteArray key = QByteArray::fromHex(_protocol->pre_hmac_verify_key[QRandomGenerator::global()->bounded(_protocol->pre_hmac_verify_key.length())].toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(), 16, &frame.value, 1, frame.hmac);
new_base_frame(50 + BASE_FRAME_PREFIX_LEN) bframe;
device test;
test.addr = 0x5656;
_protocol->base_frame_maker(&frame, (base_frame *)&bframe, _protocol->self_addr, &test);
zigbee_protocol::ZigbeeFrame zf(0x81,0x81,0x5656,(char*)&bframe,bframe.length);
data_parser(zf, true);
}
if (message["type"] == "demo_recv_data" || message["type"] == "zigbee_raw_data")
{
QString data = message["data_hex"].toString();
QByteArray bdata;
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
zigbee_protocol::ZigbeeFrame zf;
zf.load_package((uint8_t*)bdata.data(),bdata.length());
data_parser(zf, message["type"] == "demo_recv_data");
}
}

View File

@ -1,23 +1,38 @@
#include "zigbeeparser.h"
#include "crypto.h"
#include <QMutex>
#include <QThread>
#include <QRandomGenerator>
ZigBeeParser::ZigBeeParser(QObject *parent)
: QObject{parent}
{
_config = Config::instance();
_protocol = zigbee_protocol::Protocol::getInstance();
_thread = new QThread();
_resolver = ZigBeeDataResolver::instance();
_resolver->moveToThread(_thread);
_config = Config::instance();
_bus = EventsBus::instance();
_event.type("zigbee_parser");
_bus->reg_event(&_event);
connect(&_event,&Event::triggered,this,&ZigBeeParser::message_parser);
connect(this, &ZigBeeParser::message_recved, _resolver, &ZigBeeDataResolver::message_parser);
connect(_resolver, &ZigBeeDataResolver::data_send, this, &ZigBeeParser::bus_data_send);
connect(_thread, &QThread::finished, this, [=](){
_thread->deleteLater();
_resolver->deleteLater();
});
_thread->start();
}
ZigBeeParser::~ZigBeeParser()
{
_bus->unreg_event(&_event);
disconnect(&_event,&Event::triggered,this,&ZigBeeParser::message_parser);
if(_thread->isRunning())
{
_thread->quit();
}
}
ZigBeeParser* ZigBeeParser::instance()
@ -32,296 +47,15 @@ ZigBeeParser* ZigBeeParser::instance()
return singleton;
}
void ZigBeeParser::data_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
src_port_parser(zframe,is_demo);
des_port_parser(zframe, is_demo);
remote_addr_parser(zframe, is_demo);
}
void ZigBeeParser::src_port_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
switch (zframe.getSrcPort()) {
case 0x81:
break;
default:
break;
}
}
void ZigBeeParser::des_port_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
if (zframe.size() <= 7)
{
qDebug()<<"ZigBee: recved package is corrupted, dropped.";
return;
}
void *frame = nullptr;
base_frame *bframe=nullptr;
hmac_frame *hframe=nullptr;
crypto_zdata_frame *czdata = nullptr;
data_frame *ddata = nullptr;
QByteArray zdata((char *)zframe.data(), zframe.size());
QString sender = QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper();
device temp,self;
QPair<device,device>* node = nullptr;
memset(&temp,0,sizeof(temp));
memset(&temp,0,sizeof(self));
self.addr = _protocol->self_addr;
if (!nodes.contains(((base_frame *)zframe.getData().data())->ori_addr))
{
temp.addr=((base_frame *)zframe.getData().data())->ori_addr;
temp.id = 0;
temp.online = 1;
temp.rand_num = 0;
temp.verified = 0;
nodes.insert(temp.addr,qMakePair(temp,self));
}
node = &nodes[((base_frame *)zframe.getData().data())->ori_addr];
bframe = (base_frame*)zframe.getData().data();
if (is_demo || bframe->des_addr == _protocol->self_addr && (node->first.id == 0||bframe->reset_num==0xDD||((bframe->id > node->first.id && bframe->id<=BASE_FRAME_RESET_NUM))))
{
node->first.addr = bframe->ori_addr;
node->first.id = bframe->id;
node->first.rand_num = bframe->rand_num;
frame = (void*)bframe->data;
}
else
{
QJsonObject object;
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("请注意节点0x"+QString::number(node->first.addr,16).toUpper()+"发送的该数据包损坏"));
object.insert("recieved", true);
object.insert("sender", sender);
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
return;
}
switch (zframe.getDesPort()) {
case 0x81:
{
hframe = (hmac_frame*)frame;
QJsonObject object;
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("sender", sender);
object.insert("note_text",QJsonValue("收到节点0x"+ sender +"发送的验证信息"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
if (_allow_list.contains(node->first.addr))
{
u8 hmac[33]="";
QByteArray key = QByteArray::fromHex(_protocol->hmac_verify_key.toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(),16,&hframe->value,1,hmac);
if (_protocol->bytecmp(hframe->hmac,hmac,32))
{
new_data_frame(15) data;
memset(&data, 0, sizeof(data));
_protocol->protocal_wrapper((data_frame *)&data, 0, 10, (u8 *)"Identified", 0);
node->first.verified = 1;
new_base_frame(15 + DATA_FRAME_PREFIX_LEN + BASE_FRAME_PREFIX_LEN) bframe;
memset(&bframe, 0, sizeof(bframe));
_protocol->base_frame_maker(&data, (base_frame *)&bframe, node->first.addr,&node->second);
zigbee_protocol::ZigbeeFrame zf(zframe.getSrcPort(),zframe.getDesPort(),zframe.getRemoteAddr(),(uint8_t *)&bframe,bframe.length);
QByteArray bdata((char *)&bframe, bframe.length);
QByteArray zdata((char *)zf.data(), zf.size());
QJsonObject object;
object.insert("baseframe_data",QJsonValue(QString(bdata.toHex(' ').toUpper())));
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("向0x"+QString::number(node->first.addr,16).toUpper()+"节点发送验证通过回复信息"));
object.insert("recieved", false);
object.insert("sender", QString::number(_protocol->self_addr,16).toUpper());
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
if(!is_demo)
_bus->push_data("serial_port",object);
}
else
{
u8 hmac[33]="";
QJsonObject object;
QByteArray latest_key = QByteArray::fromHex(_protocol->hmac_verify_key.toLatin1());
for (auto key_str : _protocol->pre_hmac_verify_key)
{
QByteArray key = QByteArray::fromHex(key_str.toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(),16,&hframe->value,1,hmac);
if (_protocol->bytecmp(hframe->hmac,hmac,32))
{
zigbee_protocol::ZigbeeFrame zf(0x82,0x82,node->first.addr);
new_crypto_zdata_frame(32) zdata;
memset(&zdata, 0, sizeof(zdata));
_protocol->zigbee_data_encrypt((u8*)latest_key.data(), 16, (crypto_zdata_frame *)&zdata, Crypto::SM4_encrypt, key_str);
new_base_frame(sizeof(zdata) + BASE_FRAME_PREFIX_LEN) bframe;
memset(&bframe, 0, sizeof(bframe));
_protocol->base_frame_maker(&zdata, (base_frame *)&bframe, node->first.addr, &node->second);
zf.setData((u8 *)&bframe, bframe.length);
QByteArray bdata((char *)&bframe, bframe.length);
QByteArray zfdata((char *)zf.data(), zf.size());
object.insert("baseframe_data",QJsonValue(QString(bdata.toHex(' ').toUpper())));
object.insert("text",QJsonValue(QString(zfdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("节点0x"+QString::number(node->first.addr,16).toUpper()+"正在使用旧密钥,发送密钥更新指令"));
object.insert("recieved", false);
object.insert("sender", QString::number(_protocol->self_addr,16).toUpper());
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
if(!is_demo)
_bus->push_data("serial_port",object);
return;
}
}
object.insert("note_text",QJsonValue("节点0x"+QString::number(node->first.addr,16).toUpper()+"验证不通过,请考虑移出认证列表"));
object.insert("recieved", true);
object.insert("sender", sender);
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
}
}
else if(_deny_list.contains(node->first.addr))
{
object.insert("sender", sender);
object.insert("text","");
object.insert("note_text",QJsonValue("节点0x"+QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper()+"被禁止接入"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
}
else {
if (!_wait_queue.contains(node->first.addr))
{
_wait_queue.append(node->first.addr);
object.insert("sender", sender);
object.insert("text","");
object.insert("note_text",QJsonValue("节点0x"+QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper()+"进入等待队列"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
}
else
{
object.insert("sender", sender);
object.insert("text","");
object.insert("note_text",QJsonValue("节点0x"+QString::number(((base_frame *)zframe.getData().data())->ori_addr,16).toUpper()+"已在等待队列"));
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
_bus->push_data("zigbee_identify_data_view",object);
}
}
break;
}
case 0x82:
{
}
case 0x83:
{
QJsonObject object;
if (node->first.verified)
{
zigbee_protocol::ZigbeeFrame dzf = zframe;
new_data_frame(72) ndata;
uint8_t data_len = 0;
memset(&ndata,0,sizeof(ndata));
if (*(u16 *)frame == CRYPTO_ZDATA_FRAME_HEAD)
{
czdata = (crypto_zdata_frame*)frame;
_protocol->zigbee_data_dectypt((uint8_t*)&ndata, &data_len, czdata, Crypto::SM4_decrypt);
dzf.setData((char*)&ndata,ndata.data_length + DATA_FRAME_PREFIX_LEN);
zdata = QByteArray((char *)dzf.data(), dzf.size());
object.insert("decrypted_text", QJsonValue(QString(zdata.toHex(' ').toUpper())));
}
object.insert("sender", sender);
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("收到节点0x"+sender+"发送的数据"));
object.insert("recieved", true);
object.insert("type","zigbee_recv_data");
if (QRandomGenerator::global()->bounded(2)!=0 && is_demo)
object.insert("decrypted_text", QJsonValue(QString(zdata.toHex(' ').toUpper())));
_bus->push_data("zigbee_recv_data_view",object);
}
else
{
object.insert("sender", sender);
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("收到节点0x"+sender+"发送的数据,但节点并未认证"));
object.insert("recieved", true);
object.insert("type","zigbee_recv_data");
_bus->push_data("zigbee_recv_data_view",object);
node->second.id=0;
new_data_frame(5) dframe;
memset(&dframe,0,sizeof (dframe));
_protocol->protocal_wrapper((data_frame *)&dframe, 0, 5, (u8 *)"RESET", false);
new_base_frame(5 + DATA_FRAME_PREFIX_LEN + BASE_FRAME_PREFIX_LEN) bframe;
memset(&bframe, 0, sizeof(bframe));
_protocol->base_frame_maker(&dframe, (base_frame *)&bframe, node->first.addr,&node->second);
zigbee_protocol::ZigbeeFrame zf(0x83,0x83,node->first.addr,(char *)&bframe,bframe.length);
QByteArray zfdata((char *)zf.data(),zf.size());
QJsonObject object;
object.insert("sender", QString::number(_protocol->self_addr,16).toUpper());
object.insert("text",QJsonValue(QString(zfdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("向节点0x"+sender+"发送重置命令"));
object.insert("recieved", false);
object.insert("type","zigbee_recv_data");
_bus->push_data("zigbee_recv_data_view",object);
}
}
default:
break;
}
}
void ZigBeeParser::remote_addr_parser(zigbee_protocol::ZigbeeFrame &zframe, bool is_demo)
{
switch (zframe.getRemoteAddr()) {
case 0xAAAA:
break;
default:
break;
}
}
void ZigBeeParser::message_parser(QJsonObject message)
{
if (message["type"] == "demo_verify_request")
emit message_recved(message, _self_addr, _allow_list, _deny_list, _wait_queue);
}
void ZigBeeParser::bus_data_send(QString type, QJsonObject data, QList<uint16_t> allow_list, QList<uint16_t> deny_list, QList<uint16_t> wait_queue)
{
hmac_frame frame;
frame.value = QRandomGenerator::global()->bounded(256);
frame.head = HMAC_FRAME_HEAD;
frame.length = 32 + HMAC_FRAME_PREFIX_LEN;
QByteArray key = QByteArray::fromHex(_protocol->hmac_verify_key.toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(), 16, &frame.value, 1, frame.hmac);
new_base_frame(50 + BASE_FRAME_PREFIX_LEN) bframe;
device test;
test.addr = 0x5656;
_protocol->base_frame_maker(&frame, (base_frame *)&bframe, _protocol->self_addr, &test);
zigbee_protocol::ZigbeeFrame zf(0x81,0x81,0x5656,(char*)&bframe,bframe.length);
data_parser(zf, true);
}
if (message["type"] == "demo_verify_key_update")
{
hmac_frame frame;
frame.value = QRandomGenerator::global()->bounded(256);
frame.head = HMAC_FRAME_HEAD;
frame.length = 32 + HMAC_FRAME_PREFIX_LEN;
QByteArray key = QByteArray::fromHex(_protocol->pre_hmac_verify_key[QRandomGenerator::global()->bounded(_protocol->pre_hmac_verify_key.length())].toLatin1());
Crypto::getInstance()->SM3_HMAC((u8 *)key.data(), 16, &frame.value, 1, frame.hmac);
new_base_frame(50 + BASE_FRAME_PREFIX_LEN) bframe;
device test;
test.addr = 0x5656;
_protocol->base_frame_maker(&frame, (base_frame *)&bframe, _protocol->self_addr, &test);
zigbee_protocol::ZigbeeFrame zf(0x81,0x81,0x5656,(char*)&bframe,bframe.length);
data_parser(zf, true);
}
if (message["type"] == "demo_recv_data" || message["type"] == "zigbee_raw_data")
{
QString data = message["data_hex"].toString();
QByteArray bdata;
QStringList td = data.split(' ');
for (auto item : td)
bdata += QByteArray::fromHex(item.toLatin1());
zigbee_protocol::ZigbeeFrame zf;
zf.load_package((uint8_t*)bdata.data(),bdata.length());
data_parser(zf, message["type"] == "demo_recv_data");
}
_bus->push_data(type, data);
_allow_list = allow_list;
_deny_list = deny_list;
_wait_queue = wait_queue;
}