mesh.h File Reference

Simple Mesh Network Algorithm.VERSION: More...

#include "mesh_typedefs.h"
Include dependency graph for mesh.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool mesh_init (const uint8_t local_node_id, const bool is_mesh_node, const char *node_name, const mesh_driver_t driver, const bool discovery)
 
bool mesh_set_node_address (const uint8_t local_node_id)
 
uint8_t mesh_get_node_address (void)
 
void mesh_set_retry_count (const uint8_t count)
 
void mesh_service (void)
 
bool mesh_send (const uint8_t dst, const mesh_protocol_t type, const void *pData, const uint8_t len, const uint8_t hop_count_max)
 
bool mesh_form_pkt (mesh_packet_t *pkt, const uint8_t dst, const mesh_protocol_t type, const uint8_t hop_count_max, uint8_t num_ptrs,...)
 
bool mesh_send_formed_pkt (mesh_packet_t *pkt)
 
bool mesh_deform_pkt (mesh_packet_t *pkt, uint8_t num_ptrs,...)
 
const mesh_rte_table_tmesh_get_routing_entry (const uint8_t route_num)
 
uint8_t mesh_get_num_routing_entries (void)
 
bool mesh_is_route_known (const uint8_t addr)
 
uint8_t mesh_get_pnd_pkt_count (void)
 
uint32_t mesh_get_expected_ack_time (uint8_t node_addr)
 
uint32_t mesh_get_max_timeout_before_packet_fails (uint8_t node_addr)
 
mesh_stats_t mesh_get_stats (void)
 
mesh_error_mask_t mesh_get_error_mask (void)
 
void mesh_reset_error_mask (void)
 Resets the error mask to zero. More...
 

Detailed Description

Simple Mesh Network Algorithm.

VERSION:

See also
mesh_config.h version and change history information.
Simple Mesh Algorithm for low powered radios.
This library has small footprint with minimal code and RAM requirements. Each node can be a repeater node, and contains its own routing table.
Types of Packets
  • NACK : "Fire-and-Forget" packet, no acknowledgment from receiver.
  • ACK : Receiver will auto-acknowledge, and packet is retransmitted if ACK not received.
  • Broadcast, and Application ACK
Example Initialization Code:
Assuming the radio functions and application receive function is provided, init() code is simple :
// Example mesh callback function :
int my_radio_init(void *data, int len)
{
// Initialize your radio chip.
}
// Example timer function
int my_timer_get(void *pData, int len) {
const char ok = (sizeof(uint32_t) == len); // Size passed in will be uint32_t
const uint32_t timerValueMs = your_sys_timer_get(); // Get your system timer value
if (ok) {
uint32_t *timer = (uint32_t*)pData;
*timer = timerValueMs;
}
return ok;
}
Mesh_DriverStruct driver;
driver.radio_init = my_radio_init;
driver.radio_send = my_radio_send;
driver.radio_recv = my_radio_recv;
driver.app_recv = my_app_recv;
driver.get_timer = my_timer_get;
char my_node_id = 0x10;
mesh_init(my_node_id, true, &driver, true);
Sample code for a node receiving data :
// Global variables
mesh_packet_t packet;
bool rx = false;
// Application receive callback
int my_app_recv(void *data, int len)
{
memcpy(&packet, data, len);
rx = true;
}
// main loop :
while(1) {
if(rx) {
rx = false;
if(mesh_is_ack_required(&packet)) {
mesh_send_ack("Hello Back", 10, &packet);
}
}
}
Warning
Care needs to be taken for single radio systems when they send out a packet. You don't want the mesh route discovery packet to be repeated at the same time by the nearby nodes because their data will collide and nothing will go through. The radio send function can then be modified with logic similar to :
char my_radio_send(char* pData, int len)
{
if (mesh_get_node_address() != pkt->nwk.src) {
if (MESH_ZERO_ADDR == pkt->mac.dst) {
const uint32_t timeSlotDelayUs = ((rand() % slots) + 1) * pkt_air_time_us;
delay_us(timeSlotDelayUs);
}
}
}

Function Documentation

bool mesh_deform_pkt ( mesh_packet_t *  pkt,
uint8_t  num_ptrs,
  ... 
)

This does the opposite of mesh_form_pkt(). Instead of copying data from the pointers and storing to the packet data, this will copy the data from the packet and store to your pointers.

Parameters
pktThe mesh packet received.
num_ptrsThe number of pairs of pointers.
Returns
false if the packet was smaller than the data being asked to store.
1 // Assume we got a packet with a uint32_t and a float :
2 uint32_t my_int = 0;
3 float my_flt = 0;
4 mesh_deform_pkt(&pkt, 2,
5  &my_flt, sizeof(my_flt),
6  &my_int, sizeof(my_int));
bool mesh_form_pkt ( mesh_packet_t *  pkt,
const uint8_t  dst,
const mesh_protocol_t  type,
const uint8_t  hop_count_max,
uint8_t  num_ptrs,
  ... 
)

Form a packet by copying the data from the given pointers as variable arguments.

See also
parameters of mesh_send()
Parameters
num_ptrsThe number of data pointer pairs; see below.
...The pairs of data pointer and the size; see below.
Returns
true if packet was formed correctly. Error may be returned if you tried to send too much data that the payload cannot hold.
Warning
Once a packet is formed, it should be immediately sent because packet route may change later, so the packet may not make it through.
1 mesh_packet_t pkt;
2 
3 // Copy single NULL string
4 mesh_form_pkt(&pkt, 1, mesh_pkt_ack, 1, 1, "\0", 1);
5 
6 // Copy two strings:
7 mesh_form_pkt(&pkt, 1, mesh_pkt_ack, 1,
8  2, // Two pairs below
9  "hello", 5, // First pair's data, and the size
10  "world", 5); // Second pair's data, and the size
11 
12 // Copy three variables (string, int, and float):
13 int my_int = 123;
14 float my_flt = 1.23;
15 mesh_form_pkt(&pkt, 1, mesh_pkt_ack, 1,
16  3,
17  "copyme", 6,
18  &my_int, sizeof(my_int),
19  &my_flt, sizeof(my_flt));
mesh_error_mask_t mesh_get_error_mask ( void  )

Mesh API to get error types and reset errors Mesh layer keeps error bit fields during its operation. The error mask can be obtained and masked with mesh_error_mask_t to detect the error type, and it can be reset by this API.

1 mesh_error_mask_t err = mesh_get_error_mask();
2 if (e & mesh_err_dup_node) {
3  // Duplicate node with our address found
4 }
Returns
errors encountered during mesh network operation.
uint32_t mesh_get_expected_ack_time ( uint8_t  node_addr)
Returns
the expected number of milliseconds it should take for the destination node to send us an ACK packet. This is the most ideal time assuming no packet is lost while sending or receiving the ACK. If the route is not known, then the timeout returned is based on the assumption that it is MESH_RTE_DISCOVERY_HOPS (#define'd) hops away.
uint32_t mesh_get_max_timeout_before_packet_fails ( uint8_t  node_addr)
Returns
similar to mesh_get_expected_ack_time(), but the returned value is the max expected timeout after we exhaust our retries.
uint8_t mesh_get_node_address ( void  )
Returns
our mesh node address.
uint8_t mesh_get_num_routing_entries ( void  )
Returns
The number of routing entries this node is maintaining.
uint8_t mesh_get_pnd_pkt_count ( void  )

If there are is no packet received from your radio, and there are not any pending packets, then mesh_service() doesn't have to be called periodically.

Returns
The number of packets that are in the pending state, means they are waiting to be acknowledged, or repeated after a timeout.
const mesh_rte_table_t* mesh_get_routing_entry ( const uint8_t  route_num)

Allows user to query all the routing entries.

Parameters
route_numThe route number to query : 0 - (N-1) When NULL is returned, no more route exists. If Non-NULL entry is returned, user can look at destination, the route to next destination, and number of hops it is away.
mesh_stats_t mesh_get_stats ( void  )
Returns
The mesh network statistics structure.
bool mesh_init ( const uint8_t  local_node_id,
const bool  is_mesh_node,
const char *  node_name,
const mesh_driver_t  driver,
const bool  discovery 
)

Initializes the Mesh Network.

Parameters
local_node_idNode ID of your local node.
is_mesh_nodetrue, if this node can participate in Mesh to repeat packets.
node_nameNode name, maximum as large as a payload.
driverThe structure of the radio driver.
discoveryIf true, then a broadcast message with data: "Hello\n" is sent to each node within 3 hops away for discovery and route update purpose.
Note
Unless changed otherwise, the retry count contains default value;
See also
mesh_set_retry_count()
bool mesh_is_route_known ( const uint8_t  addr)
Returns
true if our routing table contains the route for the given destination address.
void mesh_reset_error_mask ( void  )

Resets the error mask to zero.

bool mesh_send ( const uint8_t  dst,
const mesh_protocol_t  type,
const void *  pData,
const uint8_t  len,
const uint8_t  hop_count_max 
)

Sends a new packet.

Parameters
dstThe destination address to send data to.
typeThe type of packet: ack, nack, app-ack
See also
mesh_protocol_t
Parameters
pDataThe pointer to the data to send.
lenThe length of the data to send.
hop_count_maxSee the 3 use cases below :
  • If this is a broadcast message, this controls the max hops packet can take.
  • If the route is known, then this parameter will not have any effect.
  • If the route is unknown, then this controls how far the packet can travel to search for our destined node. You can pass MESH_HOP_COUNT_MAX if you want the mesh algorithm to figure it out at the cost of utilizing the network a little more and decreasing its efficiency.
Returns
true if the packet was sent successfully
Warning
This function SHOULD NOT be used to send an ACK back because infinite loop of back-and-forth ACKs may occur.
See also
mesh_send_ack()
Note
This method and mesh_service() can be called from different threads because mesh_service() will skip its execution if we are inside a critical section.
bool mesh_send_formed_pkt ( mesh_packet_t *  pkt)

Send a packet that is already formed.

Parameters
pktThe packet pointer formed by mesh_form_pkt().
void mesh_service ( void  )

This method should be called periodically. This method gets the radio data, and runs the mesh algorithm. When a packet is received for you, the app_recv() call-back will be called.

Note
When N1 sends a packet to 4 nodes it can transmit to, all four nodes will repeat the packet if the route is unknown, so we need these nodes to discard the packets they repeat to each other. However, when the origin node doesn't get an ACK back, it will r-esend the packet with the retries_rem decremented, such that all these nodes can repeat the packet instead of throwing it away. The destined node needs to only send data to application layer if packet is not a duplicate, however, for every re-sent packet, it needs to ACK back the packet.
bool mesh_set_node_address ( const uint8_t  local_node_id)

This method allows to change the node address after mesh_init() has been called.

Parameters
local_node_idNode ID of your local node.
void mesh_set_retry_count ( const uint8_t  count)
Parameters
countNumber of retries used for ACK packet if ACK not received; see note below. Max value is MESH_RETRY_COUNT_MAX. Optimal value is 2 (default unless changed).
Note
The retries apply if routes do not change but the actual retry count may be higher if nodes change routes frequency. For example, if retries are set to 2, and a node N1 sends packet to N3 through N2, then the packet may be sent 6 times:
  • Send original packet, if no ACK, then re-send 2 more times.
  • Remove N3 route through N2 and re-send original packet to discover new route.
  • Re-send packet 2 more times if ACK still not received.