9#if defined(__linux) && !defined(__ARDUINO_X86__)
12#if defined(RF24NETWORK_CCM)
13 #include <RF24Network/RF24CCM.h>
16template<
class network_t,
class radio_t>
21#if !defined(MESH_NOMASTER)
29template<
class network_t,
class radio_t>
34 radio.stopListening();
39 radio.setChannel(channel);
40 radio.setDataRate(data_rate);
41 network.returnSysMsgs =
true;
58template<
class network_t,
class radio_t>
61 uint8_t type = network.update();
64#if !defined(MESH_NOMASTER)
65 if (type == NETWORK_REQ_ADDRESS) {
71 RF24NetworkHeader* header = (RF24NetworkHeader*)(&network.frame_buffer);
72 header->to_node = header->from_node;
74 int16_t returnAddr = 0;
76 returnAddr =
getAddress(network.frame_buffer[
sizeof(RF24NetworkHeader)]);
77 network.write(*header, &returnAddr,
sizeof(returnAddr));
81 memcpy(&addr, &network.frame_buffer[
sizeof(RF24NetworkHeader)],
sizeof(addr));
83 network.write(*header, &returnAddr,
sizeof(returnAddr));
87 uint16_t* fromAddr = (uint16_t*)network.frame_buffer;
98template<
class network_t,
class radio_t>
103 RF24NetworkHeader header(to_node, msg_type);
104 return network.write(header, data, size);
109template<
class network_t,
class radio_t>
115 uint32_t lookupStart = millis();
116 uint32_t retryDelay = 5;
127 return write(toNode, data, msg_type, size);
132template<
class network_t,
class radio_t>
135 radio.stopListening();
136 radio.setChannel(_channel);
137 radio.startListening();
142template<
class network_t,
class radio_t>
145 network.networkFlags = allow ? network.networkFlags & ~FLAG_NO_POLL : network.networkFlags | FLAG_NO_POLL;
150template<
class network_t,
class radio_t>
158#if RF24MESH_CONN_CHECK_TYPE == RF24MESH_CONN_CHECK_PARENT
159 RF24NetworkHeader header;
160 header.to_node = network.parent();
161 header.type = NETWORK_PING;
163 if (network.write(header, 0, 0)) {
175 case -2:
return false;
177 case 0:
return false;
191template<
class network_t,
class radio_t>
196 if (!nodeID)
return 0;
200#if !defined(MESH_NOMASTER)
212 if (network.write(header, &nodeID,
sizeof(nodeID))) {
213 uint32_t timer = millis();
221 memcpy(&address, network.frame_buffer +
sizeof(RF24NetworkHeader),
sizeof(address));
229template<
class network_t,
class radio_t>
233 if (address == 0)
return 0;
236#if !defined(MESH_NOMASTER)
239 if (
addrList[i].address == address) {
248 if (network.write(header, &address,
sizeof(address))) {
249 uint32_t timer = millis();
255 memcpy(&ID, &network.frame_buffer[
sizeof(RF24NetworkHeader)],
sizeof(ID));
263template<
class network_t,
class radio_t>
264uint8_t ESBMesh<network_t, radio_t>::getLevel(uint16_t address)
276template<
class network_t,
class radio_t>
277void ESBMesh<network_t, radio_t>::beginDefault()
279 radio.stopListening();
286template<
class network_t,
class radio_t>
292 if (network.write(header, 0, 0)) {
302template<
class network_t,
class radio_t>
306 if (
addrList[i].address == address) {
317template<
class network_t,
class radio_t>
320 if (radio.available()) network.update();
322 uint8_t reqCounter = 0;
323 uint8_t totalReqs = 0;
327 uint32_t start = millis();
328 while (!requestAddress(reqCounter)) {
329 if (millis() - start > timeout)
break;
331 uint32_t timeoutInternal = 50 + ((totalReqs + 1) * (reqCounter + 1)) * 2;
332 uint32_t startInternal = millis();
333 while (millis() - startInternal < timeoutInternal) {
338 reqCounter = reqCounter % 4;
340 totalReqs = totalReqs % 10;
347template<
class network_t,
class radio_t>
348bool ESBMesh<network_t, radio_t>::requestAddress(uint8_t level)
353 network.multicast(header, 0, 0, level);
355 const uint32_t pollStart = millis();
356#define MESH_MAXPOLLS 4
358 uint8_t pollCount = 0;
360 while (millis() - pollStart < 55 && pollCount <
MESH_MAXPOLLS) {
361#if defined(RF24MESH_DEBUG)
362 bool goodSignal = radio.testRPD();
364 if (network.update() == NETWORK_POLL) {
365 uint16_t contact = 0;
366 memcpy(&contact, &network.frame_buffer[0],
sizeof(contact));
370 for (uint8_t i = 0; i < pollCount; ++i) {
371 if (contact == contactNode[i]) {
377 contactNode[pollCount] = contact;
379 IF_RF24MESH_DEBUG(printf_P(PSTR(
"MSH Poll %c -64dbm from 0%o \n"), (goodSignal ?
'>' :
'<'), contact));
387 IF_RF24MESH_DEBUG(printf_P(PSTR(
"MSH Polls from level %d: %d\n"), level, pollCount));
389 if (!pollCount)
return 0;
391 for (uint8_t i = 0; i < pollCount; i++) {
393 bool gotResponse = 0;
396 header.type = NETWORK_REQ_ADDRESS;
397 header.reserved = _nodeID;
398 header.to_node = contactNode[i];
401 network.write(header, 0, 0, contactNode[i]);
403 IF_RF24MESH_DEBUG(printf_P(PSTR(
"MSH Request address from: 0%o\n"), contactNode[i]));
405 const uint32_t responseStart = millis();
407 while (millis() - responseStart < 225) {
408 if (network.update() == NETWORK_ADDR_RESPONSE) {
409 if (network.frame_buffer[7] == _nodeID) {
410 uint16_t newAddy = 0;
411 memcpy(&newAddy, &network.frame_buffer[
sizeof(RF24NetworkHeader)],
sizeof(newAddy));
412 uint16_t mask = 0xFFFF;
413 newAddy &= ~(mask << (3 * getLevel(contactNode[i])));
414 if (newAddy == contactNode[i]) {
427 uint16_t newAddress = 0;
428 memcpy(&newAddress, network.frame_buffer +
sizeof(RF24NetworkHeader),
sizeof(newAddress));
430 IF_RF24MESH_DEBUG(printf_P(PSTR(
"Set address: Current: 0%o New: 0%o\n"), mesh_address, newAddress));
431 mesh_address = newAddress;
433 radio.stopListening();
434 network.begin(mesh_address);
437 if (getNodeID(mesh_address) != _nodeID) {
438 if (getNodeID(mesh_address) != _nodeID) {
451template<
class network_t,
class radio_t>
455#if !defined(MESH_NOMASTER)
456 if (nodeID == 0 &&
addrList ==
nullptr) {
468#if !defined(MESH_NOMASTER)
470template<
class network_t,
class radio_t>
478template<
class network_t,
class radio_t>
488 if (searchBy ==
false) {
491 #if defined(__linux) && !defined(__ARDUINO_X86__)
498 if (
addrList[i].address == address) {
501 #if defined(__linux) && !defined(__ARDUINO_X86__)
521 #if defined(__linux) && !defined(__ARDUINO_X86__)
528template<
class network_t,
class radio_t>
532 #if defined(__linux) && !defined(__ARDUINO_X86__)
533 std::ifstream infile(
"dhcplist.txt", std::ifstream::binary);
536 infile.seekg(0, infile.end);
537 int length = infile.tellg();
538 infile.seekg(0, infile.beg);
552template<
class network_t,
class radio_t>
555 #if defined(__linux) && !defined(__ARDUINO_X86__)
556 std::ofstream outfile(
"dhcplist.txt", std::ofstream::binary | std::ofstream::trunc);
567template<
class network_t,
class radio_t>
575 RF24NetworkHeader header;
576 memcpy(&header, network.frame_buffer,
sizeof(RF24NetworkHeader));
581 if (!header.reserved || header.type != NETWORK_REQ_ADDRESS) {
587 uint8_t shiftVal = 0;
588 bool extraChild =
false;
591 fwd_by = header.from_node;
611 newAddress = fwd_by | (i << shiftVal);
617 if (
addrList[i].address == newAddress &&
addrList[i].nodeID != header.reserved) {
624 header.type = NETWORK_ADDR_RESPONSE;
625 header.to_node = header.from_node;
630 #if defined(SLOW_ADDR_POLL_RESPONSE)
631 delay(SLOW_ADDR_POLL_RESPONSE);
636 if (!network.write(header, &newAddress,
sizeof(newAddress))) {
637 network.write(header, &newAddress,
sizeof(newAddress));
642 network.write(header, &newAddress,
sizeof(newAddress), header.to_node);
658template<
class network_t,
class radio_t>
662 this->meshCallback = meshCallback;
669#if defined(RF24NETWORK_CCM)
672#if defined(ARDUINO_ARCH_NRF52) || defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_NRF54L15)
#define MESH_ADDR_RELEASE
#define MESH_MULTICAST_ADDRESS
#define IF_RF24MESH_DEBUG(x)
#define MESH_MAX_CHILDREN
Set 1 to 4 (Default: 4) Restricts the maximum children per node.
#define MESH_LOOKUP_TIMEOUT
How long to wait in ms for a response during individual address lookups.
#define IF_RF24MESH_DEBUG_MINIMAL(x)
#define MESH_DEFAULT_ADDRESS
#define MESH_CONNECTION_CHECK_ATTEMPTS
Number of attempts to verify a connection.
#define MESH_MEM_ALLOC_SIZE
master node memory allocation
#define MESH_WRITE_TIMEOUT
How long RF24Mesh::write() retries address lookups before timing out. Allows multiple attempts.
int16_t getNodeID(uint16_t address=MESH_BLANK_ID)
void setStaticAddress(uint8_t nodeID, uint16_t address)
uint16_t renewAddress(uint32_t timeout=MESH_RENEWAL_TIMEOUT)
Reconnect to the mesh and renew the current RF24Network address.
void setChild(bool allow)
bool begin(uint8_t channel=MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate=RF24_1MBPS, uint32_t timeout=MESH_RENEWAL_TIMEOUT)
void setCallback(void(*meshCallback)(void))
uint8_t addrListTop
The number of entries in the addrListStruct of assigned addresses.
ESBMesh(radio_t &_radio, network_t &_network)
addrListStruct * addrList
A array of addrListStruct elements for assigned addresses.
void setNodeID(uint8_t nodeID)
bool write(const void *data, uint8_t msg_type, size_t size, uint8_t nodeID=0)
void setChannel(uint8_t _channel)
void setAddress(uint8_t nodeID, uint16_t address, bool searchBy=false)
int16_t getAddress(uint8_t nodeID)
Convert a nodeID into an RF24Network address.
A struct for storing a nodeID and an address in a single element of the ESBMesh::addrList array.