ProtocolParser/app_source/source/zigbeedataresolver.cpp

469 lines
21 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
bool addr_check = false, id_check = false, reset_flag_check = false;
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();
addr_check = bframe->des_addr == _protocol->self_addr;
id_check = node->first.id == 0 || ((bframe->id > node->first.id && bframe->id<=BASE_FRAME_RESET_NUM));
reset_flag_check = bframe->reset_num==0xDD;
if (is_demo || addr_check && (id_check||reset_flag_check))
{
node->first.addr = bframe->ori_addr;
node->first.id = bframe->id;
node->first.rand_num = bframe->rand_num;
frame = (void*)bframe->data;
}
else
{
QString error_str;
QJsonObject object;
if (!addr_check)
error_str += "地址错误包目的地址为0x" + QString::number(bframe->des_addr, 16).toUpper();
if(!(id_check||reset_flag_check))
error_str += "包id错误且重置标志位未标记为生效当前包ID为" + QString::number(bframe->id) + "系统存储ID为" + QString::number(node->first.id);
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("note_text",QJsonValue("请注意节点0x"+QString::number(node->first.addr,16).toUpper()+"发送的该数据包损坏"+error_str));
object.insert("recieved", true);
object.insert("sender", sender);
object.insert("type","zigbee_recv_data");
emit data_send("zigbee_recv_data_view",object);
return;
}
switch (zframe.getDesPort()) {
case 0x81:
{
QJsonObject object;
hframe = (hmac_frame*)frame;
object.insert("text",QJsonValue(QString(zdata.toHex(' ').toUpper())));
object.insert("sender", sender);
object.insert("recieved", true);
object.insert("type","zigbee_identify_data");
if(*(u16*)frame != HMAC_FRAME_HEAD)
{
object.insert("note_text",QJsonValue("收到节点0x"+ sender +"发送的数据包,但并非验证信息,请检查下位机发送是否有误"));
emit data_send("zigbee_identify_data_view",object);
return;
}
else
object.insert("note_text",QJsonValue("收到节点0x"+ sender +"发送的验证信息"));
emit data_send("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");
emit data_send("zigbee_identify_data_view",object);
if(!is_demo)
emit data_send("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");
emit data_send("zigbee_identify_data_view",object);
if(!is_demo)
emit data_send("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");
emit data_send("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");
emit data_send("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");
emit data_send("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");
emit data_send("zigbee_identify_data_view",object);
}
}
break;
}
case 0x82:
{
}
case 0x83:
{
QJsonObject object;
if (node->first.verified)
{
QString note_text;
new_data_frame(72) ndata;
uint8_t data_len = 0;
memset(&ndata,0,sizeof(ndata));
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 (*(u16 *)frame == CRYPTO_ZDATA_FRAME_HEAD)
{
note_text = "解密数据为按照未加密传输重新打包的原始数据,因此数据长度会有差异\n";
new_base_frame(sizeof(ndata)) nbframe;
memcpy(&nbframe, bframe, BASE_FRAME_PREFIX_LEN);
zigbee_protocol::ZigbeeFrame nzframe = zframe;
czdata = (crypto_zdata_frame*)frame;
_protocol->zigbee_data_dectypt((uint8_t*)&ndata, &data_len, czdata, Crypto::SM4_decrypt);
if(*(u16 *)&ndata != DATA_FRAME_HEAD)
{
note_text = "数据包错误,请检查是否解密失败或为数据帧,已下发重置命令\n若更换密钥,请等待下位机进行重新认证或重启下位机";
object.insert("note_text",QJsonValue(note_text));
emit data_send("zigbee_recv_data_view",object);
node->second.id=0;
node->second.verified=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);
emit data_send("serial_port",object);
return;
}
else
{
memcpy(nbframe.data, &ndata, ndata.data_length + DATA_FRAME_PREFIX_LEN);
nbframe.length = BASE_FRAME_PREFIX_LEN + ndata.data_length + DATA_FRAME_PREFIX_LEN;
nzframe.setData((char*)&nbframe,nbframe.length);
zdata = QByteArray((char *)nzframe.data(), nzframe.size());
object.insert("decrypted_text", QJsonValue(QString(zdata.toHex(' ').toUpper())));
ddata = (data_frame*)&ndata;
}
}
else if (*(u16 *)frame != DATA_FRAME_HEAD)
{
object.insert("note_text",QJsonValue("收到节点0x"+sender+"发送的数据,但不是数据帧或加密帧,请检查下位机发送是否有误"));
emit data_send("zigbee_recv_data_view",object);
return;
}
else{
ddata = (data_frame*)frame;
}
if(ddata!=nullptr)
{
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();
if (!name_list.length())
break;
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]) + ' ';
}
object.insert("note_text",QJsonValue(note_text));
break;
}
default:
break;
}
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);
}
}
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);
node->second.id=0;
node->second.verified=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);
if(!is_demo)
emit data_send("serial_port",object);
}
break;
}
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)
{
QMutex mutex;
mutex.lock();
_self_addr = self_addr;
mutex.unlock();
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");
}
}
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;
}