ProtocolParser/app_source/dlln3x/DLLN3X.cpp

336 lines
8.5 KiB
C++

#include "DLLN3X.h"
#include <QTime>
#include <QCoreApplication>
using namespace zigbee_protocol;
DLLN3X::DLLN3X(QObject *parent)
: QObject{parent}
{
}
DLLN3X* DLLN3X::instance(){
static DLLN3X instance;
return &instance;
}
void DLLN3X::init(QSerialPort* DSerial, uint32_t baudrate)
{
_DSerial = DSerial;
uint8_t i = 0;
for (; i < 7; i++)
if (baudrate == _baud_rate_list[i])
{
i = 20;
break;
}
if (i != 20)
return;
_DSerial->setBaudRate(baudrate);
_DSerial->setDataBits(QSerialPort::Data8);
_DSerial->setParity(QSerialPort::NoParity);
_DSerial->setStopBits(QSerialPort::OneStop);
if (!_DSerial->isOpen())
{
if (!_DSerial->open(QIODevice::ReadWrite))
return;
}
rled_blink();
read_addr();
read_baudrate();
read_channel();
read_network_id();
}
ZigbeeFrame DLLN3X::recv(bool non_blocked)
{
uint8_t buf[66] = "", length = 0;
ZigbeeFrame zf;
if (non_blocked) {
if (_DSerial->bytesAvailable() < 6)
return zf;
}
_recv_lock = true;
length = readBytesUntil(0xFF, buf, 65);
_recv_lock = false;
zf.load_package(buf, length);
return zf;
}
bool DLLN3X::send(ZigbeeFrame zf)
{
if(!_DSerial->isOpen())
return false;
bool status = false;
uint8_t len = zf.size();
if (zf.getSrcPort() < 0x80 || len > 66)
return false;
status = _DSerial->write((char *)zf.data(),len);
status = _DSerial->flush();
return status;
}
bool DLLN3X::send_cmd(uint8_t des_port, uint8_t arg, uint8_t* data, uint8_t data_length)
{
ZigbeeFrame zf(0x80, des_port, 0x0000);
if (data_length + 4 > 63)
return false;
zf.append(arg);
zf.addData(data, data_length);
return send(zf);
}
void DLLN3X::rled_blink(uint8_t time)
{
uint8_t gap = 5;
// for (int i = 0; i < time; i += gap) {
// if (i % 2 != 0)
// send_cmd(0x20, gap);
// else
// _sleep(gap * 250);
// }
send_cmd(0x20, gap);
}
uint16_t DLLN3X::read_addr()
{
_self_addr = rw_config(CONFIG::ADDR);
return _self_addr;
}
uint8_t DLLN3X::set_addr(uint16_t addr)
{
uint8_t resp = rw_config(CONFIG::ADDR, addr, CONFIG_RW_MASK::WRITE);
if (resp == CONFIG_RESPONSE::DONE)
{
_self_addr = addr;
soft_reboot();
}
return resp;
}
uint32_t DLLN3X::read_baudrate()
{
if (_self_baud_rate != 0)
return _self_baud_rate;
uint8_t arg = rw_config(CONFIG::BAUDRATE);
_self_baud_rate = _baud_rate_list[arg];
return _self_baud_rate;
}
uint8_t DLLN3X::set_baudrate(uint32_t baud_rate)
{
uint8_t arg = 0;
uint8_t i = 0;
for (; i < 13; i++)
{
if (baud_rate == _baud_rate_list[i])
{
arg = i;
break;
}
}
if (arg != i)
return CONFIG_RESPONSE::CMD_ERROR;
uint8_t resp = rw_config(CONFIG::BAUDRATE, arg, CONFIG_RW_MASK::WRITE);
if (resp == CONFIG_RESPONSE::DONE)
{
_self_baud_rate = baud_rate;
soft_reboot();
}
return resp;
}
uint8_t DLLN3X::read_network_id()
{
if (_self_network_id != 0)
return _self_network_id;
_self_network_id = rw_config(CONFIG::NETWORKID);
return _self_network_id;
}
uint8_t DLLN3X::set_network_id(uint16_t network_id)
{
uint8_t resp = rw_config(CONFIG::NETWORKID, network_id, CONFIG_RW_MASK::WRITE);
if (resp == CONFIG_RESPONSE::DONE)
{
_self_network_id = network_id;
soft_reboot();
}
return resp;
}
uint8_t DLLN3X::read_channel()
{
if (_self_channel != 0)
return _self_channel;
_self_channel = rw_config(CONFIG::CHANNEL);
return _self_channel;
}
uint8_t DLLN3X::set_channel(uint8_t channel)
{
uint8_t resp = rw_config(CONFIG::CHANNEL, channel, CONFIG_RW_MASK::WRITE);
if (resp == CONFIG_RESPONSE::DONE)
{
_self_channel = channel;
soft_reboot();
}
return resp;
}
uint16_t DLLN3X::rw_config(CONFIG arg, uint16_t data, CONFIG_RW_MASK mask)
{
uint8_t cmd_arg = arg|mask;
if (mask == CONFIG_RW_MASK::WRITE)
{
if (arg == CONFIG::ADDR || arg == CONFIG::NETWORKID)
{
send_cmd(0x21, cmd_arg, (uint8_t *)&data, 2);
}
else
send_cmd(0x21, cmd_arg, (uint8_t *)&data, 1);
}
else
send_cmd(0x21, cmd_arg);
ZigbeeFrame zf = recv(false);
if (zf.getSrcPort() != 0x21 || zf.getDesPort() != 0x80 || zf.getRemoteAddr() != 0x0000)
return 0;
switch (arg) {
case CONFIG::ADDR: {
if (zf.getData()[0] != 0x21) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
printf("DLLN3X write config error: 0x");
printf("%X\n", zf.getData()[0]);
}
return zf.getData()[0];
} else
return (zf.getData()[2] << 8) | zf.getData()[1];
}
case CONFIG::NETWORKID: {
if (zf.getData()[0] != 0x22) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
printf("DLLN3X write config error: 0x");
printf("%X\n", zf.getData()[0]);
}
return zf.getData()[0];
} else
return (zf.getData()[2] << 8) | zf.getData()[1];
}
case CONFIG::CHANNEL: {
if (zf.getData()[0] != 0x23) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
printf("DLLN3X write config error: 0x");
printf("%X\n", zf.getData()[0]);
}
return zf.getData()[0];
} else
return zf.getData()[1];
}
case CONFIG::BAUDRATE: {
if (zf.getData()[0] != 0x24) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
printf("DLLN3X write config error: 0x");
printf("%X\n", zf.getData()[0]);
}
return zf.getData()[0];
} else
return zf.getData()[1];
}
default:
return CONFIG_RESPONSE::CMD_ERROR;
}
}
void DLLN3X::soft_reboot()
{
send_cmd(0x21, CONFIG::SOFT_REBOOT);
_self_addr = 0;
_self_baud_rate = 0;
_self_channel = 0;
_self_network_id = 0;
}
uint8_t DLLN3X::get_link_quality(uint16_t des_addr, uint16_t src_addr)
{
if (des_addr == 0x0000 || des_addr == 0xFFFF)
return CONFIG_RESPONSE::CMD_ERROR;
ZigbeeFrame zf(0x80, 0x23, src_addr), r_zf;
zf.addData((uint8_t *)&des_addr, 2);
r_zf = recv(false);
uint16_t pkg_des_addr = (r_zf.getData()[1] << 8) | r_zf.getData()[0];
if (pkg_des_addr != des_addr)
return CONFIG_RESPONSE::PKG_DATA_ERROR;
else
return r_zf.getData()[2];
}
enum DLLN3X::PIN_CONTROL DLLN3X::pin_control(PIN pin, PIN_CONTROL cmd)
{
send_cmd(pin, cmd);
if (cmd == PIN_CONTROL::READ_PIN)
{
ZigbeeFrame zf = recv(false);
return PIN_CONTROL(zf.getData()[0] ^ 0x10);
}
return cmd;
}
void DLLN3X::loop()
{
if (_DSerial && _DSerial->bytesAvailable() > 7 && !_recv_lock) {
ZigbeeFrame zf = recv();
printf("Message: ");
for (int i = 0; i < zf.size(); i++) {
printf("%02X ", zf[i]);
}
printf("at port %02X from %04X:%02X.\n", zf.getDesPort(), zf.getRemoteAddr(), zf.getSrcPort());
if (zf.getSrcPort() == 0x22)
{
printf("DLLN3X send msg error: 0x");
printf("%X",zf.getData()[0]);
printf(", Send data to incorrect port: 0x");
printf("%X\n",zf.getData()[1]);
}
emit recved(zf);
}
}
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)
{
qint64 bytesReadNow = _DSerial->read((char *)(buffer) + bytesRead, 1);
bytesRead += bytesReadNow;
data.append((char *)(buffer) + bytesRead - bytesReadNow, bytesReadNow);
if (data.contains(delimiter) || !(_DSerial->waitForReadyRead(20) || _DSerial->bytesAvailable()))
{
break;
}
}
else
qDebug()<<"DL-LN3X: Read byte timeout!";
return bytesRead;
}
void DLLN3X::_sleep(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
void DLLN3X::setcallback(void (*callback)(ZigbeeFrame& zf)) { _callback = callback; }