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 # DLLN3X_zigbee_mesh_module_library
This library allows you to use DLLN3X ZigBee mesh module very easily. 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 # Available Features
1. Basic message sending and receiving. 1. Basic message sending and receiving.
2. Module address reading. 2. Module address reading.
3. On-chip red led flashing control. 3. On-chip red led flashing control.
4. Configuration reading, modification (baud rate, address, etc.).(TODO) 4. Configuration reading, modification (baud rate, address, etc.).
5. Error Report.(TODO) 5. Error Report.
6. Link quality test.(TODO) 6. Link quality test.
7. On-chip pin control.(TODO) 7. On-chip pin control.
# Example run results # Example run results
@ -17,6 +19,13 @@ This library allows you to use DLLN3X ZigBee mesh module very easily.
# Change Log # 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** **V1.0.4 2023.1.26**
- Bug fixes and stability improvements. - Bug fixes and stability improvements.

View File

@ -1,16 +1,15 @@
#include "DLLN3X.h" #include "DLLN3X.h"
using namespace zigbee_protocol;
DLLN3X dlln33; //Instantiating DLLN3X module DLLN3X dlln33; //Instantiating DLLN3X module
zigbee_frame zframe; void zigbee_call_back(ZigbeeFrame &zframe) {
void zigbee_call_back(uint8_t orig_port, switch (zframe.getDesPort()) {
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length) {
switch (dest_port) {
case 0x82: case 0x82:
{ {
/* Do everything you want to do */ /* Do everything you want to do */
char temp[200]; 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); Serial.println(temp);
break; break;
} }
@ -30,21 +29,32 @@ void setup() {
Serial.println("Waiting for DLLN3X to connect........"); Serial.println("Waiting for DLLN3X to connect........");
delay(1000); delay(1000);
} }
char temp[20]; char temp[50];
sprintf(temp, "DLLN3X addr: 0x%04X.",dlln33.read_addr()); sprintf(temp, "DLLN3X addr: 0x%04X.",dlln33.read_addr());
Serial.println(temp); 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; uint64_t interval = 5000, pre_milli = 0;
void loop() { void loop() {
dlln33.loop(); dlln33.loop();
if (millis() - pre_milli >= interval) { if (millis() - pre_milli >= interval) {
zframe.src_port = 0x81; ZigbeeFrame zf;
zframe.des_port = 0x82; zf.setSrcPort(0x81);
*((uint16_t *)&zframe.remote_addrL) = dlln33.read_addr(); // send pkg to self. zf.setDesPort(0x82);
strncpy((char*)zframe.data,"Hello to port 0x82!",19); zf.setRemoteAddr(dlln33.read_addr());
zframe.length = 19; zf.setData("Hello to port 0x82!");
dlln33.send(&zframe); dlln33.send(zf);
zf = zf + "I'm port 0x81!";
dlln33.send(zf);
pre_milli = millis(); 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 DLLN3X KEYWORD1
zigbee_frame KEYWORD1 ZigbeeFrame KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
####################################### #######################################
_clear KEYWORD2 setDesPort KEYWORD2
_pack KEYWORD2 setSrcPort KEYWORD2
_depack KEYWORD2 setRemoteAddr KEYWORD2
_callback KEYWORD2 getDesPort KEYWORD2
init KEYWORD2 getSrcPort KEYWORD2
recv KEYWORD2 getRemoteAddr KEYWORD2
send KEYWORD2 getLength KEYWORD2
rled_blink KEYWORD2 getDataLength KEYWORD2
loop KEYWORD2 getData KEYWORD2
setcallback KEYWORD2 setData KEYWORD2
read_addr 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) # Instances (KEYWORD2)
####################################### #######################################

View File

@ -1,11 +1,11 @@
name= DLLN3X ZigBee Mesh Module Library name= DLLN3X ZigBee Mesh Module Library
version= 1.0.4 version= 1.1.0
author= Dylan Liu <mentalflow@ourdocs.cn> author= Dylan Liu <mentalflow@ourdocs.cn>
maintainer= Dylan Liu <mentalflow@ourdocs.cn> maintainer= Dylan Liu <mentalflow@ourdocs.cn>
sentence= This library allows you to use DLLN3X ZigBee mesh module very easily. 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 category= Communication
architectures= * architectures= *
includes= DLLN3X.h includes= DLLN3X.h zigbeeframe.h
license= MIT license= MIT
url= https://github.com/mentalfl0w/DLLN3X_zigbee_mesh_module_library url= https://github.com/mentalfl0w/DLLN3X_zigbee_mesh_module_library

View File

@ -1,218 +1,290 @@
#include "DLLN3X.h" #include "DLLN3X.h"
DLLN3X::DLLN3X(){} using namespace zigbee_protocol;
DLLN3X::~DLLN3X() {}
void DLLN3X::init(HardwareSerial *DSerial) DLLN3X::DLLN3X() { }
DLLN3X::~DLLN3X() { }
void DLLN3X::init(HardwareSerial* DSerial)
{ {
_DSerial = DSerial; _DSerial = DSerial;
DSerial->begin(115200); DSerial->begin(115200);
DSerial->setTimeout(10000);
rled_blink(); rled_blink();
read_addr(); 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 = DSerial;
DSerial->begin(115200); DSerial->begin(115200);
DSerial->setTimeout(10000);
rled_blink(); rled_blink();
read_addr(); read_addr();
read_baudrate();
read_channel();
read_network_id();
} }
#endif
void DLLN3X::_clear() ZigbeeFrame DLLN3X::recv(bool non_blocked)
{ {
while (_DSerial->available()) uint8_t buf[65] = "", length = 0;
_DSerial->read(); ZigbeeFrame zf;
} if (non_blocked) {
if (_DSerial->available() < 6)
int DLLN3X::_pack(uint8_t buf[], uint8_t data[], int length) return zf;
{
int count = 0;
for (int i = 0; i < length; i++)
{
if (data[i] == 0xFE)
{
buf[count++] = data[i];
buf[count++] = 0xFC;
}
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; _recv_lock = true;
_DSerial->readBytesUntil(0xFF, (char *)frame, 64); length = _DSerial->readBytesUntil(0xFF, buf, 65);
_DSerial->read(); buf[length] = _DSerial->read();
_recv_lock = false; _recv_lock = false;
zf.load_package(buf, length + 1);
return zf;
} }
bool DLLN3X::recv(uint8_t *orig_port, bool DLLN3X::send(ZigbeeFrame zf)
uint8_t *dest_port, uint16_t *addr,
uint8_t data[], int *length)
{ {
_recv_lock = true; if (zf.getSrcPort() < 0x80)
uint8_t buf[200] = "";
uint8_t head = 0, tail = 0;
if(_DSerial->available()<6)
return false; return false;
head = _DSerial->read(); return _DSerial->write(zf.data(), zf.size());
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;
}
} }
bool DLLN3X::send(uint8_t orig_port, bool DLLN3X::send_cmd(uint8_t des_port, uint8_t arg, uint8_t* data, uint8_t data_length)
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length)
{ {
if (orig_port<0x80) ZigbeeFrame zf(0x80, des_port, 0x0000);
if (data_length - 4 > 63 - 1)
return false; return false;
uint8_t send_buf[208] = {0xFE}, buf[200] = ""; zf.append(arg);
uint8_t head = 0, buf_length = 0; zf.addData(data, data_length);
buf_length = _pack(buf, data, length); return send(zf);
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);
} }
bool DLLN3X::send(zigbee_frame *frame) void DLLN3X::rled_blink(uint8_t time)
{
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)
{ {
uint8_t gap = 5; uint8_t gap = 5;
for (int i = 0; i < time; i += gap) for (int i = 0; i < time; i += gap) {
{ if (i % 2 != 0)
if (i%2!=0) send_cmd(0x20, gap);
send(orig_port, 0x20, addr, &gap, 1);
else else
delay(gap*200); delay(gap * 250);
} }
} }
uint16_t DLLN3X::read_addr() uint16_t DLLN3X::read_addr()
{ {
if (self_addr!=0) if (_self_addr != 0)
return self_addr; return _self_addr;
uint8_t orig_port = 0xFF, dest_port = 0xFF; _self_addr = rw_config(CONFIG::ADDR);
uint8_t arg = 0x01; return _self_addr;
uint16_t addr = 0xFFFF; }
uint8_t data[60] = "";
int length = 0; uint8_t DLLN3X::set_addr(uint16_t addr)
send(0x80, 0x21, 0x0000, &arg, 1); {
while(_DSerial->available()<10); uint8_t resp = rw_config(CONFIG::ADDR, addr, CONFIG_RW_MASK::WRITE);
_recv_lock = true; if (resp == CONFIG_RESPONSE::DONE)
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)
{ {
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
send_cmd(0x21, cmd_arg, (uint8_t *)&data, 1);
} }
else else
{ send_cmd(0x21, cmd_arg);
this->self_addr = data[1] + (data[2] << 8); ZigbeeFrame zf = recv(false);
return this->self_addr; 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() void DLLN3X::loop()
{ {
uint8_t orig_port = 0xFF, dest_port = 0xFF; if (_DSerial->available() > 7 && !_recv_lock) {
uint16_t addr = 0xFFFF; ZigbeeFrame zf = recv();
uint8_t data[200] = "";
int length = 0;
if (_DSerial->available()>7&&!_recv_lock)
{
recv(&orig_port,&dest_port,&addr,data,&length);
Serial.print("Message: "); Serial.print("Message: ");
for (int i = 0; i < length;i++) for (int i = 0; i < zf.size(); i++) {
{
char temp[3]; char temp[3];
sprintf(temp, "%02X ", data[i]); sprintf(temp, "%02X ", zf[i]);
Serial.print(temp); Serial.print(temp);
} }
char temp[200]; char temp[30];
sprintf(temp, "at port %02X from %04X:%02X.", dest_port, addr, orig_port); sprintf(temp, "at port %02X from %04X:%02X.", zf.getDesPort(), zf.getRemoteAddr(), zf.getSrcPort());
Serial.println(temp); Serial.println(temp);
if (_callback!=nullptr) if (zf.getSrcPort() == 0x22)
_callback(orig_port, dest_port, addr, data, length); {
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, void DLLN3X::setcallback(void (*callback)(ZigbeeFrame& zf)) { _callback = callback; }
uint8_t dest_port, uint16_t addr,
uint8_t data[], int length))
{
_callback = callback;
}

View File

@ -1,62 +1,60 @@
#ifndef _DLLN3X_H_ #ifndef _DLLN3X_H_
#define _DLLN3X_H_ #define _DLLN3X_H_
#include "zigbeeframe.h"
#include <Arduino.h> #include <Arduino.h>
#if __has_include(<SoftwareSerial.h>)
#include <SoftwareSerial.h> #include <SoftwareSerial.h>
#endif
typedef struct zigbee_frame namespace zigbee_protocol {
{ class DLLN3X {
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
{
private: private:
void _clear();
bool _online = false, _recv_lock = false; bool _online = false, _recv_lock = false;
int _pack(uint8_t buf[], uint8_t data[], int length); uint8_t _self_channel = 0;
int _depack(uint8_t buf[], uint8_t data[], int length); uint16_t _self_addr = 0x0000, _self_network_id = 0x0000;
Stream *_DSerial; uint32_t _self_baud_rate = 0;
void (*_callback) (uint8_t orig_port, const uint32_t _baud_rate_list[13] = {2400, 4800, 9600, 14400, 19200,
uint8_t dest_port, uint16_t addr, 28800, 38400, 57600, 115200,
uint8_t data[], int length)=nullptr; 230400, 125000, 250000, 500000};
Stream* _DSerial;
void (*_callback)(ZigbeeFrame& zf) = nullptr;
public: 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();
~DLLN3X(); ~DLLN3X();
void init(HardwareSerial *DSerial); void init(HardwareSerial* DSerial);
void init(SoftwareSerial *DSerial); #if __has_include(<SoftwareSerial.h>)
void recv(zigbee_frame *frame); void init(SoftwareSerial* DSerial);
bool recv(uint8_t *orig_port, #endif
uint8_t *dest_port, uint16_t *addr, ZigbeeFrame recv(bool non_blocked = true);
uint8_t data[], int *length); bool send(ZigbeeFrame zf);
bool send(uint8_t orig_port, bool send_cmd(uint8_t des_port, uint8_t arg, uint8_t* data = nullptr, uint8_t data_length = 0);
uint8_t dest_port, uint16_t addr, void rled_blink(uint8_t time = 50);
uint8_t data[], int length); void loop();
bool send(zigbee_frame *frame); void setcallback(void (*callback)(ZigbeeFrame& zf));
void rled_blink(uint8_t orig_port = 0x80, uint16_t rw_config(CONFIG arg, uint16_t data = 0, CONFIG_RW_MASK mask = CONFIG_RW_MASK::READ);
uint16_t addr = 0x00, uint8_t time = 50); uint8_t read_network_id();
void loop(); uint8_t set_network_id(uint16_t network_id);
void setcallback(void (*callback)(uint8_t orig_port, uint8_t read_channel();
uint8_t dest_port, uint16_t addr, uint8_t set_channel(uint8_t channel);
uint8_t data[], int length)); uint16_t read_addr();
uint16_t read_addr(); uint8_t set_addr(uint16_t addr);
uint16_t self_addr = 0x0000; 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 #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