9#if defined(__linux) && !defined(__ARDUINO_X86__)
13template<
class network_t,
class radio_t>
18#if !defined(MESH_NOMASTER)
19 addrMemAllocated =
false;
25template<
class network_t,
class radio_t>
30 radio.stopListening();
35 radio.setChannel(channel);
36 radio.setDataRate(data_rate);
37 network.returnSysMsgs =
true;
39 if (getNodeID() > 0) {
45#if !defined(MESH_NOMASTER)
46 if (!addrMemAllocated) {
47 addrMemAllocated =
true;
54 network.begin(mesh_address);
62template<
class network_t,
class radio_t>
65 uint8_t type = network.update();
68#if !defined(MESH_NOMASTER)
69 if (type == NETWORK_REQ_ADDRESS) {
75 RF24NetworkHeader* header = (RF24NetworkHeader*)(&network.frame_buffer);
76 header->to_node = header->from_node;
78 int16_t returnAddr = 0;
80 returnAddr = getAddress(network.frame_buffer[
sizeof(RF24NetworkHeader)]);
81 network.write(*header, &returnAddr,
sizeof(returnAddr));
85 memcpy(&addr, &network.frame_buffer[
sizeof(RF24NetworkHeader)],
sizeof(addr));
86 returnAddr = getNodeID(addr);
87 network.write(*header, &returnAddr,
sizeof(returnAddr));
91 uint16_t* fromAddr = (uint16_t*)network.frame_buffer;
92 for (uint8_t i = 0; i < addrListTop; i++) {
93 if (addrList[i].address == *fromAddr) {
94 addrList[i].address = 0;
106template<
class network_t,
class radio_t>
111 RF24NetworkHeader header(to_node, msg_type);
112 return network.write(header, data, size);
117template<
class network_t,
class radio_t>
124 uint32_t retryDelay = 5;
127 while ((toNode = getAddress(nodeID)) < 0) {
128 if (millis() > lookupTimeout || toNode == -2) {
135 return write(toNode, data, msg_type, size);
140template<
class network_t,
class radio_t>
143 radio.stopListening();
144 radio.setChannel(_channel);
145 radio.startListening();
150template<
class network_t,
class radio_t>
153 network.networkFlags = allow ? network.networkFlags & ~FLAG_NO_POLL : network.networkFlags | FLAG_NO_POLL;
158template<
class network_t,
class radio_t>
162 if (getAddress(_nodeID) < 1) {
163 if (getAddress(_nodeID) < 1) {
172template<
class network_t,
class radio_t>
177 if (!nodeID)
return 0;
181#if !defined(MESH_NOMASTER)
183 for (uint8_t i = 0; i < addrListTop; i++) {
184 if (addrList[i].nodeID == nodeID) {
185 return addrList[i].address;
193 if (network.write(header, &nodeID,
sizeof(nodeID))) {
194 uint32_t timer = millis();
202 memcpy(&address, network.frame_buffer +
sizeof(RF24NetworkHeader),
sizeof(address));
210template<
class network_t,
class radio_t>
214 if (address == 0)
return 0;
217#if !defined(MESH_NOMASTER)
219 for (uint8_t i = 0; i < addrListTop; i++) {
220 if (addrList[i].address == address) {
221 return addrList[i].nodeID;
229 if (network.write(header, &address,
sizeof(address))) {
230 uint32_t timer = millis();
236 memcpy(&ID, &network.frame_buffer[
sizeof(RF24NetworkHeader)],
sizeof(ID));
244template<
class network_t,
class radio_t>
257template<
class network_t,
class radio_t>
260 radio.stopListening();
267template<
class network_t,
class radio_t>
273 if (network.write(header, 0, 0)) {
282template<
class network_t,
class radio_t>
285 if (radio.available()) network.update();
287 uint8_t reqCounter = 0;
288 uint8_t totalReqs = 0;
292 uint32_t start = millis();
293 while (!requestAddress(reqCounter)) {
294 if (millis() - start > timeout)
break;
296 uint32_t timeoutInternal = 50 + ((totalReqs + 1) * (reqCounter + 1)) * 2;
297 uint32_t startInternal = millis();
298 while (millis() - startInternal < timeoutInternal) {
303 reqCounter = reqCounter % 4;
305 totalReqs = totalReqs % 10;
312template<
class network_t,
class radio_t>
318 network.multicast(header, 0, 0, level);
320 uint32_t timr = millis();
321#define MESH_MAXPOLLS 4
323 uint8_t pollCount = 0;
326#if defined(MESH_DEBUG)
327 bool goodSignal = radio.testRPD();
330 if (network.update() == NETWORK_POLL) {
332 memcpy(&contactNode[pollCount], &network.frame_buffer[0],
sizeof(uint16_t));
333 if (pollCount > 0 && contactNode[pollCount] != contactNode[pollCount - 1]) {
340 IF_MESH_DEBUG(printf_P(PSTR(
"%u: MSH Poll %c -64dbm\n"), millis(), (goodSignal ?
'>' :
'<')));
345 IF_MESH_DEBUG(printf_P(PSTR(
"%u: MSH No poll from level %d\n"), millis(), level));
349 IF_MESH_DEBUG(printf_P(PSTR(
"%u: MSH Poll OK\n"), millis()));
356 IF_MESH_DEBUG(printf_P(PSTR(
"%u: MSH Got poll from level %d count %d\n"), millis(), level, pollCount));
358 bool gotResponse = 0;
359 for (uint8_t i = 0; i < pollCount; i++) {
361 header.type = NETWORK_REQ_ADDRESS;
362 header.reserved = _nodeID;
363 header.to_node = contactNode[i];
366 network.write(header, 0, 0, contactNode[i]);
368 IF_MESH_DEBUG(printf_P(PSTR(
"%u: MSH Request address from: 0%o\n"), millis(), contactNode[i]));
372 while (millis() - timr < 225) {
373 if (network.update() == NETWORK_ADDR_RESPONSE) {
374 if (network.frame_buffer[7] == _nodeID) {
375 uint16_t newAddy = 0;
376 memcpy(&newAddy, &network.frame_buffer[
sizeof(RF24NetworkHeader)],
sizeof(newAddy));
377 uint16_t mask = 0xFFFF;
378 newAddy &= ~(mask << (3 * getLevel(contactNode[i])));
379 if (newAddy == contactNode[i]) {
394 uint16_t newAddress = 0;
395 memcpy(&newAddress, network.frame_buffer +
sizeof(RF24NetworkHeader),
sizeof(newAddress));
397 IF_MESH_DEBUG(printf_P(PSTR(
"Set address 0%o rcvd 0%o\n"), mesh_address, newAddress));
398 mesh_address = newAddress;
400 radio.stopListening();
401 network.begin(mesh_address);
404 if (getNodeID(mesh_address) != _nodeID) {
405 if (getNodeID(mesh_address) != _nodeID) {
415template<
class network_t,
class radio_t>
422#if !defined(MESH_NOMASTER)
424template<
class network_t,
class radio_t>
427 setAddress(nodeID, address);
432template<
class network_t,
class radio_t>
436 for (uint8_t i = 0; i < addrListTop; i++) {
437 if (searchBy ==
false) {
438 if (addrList[i].nodeID == nodeID) {
439 addrList[i].address = address;
440 #if defined(__linux) && !defined(__ARDUINO_X86__)
447 if (addrList[i].address == address) {
449 addrList[i].nodeID = nodeID;
450 #if defined(__linux) && !defined(__ARDUINO_X86__)
461 addrList[addrListTop].address = address;
462 addrList[addrListTop++].nodeID = nodeID;
463 #if defined(__linux) && !defined(__ARDUINO_X86__)
470template<
class network_t,
class radio_t>
474 #if defined(__linux) && !defined(__ARDUINO_X86__)
475 std::ifstream infile(
"dhcplist.txt", std::ifstream::binary);
478 infile.seekg(0, infile.end);
479 int length = infile.tellg();
480 infile.seekg(0, infile.beg);
494template<
class network_t,
class radio_t>
497 #if defined(__linux) && !defined(__ARDUINO_X86__)
498 std::ofstream outfile(
"dhcplist.txt", std::ofstream::binary | std::ofstream::trunc);
500 for (
int i = 0; i < addrListTop; i++) {
509template<
class network_t,
class radio_t>
517 RF24NetworkHeader header;
518 memcpy(&header, network.frame_buffer,
sizeof(RF24NetworkHeader));
523 if (!header.reserved || header.type != NETWORK_REQ_ADDRESS) {
524 IF_MESH_DEBUG(printf_P(PSTR(
"%u: MSH Invalid id or type rcvd\n"), millis()));
529 uint8_t shiftVal = 0;
530 bool extraChild =
false;
533 fwd_by = header.from_node;
553 newAddress = fwd_by | (i << shiftVal);
557 for (uint8_t i = 0; i < addrListTop; i++) {
558 IF_MESH_DEBUG_MINIMAL(printf_P(PSTR(
"ID: %d ADDR: 0%o\n"), addrList[i].nodeID, addrList[i].address));
559 if (addrList[i].address == newAddress && addrList[i].nodeID != header.reserved) {
566 header.type = NETWORK_ADDR_RESPONSE;
567 header.to_node = header.from_node;
570 setAddress(header.reserved, newAddress);
572 #if defined(SLOW_ADDR_POLL_RESPONSE)
573 delay(SLOW_ADDR_POLL_RESPONSE);
578 if (!network.write(header, &newAddress,
sizeof(newAddress))) {
579 network.write(header, &newAddress,
sizeof(newAddress));
584 network.write(header, &newAddress,
sizeof(newAddress), header.to_node);
600template<
class network_t,
class radio_t>
604 this->meshCallback = meshCallback;
611#if defined(ARDUINO_ARCH_NRF52) || defined(ARDUINO_ARCH_NRF52840)
#define MESH_ADDR_RELEASE
#define MESH_MULTICAST_ADDRESS
#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_MESH_DEBUG_MINIMAL(x)
#define MESH_DEFAULT_ADDRESS
#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))
ESBMesh(radio_t &_radio, network_t &_network)
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.
uint8_t nodeID
The nodeID of an network node (child)
uint16_t address
The logical address of an network node (child)