RF24Ethernet - TCP/IP over RF24Network v2.2.0
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Ethernet.h
Go to the documentation of this file.
1/*
2 RF24Ethernet by TMRh20 2014-2015
3
4 https://github.com/TMRh20
5
6 RF24Ethernet.h - Arduino implementation of a uIP wrapper class.
7 Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
8 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
9 All rights reserved.
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#ifndef RF24Ethernet_h
23#define RF24Ethernet_h
24
25/**
26 * @file RF24Ethernet.h
27 *
28 * Class declaration for RF24Ethernet
29 */
30
31#include <Arduino.h>
32#include "RF24BoardConfig.h"
33
34/**************************************/
35#if USE_LWIP < 1
36extern "C" {
37 #include "uip-conf.h"
38 #include "utility/uip.h"
39
40 #include "utility/uiptimer.h"
41 #include "utility/uip_arp.h"
42}
43#endif
44
45#if USE_LWIP == 2
46 #include <zephyr/kernel.h>
47 #include <zephyr/net/net_if.h>
48 #include <zephyr/net/ethernet.h>
49 #include <zephyr/net/net_ip.h>
50 #include <zephyr/net/net_core.h>
51 #include <zephyr/net/net_pkt.h>
52 #include <zephyr/kernel.h>
53 #include <zephyr/irq.h>
54 #include <zephyr/sys/byteorder.h>
55
56 #ifndef HTONS
57 #define HTONS(x) sys_cpu_to_be16(x)
58 #endif
59
60 #ifndef htons
61 #define htons(x) sys_cpu_to_be16(x)
62 #endif
63#endif
64
65/**************************************/
66
67#include "RF24Ethernet_config.h"
68#if defined(ARDUINO_ARCH_NRF52) || defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52833) || defined ARDUINO_NRF54L15
69 #include <nrf_to_nrf.h>
70#endif
71#include <RF24.h>
72#include <RF24Network.h>
73#include <RF24Mesh.h>
74#if !defined(RF24_TAP) // Using RF24Mesh
75 #include <RF24Mesh.h>
76#endif
77
78/**************************************/
79
80#include "ethernet_comp.h"
81
82#if __has_include(<IPAddress.h>)
83 #include <IPAddress.h>
84#elif __has_include("IPAddress.h")
85 #include "IPAddress.h"
86#else
87 #include <Arduino.h>
88#endif
89#include "RF24Client.h"
90#include "RF24Server.h"
91
92#if UIP_CONF_UDP > 0 || USE_LWIP > 0
93 #include "RF24Udp.h"
94 #include "Dns.h"
95#endif
96
97#define UIPETHERNET_FREEPACKET 1
98#define UIPETHERNET_SENDPACKET 2
99
100//#define TUN // Use only the tcp protocol, no ethernet headers or arps
101#define TAP // Include ethernet headers
102
103#if defined(TAP)
104 #define BUF ((struct uip_eth_hdr*)&uip_buf[0])
105#endif
106//#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
107
108#define uip_seteth_addr(eaddr) \
109 do { \
110 uip_ethaddr.addr[0] = eaddr[0]; \
111 uip_ethaddr.addr[1] = eaddr[1]; \
112 uip_ethaddr.addr[2] = eaddr[2]; \
113 uip_ethaddr.addr[3] = eaddr[3]; \
114 uip_ethaddr.addr[4] = eaddr[4]; \
115 uip_ethaddr.addr[5] = eaddr[5]; \
116 } while (0)
117#define uip_ip_addr(addr, ip) memcpy(addr, &ip[0], 4)
118
119#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8, a[1] & 0xFF, a[1] >> 8) // TODO this is not IPV6 capable
120
121#define uip_seteth_addr(eaddr) \
122 do { \
123 uip_ethaddr.addr[0] = eaddr[0]; \
124 uip_ethaddr.addr[1] = eaddr[1]; \
125 uip_ethaddr.addr[2] = eaddr[2]; \
126 uip_ethaddr.addr[3] = eaddr[3]; \
127 uip_ethaddr.addr[4] = eaddr[4]; \
128 uip_ethaddr.addr[5] = eaddr[5]; \
129 } while (0)
130
131/**************************************/
132
133/**
134 * @warning <b>This is used internally. Use IPAddress instead. </b>
135 */
136typedef struct
137{
138 int a, b, c, d;
139} IP_ADDR;
140
141/**************************************/
142
143class RF24;
144template<class radio_t>
146
147/**************************************/
148
150{ //: public Print {
151public:
152/**
153 * Constructor to set up the Ethernet layer. Requires the radio and network to be configured by the user
154 * this allows users to set custom settings at the radio or network level
155 */
156#if !defined(RF24_TAP) // Using RF24Mesh
157 RF24EthernetClass(RF24& _radio, RF24Network& _network, RF24Mesh& _mesh);
158#else
159 RF24EthernetClass(RF24& _radio, RF24Network& _network);
160#endif
161#if defined NRF52_RADIO_LIBRARY
162 #if !defined(RF24_TAP)
163 RF24EthernetClass(nrf_to_nrf& _radio, RF52Network& _network, RF52Mesh& _mesh);
164 #else
165 RF24EthernetClass(nrf_to_nrf& _radio, RF52Network& _network);
166 #endif
167#endif
168
169 /** Basic constructor */
171
172 /**
173 * @note Deprecated, maintained for backwards compatibility with old examples
174 *
175 * This function is no longer needed, and does nothing
176 */
177 void use_device();
178
179 /**
180 * Configure the IP address and subnet mask of the node. This is independent of the RF24Network layer, so the IP
181 * and subnet only have to conform to standard IP routing rules within your network
182 */
183 void begin(IP_ADDR myIP, IP_ADDR subnet);
184
185 /**
186 * Configure the IP address and subnet mask of the node. This is independent of the RF24Network layer, so the IP
187 * and subnet only have to conform to standard IP routing rules within your network
188 */
189 void begin(IPAddress ip);
190 void begin(IPAddress ip, IPAddress dns);
191 void begin(IPAddress ip, IPAddress dns, IPAddress gateway);
192 void begin(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
193
194 /**
195 * Configure the gateway IP address. This is generally going to be your master node with RF24Network address 00.
196 */
197 void set_gateway(IPAddress gwIP);
198
199 /**
200 * Listen to a specified port - This will likely be changed to closer match the Arduino Ethernet API with server.begin();
201 */
202 void listen(uint16_t port);
203
204 /**
205 * Sets the MAC address of the RF24 module, which is an RF24Network address
206 * Specify an Octal address to assign to this node, which will be used as the Ethernet mac address
207 * If setting up only a few nodes, use 01 to 05
208 * Please reference the RF24Network documentation for information on setting up a static network
209 * RF24Mesh will be integrated to provide this automatically
210 */
211 void setMac(uint16_t address);
212
213 /** Sets the Radio channel/frequency to use (0-127) */
214 void setChannel(uint8_t channel);
215
216 /** Indicates whether data is available. */
218
219 /** Returns the local IP address */
220 IPAddress localIP();
221
222 /** Returns the subnet mask */
223 IPAddress subnetMask();
224
225 /** Returns the gateway IP address */
226 IPAddress gatewayIP();
227
228 /** Returns the DNS server IP address */
229 IPAddress dnsServerIP();
230
231 /** Keeps the TCP/IP stack running & processing incoming data */
232 void update();
233 // uint8_t *key;
234
236
237#if defined NRF52_RADIO_LIBRARY
238 nrf_to_nrf& radio;
239#else
240 RF24& radio;
241#endif
242
243#if !defined NRF52_RADIO_LIBRARY
244 RF24Network& network;
245 #if !defined(RF24_TAP) // Using RF24Mesh
246 RF24Mesh& mesh;
247 #endif
248#else
249 RF52Network& network;
250 #if !defined(RF24_TAP) // Using RF24Mesh
251 RF52Mesh& mesh;
252 #endif
253#endif
254
255#if USE_LWIP == 1
256
257 static bool useCoreLocking;
258 static constexpr unsigned MAX_FRAME_SIZE = MAX_PAYLOAD_SIZE; // packet size excluding FCS
259 static constexpr unsigned MIN_FRAME_SIZE = 28;
260 static constexpr unsigned MAX_RX_QUEUE = 2;
261 static constexpr uint32_t NetIF_Speed_BPS = 1000000;
262 static netif myNetif;
263
264 struct alignas(4) EthQueue
265 {
266 uint32_t nRead;
267 uint32_t nWrite;
268 uint8_t data[MAX_RX_QUEUE][MAX_FRAME_SIZE] __attribute__((aligned(4)));
269 uint16_t len[MAX_RX_QUEUE];
270 };
272
273 static bool isUnicast(const uint8_t frame);
274 /** Used internally to initialize incoming data queue */
275 static void initRXQueue(EthQueue* RXQueue);
276 /** Used internally to write to the internal data queue */
277 static void writeRXQueue(EthQueue* RXQueue, const uint8_t* ethFrame, uint16_t lenEthFrame);
278
279private:
280 static constexpr uint16_t ETHERNET_MTU = 1500;
281 static constexpr uint8_t MacAddr[6] = {0, 1, 2, 3, 4};
282 static bool isConnected;
283
284 static pbuf* readRXQueue(EthQueue* RXQueue);
285
286 static void EthRX_Handler(const uint8_t* ethFrame, const uint16_t lenEthFrame);
287 alignas(4) static uint8_t networkBuffer[MAX_PAYLOAD_SIZE];
288
289#endif
290
291#if USE_LWIP < 1
292 IPAddress _dnsServerAddress;
293#else
294 static IPAddress _dnsServerAddress;
295#endif
296
297 void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);
298
299 // tick() must be called at regular intervals to process the incoming serial
300 // data and issue IP events to the sketch. It does not return until all IP
301 // events have been processed.
302 static void tick();
303 static void network_send();
304
305 uint8_t RF24_Channel;
306
307#if USE_LWIP < 1
308 struct timer periodic_timer;
309 #if defined RF24_TAP
310 struct timer arp_timer;
311 #endif
312#endif
313
314#if USE_LWIP == 2
315
316 bool isInitialized;
317 int sendFrame(const uint8_t* data, size_t len);
318 uint8_t outputBuffer[MAX_PAYLOAD_SIZE];
319 IPAddress ethLocalIP;
320#endif
321
322 friend class RF24Server;
323 friend class RF24Client;
324 friend class RF24UDP;
325};
326
328
330
331/**
332 * @example Getting_Started_SimpleServer_Mesh.ino
333 * <b>Updated: TMRh20 2014 </b><br>
334 *
335 * This is an example of how to use the RF24Ethernet class to create a web server which will allow you to connect via
336 * any device with a web-browser. The url is http://your_chosen_IP:1000
337 */
338
339/**
340 * @example Getting_Started_SimpleClient_Mesh.ino
341 *
342 * This is an example of how to use the RF24Ethernet class to connect out to a web server and retrieve data via HTTP.
343 */
344
345/**
346 * @example Getting_Started_SimpleClient_Mesh_DNS.ino
347 *
348 * This is an example of how to use the RF24Ethernet class to connect out to a web server and retrieve data via HTTP,
349 * using DNS lookups instead of IP address.
350 */
351
352/**
353 * @example SimpleClient_Mesh.ino
354 *
355 * This is an example of how to use the RF24Ethernet class to connect out to a web server and retrieve data via HTTP.
356 * It also demonstrates how to read from the HTTP header to read the Content-Length before reading the data.
357 */
358
359/**
360 * @example InteractiveServer_Mesh.ino
361 *
362 * This is an example of how to create a more advanced interactive web server.<br>
363 * This example uses [HTML.h](InteractiveServer__Mesh_2HTML_8h.html) from the
364 * example's directory.
365 */
366
367/**
368 * @example mqtt_basic.ino
369 *
370 * This is the example taken from the MQTT library https://github.com/256dpi/arduino-mqtt/ & slightly modified to include RF24Ethernet/RF24Mesh.
371 */
372
373/**
374 * @example mqtt_basic_no_blk.ino
375 *
376 * This is similar to the mqtt_basic example, but uses a non-blocking connect function.
377 */
378/**
379 * @example mqtt_basic_2.ino
380 *
381 * A copy of the initial MQTT example using MQTT library https://github.com/256dpi/arduino-mqtt/ slightly modified to include RF24Ethernet/RF24Mesh.
382 */
383
384/**
385 * @example InteractiveServer_Mesh_Headless.ino
386 *
387 * This example demonstrates "headless' use of a server, without a gateway device like Raspberry Pi/Linux.
388 */
389
390/**
391 * @example SimpleClient_Mesh_Headless.ino
392 *
393 * This example demonstrates "headless" use of a client, without a gateway device like Raspberry Pi/Linux
394 */
395
396#endif // RF24Ethernet_h
RF24EthernetClass RF52EthernetClass
RF24EthernetClass RF24Ethernet
uint32_t networkCorruption
friend class RF24UDP
static EthQueue RXQueue
void setMac(uint16_t address)
void setChannel(uint8_t channel)
RF24EthernetClass(RF24 &_radio, RF24Network &_network, RF24Mesh &_mesh)
friend class RF24Server
static constexpr unsigned MIN_FRAME_SIZE
static void writeRXQueue(EthQueue *RXQueue, const uint8_t *ethFrame, uint16_t lenEthFrame)
static void initRXQueue(EthQueue *RXQueue)
IPAddress dnsServerIP()
void listen(uint16_t port)
IPAddress subnetMask()
void set_gateway(IPAddress gwIP)
static constexpr unsigned MAX_FRAME_SIZE
static bool isUnicast(const uint8_t frame)
RF24Network & network
static netif myNetif
static constexpr unsigned MAX_RX_QUEUE
friend class RF24Client
void begin(IP_ADDR myIP, IP_ADDR subnet)
static constexpr uint32_t NetIF_Speed_BPS
static bool useCoreLocking
IPAddress gatewayIP()
uint16_t len[MAX_RX_QUEUE]
uint8_t data[MAX_RX_QUEUE][MAX_FRAME_SIZE] __attribute__((aligned(4)))