V1.1.0 Update

This commit is contained in:
Mentalflow 2023-03-18 13:25:22 +08:00
parent 9dd60e1ca5
commit 8c7e5b75f1
Signed by: Mentalflow
GPG Key ID: 5AE68D4401A2EE71
8 changed files with 623 additions and 246 deletions

View File

@ -1,15 +1,17 @@
# DLLN3X_zigbee_mesh_module_library
This library allows you to use DLLN3X ZigBee mesh module very easily.
This library is now complete, the remaining work is mainly maintenance and bug fixes, welcome feedback by opening issues.
# Available Features
1. Basic message sending and receiving.
2. Module address reading.
3. On-chip red led flashing control.
4. Configuration reading, modification (baud rate, address, etc.).(TODO)
5. Error Report.(TODO)
6. Link quality test.(TODO)
7. On-chip pin control.(TODO)
4. Configuration reading, modification (baud rate, address, etc.).
5. Error Report.
6. Link quality test.
7. On-chip pin control.
# Example run results
@ -17,6 +19,13 @@ This library allows you to use DLLN3X ZigBee mesh module very easily.
# Change Log
**V1.1.0 2023.3.18**
+ Completely rewritten.
+ Join the ZigbeeFrame container.
+ Greatly improve stability.
+ Supports configuration reading and modification, link quality testing, on-board pin control, error reporting, etc.
**V1.0.4 2023.1.26**
- Bug fixes and stability improvements.

View File

@ -1,16 +1,15 @@
#include "DLLN3X.h"
using namespace zigbee_protocol;
DLLN3X dlln33; //Instantiating DLLN3X module
zigbee_frame zframe;
void zigbee_call_back(uint8_t orig_port,
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length) {
switch (dest_port) {
void zigbee_call_back(ZigbeeFrame &zframe) {
switch (zframe.getDesPort()) {
case 0x82:
{
/* Do everything you want to do */
char temp[200];
sprintf(temp, "Hello from port 0x%X: %s",orig_port,data);
sprintf(temp, "Hello from port 0x%X: %.*s",zframe.getSrcPort(),zframe.getDataLength(),zframe.getData().data());
Serial.println(temp);
break;
}
@ -30,21 +29,32 @@ void setup() {
Serial.println("Waiting for DLLN3X to connect........");
delay(1000);
}
char temp[20];
char temp[50];
sprintf(temp, "DLLN3X addr: 0x%04X.",dlln33.read_addr());
Serial.println(temp);
sprintf(temp, "DLLN3X network id: 0x%04X.",dlln33.read_network_id());
Serial.println(temp);
sprintf(temp, "DLLN3X channel: 0x%02X.",dlln33.read_channel());
Serial.println(temp);
sprintf(temp, "DLLN3X baud rate: %d.",dlln33.read_baudrate());
Serial.println(temp);
dlln33.set_addr(0xFFFF); //test error report
//dlln33.get_link_quality(YOUR_ANOTHER_CHIP_ADDR); //test link quility
dlln33.pin_control(DLLN3X::PIN::PIN4, DLLN3X::PIN_CONTROL::HIGH); //test pin, PIN4 is TTx, PIN5 is TRx
}
uint64_t interval = 5000, pre_milli = 0;
void loop() {
dlln33.loop();
if (millis() - pre_milli >= interval) {
zframe.src_port = 0x81;
zframe.des_port = 0x82;
*((uint16_t *)&zframe.remote_addrL) = dlln33.read_addr(); // send pkg to self.
strncpy((char*)zframe.data,"Hello to port 0x82!",19);
zframe.length = 19;
dlln33.send(&zframe);
ZigbeeFrame zf;
zf.setSrcPort(0x81);
zf.setDesPort(0x82);
zf.setRemoteAddr(dlln33.read_addr());
zf.setData("Hello to port 0x82!");
dlln33.send(zf);
zf = zf + "I'm port 0x81!";
dlln33.send(zf);
pre_milli = millis();
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -7,24 +7,53 @@
#######################################
DLLN3X KEYWORD1
zigbee_frame KEYWORD1
ZigbeeFrame KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
_clear KEYWORD2
_pack KEYWORD2
_depack KEYWORD2
_callback KEYWORD2
setDesPort KEYWORD2
setSrcPort KEYWORD2
setRemoteAddr KEYWORD2
getDesPort KEYWORD2
getSrcPort KEYWORD2
getRemoteAddr KEYWORD2
getLength KEYWORD2
getDataLength KEYWORD2
getData KEYWORD2
setData KEYWORD2
addData KEYWORD2
clear KEYWORD2
data KEYWORD2
data_size KEYWORD2
size KEYWORD2
append KEYWORD2
pack KEYWORD2
depack KEYWORD2
make_package KEYWORD2
get_package KEYWORD2
load_package KEYWORD2
print KEYWORD2
init KEYWORD2
recv KEYWORD2
send KEYWORD2
send_cmd KEYWORD2
rled_blink KEYWORD2
loop KEYWORD2
setcallback KEYWORD2
rw_config KEYWORD2
read_network_id KEYWORD2
set_network_id KEYWORD2
read_channel KEYWORD2
set_channel KEYWORD2
read_addr KEYWORD2
set_addr KEYWORD2
read_baudrate KEYWORD2
set_baudrate KEYWORD2
soft_reboot KEYWORD2
get_link_quality KEYWORD2
pin_control KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################

View File

@ -1,11 +1,11 @@
name= DLLN3X ZigBee Mesh Module Library
version= 1.0.4
version= 1.1.0
author= Dylan Liu <mentalflow@ourdocs.cn>
maintainer= Dylan Liu <mentalflow@ourdocs.cn>
sentence= This library allows you to use DLLN3X ZigBee mesh module very easily.
paragraph= This library currently allows basic send and receive operations using the DLLN3X module, with more features to come.
paragraph= This library currently allows basic send and receive operations, config read/modify, link quility test, pin control and more.
category= Communication
architectures= *
includes= DLLN3X.h
includes= DLLN3X.h zigbeeframe.h
license= MIT
url= https://github.com/mentalfl0w/DLLN3X_zigbee_mesh_module_library

View File

@ -1,218 +1,290 @@
#include "DLLN3X.h"
DLLN3X::DLLN3X(){}
DLLN3X::~DLLN3X() {}
using namespace zigbee_protocol;
void DLLN3X::init(HardwareSerial *DSerial)
DLLN3X::DLLN3X() { }
DLLN3X::~DLLN3X() { }
void DLLN3X::init(HardwareSerial* DSerial)
{
_DSerial = DSerial;
DSerial->begin(115200);
DSerial->setTimeout(10000);
rled_blink();
read_addr();
read_baudrate();
read_channel();
read_network_id();
}
void DLLN3X::init(SoftwareSerial *DSerial)
#if __has_include(<SoftwareSerial.h>)
void DLLN3X::init(SoftwareSerial* DSerial)
{
_DSerial = DSerial;
DSerial->begin(115200);
DSerial->setTimeout(10000);
rled_blink();
read_addr();
read_baudrate();
read_channel();
read_network_id();
}
#endif
void DLLN3X::_clear()
ZigbeeFrame DLLN3X::recv(bool non_blocked)
{
while (_DSerial->available())
_DSerial->read();
}
int DLLN3X::_pack(uint8_t buf[], uint8_t data[], int length)
{
int count = 0;
for (int i = 0; i < length; i++)
{
if (data[i] == 0xFE)
{
buf[count++] = data[i];
buf[count++] = 0xFC;
uint8_t buf[65] = "", length = 0;
ZigbeeFrame zf;
if (non_blocked) {
if (_DSerial->available() < 6)
return zf;
}
else if (data[i] == 0xFF)
{
buf[count++] = 0xFE;
buf[count++] = 0xFD;
}
else
{
buf[count++] = data[i];
}
}
return count;
}
int DLLN3X::_depack(uint8_t buf[], uint8_t data[], int length)
{
int count = 0;
for (int i = 0; i < length; i++)
{
if (buf[i] != 0xFE)
{
data[count++] = buf[i];
}
else if (buf[i + 1] == 0xFD)
{
data[count++] = 0xFF;
i++;
}
else if (buf[i + 1] == 0xFC)
{
data[count++] = 0xFE;
i++;
}
}
return count;
}
void DLLN3X::recv(zigbee_frame *frame)
{
_recv_lock = true;
_DSerial->readBytesUntil(0xFF, (char *)frame, 64);
_DSerial->read();
length = _DSerial->readBytesUntil(0xFF, buf, 65);
buf[length] = _DSerial->read();
_recv_lock = false;
zf.load_package(buf, length + 1);
return zf;
}
bool DLLN3X::recv(uint8_t *orig_port,
uint8_t *dest_port, uint16_t *addr,
uint8_t data[], int *length)
bool DLLN3X::send(ZigbeeFrame zf)
{
_recv_lock = true;
uint8_t buf[200] = "";
uint8_t head = 0, tail = 0;
if(_DSerial->available()<6)
if (zf.getSrcPort() < 0x80)
return false;
head = _DSerial->read();
if (head == 0xFE)
{
*length = _DSerial->read();
*length -= 4;
*orig_port = _DSerial->read();
*dest_port = _DSerial->read();
*addr = _DSerial->read();
*addr += _DSerial->read() << 8;
int count = 0;
for (int i = 0; i < *length; i++)
{
while(_DSerial->available()<1);
buf[count++] = _DSerial->read();
if (buf[count-1]==0xFE)
{
while(_DSerial->available()<1);
buf[count++]=_DSerial->read();
}
}
*length = count;
while(_DSerial->available()<1);
_DSerial->read(); // read pkg tail
*length = _depack(buf, data, *length);
_recv_lock = false;
return true;
}
else
{
_recv_lock = false;
return false;
}
return _DSerial->write(zf.data(), zf.size());
}
bool DLLN3X::send(uint8_t orig_port,
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length)
bool DLLN3X::send_cmd(uint8_t des_port, uint8_t arg, uint8_t* data, uint8_t data_length)
{
if (orig_port<0x80)
ZigbeeFrame zf(0x80, des_port, 0x0000);
if (data_length - 4 > 63 - 1)
return false;
uint8_t send_buf[208] = {0xFE}, buf[200] = "";
uint8_t head = 0, buf_length = 0;
buf_length = _pack(buf, data, length);
send_buf[1] = length+4;
send_buf[2] = orig_port;
send_buf[3] = dest_port;
send_buf[4] = addr & 0xFF;
send_buf[5] = (addr & 0xFF00) >> 8;
memcpy(send_buf + 6, buf, buf_length);
send_buf[6 + buf_length] = 0xFF;
return _DSerial->write(send_buf, buf_length + 7);
zf.append(arg);
zf.addData(data, data_length);
return send(zf);
}
bool DLLN3X::send(zigbee_frame *frame)
{
return send(frame->src_port, frame->des_port, (frame->remote_addrH << 8) | (frame->remote_addrL & 0xFF),
frame->data, frame->length);
}
void DLLN3X::rled_blink(uint8_t orig_port, uint16_t addr, uint8_t time)
void DLLN3X::rled_blink(uint8_t time)
{
uint8_t gap = 5;
for (int i = 0; i < time; i += gap)
{
if (i%2!=0)
send(orig_port, 0x20, addr, &gap, 1);
for (int i = 0; i < time; i += gap) {
if (i % 2 != 0)
send_cmd(0x20, gap);
else
delay(gap*200);
delay(gap * 250);
}
}
uint16_t DLLN3X::read_addr()
{
if (self_addr!=0)
return self_addr;
uint8_t orig_port = 0xFF, dest_port = 0xFF;
uint8_t arg = 0x01;
uint16_t addr = 0xFFFF;
uint8_t data[60] = "";
int length = 0;
send(0x80, 0x21, 0x0000, &arg, 1);
while(_DSerial->available()<10);
_recv_lock = true;
recv(&orig_port, &dest_port, &addr, data, &length);
_recv_lock = false;
if (orig_port!=0x21||dest_port!=0x80||addr !=0x0000||length!=3||data[0]!=0x21)
if (_self_addr != 0)
return _self_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)
{
return 0;
_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;
for (uint8_t i = 0; i < 13; i++)
{
if (baud_rate == _baud_rate_list[i])
{
arg = i;
break;
}
}
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
{
this->self_addr = data[1] + (data[2] << 8);
return this->self_addr;
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.getDataLength() != 3 || zf.getData()[0] != 0x21) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
Serial.print("DLLN3X write config error: 0x");
Serial.println(zf.getData()[0], HEX);
}
return zf.getData()[0];
} else
return (zf.getData()[2] << 8) | zf.getData()[1];
}
case CONFIG::NETWORKID: {
if (zf.getDataLength() != 3 || zf.getData()[0] != 0x22) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
Serial.print("DLLN3X write config error: 0x");
Serial.println(zf.getData()[0], HEX);
}
return zf.getData()[0];
} else
return (zf.getData()[2] << 8) | zf.getData()[1];
}
case CONFIG::CHANNEL: {
if (zf.getDataLength() != 2 || zf.getData()[0] != 0x23) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
Serial.print("DLLN3X write config error: 0x");
Serial.println(zf.getData()[0], HEX);
}
return zf.getData()[0];
} else
return zf.getData()[1];
}
case CONFIG::BAUDRATE: {
if (zf.getDataLength() != 2 || zf.getData()[0] != 0x24) {
if (zf.getData()[0] != CONFIG_RESPONSE::DONE)
{
Serial.print("DLLN3X write config error: 0x");
Serial.println(zf.getData()[0], HEX);
}
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()
{
uint8_t orig_port = 0xFF, dest_port = 0xFF;
uint16_t addr = 0xFFFF;
uint8_t data[200] = "";
int length = 0;
if (_DSerial->available()>7&&!_recv_lock)
{
recv(&orig_port,&dest_port,&addr,data,&length);
if (_DSerial->available() > 7 && !_recv_lock) {
ZigbeeFrame zf = recv();
Serial.print("Message: ");
for (int i = 0; i < length;i++)
{
for (int i = 0; i < zf.size(); i++) {
char temp[3];
sprintf(temp, "%02X ", data[i]);
sprintf(temp, "%02X ", zf[i]);
Serial.print(temp);
}
char temp[200];
sprintf(temp, "at port %02X from %04X:%02X.", dest_port, addr, orig_port);
char temp[30];
sprintf(temp, "at port %02X from %04X:%02X.", zf.getDesPort(), zf.getRemoteAddr(), zf.getSrcPort());
Serial.println(temp);
if (_callback!=nullptr)
_callback(orig_port, dest_port, addr, data, length);
if (zf.getSrcPort() == 0x22)
{
Serial.print("DLLN3X send msg error: 0x");
Serial.print(zf.getData()[0], HEX);
Serial.print(", Send data to incorrect port: 0x");
Serial.print(zf.getData()[1], HEX);
}
if (_callback != nullptr)
_callback(zf);
}
}
void DLLN3X::setcallback(void (*callback)(uint8_t orig_port,
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length))
{
_callback = callback;
}
void DLLN3X::setcallback(void (*callback)(ZigbeeFrame& zf)) { _callback = callback; }

View File

@ -1,62 +1,60 @@
#ifndef _DLLN3X_H_
#define _DLLN3X_H_
#include "zigbeeframe.h"
#include <Arduino.h>
#if __has_include(<SoftwareSerial.h>)
#include <SoftwareSerial.h>
typedef struct zigbee_frame
{
uint8_t length;
uint8_t src_port;
uint8_t des_port;
uint8_t remote_addrL;
uint8_t remote_addrH;
uint8_t data[59];
}zigbee_frame;
#define new_zigbee_frame(num) \
struct \
{ \
uint8_t length; \
uint8_t src_port; \
uint8_t des_port; \
uint8_t remote_addrL;\
uint8_t remote_addrH;\
uint8_t data[num]; \
}
class DLLN3X
{
#endif
namespace zigbee_protocol {
class DLLN3X {
private:
void _clear();
bool _online = false, _recv_lock = false;
int _pack(uint8_t buf[], uint8_t data[], int length);
int _depack(uint8_t buf[], uint8_t data[], int length);
Stream *_DSerial;
void (*_callback) (uint8_t orig_port,
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length)=nullptr;
uint8_t _self_channel = 0;
uint16_t _self_addr = 0x0000, _self_network_id = 0x0000;
uint32_t _self_baud_rate = 0;
const uint32_t _baud_rate_list[13] = {2400, 4800, 9600, 14400, 19200,
28800, 38400, 57600, 115200,
230400, 125000, 250000, 500000};
Stream* _DSerial;
void (*_callback)(ZigbeeFrame& zf) = nullptr;
public:
enum CONFIG_RW_MASK {READ = 0x00, WRITE = 0x10};
enum CONFIG { ADDR = 0x01, NETWORKID = 0x02, CHANNEL = 0x03, BAUDRATE = 0x04 , SOFT_REBOOT = 0x10};
enum CONFIG_RESPONSE {
DONE = 0x00,
PORT_REMOTE_ACCESS_DENIED = 0xF0,
CMD_ERROR = 0xF8,
PKG_LENGTH_ERROR = 0xF9,
PKG_DATA_ERROR = 0xFA
};
enum PIN_CONTROL{ HIGH = 0x11, LOW = 0x10, READ_PIN = 0x12};
enum PIN{ PIN4 = 0x44, PIN5 = 0x45};
DLLN3X();
~DLLN3X();
void init(HardwareSerial *DSerial);
void init(SoftwareSerial *DSerial);
void recv(zigbee_frame *frame);
bool recv(uint8_t *orig_port,
uint8_t *dest_port, uint16_t *addr,
uint8_t data[], int *length);
bool send(uint8_t orig_port,
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length);
bool send(zigbee_frame *frame);
void rled_blink(uint8_t orig_port = 0x80,
uint16_t addr = 0x00, uint8_t time = 50);
void loop();
void setcallback(void (*callback)(uint8_t orig_port,
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length));
uint16_t read_addr();
uint16_t self_addr = 0x0000;
};
void init(HardwareSerial* DSerial);
#if __has_include(<SoftwareSerial.h>)
void init(SoftwareSerial* DSerial);
#endif
ZigbeeFrame recv(bool non_blocked = true);
bool send(ZigbeeFrame zf);
bool send_cmd(uint8_t des_port, uint8_t arg, uint8_t* data = nullptr, uint8_t data_length = 0);
void rled_blink(uint8_t time = 50);
void loop();
void setcallback(void (*callback)(ZigbeeFrame& zf));
uint16_t rw_config(CONFIG arg, uint16_t data = 0, CONFIG_RW_MASK mask = CONFIG_RW_MASK::READ);
uint8_t read_network_id();
uint8_t set_network_id(uint16_t network_id);
uint8_t read_channel();
uint8_t set_channel(uint8_t channel);
uint16_t read_addr();
uint8_t set_addr(uint16_t addr);
uint32_t read_baudrate();
uint8_t set_baudrate(uint32_t baud_rate);
void soft_reboot();
uint8_t get_link_quality(uint16_t des_addr, uint16_t src_addr = 0x0000);
enum PIN_CONTROL pin_control(PIN pin, PIN_CONTROL cmd);
};
}
#endif

259
src/zigbeeframe.h Normal file
View File

@ -0,0 +1,259 @@
#ifndef _ZIGBEEFRAME_H_
#define _ZIGBEEFRAME_H_
#include <Arduino.h>
#include <cstring>
#include <iostream>
#include <vector>
namespace zigbee_protocol {
class ZigbeeFrame {
private:
const uint8_t head = 0xFE, tail = 0xFF;
uint8_t _length = 0, _src_port = 0, _des_port = 0;
uint8_t _pack_len = 0;
uint16_t _remote_addr = 0;
std::vector<uint8_t> _data, _packed_data, _package;
public:
ZigbeeFrame(char* data) { setData((uint8_t*)data, strlen(data)); };
ZigbeeFrame(char* data, uint8_t length) { setData((uint8_t*)data, length); };
ZigbeeFrame(uint8_t* data, uint8_t length) { setData(data, length); };
ZigbeeFrame(uint8_t src_port, uint8_t des_port, uint16_t remote_addr, uint8_t* data, uint8_t data_length)
{
_length = data_length + 4;
_src_port = src_port;
_des_port = des_port;
_remote_addr = remote_addr;
setData(data, data_length);
};
ZigbeeFrame(uint8_t src_port, uint8_t des_port, uint16_t remote_addr, char* data, uint8_t data_length)
{
_length = data_length + 4;
_src_port = src_port;
_des_port = des_port;
_remote_addr = remote_addr;
setData((uint8_t*)data, data_length);
};
ZigbeeFrame(uint8_t src_port, uint8_t des_port, uint16_t remote_addr)
{
_src_port = src_port;
_des_port = des_port;
_remote_addr = remote_addr;
};
ZigbeeFrame(const ZigbeeFrame& zf)
{
_length = zf._length;
_src_port = zf._src_port;
_des_port = zf._des_port;
_pack_len = zf._pack_len;
_remote_addr = zf._remote_addr;
_data = zf._data;
_packed_data = zf._packed_data;
_package = zf._package;
};
ZigbeeFrame(const ZigbeeFrame* zf)
{
_length = zf->_length;
_src_port = zf->_src_port;
_des_port = zf->_des_port;
_pack_len = zf->_pack_len;
_remote_addr = zf->_remote_addr;
_data = zf->_data;
_packed_data = zf->_packed_data;
_package = zf->_package;
};
ZigbeeFrame() {};
~ZigbeeFrame() {};
void setDesPort(uint8_t des_port) { _des_port = des_port; };
void setSrcPort(uint8_t src_port) { _src_port = src_port; };
void setRemoteAddr(uint16_t remote_addr) { _remote_addr = remote_addr; };
uint8_t getDesPort() { return _des_port; };
uint8_t getSrcPort() { return _src_port; };
uint16_t getRemoteAddr() { return _remote_addr; };
uint8_t getLength(){ return _data.size() + 4;};
uint8_t getDataLength(){ return _data.size();};
std::vector<uint8_t>& getData(){ return _data; };
void setData(uint8_t* data, uint8_t length)
{
_data.clear();
addData(data, length);
};
void setData(char* data) { setData((uint8_t*)data, strlen(data)); };
void setData(char* data, uint8_t length) { setData((uint8_t*)data, length); };
void setData(std::vector<uint8_t> data) { _data = data; };
void addData(char* data) { addData(data, strlen(data)); };
void addData(uint8_t* data, uint8_t length)
{
for (uint8_t i = 0; i < length; i++) {
_data.push_back(data[i]);
}
};
void addData(char* data, uint8_t length) { addData((uint8_t*)data, length); };
void addData(std::vector<uint8_t> data) { _data.insert(_data.end(), data.begin(), data.end()); };
void clear()
{
_package.clear();
_packed_data.clear();
_data.clear();
};
uint8_t* data()
{
get_package();
return _package.data();
};
uint8_t data_size() { return _data.size(); };
uint8_t size()
{
get_package();
return _package.size();
};
void append(uint8_t byte)
{
_data.push_back(byte);
_length = _data.size() + 4;
};
void pack() { pack(_data, _packed_data); };
void pack(std::vector<uint8_t> data, std::vector<uint8_t>& pack_data)
{
pack_data.clear();
for (int i = 0; i < data.size(); i++) {
if (data[i] == 0xFE) {
pack_data.push_back(data[i]);
pack_data.push_back(0xFC);
} else if (data[i] == 0xFF) {
pack_data.push_back(0xFE);
pack_data.push_back(0xFD);
} else {
pack_data.push_back(data[i]);
}
}
};
void depack() { depack(_data, _packed_data); };
void depack(std::vector<uint8_t>& data, std::vector<uint8_t> pack_data)
{
data.clear();
for (int i = 0; i < pack_data.size(); i++) {
if (pack_data[i] != 0xFE) {
data.push_back(pack_data[i]);
} else if (pack_data[i + 1] == 0xFD) {
data.push_back(0xFF);
i++;
} else if (pack_data[i + 1] == 0xFC) {
data.push_back(0xFE);
i++;
}
}
};
void make_package(uint8_t src_port, uint8_t des_port, uint16_t remote_addr, std::vector<uint8_t>& package,
std::vector<uint8_t> data, std::vector<uint8_t>& pack_data)
{
pack(data, pack_data);
package.clear();
package.push_back(head);
package.push_back(data.size() + 4);
package.push_back(src_port);
package.push_back(des_port);
package.push_back(remote_addr & 0xFF);
package.push_back((remote_addr >> 8) & 0xFF);
package.insert(package.end(), pack_data.begin(), pack_data.end());
package.push_back(tail);
};
std::vector<uint8_t> get_package()
{
make_package(_src_port, _des_port, _remote_addr, _package, _data, _packed_data);
return _package;
};
void load_package(std::vector <uint8_t> &buf)
{
load_package(buf.data(),buf.size());
};
void load_package(uint8_t *buf, uint8_t length)
{
_packed_data.clear();
for (uint8_t i=0;i<length;i++)
{
_package.push_back(buf[i]);
if (i>5 && i<length-1)
_packed_data.push_back(buf[i]);
}
_length = _package[1];
_src_port = _package[2];
_des_port = _package[3];
_remote_addr = _package[4] | (_package[5]<<8);
depack(_data, _packed_data);
};
void print()
{
get_package();
Serial.print("src_port:");
Serial.println(_src_port, HEX);
Serial.print("des_port:");
Serial.println(_des_port, HEX);
Serial.print("remote_addr:");
Serial.println(_remote_addr, HEX);
Serial.print("data:");
for (auto byte : _data) {
char buf[4];
sprintf(buf, "%02X ", byte);
Serial.print(buf);
}
Serial.println();
Serial.print("packed_data:");
for (auto byte : _packed_data) {
char buf[4];
sprintf(buf, "%02X ", byte);
Serial.print(buf);
}
Serial.println();
Serial.print("package:");
for (auto byte : _package) {
char buf[4];
sprintf(buf, "%02X ", byte);
Serial.print(buf);
}
Serial.println();
}
ZigbeeFrame operator+(const ZigbeeFrame& zf)
{
ZigbeeFrame temp(this);
temp.addData(zf._data);
return temp;
};
void operator+=(const ZigbeeFrame& zf) { addData(zf._data); };
void operator=(const ZigbeeFrame& zf)
{
_length = zf._length;
_src_port = zf._src_port;
_des_port = zf._des_port;
_pack_len = zf._pack_len;
_remote_addr = zf._remote_addr;
_data = zf._data;
_packed_data = zf._packed_data;
_package = zf._package;
};
ZigbeeFrame operator+(char* data)
{
ZigbeeFrame temp(this);
temp.addData(data);
return temp;
};
uint8_t& operator[](uint8_t i)
{
get_package();
return _package[i];
};
void operator+=(char* data) { addData(data, (uint8_t)strlen(data)); };
friend std::ostream& operator<<(std::ostream& os, const ZigbeeFrame& zf)
{
os << "src_port:" << zf._src_port << '\n'
<< "des_port:" << zf._des_port << '\n'
<< "remote_addr:" << zf._remote_addr << '\n'
<< "packed_data:";
for (auto byte : zf._packed_data)
os << std::hex << std::uppercase << byte << ' ';
os << '\n';
return os;
}
};
}
#endif