diff --git a/README.md b/README.md index 0bfed88..66e27cb 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/examples/dlln3x_test/dlln3x_test.ino b/examples/dlln3x_test/dlln3x_test.ino index 6d058a3..2b511b1 100644 --- a/examples/dlln3x_test/dlln3x_test.ino +++ b/examples/dlln3x_test/dlln3x_test.ino @@ -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(); } } \ No newline at end of file diff --git a/imgs/example.png b/imgs/example.png index e96ad34..7cdb86d 100644 Binary files a/imgs/example.png and b/imgs/example.png differ diff --git a/keywords.txt b/keywords.txt index 51f0d1e..e8d11dc 100644 --- a/keywords.txt +++ b/keywords.txt @@ -7,24 +7,53 @@ ####################################### DLLN3X KEYWORD1 -zigbee_frame KEYWORD1 +ZigbeeFrame KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### -_clear KEYWORD2 -_pack KEYWORD2 -_depack KEYWORD2 -_callback KEYWORD2 -init KEYWORD2 -recv KEYWORD2 -send KEYWORD2 -rled_blink KEYWORD2 -loop KEYWORD2 -setcallback KEYWORD2 -read_addr 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) ####################################### diff --git a/library.properties b/library.properties index eb70bd4..280d76f 100644 --- a/library.properties +++ b/library.properties @@ -1,11 +1,11 @@ name= DLLN3X ZigBee Mesh Module Library -version= 1.0.4 +version= 1.1.0 author= Dylan Liu maintainer= Dylan Liu 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 diff --git a/src/DLLN3X.cpp b/src/DLLN3X.cpp index 1c6663c..a12d326 100644 --- a/src/DLLN3X.cpp +++ b/src/DLLN3X.cpp @@ -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() +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; - } - else if (data[i] == 0xFF) - { - buf[count++] = 0xFE; - buf[count++] = 0xFD; - } - else - { - buf[count++] = data[i]; - } + uint8_t buf[65] = "", length = 0; + ZigbeeFrame zf; + if (non_blocked) { + if (_DSerial->available() < 6) + return zf; } - 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 + send_cmd(0x21, cmd_arg, (uint8_t *)&data, 1); } else - { - this->self_addr = data[1] + (data[2] << 8); - return this->self_addr; + 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; } diff --git a/src/DLLN3X.h b/src/DLLN3X.h index 028bdef..9099e77 100644 --- a/src/DLLN3X.h +++ b/src/DLLN3X.h @@ -1,62 +1,60 @@ #ifndef _DLLN3X_H_ #define _DLLN3X_H_ +#include "zigbeeframe.h" #include +#if __has_include() #include - -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() + 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 diff --git a/src/zigbeeframe.h b/src/zigbeeframe.h new file mode 100644 index 0000000..aa7c431 --- /dev/null +++ b/src/zigbeeframe.h @@ -0,0 +1,259 @@ +#ifndef _ZIGBEEFRAME_H_ +#define _ZIGBEEFRAME_H_ +#include +#include +#include +#include + +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 _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& 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 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 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 data, std::vector& 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& data, std::vector 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& package, + std::vector data, std::vector& 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 get_package() + { + make_package(_src_port, _des_port, _remote_addr, _package, _data, _packed_data); + return _package; + }; + void load_package(std::vector &buf) + { + load_package(buf.data(),buf.size()); + }; + void load_package(uint8_t *buf, uint8_t length) + { + _packed_data.clear(); + for (uint8_t i=0;i5 && i