RF24Gateway - TCP/IP over RF24Network v2.0.0
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Gateway.h
1
2
3#ifndef __RF24GATEWAY_H__
4#define __RF24GATEWAY_H__
5
6/**
7 * @file RF24Gateway.h
8 *
9 * Class declaration for RF24Gateway
10 */
11#include "net/if_arp.h"
12#include <cstdlib>
13#include <cstdint>
14#include <iostream>
15#include <string>
16#include <sys/socket.h>
17#include <netinet/in.h>
18#include <linux/if.h>
19#include <linux/if_tun.h>
20#include <ifaddrs.h>
21#include <arpa/inet.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <sys/ioctl.h>
25#include <netdb.h>
26#include <fstream>
27
28#include <RF24/RF24.h>
29#include <RF24Network/RF24Network.h>
30#include <RF24Mesh/RF24Mesh.h>
31
32#ifndef IFF_MULTI_QUEUE
33 #define IFF_MULTI_QUEUE 0x0100
34#endif
35
36#ifndef DEBUG_LEVEL
37 #define DEBUG_LEVEL 0
38#endif // DEBUG_LEVEL
39
40#define BACKLOG 10 /* Passed to listen() */
41
42class RF24;
43
44template<class radio_t>
46
47template<class network_t, class radio_t>
48class ESBMesh;
49
50/**
51 * @tparam mesh_t The `mesh` object's type. Defaults to `RF24Mesh` for legacy behavior.
52 * This new abstraction is really meant for using the nRF52840 SoC as a drop-in replacement
53 * for the nRF24L01 radio. For more detail, see the
54 * [nrf_to_nrf Arduino library](https://github.com/TMRh20/nrf_to_nrf).
55 * @tparam network_t The `network` object's type. Defaults to `RF24Network` for legacy behavior.
56 * This new abstraction is really meant for using the nRF52840 SoC as a drop-in replacement
57 * for the nRF24L01 radio. For more detail, see the
58 * [nrf_to_nrf Arduino library](https://github.com/TMRh20/nrf_to_nrf).
59 * @tparam radio_t The `radio` object's type. Defaults to `RF24` for legacy behavior.
60 * This new abstraction is really meant for using the nRF52840 SoC as a drop-in replacement
61 * for the nRF24L01 radio. For more detail, see the
62 * [nrf_to_nrf Arduino library](https://github.com/TMRh20/nrf_to_nrf).
63 */
64template<class mesh_t = ESBMesh<ESBNetwork<RF24>, RF24>, class network_t = ESBNetwork<RF24>, class radio_t = RF24>
66{
67
68 /**
69 * @name RF24Gateway (RPi/Linux)
70 *
71 * RF24Gateway library for devices with an IP stack
72 */
73 /**@{*/
74
75public:
76 /**
77 * ESBGateway constructor.
78 * @code
79 * RF24 radio(7,8);
80 * RF24Network network(radio);
81 * RF24Mesh mesh(radio,network);
82 * RF24Gateway gateway(radio,network,mesh);
83 * @endcode
84 */
85 ESBGateway(radio_t& _radio, network_t& _network, mesh_t& _mesh);
86
87 /**
88 * Begin function for use with RF24Mesh (TUN interface)
89 *
90 * @param nodeID The RF24Mesh nodeID to use
91 * @param channel The radio channel to use (1-127)
92 * @param data_rate The RF24 datarate to use (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
93 *
94 * @code gw.begin(); //Start the gateway using RF24Mesh, with nodeID 0 (Master) @endcode
95 * @code uint8_t nodeID; gw.begin(nodeID); //Start the gateway using RF24Mesh, with nodeID 1 (Child node) @endcode
96 */
97 void begin(uint8_t nodeID = 0, uint8_t channel = 97, rf24_datarate_e data_rate = RF24_1MBPS);
98
99 /**
100 * Begin function for use with a TAP (Ethernet) interface. RF24Mesh can be used for address assignment, but
101 * ARP will be used to perform the lookups.
102 *
103 * @param address The RF24Network address to use
104 * @param channel The radio channel (0-127) to use
105 * @param data_rate The RF24 datarate to use (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
106 * @param meshEnable Whether to use RF24Mesh for address assignment
107 * @param nodeID The RF24Mesh nodeID to use **if** meshEnable has been set to true
108 *
109 * @code uint16_t address=00; gw.begin(address); //Start the gateway without using RF24Mesh, with RF24Network address 00 (Master) @endcode
110 * @code uint16_t address=01; gw.begin(address); //Start the gateway without using RF24Mesh, with RF24Network address 01 (Child) @endcode
111 */
112 void begin(uint16_t address, uint8_t channel = 97, rf24_datarate_e data_rate = RF24_1MBPS, bool meshEnable = 0, uint8_t nodeID = 0);
113
114 /**
115 * Once the Gateway has been started via begin() , call setIP to configure the IP and
116 * subnet mask.
117 *
118 * @param ip_addr A character array containing the numeric IP address ie: 192.168.1.1
119 * @param mask A character array containing the subnet mask ie: 255.255.255.0
120 * @return -1 if failed, 0 on success
121 */
122 int setIP(char* ip_addr, char* mask);
123
124 /**
125 * Calling update() keeps the network and mesh layers active and processing data. This needs to be called regularly.
126 * @code
127 * gw.update();
128 * if(network.available()){
129 * ...do something
130 * }
131 * @endcode
132 * @param interrupts Set true if called from an interrupt handler & call poll() from the main loop or a thread.
133 */
134 void update(bool interrupts = 0);
135
136 /**
137 * gw.poll(); needs to be called to handle incoming data from the network interface.
138 * The function will perform a delayed wait of max 3ms unless otherwise specified.
139 * @param waitDelay How long in milliseconds this function will wait for incoming data.
140 */
141 void poll(uint32_t waitDelay = 3);
142
143 /**
144 * When using interrupts (gwNodeInt, ncursesInt examples) users need to call
145 * this function to disable interrupts before accessing the radio and again to
146 * re-enable interrupts when complete
147 * @param enable 0 to disable interrupts and access the radio, 1 to re-enable
148 */
149 void interrupts(bool enable = 1);
150
151 /**@}*/
152 /**
153 * @name Advanced Operation
154 *
155 * More advanced methods and options
156 */
157 /**@{*/
158
159 uint16_t thisNodeAddress; /**< Address of our node in Octal format (01,021, etc) */
160 uint8_t thisNodeID; /**< NodeID (0-255) */
161
162 bool meshEnabled(); /**< Is RF24Mesh enabled? */
163 bool config_TUN; /**< Using a TAP(false) or TUN(true) interface */
165
166 uint32_t ifDropped()
167 {
168 return droppedIncoming;
169 }
170
171 void sendUDP(uint8_t nodeID, RF24NetworkFrame frame);
172
173 /**@}*/
174 /**
175 * @name Routing Table
176 *
177 * Utilizing a routing table to provide complete connectivity
178 */
179 /**@{*/
180
181 /**
182 * If a user has created a file "routing.txt" in the RF24Gateway working directory, it will be loaded <br>
183 * at startup into the routing table. The file should contain standard routing table entries as follows: <br>
184 * IP<space>NetMask<space>Gateway <br>
185 * ie: routing.txt
186 * @code
187 * 10.1.4.0 255.255.255.0 10.1.3.33
188 * 0.0.0.0 0.0.0.0 10.1.3.34 @endcode
189 *
190 * The first example entry would route all traffic to the 10.1.4.x subnet to 10.1.3.33 <br>
191 * All other traffic not destined for the RF24 nodes will use 10.1.3.34 as the gateway
192 *
193 * Data can be accessed using standard linux Internet address manipulation routines as follows:
194 * @code
195 * printf("**IP\t\tMask\t\tGateway**\n");
196 * for(int i=0; i<gw.routingTableSize; i++){
197 * printf("%s \t",inet_ntoa(gw.routingStruct[i].ip));//inet_ntoa uses a statically assigned buffer, so the printf calls need to be done separately
198 * printf("%s \t",inet_ntoa(gw.routingStruct[i].mask));
199 * printf("%s\n", inet_ntoa(gw.routingStruct[i].gw));
200 * //std::cout << inet_ntoa(gw.routingStruct[i].ip) << " \t" << inet_ntoa(gw.routingStruct[i].mask) << " \t" << inet_ntoa(gw.routingStruct[i].gw) << std::endl;
201 * }
202 * printf("*****\n");
203 *
204 * Users can modify the routing table as desired, but changes made in code will not currently be saved to file
205 *
206 * @endcode
207 *
208 */
210 {
211 struct in_addr ip;
212 struct in_addr mask;
213 struct in_addr gw;
214 };
215
216 /**
217 * The array that holds the routing structure data. See routeStruct
218 */
220
221 /**
222 * The size of the existing routing table loaded into memory. See routeStruct
223 */
225
226private:
227 radio_t& radio;
228 network_t& network;
229 mesh_t& mesh;
230
231 bool begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel);
232 bool mesh_enabled;
233
234 uint32_t droppedIncoming;
235
236 uint8_t channel;
237 rf24_datarate_e dataRate;
238 char tunName[IFNAMSIZ];
239 int tunFd;
240
241 unsigned long packets_sent; /**< How many have we sent already */
242 uint32_t interfaceInTimer;
243
244 void handleRadioOut();
245 void handleRadioIn();
246 void handleRX(uint32_t waitDelay = 0);
247 void handleTX();
248 volatile bool gotInterrupt;
249 int configDevice(uint16_t address);
250 int allocateTunDevice(char* dev, int flags, uint16_t address);
251
252 struct msgStruct
253 {
254 std::uint8_t message[MAX_PAYLOAD_SIZE];
255 std::size_t size;
256 };
257
258 std::queue<msgStruct> rxQueue;
259 std::queue<msgStruct> txQueue;
260
261 // void printPayload(std::string buffer, std::string debugMsg = "");
262 // void printPayload(char* buffer, int nread, std::string debugMsg = "");
263
264 int s; // Socket variable for sending UDP
265 void setupSocket();
266 struct sockaddr_in addr;
267 struct in_addr getLocalIP();
268
269 void loadRoutingTable();
270};
271
272/**
273 * A type definition of the template class `ESBGateway` to maintain backward compatibility.
274 *
275 * ```.cpp
276 * RF24 radio(7, 8);
277 * RF24Network network(radio);
278 * RF24Mesh mesh(radio, network);
279 *
280 * RF24Gateway gateway(radio, network, mesh);
281 * // is equivalent to
282 * ESBGateway<ESBMesh<ESBNetwork<RF24>, RF24>, ESBNetwork<RF24>, RF24> gateway(radio, network, mesh);
283 * ```
284 */
286
287/**
288 * @example RF24GatewayNode.cpp
289 *
290 * A simple example of using RF24Gateway node to forward IP traffic automatically to a network interface, while
291 * managing standard RF24Network user payloads independently.
292 */
293
294/**
295 * @example RF24Gateway_ncurses.cpp
296 * RF24Gateway NCurses interface - TMRh20 2015 <br>
297 * This is a generic tool for nodes supporting or combining with RF24Ethernet and/or RF24Network.
298 *
299 * The tool provides a simple interface for monitoring information and activity regarding the RF24Gateway: <br>
300 * a: Interface statistics from /proc/net/dev <br>
301 * b: RF24Mesh address/id assignments <br>
302 * c: RF24Network/Radio information <br>
303 * d: Active IP connections (optional) <br>
304 *
305 * **Requirements: NCurses** <br>
306 * Install NCurses: apt-get install libncurses5-dev
307 * Optional: Enable nf_conntrack: @code modprobe nf_conntrack_ipv4 @endcode
308 *
309 * @image html ncurses.JPG
310 */
311
312/**
313 * @example RF24GatewayNodeInt.cpp
314 * A copy of the RF24GatewayNode example using interrupts.
315 */
316
317/**
318 * @example RF24Gateway_ncursesInt.cpp
319 * A copy of the ncurses example using interrupts.
320 */
321
322/**
323 * @example bClient.sh
324 * Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with
325 * the sensor nodes. <br>Example of on demand LED/Lighting control using a Bash script.
326 */
327
328/**
329 * @example nodeClient.js
330 * Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with
331 * the sensor nodes. <br> Example of on demand LED/Lighting control using a NodeJS script.
332 */
333
334/**
335 * @example pyClient.py
336 * Once RF24Gateway and RF24Ethernet are configured, standard tools can be used to interact with
337 * the sensor nodes. <br> Example of scheduled LED/Lighting control using a Python script.
338 */
339
340#endif
bool config_TUN
bool meshEnabled()
uint16_t thisNodeAddress
int setIP(char *ip_addr, char *mask)
routeStruct routingStruct[256]
void interrupts(bool enable=1)
void poll(uint32_t waitDelay=3)
ESBGateway(radio_t &_radio, network_t &_network, mesh_t &_mesh)
void begin(uint8_t nodeID=0, uint8_t channel=97, rf24_datarate_e data_rate=RF24_1MBPS)
uint32_t ifDropped()
uint8_t thisNodeID
void update(bool interrupts=0)
bool fifoCleared
uint8_t routingTableSize
void sendUDP(uint8_t nodeID, RF24NetworkFrame frame)