Skip to content

Commit

Permalink
Template layer for radio HW abstraction (#26)
Browse files Browse the repository at this point in the history
* Update for recent template changes to RF24Network and RF24Mesh
  see nRF24/RF24Network#204
* convert RF24Gateway class into a template
  uses a typedef for backward compatibility 
* Update docs for v2.0

---------

Co-authored-by: TMRh20 <[email protected]>
  • Loading branch information
2bndy5 and TMRh20 authored Jun 21, 2023
1 parent b8b7d8e commit 7bf8ec0
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 33 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,34 @@ RF24Ethernet allows small Arduino/AVR devices to communicate using TCP/IP over n
RF24Gateway allows a RPi/Linux device to act as a gateway for those nodes, handling IP traffic automatically, while allowing users
to utilize standard RF24Network messages as well.

Introducing **RF24Network & RF24Mesh & RF24Gateway v2.0** with some *significant API changes*, adding the use of [C++ Templates](https://cplusplus.com/doc/oldtutorial/templates/)
in order to support a range of ESB enabled radios, most recently NRF52x radios.

**Important Notes:**
- Any network layer that uses v2 needs to have RF24Network/RF24Mesh dependencies of v2 or newer. RF24 v1.x is an exception here.
- General usage should remain backward compatible, see the included examples of the related libraries for more info
- Any third party libs that extend the network/mesh layer may also need to be updated to incorporate the new templated class prototypes:
```cpp
template<class radio_t>
class ESBNetwork;

template<class network_t, class radio_t>
class ESBMesh;
```
- Third party libs should also be able to use the backward-compatible typedef in their template:
- ESBGateway.h:
```cpp
template<typename network_t, typename mesh_t>
class ESBGateway
```
and inform the compiler what types they intend to support:
- ESBGateway.cpp:
```cpp
template class ESBGateway<RF24Network, RF24Mesh>;
```
- The auto installers do not perform a version check like package managers, so having the correct versions of the software is important.
- We *will* be maintaining the v1.x versions with bugfixes etc for those who cannot or do not wish to migrate to the newer template approach.
### Documentation:
http://nRF24.github.io/RF24Gateway
Expand Down
72 changes: 49 additions & 23 deletions RF24Gateway.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,34 @@

/***************************************************************************************/

RF24Gateway::RF24Gateway(RF24& _radio, RF24Network& _network, RF24Mesh& _mesh) : radio(_radio), network(_network), mesh(_mesh)
template<class mesh_t, class network_t, class radio_t>
ESBGateway<mesh_t, network_t, radio_t>::ESBGateway(radio_t& _radio, network_t& _network, mesh_t& _mesh) : radio(_radio), network(_network), mesh(_mesh)
{
interruptInProgress = 0;
interruptsEnabled = 1;
}

/***************************************************************************************/

void RF24Gateway::begin(uint8_t nodeID, uint8_t _channel, rf24_datarate_e data_rate)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::begin(uint8_t nodeID, uint8_t _channel, rf24_datarate_e data_rate)
{
mesh_enabled = true;
begin(true, mesh_enabled, 0, nodeID, data_rate, _channel);
}

/***************************************************************************************/

void RF24Gateway::begin(uint16_t address, uint8_t _channel, rf24_datarate_e data_rate, bool meshEnable, uint8_t nodeID)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::begin(uint16_t address, uint8_t _channel, rf24_datarate_e data_rate, bool meshEnable, uint8_t nodeID)
{
begin(0, mesh_enabled, address, nodeID, data_rate, _channel);
}

/***************************************************************************************/

bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel)
template<class mesh_t, class network_t, class radio_t>
bool ESBGateway<mesh_t, network_t, radio_t>::begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel)
{
#if (DEBUG_LEVEL >= 1)
printf("GW Begin\n");
Expand Down Expand Up @@ -93,7 +97,8 @@ bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8

/***************************************************************************************/

void RF24Gateway::loadRoutingTable()
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::loadRoutingTable()
{
std::ifstream infile("routing.txt", std::ifstream::in);
if (!infile) {
Expand Down Expand Up @@ -145,14 +150,16 @@ void RF24Gateway::loadRoutingTable()

/***************************************************************************************/

bool RF24Gateway::meshEnabled()
template<class mesh_t, class network_t, class radio_t>
bool ESBGateway<mesh_t, network_t, radio_t>::meshEnabled()
{
return mesh_enabled;
}

/***************************************************************************************/

int RF24Gateway::configDevice(uint16_t address)
template<class mesh_t, class network_t, class radio_t>
int ESBGateway<mesh_t, network_t, radio_t>::configDevice(uint16_t address)
{
std::string tunTapDevice = "tun_nrf24";
strcpy(tunName, tunTapDevice.c_str());
Expand All @@ -179,7 +186,8 @@ int RF24Gateway::configDevice(uint16_t address)

/***************************************************************************************/

int RF24Gateway::allocateTunDevice(char* dev, int flags, uint16_t address)
template<class mesh_t, class network_t, class radio_t>
int ESBGateway<mesh_t, network_t, radio_t>::allocateTunDevice(char* dev, int flags, uint16_t address)
{
struct ifreq ifr;
int fd;
Expand Down Expand Up @@ -241,7 +249,8 @@ int RF24Gateway::allocateTunDevice(char* dev, int flags, uint16_t address)

/***************************************************************************************/

int RF24Gateway::setIP(char* ip_addr, char* mask)
template<class mesh_t, class network_t, class radio_t>
int ESBGateway<mesh_t, network_t, radio_t>::setIP(char* ip_addr, char* mask)
{
struct ifreq ifr;
struct sockaddr_in sin;
Expand Down Expand Up @@ -301,7 +310,9 @@ int RF24Gateway::setIP(char* ip_addr, char* mask)
}

/***************************************************************************************/
void RF24Gateway::interrupts(bool enable)

template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::interrupts(bool enable)
{
if (enable) {
interruptsEnabled = enable;
Expand All @@ -319,7 +330,8 @@ void RF24Gateway::interrupts(bool enable)

/***************************************************************************************/

void RF24Gateway::update(bool interrupts)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::update(bool interrupts)
{

if (interrupts) {
Expand All @@ -346,7 +358,8 @@ void RF24Gateway::update(bool interrupts)

/***************************************************************************************/

void RF24Gateway::poll(uint32_t waitDelay)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::poll(uint32_t waitDelay)
{

handleRX(waitDelay);
Expand All @@ -369,9 +382,11 @@ void RF24Gateway::poll(uint32_t waitDelay)
handleRadioOut();
interruptsEnabled = 1;
}

/***************************************************************************************/

void RF24Gateway::handleRadioIn()
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::handleRadioIn()
{
if (mesh_enabled) {
while (mesh.update()) {
Expand Down Expand Up @@ -422,7 +437,8 @@ void RF24Gateway::handleRadioIn()

/***************************************************************************************/

struct in_addr RF24Gateway::getLocalIP()
template<class mesh_t, class network_t, class radio_t>
struct in_addr ESBGateway<mesh_t, network_t, radio_t>::getLocalIP()
{
struct ifaddrs *ifap, *ifa;
int family, s, n;
Expand Down Expand Up @@ -458,7 +474,8 @@ struct in_addr RF24Gateway::getLocalIP()

/***************************************************************************************/

void RF24Gateway::handleRadioOut()
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::handleRadioOut()
{
bool ok = 0;

Expand Down Expand Up @@ -588,7 +605,8 @@ void RF24Gateway::handleRadioOut()

/***************************************************************************************/

void RF24Gateway::handleRX(uint32_t waitDelay)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::handleRX(uint32_t waitDelay)
{
fd_set socketSet;
struct timeval selectTimeout;
Expand Down Expand Up @@ -637,7 +655,8 @@ void RF24Gateway::handleRX(uint32_t waitDelay)

/***************************************************************************************/

void RF24Gateway::handleTX()
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::handleTX()
{

if (rxQueue.size() < 1)
Expand Down Expand Up @@ -684,21 +703,24 @@ void RF24Gateway::handleTX()
rxQueue.pop();
}

/***************************************************************************************/
/***************************************************************************************
void printPayload(std::string buffer, std::string debugMsg = "")
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::printPayload(std::string buffer, std::string debugMsg)
{
}
/***************************************************************************************/
/***************************************************************************************
void printPayload(char* buffer, int nread, std::string debugMsg = "")
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::printPayload(char* buffer, int nread, std::string debugMsg)
{
}
/***************************************************************************************/

void RF24Gateway::setupSocket()
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::setupSocket()
{
int ret;
const char* myAddr = "127.0.0.1";
Expand All @@ -720,7 +742,8 @@ void RF24Gateway::setupSocket()

/***************************************************************************************/

void RF24Gateway::sendUDP(uint8_t nodeID, RF24NetworkFrame frame)
template<class mesh_t, class network_t, class radio_t>
void ESBGateway<mesh_t, network_t, radio_t>::sendUDP(uint8_t nodeID, RF24NetworkFrame frame)
{

uint8_t buffer[MAX_PAYLOAD_SIZE + 11];
Expand All @@ -737,3 +760,6 @@ void RF24Gateway::sendUDP(uint8_t nodeID, RF24NetworkFrame frame)
exit(1);
}
}

// ensure the compiler is aware of the possible datatype for the template class
template class ESBGateway<ESBMesh<ESBNetwork<RF24>, RF24>, ESBNetwork<RF24>, RF24>;
60 changes: 50 additions & 10 deletions RF24Gateway.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,29 @@
#define BACKLOG 10 /* Passed to listen() */

class RF24;
class RF24Network;
class RF24Mesh;

class RF24Gateway
template<class radio_t>
class ESBNetwork;

template<class network_t, class radio_t>
class ESBMesh;

/**
* @tparam mesh_t The `mesh` object's type. Defaults to `RF24Mesh` for legacy behavior.
* This new abstraction is really meant for using the nRF52840 SoC as a drop-in replacement
* for the nRF24L01 radio. For more detail, see the
* [nrf_to_nrf Arduino library](https://github.com/TMRh20/nrf_to_nrf).
* @tparam network_t The `network` object's type. Defaults to `RF24Network` for legacy behavior.
* This new abstraction is really meant for using the nRF52840 SoC as a drop-in replacement
* for the nRF24L01 radio. For more detail, see the
* [nrf_to_nrf Arduino library](https://github.com/TMRh20/nrf_to_nrf).
* @tparam radio_t The `radio` object's type. Defaults to `RF24` for legacy behavior.
* This new abstraction is really meant for using the nRF52840 SoC as a drop-in replacement
* for the nRF24L01 radio. For more detail, see the
* [nrf_to_nrf Arduino library](https://github.com/TMRh20/nrf_to_nrf).
*/
template<class mesh_t = ESBMesh<ESBNetwork<RF24>, RF24>, class network_t = ESBNetwork<RF24>, class radio_t = RF24>
class ESBGateway
{

/**
Expand All @@ -55,9 +74,15 @@ class RF24Gateway

public:
/**
* RF24Gateway constructor.
* ESBGateway constructor.
* @code
* RF24 radio(7,8);
* RF24Network network(radio);
* RF24Mesh mesh(radio,network);
* RF24Gateway gateway(radio,network,mesh);
* @endcode
*/
RF24Gateway(RF24& _radio, RF24Network& _network, RF24Mesh& _mesh);
ESBGateway(radio_t& _radio, network_t& _network, mesh_t& _mesh);

/**
* Begin function for use with RF24Mesh (TUN interface)
Expand Down Expand Up @@ -199,9 +224,9 @@ class RF24Gateway
uint8_t routingTableSize;

private:
RF24& radio;
RF24Network& network;
RF24Mesh& mesh;
radio_t& radio;
network_t& network;
mesh_t& mesh;

bool begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel);
bool mesh_enabled;
Expand Down Expand Up @@ -235,8 +260,8 @@ class RF24Gateway
std::queue<msgStruct> rxQueue;
std::queue<msgStruct> txQueue;

void printPayload(std::string buffer, std::string debugMsg = "");
void printPayload(char* buffer, int nread, std::string debugMsg = "");
// void printPayload(std::string buffer, std::string debugMsg = "");
// void printPayload(char* buffer, int nread, std::string debugMsg = "");

int s; //Socket variable for sending UDP
void setupSocket();
Expand All @@ -246,6 +271,21 @@ class RF24Gateway
void loadRoutingTable();
};

/**
* A type definition of the template class `ESBGateway` to maintain backward compatibility.
*
* ```.cpp
* RF24 radio(7, 8);
* RF24Network network(radio);
* RF24Mesh mesh(radio, network);
*
* RF24Gateway gateway(radio, network, mesh);
* // is equivalent to
* ESBGateway<ESBMesh<ESBNetwork<RF24>, RF24>, ESBNetwork<RF24>, RF24> gateway(radio, network, mesh);
* ```
*/
typedef ESBGateway<ESBMesh<ESBNetwork<RF24>, RF24>, ESBNetwork<RF24>, RF24> RF24Gateway;

/**
* @example RF24GatewayNode.cpp
*
Expand Down
30 changes: 30 additions & 0 deletions docs/main_page.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,36 @@ standard RF24Network payloads.

This allows users to deploy and manage hybrid networks, consisting of nodes communicating via TCP/IP and RF24Network Messages

## News - 2023 API Changes

Introducing **RF24Network, RF24Mesh & RF24Gateway v2.0** with some *significant API changes*, adding the use of [C++ Templates](https://cplusplus.com/doc/oldtutorial/templates/)
in order to support a range of ESB enabled radios, most recently NRF52x radios.

**Important Notes:**
- Any network layer that uses v2 needs to have RF24Network/RF24Mesh dependencies of v2 or newer. RF24 v1.x is an exception here.
- General usage should remain backward compatible, see the included examples of the related libraries for more info
- Any third party libs that extend the network/mesh layer may also need to be updated to incorporate the new templated class prototypes:
```cpp
template<class radio_t>
class ESBNetwork;

template<class network_t, class radio_t>
class ESBMesh;
```
- Third party libs should also be able to use the backward-compatible typedef in their template:
- ESBGateway.h:
```cpp
template<typename network_t, typename mesh_t>
class ESBGateway
```
and inform the compiler what types they intend to support:
- ESBGateway.cpp:
```cpp
template class ESBGateway<RF24Network, RF24Mesh>;
```
- The auto installers do not perform a version check like package managers, so having the correct versions of the software is important.
- We *will* be maintaining the v1.x versions with bugfixes etc for those who cannot or do not wish to migrate to the newer template approach.
## Installation
See http://nRF24.github.io/RF24 for installation instructions using the installer, or clone the RF24 libs and run 'make install' for each one.
Expand Down

0 comments on commit 7bf8ec0

Please sign in to comment.