forked from nRF24/RF24Network
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RF24Network.h
1304 lines (1177 loc) · 54.5 KB
/
RF24Network.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Copyright (C) 2011 James Coliz, Jr. <[email protected]>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#ifndef __RF24NETWORK_H__
#define __RF24NETWORK_H__
/**
* @file RF24Network.h
*
* Class declaration for RF24Network
*/
#include <stddef.h>
#include <stdint.h>
#include "RF24Network_config.h"
#if (defined (__linux) || defined (linux)) && !defined (__ARDUINO_X86__)
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/time.h>
#include <stddef.h>
#include <assert.h>
#include <map>
#include <utility> // std::pair
#include <queue>
//ATXMega
#elif defined(XMEGA_D3)
#include "../../rf24lib/rf24lib/RF24.h"
#endif
/**
*/
/* Header types range */
#define MIN_USER_DEFINED_HEADER_TYPE 0
#define MAX_USER_DEFINED_HEADER_TYPE 127
/**
*/
// ACK Response Types
/**
* **Reserved network message types**
*
* The network will determine whether to automatically acknowledge payloads based on their general type <br>
*
* **User types** (1-127) 1-64 will NOT be acknowledged <br>
* **System types** (128-255) 192 through 255 will NOT be acknowledged<br>
*
* @defgroup DEFINED_TYPES Reserved System Message Types
*
* System types can also contain message data.
*
* @{
*/
/**
* A NETWORK_ADDR_RESPONSE type is utilized to manually route custom messages containing a single RF24Network address
*
* Used by RF24Mesh
*
* If a node receives a message of this type that is directly addressed to it, it will read the included message, and forward the payload
* on to the proper recipient. <br>
* This allows nodes to forward multicast messages to the master node, receive a response, and forward it back to the requester.
*/
#define NETWORK_ADDR_RESPONSE 128
//#define NETWORK_ADDR_CONFIRM 129
/**
* Messages of type NETWORK_PING will be dropped automatically by the recipient. A NETWORK_ACK or automatic radio-ack will indicate to the sender whether the
* payload was successful. The time it takes to successfully send a NETWORK_PING is the round-trip-time.
*/
#define NETWORK_PING 130
/**
* External data types are used to define messages that will be passed to an external data system. This allows RF24Network to route and pass any type of data, such
* as TCP/IP frames, while still being able to utilize standard RF24Network messages etc.
*
* **Linux**
* Linux devices (defined RF24_LINUX) will buffer all data types in the user cache.
*
* **Arduino/AVR/Etc:** Data transmitted with the type set to EXTERNAL_DATA_TYPE will not be loaded into the user cache. <br>
* External systems can extract external data using the following process, while internal data types are cached in the user buffer, and accessed using network.read() :
* @code
* uint8_t return_type = network.update();
* if(return_type == EXTERNAL_DATA_TYPE){
* uint16_t size = network.frag_ptr->message_size;
* memcpy(&myDataBuffer,network.frag_ptr->message_buffer,network.frag_ptr->message_size);
* }
* @endcode
*/
#define EXTERNAL_DATA_TYPE 131
/**
* Messages of this type designate the first of two or more message fragments, and will be re-assembled automatically.
*/
#define NETWORK_FIRST_FRAGMENT 148
/**
* Messages of this type indicate a fragmented payload with two or more message fragments.
*/
#define NETWORK_MORE_FRAGMENTS 149
/**
* Messages of this type indicate the last fragment in a sequence of message fragments.
* Messages of this type do not receive a NETWORK_ACK
*/
#define NETWORK_LAST_FRAGMENT 150
//#define NETWORK_LAST_FRAGMENT 201
// NO ACK Response Types
//#define NETWORK_ACK_REQUEST 192
/**
* Messages of this type are used internally, to signal the sender that a transmission has been completed.
* RF24Network does not directly have a built-in transport layer protocol, so message delivery is not 100% guaranteed.<br>
* Messages can be lost via corrupted dynamic payloads, or a NETWORK_ACK can fail, while the message was actually successful.
*
* NETWORK_ACK messages can be utilized as a traffic/flow control mechanism, since transmitting nodes will be forced to wait until
* the payload is transmitted across the network and acknowledged, before sending additional data.
*
* In the event that the transmitting device will be waiting for a direct response, manually sent by the recipient, a NETWORK_ACK is not required. <br>
* User messages utilizing a 'type' with a decimal value of 64 or less will not be acknowledged across the network via NETWORK_ACK messages.
*/
#define NETWORK_ACK 193
/**
* Used by RF24Mesh
*
* Messages of this type are used with multi-casting , to find active/available nodes.
* Any node receiving a NETWORK_POLL sent to a multicast address will respond directly to the sender with a blank message, indicating the
* address of the available node via the header.
*/
#define NETWORK_POLL 194
/**
* Used by RF24Mesh
*
* Messages of this type are used to request information from the master node, generally via a unicast (direct) write.
* Any (non-master) node receiving a message of this type will manually forward it to the master node using an normal network write.
*/
#define NETWORK_REQ_ADDRESS 195
//#define NETWORK_ADDR_LOOKUP 196
//#define NETWORK_ADDR_RELEASE 197
/** @} */
#define NETWORK_MORE_FRAGMENTS_NACK 200
/** Internal defines for handling written payloads */
#define TX_NORMAL 0
#define TX_ROUTED 1
#define USER_TX_TO_PHYSICAL_ADDRESS 2 //no network ACK
#define USER_TX_TO_LOGICAL_ADDRESS 3 // network ACK
#define USER_TX_MULTICAST 4
#define MAX_FRAME_SIZE 32 //Size of individual radio frames
#define FRAME_HEADER_SIZE 10 //Size of RF24Network frames - data
#define USE_CURRENT_CHANNEL 255 // Use current radio channel when setting up the network
/** Internal defines for handling internal payloads - prevents reading additional data from the radio
* when buffers are full */
#define FLAG_HOLD_INCOMING 1
/** FLAG_BYPASS_HOLDS is mainly for use with RF24Mesh as follows:
* a: Ensure no data in radio buffers, else exit
* b: Address is changed to multicast address for renewal
* c: Holds Cleared (bypass flag is set)
* d: Address renewal takes place and is set
* e: Holds Enabled (bypass flag off)
*/
#define FLAG_BYPASS_HOLDS 2
#define FLAG_FAST_FRAG 4
#define FLAG_NO_POLL 8
class RF24;
/**
* Header which is sent with each message
*
* The frame put over the air consists of this header and a message
*
* Headers are addressed to the appropriate node, and the network forwards them on to their final destination.
*/
struct RF24NetworkHeader
{
uint16_t from_node; /**< Logical address where the message was generated */
uint16_t to_node; /**< Logical address where the message is going */
uint16_t id; /**< Sequential message ID, incremented every time a new frame is constructed */
/**
* Message Types:
* User message types 1 through 64 will NOT be acknowledged by the network, while message types 65 through 127 will receive a network ACK.
* System message types 192 through 255 will NOT be acknowledged by the network. Message types 128 through 192 will receive a network ACK. <br>
* <br><br>
*/
unsigned char type; /**< <b>Type of the packet. </b> 0-127 are user-defined types, 128-255 are reserved for system */
/**
* During fragmentation, it carries the fragment_id, and on the last fragment
* it carries the header_type.<br>
*/
unsigned char reserved; /**< *Reserved for system use* */
static uint16_t next_id; /**< The message ID of the next message to be sent (unused)*/
/**
* Default constructor
*
* Simply constructs a blank header
*/
RF24NetworkHeader() {}
/**
* Send constructor
*
* @note Now supports automatic fragmentation for very long messages, which can be sent as usual if fragmentation is enabled.
*
* Fragmentation is enabled by default for all devices except ATTiny <br>
* Configure fragmentation and max payload size in RF24Network_config.h
*
* Use this constructor to create a header and then send a message
*
* @code
* uint16_t recipient_address = 011;
*
* RF24NetworkHeader header(recipient_address,'t');
*
* network.write(header,&message,sizeof(message));
* @endcode
*
* @param _to The Octal format, logical node address where the message is going
* @param _type The type of message which follows. Only 0-127 are allowed for
* user messages. Types 1-64 will not receive a network acknowledgement.
*/
RF24NetworkHeader(uint16_t _to, unsigned char _type = 0): to_node(_to), id(next_id++), type(_type) {}
/**
* Create debugging string
*
* Useful for debugging. Dumps all members into a single string, using
* internal static memory. This memory will get overridden next time
* you call the method.
*
* @return String representation of this object
*/
const char* toString(void) const;
};
/**
* Frame structure for internal message handling, and for use by external applications
*
* The actual frame put over the air consists of a header (8-bytes) and a message payload (Up to 24-bytes)<br>
* When data is received, it is stored using the RF24NetworkFrame structure, which includes:
* 1. The header
* 2. The size of the included message
* 3. The 'message' or data being received
*
*
*/
struct RF24NetworkFrame
{
RF24NetworkHeader header; /**< Header which is sent with each message */
uint16_t message_size; /**< The size in bytes of the payload length */
/**
* On Arduino, the message buffer is just a pointer, and can be pointed to any memory location.
* On Linux the message buffer is a standard byte array, equal in size to the defined MAX_PAYLOAD_SIZE
*/
#if defined (RF24_LINUX)
uint8_t message_buffer[MAX_PAYLOAD_SIZE]; //< Array to store the message
#else
uint8_t *message_buffer; //< Pointer to the buffer storing the actual message
#endif
/**
* Default constructor
*
* Simply constructs a blank frame. Frames are generally used internally. See RF24NetworkHeader.
*/
//RF24NetworkFrame() {}
RF24NetworkFrame() {}
/**
* Constructor - create a network frame with data
* Frames are constructed and handled differently on Arduino/AVR and Linux devices (defined RF24_LINUX)
*
* <br>
* **Linux:**
* @param _header The RF24Network header to be stored in the frame
* @param _message The 'message' or data.
* @param _len The size of the 'message' or data.
*
* <br>
* **Arduino/AVR/Etc.**
* @see RF24Network.frag_ptr
* @param _header The RF24Network header to be stored in the frame
* @param _message_size The size of the 'message' or data
*
*
* Frames are used internally and by external systems. See RF24NetworkHeader.
*/
#if defined (RF24_LINUX)
RF24NetworkFrame(RF24NetworkHeader& _header, const void* _message = NULL, uint16_t _len = 0) :
header(_header), message_size(_len) {
if (_message && _len) {
memcpy(message_buffer,_message,_len);
}
}
#else
RF24NetworkFrame(RF24NetworkHeader &_header, uint16_t _message_size):
header(_header), message_size(_message_size){
}
#endif
/**
* Create debugging string
*
* Useful for debugging. Dumps all members into a single string, using
* internal static memory. This memory will get overridden next time
* you call the method.
*
* @return String representation of this object
*/
const char* toString(void) const;
};
/**
* 2014-2015 - Optimized Network Layer for RF24 Radios
*
* This class implements an OSI Network Layer using nRF24L01(+) radios driven
* by RF24 library.
*/
class RF24Network
{
/**@}*/
/**
* @name Primary Interface
*
* These are the main methods you need to operate the network
*/
/**@{*/
public:
/**
* Construct the network
*
* @param _radio The underlying radio driver instance
*
*/
RF24Network( RF24& _radio );
/**
* Bring up the network using the current radio frequency/channel.
* Calling begin brings up the network, and configures the address, which designates the location of the node within RF24Network topology.
* @note Node addresses are specified in Octal format, see <a href=Addressing.html>RF24Network Addressing</a> for more information.
* @warning Be sure to 'begin' the radio first.
*
* **Example 1:** Begin on current radio channel with address 0 (master node)
* @code
* network.begin(00);
* @endcode
* **Example 2:** Begin with address 01 (child of master)
* @code
* network.begin(01);
* @endcode
* **Example 3:** Begin with address 011 (child of 01, grandchild of master)
* @code
* network.begin(011);
* @endcode
*
* @see begin(uint8_t _channel, uint16_t _node_address )
* @param _node_address The logical address of this node
*
*/
inline void begin(uint16_t _node_address){
begin(USE_CURRENT_CHANNEL,_node_address);
}
/**
* Main layer loop
*
* This function must be called regularly to keep the layer going. This is where payloads are
* re-routed, received, and all the action happens.
*
* @see
*
* @return Returns the type of the last received payload.
*/
uint8_t update(void);
/**
* Test whether there is a message available for this node
*
* @return Whether there is a message available for this node
*/
bool available(void);
/**
* Read the next available header
*
* Reads the next available header without advancing to the next
* incoming message. Useful for doing a switch on the message type
*
* If there is no message available, the header is not touched
*
* @param[out] header The header (envelope) of the next message
*/
uint16_t peek(RF24NetworkHeader& header);
/**
* Read a message
*
* @code
* while ( network.available() ) {
* RF24NetworkHeader header;
* uint32_t time;
* network.peek(header);
* if(header.type == 'T'){
* network.read(header,&time,sizeof(time));
* Serial.print("Got time: ");
* Serial.println(time);
* }
* }
* @endcode
* @param[out] header The header (envelope) of this message
* @param[out] message Pointer to memory where the message should be placed
* @param maxlen The largest message size which can be held in @p message
* @return The total number of bytes copied into @p message
*/
uint16_t read(RF24NetworkHeader& header, void* message, uint16_t maxlen);
/**
* Send a message
*
* @note RF24Network now supports fragmentation for very long messages, send as normal. Fragmentation
* may need to be enabled or configured by editing the RF24Network_config.h file. Default max payload size is 120 bytes.
*
* @code
* uint32_t time = millis();
* uint16_t to = 00; // Send to master
* RF24NetworkHeader header(to, 'T'); // Send header type 'T'
* network.write(header,&time,sizeof(time));
* @endcode
* @param[in,out] header The header (envelope) of this message. The critical
* thing to fill in is the @p to_node field so we know where to send the
* message. It is then updated with the details of the actual header sent.
* @param message Pointer to memory where the message is located
* @param len The size of the message
* @return Whether the message was successfully received
*/
bool write(RF24NetworkHeader& header,const void* message, uint16_t len);
/**@}*/
/**
* @name Advanced Configuration
*
* For advanced configuration of the network
*/
/**@{*/
/**
* Construct the network in dual head mode using two radio modules.
* @note Not working on RPi. Radios will share MISO, MOSI and SCK pins, but require separate CE,CS pins.
* @code
* RF24 radio(7,8);
* RF24 radio1(4,5);
* RF24Network(radio.radio1);
* @endcode
* @param _radio The underlying radio driver instance
* @param _radio1 The second underlying radio driver instance
*/
RF24Network( RF24& _radio, RF24& _radio1);
/**
* By default, multicast addresses are divided into levels.
*
* Nodes 1-5 share a multicast address, nodes n1-n5 share a multicast address, and nodes n11-n55 share a multicast address.<br>
*
* This option is used to override the defaults, and create custom multicast groups that all share a single
* address. <br>
* The level should be specified in decimal format 1-6 <br>
* @see multicastRelay
* @param level Levels 1 to 6 are available. All nodes at the same level will receive the same
* messages if in range. Messages will be routed in order of level, low to high by default, with the
* master node (00) at multicast Level 0
*/
void multicastLevel(uint8_t level);
/**
* Enabling this will allow this node to automatically forward received multicast frames to the next highest
* multicast level. Duplicate frames are filtered out, so multiple forwarding nodes at the same level should
* not interfere. Forwarded payloads will also be received.
* @see multicastLevel
*/
bool multicastRelay;
/**
* Set up the watchdog timer for sleep mode using the number 0 through 10 to represent the following time periods:<br>
* wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s
* @code
* setup_watchdog(7); // Sets the WDT to trigger every second
* @endcode
* @param prescalar The WDT prescaler to define how often the node will wake up. When defining sleep mode cycles, this time period is 1 cycle.
*/
void setup_watchdog(uint8_t prescalar);
/**
* @note: This value is automatically assigned based on the node address
* to reduce errors and increase throughput of the network.
*
* Sets the timeout period for individual payloads in milliseconds at staggered intervals.
* Payloads will be retried automatically until success or timeout
* Set to 0 to use the normal auto retry period defined by radio.setRetries()
*
*/
uint32_t txTimeout; /**< Network timeout value */
/**
* This only affects payloads that are routed by one or more nodes.
* This specifies how long to wait for an ack from across the network.
* Radios sending directly to their parent or children nodes do not
* utilize this value.
*/
uint16_t routeTimeout; /**< Timeout for routed payloads */
/**@}*/
/**
* @name Advanced Operation
*
* For advanced operation of the network
*/
/**@{*/
/**
* Return the number of failures and successes for all transmitted payloads, routed or sent directly
* @note This needs to be enabled via #define ENABLE_NETWORK_STATS in RF24Network_config.h
*
* @code
* bool fails, success;
* network.failures(&fails,&success);
* @endcode
*
*/
void failures(uint32_t *_fails, uint32_t *_ok);
#if defined (RF24NetworkMulticast)
/**
* Send a multicast message to multiple nodes at once
* Allows messages to be rapidly broadcast through the network
*
* Multicasting is arranged in levels, with all nodes on the same level listening to the same address
* Levels are assigned by network level ie: nodes 01-05: Level 1, nodes 011-055: Level 2
* @see multicastLevel
* @see multicastRelay
* @param message Pointer to memory where the message is located
* @param len The size of the message
* @param level Multicast level to broadcast to
* @return Whether the message was successfully sent
*/
bool multicast(RF24NetworkHeader& header,const void* message, uint16_t len, uint8_t level);
#endif
/**
* Writes a direct (unicast) payload. This allows routing or sending messages outside of the usual routing paths.
* The same as write, but a physical address is specified as the last option.
* The payload will be written to the physical address, and routed as necessary by the recipient
*/
bool write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect);
/**
* Sleep this node - For AVR devices only
* @note NEW - Nodes can now be slept while the radio is not actively transmitting. This must be manually enabled by uncommenting
* the #define ENABLE_SLEEP_MODE in RF24Network_config.h
* @note Setting the interruptPin to 255 will disable interrupt wake-ups
* @note The watchdog timer should be configured in setup() if using sleep mode.
* This function will sleep the node, with the radio still active in receive mode.
*
* The node can be awoken in two ways, both of which can be enabled simultaneously:
* 1. An interrupt - usually triggered by the radio receiving a payload. Must use pin 2 (interrupt 0) or 3 (interrupt 1) on Uno, Nano, etc.
* 2. The watchdog timer waking the MCU after a designated period of time, can also be used instead of delays to control transmission intervals.
* @code
* if(!network.available()){ network.sleepNode(1,0); } //Sleeps the node for 1 second or a payload is received
*
* Other options:
* network.sleepNode(0,0); // Sleep this node for the designated time period, or a payload is received.
* network.sleepNode(1,255); // Sleep this node for 1 cycle. Do not wake up until then, even if a payload is received ( no interrupt )
* @endcode
* @see setup_watchdog()
* @param cycles: The node will sleep in cycles of 1s. Using 2 will sleep 2 WDT cycles, 3 sleeps 3WDT cycles...
* @param interruptPin: The interrupt number to use (0,1) for pins two and three on Uno,Nano. More available on Mega etc.
* @return True if sleepNode completed normally, after the specified number of cycles. False if sleep was interrupted
*/
bool sleepNode( unsigned int cycles, int interruptPin, uint8_t INTERRUPT_MODE=0); //added interrupt mode support (default 0=LOW)
/**
* This node's parent address
*
* @return This node's parent address, or -1 if this is the base
*/
uint16_t parent() const;
/**
* Provided a node address and a pipe number, will return the RF24Network address of that child pipe for that node
*/
uint16_t addressOfPipe( uint16_t node,uint8_t pipeNo );
/**
* @note Addresses are specified in octal: 011, 034
* @return True if a supplied address is valid
*/
bool is_valid_address( uint16_t node );
/**@}*/
/**
* @name Deprecated
*
* Maintained for backwards compatibility
*/
/**@{*/
/**
* Bring up the network on a specific radio frequency/channel.
* @note Use radio.setChannel() to configure the radio channel
*
* **Example 1:** Begin on channel 90 with address 0 (master node)
* @code
* network.begin(90,0);
* @endcode
* **Example 2:** Begin on channel 90 with address 01 (child of master)
* @code
* network.begin(90,01);
* @endcode
* **Example 3:** Begin on channel 90 with address 011 (child of 01, grandchild of master)
* @code
* network.begin(90,011);
* @endcode
*
* @param _channel The RF channel to operate on
* @param _node_address The logical address of this node
*
*/
void begin(uint8_t _channel, uint16_t _node_address );
/**@}*/
/**
* @name External Applications/Systems
*
* Interface for External Applications and Systems ( RF24Mesh, RF24Ethernet )
*/
/**@{*/
/** The raw system frame buffer of received data. */
uint8_t frame_buffer[MAX_FRAME_SIZE];
/**
* **Linux** <br>
* Data with a header type of EXTERNAL_DATA_TYPE will be loaded into a separate queue.
* The data can be accessed as follows:
* @code
* RF24NetworkFrame f;
* while(network.external_queue.size() > 0){
* f = network.external_queue.front();
* uint16_t dataSize = f.message_size;
* //read the frame message buffer
* memcpy(&myBuffer,&f.message_buffer,dataSize);
* network.external_queue.pop();
* }
* @endcode
*/
#if defined (RF24_LINUX)
std::queue<RF24NetworkFrame> external_queue;
#endif
#if !defined ( DISABLE_FRAGMENTATION ) && !defined (RF24_LINUX)
/**
* **ARDUINO** <br>
* The frag_ptr is only used with Arduino (not RPi/Linux) and is mainly used for external data systems like RF24Ethernet. When
* an EXTERNAL_DATA payload type is received, and returned from network.update(), the frag_ptr will always point to the starting
* memory location of the received frame. <br>This is used by external data systems (RF24Ethernet) to immediately copy the received
* data to a buffer, without using the user-cache.
*
* @see RF24NetworkFrame
*
* @code
* uint8_t return_type = network.update();
* if(return_type == EXTERNAL_DATA_TYPE){
* uint16_t size = network.frag_ptr->message_size;
* memcpy(&myDataBuffer,network.frag_ptr->message_buffer,network.frag_ptr->message_size);
* }
* @endcode
* Linux devices (defined as RF24_LINUX) currently cache all payload types, and do not utilize frag_ptr.
*/
RF24NetworkFrame* frag_ptr;
#endif
/**
* Variable to determine whether update() will return after the radio buffers have been emptied (DEFAULT), or
* whether to return immediately when (most) system types are received.
*
* As an example, this is used with RF24Mesh to catch and handle system messages without loading them into the user cache.
*
* The following reserved/system message types are handled automatically, and not returned.
*
* | System Message Types <br> (Not Returned) |
* |-----------------------|
* | NETWORK_ADDR_RESPONSE |
* | NETWORK_ACK |
* | NETWORK_PING |
* | NETWORK_POLL <br>(With multicast enabled) |
* | NETWORK_REQ_ADDRESS |
*
*/
bool returnSysMsgs;
/**
* Network Flags allow control of data flow
*
* Incoming Blocking: If the network user-cache is full, lets radio cache fill up. Radio ACKs are not sent when radio internal cache is full.<br>
* This behaviour may seem to result in more failed sends, but the payloads would have otherwise been dropped due to the cache being full.<br>
*
* | FLAGS | Value | Description |
* |-------|-------|-------------|
* |FLAG_HOLD_INCOMING| 1(bit_1) | INTERNAL: Set automatically when a fragmented payload will exceed the available cache |
* |FLAG_BYPASS_HOLDS| 2(bit_2) | EXTERNAL: Can be used to prevent holds from blocking. Note: Holds are disabled & re-enabled by RF24Mesh when renewing addresses. This will cause data loss if incoming data exceeds the available cache space|
* |FLAG_FAST_FRAG| 4(bit_3) | INTERNAL: Replaces the fastFragTransfer variable, and allows for faster transfers between directly connected nodes. |
* |FLAG_NO_POLL| 8(bit_4) | EXTERNAL/USER: Disables NETWORK_POLL responses on a node-by-node basis. |
*
*/
uint8_t networkFlags;
private:
uint32_t txTime;
bool write(uint16_t, uint8_t directTo);
bool write_to_pipe( uint16_t node, uint8_t pipe, bool multicast );
uint8_t enqueue(RF24NetworkHeader *header);
bool is_direct_child( uint16_t node );
bool is_descendant( uint16_t node );
uint16_t direct_child_route_to( uint16_t node );
//uint8_t pipe_to_descendant( uint16_t node );
void setup_address(void);
bool _write(RF24NetworkHeader& header,const void* message, uint16_t len, uint16_t writeDirect);
struct logicalToPhysicalStruct{
uint16_t send_node;
uint8_t send_pipe;
bool multicast;
};
bool logicalToPhysicalAddress(logicalToPhysicalStruct *conversionInfo);
RF24& radio; /**< Underlying radio driver, provides link/physical layers */
#if defined (DUAL_HEAD_RADIO)
RF24& radio1;
#endif
#if defined (RF24NetworkMulticast)
uint8_t multicast_level;
#endif
uint16_t node_address; /**< Logical node address of this unit, 1 .. UINT_MAX */
//const static int frame_size = 32; /**< How large is each frame over the air */
uint8_t frame_size;
const static unsigned int max_frame_payload_size = MAX_FRAME_SIZE-sizeof(RF24NetworkHeader);
#if defined (RF24_LINUX)
std::queue<RF24NetworkFrame> frame_queue;
std::map< uint16_t, RF24NetworkFrame> frameFragmentsCache;
bool appendFragmentToFrame(RF24NetworkFrame frame);
#else
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
#if !defined (NUM_USER_PAYLOADS)
#define NUM_USER_PAYLOADS 3
#endif
#endif
#if !defined (NUM_USER_PAYLOADS)
#define NUM_USER_PAYLOADS 5
#endif
#if defined (DISABLE_USER_PAYLOADS)
uint8_t frame_queue[1]; /**< Space for a small set of frames that need to be delivered to the app layer */
#else
uint8_t frame_queue[MAIN_BUFFER_SIZE]; /**< Space for a small set of frames that need to be delivered to the app layer */
#endif
uint8_t* next_frame; /**< Pointer into the @p frame_queue where we should place the next received frame */
#if !defined ( DISABLE_FRAGMENTATION )
RF24NetworkFrame frag_queue;
uint8_t frag_queue_message_buffer[MAX_PAYLOAD_SIZE]; //frame size + 1
#endif
#endif
//uint8_t frag_queue[MAX_PAYLOAD_SIZE + 11];
//RF24NetworkFrame frag_queue;
uint16_t parent_node; /**< Our parent's node address */
uint8_t parent_pipe; /**< The pipe our parent uses to listen to us */
uint16_t node_mask; /**< The bits which contain signfificant node address information */
#if defined ENABLE_NETWORK_STATS
static uint32_t nFails;
static uint32_t nOK;
#endif
public:
};
/**
* @example helloworld_tx.ino
*
* Simplest possible example of using RF24Network. Put this sketch
* on one node, and helloworld_rx.pde on the other. Tx will send
* Rx a nice message every 2 seconds which rx will print out for us.
*/
/**
* @example helloworld_rx.ino
*
* Simplest possible example of using RF24Network. Put this sketch
* on one node, and helloworld_tx.pde on the other. Tx will send
* Rx a nice message every 2 seconds which rx will print out for us.
*/
/**
* @example Network_Ping.ino
*
* Example to give users an understanding of addressing and topology in the mesh network
* Using this sketch, each node will send a ping to the base every
* few seconds. The RF24Network library will route the message across
* the mesh to the correct node.
*
*/
/**
* @example Network_Ping_Sleep.ino
*
* Example: This is almost exactly the same as the Network_Ping example, but with use
* of the integrated sleep mode.
*
* This example demonstrates how nodes on the network utilize sleep mode to conserve power. For example,
* the radio itself will draw about 13.5mA in receive mode. In sleep mode, it will use as little as 22ua (.000022mA)
* of power when not actively transmitting or receiving data. In addition, the Arduino is powered down as well,
* dropping network power consumption dramatically compared to previous capabilities. <br>
* Note: Sleeping nodes generate traffic that will wake other nodes up. This may be mitigated with further modifications. Sleep
* payloads are currently always routed to the master node, which will wake up intermediary nodes. Routing nodes can be configured
* to go back to sleep immediately.
* The displayed millis() count will give an indication of how much a node has been sleeping compared to the others, as millis() will
* not increment while a node sleeps.
*<br>
* - Using this sketch, each node will send a ping to every other node in the network every few seconds.<br>
* - The RF24Network library will route the message across the mesh to the correct node.<br>
*
*/
/**
* @example sensornet.pde
*
* Example of a sensor network.
* This sketch demonstrates how to use the RF24Network library to
* manage a set of low-power sensor nodes which mostly sleep but
* awake regularly to send readings to the base.
*/
/**
* @mainpage Network Layer for RF24 Radios
*
* This class implements an <a href="http://en.wikipedia.org/wiki/Network_layer">OSI Network Layer</a> using nRF24L01(+) radios driven
* by the newly optimized <a href="http://tmrh20.github.com/RF24/">RF24</a> library fork.
*
* @section Purpose Purpose/Goal
*
* Original: Create an alternative to ZigBee radios for Arduino communication.
*
* New: Enhance the current functionality for maximum efficiency, reliability, and speed
*
* Xbees are excellent little radios, backed up by a mature and robust standard
* protocol stack. They are also expensive.
*
* For many Arduino uses, they seem like overkill. So I am working to improve the current
* standard for nRF24L01 radios. The best RF24 modules are available for less than
* $6 from many sources. With the RF24Network layer, I hope to cover many
* common communication scenarios.
*
* Please see the @ref Zigbee page for a comparison against the ZigBee protocols
*
* @section Features Features
*
* <b>Whats new? </b><br>
* @li New: (Dec 8) Merge of RPi and Arduino code. Finally moving closer to a stable release. Report issues at https://github.com/TMRh20/RF24Network/issues
* @li New functionality: (Dec 8) Support for fragmented multicast payloads on both RPi and Arduino
* @li New functionality: (Nov 24) Fragmentation & reassembly supported on both RPi and Arduino
* @li Note: structure of network frames is changed, these are only used by external applications like RF24Ethernet and RF24toTUN, and for fragmentation
* @li New functionality: User message types 1 through 64 will not receive a network ack
*
* The layer provides:
* @li <b>New</b> (2014): Network ACKs: Efficient acknowledgement of network-wide transmissions, via dynamic radio acks and network protocol acks.
* @li <b>New</b> (2014): Updated addressing standard for optimal radio transmission.
* @li <b>New</b> (2014): Extended timeouts and staggered timeout intervals. The new txTimeout variable allows fully automated extended timeout periods via auto-retry/auto-reUse of payloads.
* @li <b>New</b> (2014): Optimization to the core library provides improvements to reliability, speed and efficiency. See https://tmrh20.github.io/RF24 for more info.
* @li <b>New</b> (2014): Built in sleep mode using interrupts. (Still under development. (Enable via RF24Network_config.h))
* @li <b>New</b> (2014): Dual headed operation: The use of dual radios for busy routing nodes or the master node enhances throughput and decreases errors. See the <a href="Tuning.html">Tuning</a> section.
* @li Host Addressing. Each node has a logical address on the local network.
* @li Message Forwarding. Messages can be sent from one node to any other, and
* this layer will get them there no matter how many hops it takes.
* @li Ad-hoc Joining. A node can join a network without any changes to any
* existing nodes.
*
* The layer does not provide:
* @li Dynamic address assignment. (See RF24Mesh)
* @li Layer 4 protocols (TCP/IP - See RF24Ethernet and RF24toTUN)
*
* @section More How to learn more
*
* @li <a href="classRF24Network.html">RF24Network Class Documentation</a>
* @li <a href="AdvancedConfig.html"> Advanced Configuration Options</a>
* @li <a href="Addressing.html"> Addressing format</a>
* @li <a href="Tuning.html"> Topology and Overview</a>
* @li <a href="https://github.com/TMRh20/RF24Network/archive/Development.zip">Download Current Development Package</a>
* @li <a href="examples.html">Examples Page</a>. Start with <a href="helloworld_rx_8ino-example.html">helloworld_rx</a> and <a href="helloworld_tx_8ino-example.html">helloworld_tx</a>.
*
* <b> Additional Information & Add-ons </b>
* @li <a href="https://github.com/TMRh20/RF24Mesh">RF24Mesh: Dynamic Mesh Layer for RF24Network Dev</a>
* @li <a href="https://github.com/TMRh20/RF24Ethernet">RF24Ethernet: TCP/IP over RF24Network</a>
* @li <a href="http://tmrh20.blogspot.com/2014/03/high-speed-data-transfers-and-wireless.html">My Blog: RF24 Optimization Overview</a>
* @li <a href="http://tmrh20.blogspot.com/2014/03/arduino-radiointercomwireless-audio.html">My Blog: RF24 Wireless Audio</a>
* @li <a href="http://maniacbug.github.com/RF24/">RF24: Original Author</a>
* @section Topology Topology for Mesh Networks using nRF24L01(+)
*
* This network layer takes advantage of the fundamental capability of the nRF24L01(+) radio to
* listen actively to up to 6 other radios at once. The network is arranged in a
* <a href="http://en.wikipedia.org/wiki/Network_Topology#Tree">Tree Topology</a>, where
* one node is the base, and all other nodes are children either of that node, or of another.
* Unlike a true mesh network, multiple nodes are not connected together, so there is only one
* path to any given node.
*
* @section Octal Octal Addressing and Topology
*
* Each node must be assigned an 15-bit address by the administrator. This address exactly
* describes the position of the node within the tree. The address is an octal number. Each
* digit in the address represents a position in the tree further from the base.
*
* @li Node 00 is the base node.
* @li Nodes 01-05 are nodes whose parent is the base.
* @li Node 021 is the second child of node 01.
* @li Node 0321 is the third child of node 021, an so on.
* @li The largest node address is 05555, so 3,125 nodes are allowed on a single channel.
* An example topology is shown below, with 5 nodes in direct communication with the master node,
* and multiple leaf nodes spread out at a distance, using intermediate nodes to reach other nodes.
*
*| | | 00 | | | 00 | | | | Master Node (00) |
*|---|----|----|----|----|----|----|----|----|-----------------------------------------------------|
*| | | 01 | | | 04 | | | | 1st level children of master (00) |
*| | 011| | 021| | |014 | | | 2nd level children of master. Children of 1st level.|
*|111| | | 121| 221| | | 114| | 3rd level children of master. Children of 2nd level.|
*| | | | |1221| |1114|2114|3114| 4th level children of master. Children of 3rd level.|
*