Green Internet of Things (IoT) generally refers to the new generation IoT design concept focusing on energy conservation and emission reduction, to minimize environmental pollution and resource waste, and to realize hazard-free emissions for the human body and the environment. Green IoT reduces energy expenditure by transforming and optimizing network devices and introducing new technology. As a brand new network configuration, IoT includes wireless and wired access networks, IP core networks and large-scale computer processing management platforms. It covers almost all the information and communication technology (ICT) industrial fields. Power consumption by huge networks is the worst bottleneck hindering ICT energy conservation and emission reduction. Also, due to restrictions imposed by the IoT itself, the IoT depends greatly on the research and application of low-power-consumption and high-energy-efficient green technology. Therefore, realizing “green” IoT is not only a requirement for social-economic development, but also a requirement for development of the IoT industry itself.

In WSN, node resource constraints make the energy expenditure reduction of nodes and the prolongation of network lifetime, the most important issue. Moreover, highly dynamic wireless links make reliable data transmission inevitable. Therefore, sending reliable sensor data to a goal node needs energy-conserving and highly fault-tolerant routing solutions.

This chapter will introduce two routing protocols: reliable energy-efficient routing (REER) [1] and K-cooperative nodes (KCN) [2], which are mainly used to deploy multi-hop collaborative WSN communication in unreliable environments.

6.1 REER Protocol

Sensors are expected to be inexpensive and deployable on a large scale in harsh environments, which implies that sensors are typically operating unattended. Often, sensor networks are also subject to a high failure rate: connectivity between nodes can be lost due to environmental noise and obstacles; nodes may die due to battery depletion, environmental changes, or malicious destruction. In such environments, reliable and energy-efficient data delivery is crucial because sensor nodes operate with limited battery power and error-prone wireless channels.

To address such issues, a great deal of research focuses on prolonging the network lifetime by exploiting energy-efficiency, supporting reliability, or achieving low-cost sensor design. However, these goals are usually orthogonal design objectives. Among these objectives, the goals of reliability and energy-efficiency usually conflict with each other. Consider two routing protocol extremes in terms of these two design objectives: unicast routing and flooding. Unicast routing is energy-efficient for reliable networks, but is not robust for dynamic networks. Flooding is very robust for dynamic and error-prone networks, but incurs a high overhead for sensor networks. Some routing protocols try to achieve a trade-off between the two extremes to make this adaptive to different network types (with different link/node failure rate, node density, etc.). For example, in directed diffusion (DD), exploratory data is periodically flooded for reliability. When a path is reinforced, it is used for a while with unicast routing in order to save on overhead.

The REER protocol to construct a “unicast-like” path is proposed to exploit broadcasting to attain high reliability during data dissemination. REER achieves both reliable and energy-efficient data delivery for dense wireless sensor networks (WSNs).

6.1.1 REER Protocol Design

6.1.1.1 Overview

In this section, we present the architecture and design of the REER protocol. An illustration of the REER routing protocol is shown in Fig. 6.1.

Fig. 6.1
figure 1

Illustration of the REER routing protocol: a RNs along the shortest path; b CNs in the cooperative fields; c cooperative data forwarding; d the forwarding mesh between two cooperative fields

A set of nodes, termed reference nodes (RNs) between the source and the sink (the source and the sink themselves are also RNs) are first selected, such that the distance between two adjacent RNs is sought to be an application-specific value (denoted by r). As depicted in Fig. 6.1a, s, a, b, c, d, t are upstream RNs. s is an upstream node with respect to a, and b is a downstream node of a.

As shown in Fig. 6.1b, for RN b, the area covered by the transmissions of its upstream RN a will be a disk centered at a with a radius of R, while the area covered by the transmissions of its downstream RN c will be a disk centered at c also with radius R. As r is set to be smaller than R, these two disks will overlap, and node b will be located within the overlapping area. This overlapping area is deemed the cooperative field of RN b (denoted by CFs). That is, the sensor nodes in CFs are the cooperative nodes (CNs) for RN b.

After the RNs and CNs are determined, each data packet will be forwarded toward the sink node by relay between groups of CNs (i.e., group-by-group, rather than hop-by-hop), as illustrated in Fig. 6.1c. The node a broadcasts and sends the data packet and all the nodes in the protocol field b then get the data packet forwarded by a. Later, a node in the protocol field of b is chosen randomly by the protocol to forward the data packet to the collaboration field c. Things repeat until the data packet finally reaches the goal node.

Figure 6.1d shows all the possible wireless links between two consecutive cooperative groups, while the quality of each of the links varies. Nodes which are not selected as RN or CN will enter the sleep mode to save energy.

This strategy provides an effective trade-off between traditional multi-path routing and single-path routing schemes. That is, it has the advantage of the error resilience of multi-path (or mesh) routing schemes, but without the associated overhead of sending multiple copies of the same packet.

The main differences between REER and traditional geographic routing protocols are the following:

  1. (1)

    REER is stateless and does not need to store any neighbor information.

  2. (2)

    In unreliable communication environments, traditional routing protocols may fail to deliver data in a timely fashion since link/node failures can be found only after trying multiple transmissions. In REER, each data packet is only broadcast once at each hop. If there is at least one of the CNs in a good status, the data packet is delivered successfully.

  3. (3)

    In REER, the number of CNs are adaptively selected before data delivery, such that the number is minimized while achieving the required reliability according to the link failure rate. Unselected nodes will enter sleep mode to save energy.

6.1.1.2 Reference Node Selection Strategy

  1. (1)

    Virtual coordinates

In the global coordinate system (0 is the origin) of Fig. 6.2, node h is an RN. Its position (\( x_{h}^{ 0} ,y_{h}^{ 0} \)) is piggybacked in the PROB message sent by h. Thus, a neighbor node i knows its position (\( x_{i}^{ 0} ,y_{i}^{ 0} \)), the position of its upstream RN h, and the sink’s location (\( x_{t}^{ 0} ,y_{t}^{ 0} \)).

Fig. 6.2
figure 2

Virtual coordinates

The virtual coordinates of a node (e.g., i in Fig. 6.2) are defined as the coordinates in the virtual two-dimensional coordinate system where the node’s upstream node (e.g., h in Fig. 6.2) is the origin, and the line between the upstream node (e.g., h in Fig. 6.2) and the sink forms the X-axis. In the example shown in Fig. 6.2, the virtual coordinates of i are denoted by (xi, yi), and can be calculated as follows:

$$ \begin{aligned} x_{i} & = hA + AC = hB \times \cos \left( \alpha \right) + \left( {BE + DE} \right) \times \sin \left( \alpha \right) \\ & = \left( {x_{i}^{0} - x_{h}^{0} } \right) \times \cos \left( \alpha \right) + \left( {y_{i}^{0} - y_{h}^{0} } \right) \times \sin \left( \alpha \right) \\ y_{i} & = DC = AB + DC - AB \\ & = BD \times \cos \left( \alpha \right) - HB \times \sin \left( \alpha \right) \\ & = \left( {y_{i}^{0} - y_{h}^{0} } \right) \times \cos \left( \alpha \right) - \left( {x_{i}^{0} - x_{h}^{0} } \right) \times \sin \left( \alpha \right) \\\upalpha & = { \arctan }\left( {\frac{{y_{t}^{0} - y_{h}^{0} }}{{x_{t}^{0} - x_{h}^{0} }}} \right) \\ \end{aligned} $$
  1. (2)

    RN-selection strategy

  1. (1)

    Illustration of RN-selection

Upon reception of a PROB message from h, node i will discard the packet under any of the following conditions:

  • the node has already received this packet.

  • xi > r.

  • ΔDi > TH.

Nodes within the shadow area (RN-selection-area) of Fig. 6.3 are deemed RN-Candidates (RNCs).

Fig. 6.3
figure 3

Illustration of RN-selection

  1. (2)

    RN-selection

If the packet is not discarded, i will start a backoff timer.

$$ t_{\text{rnc}} = \tau \times \Delta D + {\text{rand}}\left( {0,\mu } \right) $$

where τ is the time value of a fixed unit slot. \( {\text{rand}}\left( {0,\mu } \right) \) returns a random value uniformly distributed \( \left[ {0,\mu } \right) \), and μ is a small constant. In order to guarantee that the node closest to the strategic position has the highest possibility to be selected as the next RN, the timeout value for the backoff timer (trnc) is proportional to ΔD.

  1. (3)

    Reply and selection messages

Assuming that i has the smallest trnc value among all the RNCs and its backoff timer expires first, it will unicast a “reply” message (REP) to its upstream RN h.

When node h receives the REP, it broadcasts a “selection” message (SEL) with the identifier of node i (already piggybacked in the REP). To guarantee that only one RNC is selected as the downstream RN, node h only accepts the first REP while ignoring later ones.

If node i receives the SEL, it is selected as the downstream RN for h. When other RNCs receive the SEL or REP, they will cancel their backoff timers.

The detailed CN-Decision-Mechanism is shown in Fig. 6.4 flowchart.

Fig. 6.4
figure 4

The process of RN-selection

6.1.1.3 Cooperative Node Selection Strategy

PROBs are broadcast by the RNs along the path from the source to the sink, starting from the source node. Note that PROB is sent only during the cooperative field establishment phase and each RN will broadcast PROB only once.

Assume node i is one of such CNCs. As RN-selection proceeds toward the sink, i will receive more PROBs. When its CNDecisionTimer expires, i is expected to receive all the PROBs and performs a CN-decision procedure. In this procedure, i checks how many PROBs it has received. If the number of PROBs is three or more, node i becomes a CN. Then, it will figure out which RN it belongs to. The cases of three-PROBs and four-PROBs are shown as Fig. 6.5.

Fig. 6.5
figure 5

Three-PROBs (a) and four-PROBs (b) cases

In the example of Fig. 6.5a, CNC i is the closest to node b of all the RNs. It receives the first PROB from a and sets the idrn of the first RE (RE[1]:idrn) to a; then it receives the second PROB from b and sets RE[2]:idrn to b; lastly, it receives the third PROB from c and sets RE[3]:idrn to c. In this example, node i knows it is a CN since its EntryIdx is equal to 3, and selects the RN indicated in the second RE (i.e., node b) as its RN.

There also exist “four-PROB” cases in which a CN receives four-PROBs. Figure 6.5b shows such an example. In a four-PROB case, only nodes RE[2]:idrn and RE[3]:idrn are eligible as the RN for the CN. The CN makes the decision by comparing which one is closer as shown in Fig. 6.6 where MyDt denotes the distance from the current CN to the sink.

Fig. 6.6
figure 6

Flowchart of the CN-decision mechanism

There should be no five (or more)-PROB cases, which would mean that r is set to too small and inefficient a value.

The detailed CN-Decision-Mechanism is shown in the flowchart of Fig. 6.6.

Note that this section only considers the case of a single flow. If multiple flows coexist, REER creates an RN-table for each flow with a unique identifier (flow-id).

6.1.1.4 Data Dissemination in REER

When the RNs and CNs are determined, the data reports are forwarded through cooperation of the group of CNs at each hop.

Assume a node i receives a broadcast data packet. Let \( {\text{Seq}}_{\text{data}}^{i} \) be the largest sequence number of the data packets that node i has so far received. It first compares \( {\text{Seq}}_{\text{data}}^{i} \) with Data.SeqNum. If Data.SeqNum is not larger than \( {\text{Seq}}_{\text{data}}^{i} \) data, the data packet is either a stale one or broadcast by i’s downstream node. In this case, node i will drop the data.

All of the candidate nodes (including the RN and the CN) will set a timer and the node with the timer ending earliest will be selected as the node to forward the data. Two schemes are available to set the timer: the random-value-based scheme and the distance-based scheme.

  1. (1)

    Random-value-based

Node i will randomly choose a backoff time (tb), and set its backoff timer to tb to perform a two-phase contention procedure

$$ t_{\text{b}} = {\text{rand}}\left( {0,T_{{\text{max}}} } \right) $$

\( T_{ \hbox{max} } \) denotes the maximum backoff timer value. Assume Ncf denotes the number of CNs in the cooperative field. In order to be differentiated from other nodes in the same cooperative field, a length of time slot ΔT should be reserved for each node.

$$ T_{ \hbox{max} } = N_{\text{cf}} \times \Delta T $$

A large ΔT helps to reduce the possibility of simultaneous data broadcasting, while a small value of ΔT decreases the data latency.

When node i detects the forwarding of a packet, it also compares \( {\text{hc}}_{\text{s}}^{i} \) (i’s hop count to the source) with Data.hcs (the hop count of the received packet). If (\( {\text{hc}}_{\text{s}}^{i} \) = Data.hcs) and (\( {\text{Seq}}_{\text{data}}^{i} \) = Data:SeqNum), it deduces that the transmission is successful since an immediate downstream node broadcast the data packet. Otherwise, node i will rebroadcast the data packet when a retransmission timer (ReTx-Timer) expires, restarting the timer until the retry limit is reached.

  1. (2)

    Distance-based scheme

The candidate node selects the value of the timer based on distance, as shown in the formula below:

$$ T_{\text{timer}}^{i} = \frac{{D_{t}^{i} - D_{ \hbox{min} } }}{{D_{ \hbox{max} } - D_{ \hbox{min} } }} \cdot T_{ \hbox{max} } $$

Among nodes 1–4 in Fig. 6.7, node 2 is closest to the sink node and thus has the smallest timer setting and will be chosen to act as the node to forward the data packet.

Fig. 6.7
figure 7

Distance-based scheme selection

In the collaboration domain of the random-value-based scheme, all the candidate nodes share equal opportunity for data forwarding and thus the energy expenditure by the nodes is equal in such a domain. The distance-based scheme chooses the candidate node closest to the sink to forward the data and thus a fixed path takes shape, so the chosen node in this path will deplete energy first. As in the figure above, the next hop node of node 5 is always node 2. Thus, the distance-based scheme considers the node’s residual energy before making a choice.

The data packet transmission sequence chart is shown in Fig. 6.8.

Fig. 6.8
figure 8

Data packet transmission sequence chart

  1. (1)

    Firstly, the previous hop node broadcasts and sends the data packet and the candidate nodes will, after getting the packet, start a countdown timer.

  2. (2)

    When the countdown timers reach their end, the nodes coming available first will unicast a data broadcast node (DBN) message to its RN and the RN will, if it receives such message, broadcast and reply with a choose data broadcast (CDB) message.

Tips::

If the first available node is a RN, it will send a CDB message directly.

  1. (3)

    Nodes failing to be selected will cancel the countdown timer and the selected ones will broadcast and send the data packet.

  2. (4)

    The follow-up nodes receive the broadcast data packet and restart the data flow. The initial sending node will cancel its sending countdown timer if it receives such a packet.

  3. (5)

    Finally, the sink node will, after receiving the broadcast data packet, send a broadcast packet saying that the sink has received the data. The other nodes will then cancel the countdown timers 2 and 7 in the figure.

6.1.2 Implementation of REER Codes

The REER protocol is realized based on the basic model introduced in Chap. 3. The main simulation process is described below. For more detail, please check the codes attached at the end of this chapter.

6.1.2.1 Header File

Add the interruption code program into wsn_intrpt_code.h as follows: #define SRC_SEND_PROB_INTRPT_CODE                1101      /*Self-break of sending in the status SrcInit*/ #define REF_TIMER_EXPIRED_INTRPT_CODE       1102      /*REP count-down breaks*/ #define COOP_TIMER_EXPIRED_INTRPT_CODE    1103      /*setting of CNs breaks */ #define SEND_DBN_INTRPT_CODE           1104                      /*DBN count-down breaks*/ #define ERASE_NODE_ANIM_INTRPT_CODE         1105      /*CNs updating icons break*/ #define RE_TRANS_DATA_INTRPT_CODE               1106      /*re-transmission of DATA packet breaks*/ #define RE_TRANS_PROB_INTRPT_CODE               1107      /*re-transmission of PROB packet breaks*/ #define GOOD_TO_FAIL_INTRPT_CODE                  1108      /*node forbidden breaks*/ #define FAIL_TO_GOOD_INTRPT_CODE                  1109      /*node available breaks*/

6.1.2.2 Node Attributes

Add two attributes to the node in the node model as shown in Fig. 6.9. These two attributes are used for the animation to update the node icons.

Fig. 6.9
figure 9

Attributes newly added to the node

NodeFailureFlag is forbidden when it is 1 and available for use when it is 0.

NodeFlag is a normal node, RN or collaboration node when it is 0, 1, or 2, respectively. When the data transmission starts, the normal nodes fall asleep to save energy.

6.1.2.3 Packet Structure

Packets required to be added for the purpose of realizing the REER protocol include PROB, REP, SEL, DBN, CDB, SINK_RECEIVED_DATA, and CANCEL_RETRANS. Of these, PROB, REP, and SEL are used to determine RNs and CNs; DBN, CDB, and SINK_RECEIVED_DATA are used when forwarding data; and CANCEL_RETRANS is used to prevent retransmission of the PROB and DATA packets.

  1. (1)

    PROB packet

The PROB packet structure is shown in Fig. 6.10 and the field statements are as follows:

Fig. 6.10
figure 10

PROB packet structure

  1. (1)

    Source and Sink represent the source node and the goal node.

  2. (2)

    SeqNum is the sequence number of the PROB packet.

  3. (3)

    NextHop and PreviousHop represent the next hop and the previous hop, respectively. When a node is about to send a data packet, it sets NextHop to be the number of the target goal node and sets the current node as PreviousHop.

  4. (4)

    RN_X and RN_Y represent the node X- and Y-coordinates, respectively.

  5. (5)

    HopCount represents the hop count from the current RN to the source node.

All the nodes which have received the PROB packet start a countdown timer and the node with its countdown timer ending first will send the REP packet first.

The sink node broadcasts a PROB packet after getting the REP packet and the other nodes will, after getting the packet broadcast by the sink node, cancel the REP packet timer.

  1. (2)

    REP packet

The REP packet has only two fields: PreviousHop and NextHop. The node whose countdown timer finishes will write its node number in PreviousHop and unicast to the previous node.

  1. (3)

    SEL packet

Both the SEL and CDB packets have two fields: Winner and NextHop. The RN sends the Winner field the ID of the node which will send the REP packet and later broadcasts. Nodes receiving this broadcast will cancel their countdown timer. The node corresponding to Winner finally receives the packet and becomes a RN to send the PROB packet further.

  1. (4)

    DBN packet

The DBN packet has four fields: PreviousHop, NextHop, SeqNum, and HopCount; the CN whose countdown timer finishes sends the DBN packet to the RN.

The RN receives only DBN packets sent by nodes in its collaboration domain and judges by comparing whether its HopCount and the D_HopCount have matching fields.

The RN only receives the first DBN packet.

  1. (5)

    CDB packet

The CDB packet structure is shown in Fig. 6.11.

Fig. 6.11
figure 11

CDB packet structure

The CDB and DBN packets have the same fields. The CDB packet will be sent under the following two conditions.

  1. (1)

    The RN will, after receiving the DBB packet sent by the CN (assumed to be i), cancel its own countdown timer and input the value of i into the Winner field of the CDB packet for broadcasting. Other CNs will cancel the countdown timer after receiving the CDB packet. However, if it is i that received the CDB packet, it will broadcast and send the saved data packet.

  2. (2)

    If the RN fails to receive the DBN packet before the end of its countdown timer, it broadcasts and sends the CDB packet directly and later broadcasts and sends the data packet.

  1. (6)

    SINK_DATA packet

The sink node will, after receiving the SINK_DATA packet, broadcast and send the packet. The packet contains three fields: PreviousHop, NextHop, and SeqNum. The node receiving such a packet will cancel its DBN countdown counter and retransmit a countdown counter.

  1. (7)

    CANCEL_RETRANS packet

The CANCEL_RETRANS packet contains four fields: PreviousHop, NextHop, SeqNum, and HopCount. The node receiving such a packet will cancel and retransmit the countdown timer.

6.1.2.4 Network Layer Process Model

  1. (1)

    Process model picture and explanations

The REER codes are all realized in the network layer model. The network layer process is as shown in Fig. 6.12. There is no screenshot of the initialization in the figure. The process model described in Chap. 3 can be used as a reference.

Fig. 6.12
figure 12

Illustration of the process model

As the modifications are made to the basic model described in Chap. 3, here we will introduce only the changes, including:

  1. (1)

    SrcSendPROB, used to send PROB packet

  2. (2)

    Various packet-handling modules, such as Handle_PROB, Handle_REP

  3. (3)

    Due processing module for timers

  4. (4)

    Processing module to switch the node status between failure and success.

See Table 6.1 for process statements (statements made in the flow sequence).

Table 6.1 Process states
Tips::

When running the model, two parameters, MaxTxRange and r_value, can get their values assigned directly. However, the setting of these two parameters is different due to different node density in different scenarios. In this model, it is recommended that the minimum settings of MaxTxRange and r_value shall be (70, 40).

  1. (2)

    Process attributes

Add the following attributes to the process (as shown in Fig. 6.13). These attributes shall be set before running. The r_value is the distance of each hop; max_TG the maximum countdown time of packet DBN when sending the data packet; LinkFailureRatio is the link failure ratio and NodeFailureRatio is the node failure ratio.

Fig. 6.13
figure 13

Newly added process attributes

Define the corresponding status variables; add and read such attributes in the SimParameters status. The codes for reading these node attributes are shown below:

/* read the node failure ratio */ if (op_ima_sim_attr_exists(''Campus Network.*.network.LinkFailureRatio'')) {     op_ima_sim_attr_get_dbl(''Campus Network.*.network.LinkFailureRatio'',                                                   &LinkFailureRatio);     XAxis = (double)LinkFailureRatio; }else {     LinkFailureRatio = LINK_FAILURE_RATIO; }

  1. (3)

    Header module of the process model

Click the icon in the toolbar of the process and add the following codes into the header module:

  1. (1)

    Add and save the PROB packet structure

typedef  struct   {   int              PkHopCountToSrc;  /*hop count to the source*/   int                 PkSenderID;        /*send the number of the RNs*/   double       sender_x;               /*send X-coordinate of the node*/   double       sender_y;              /*send Y-coordinate of the node*/  }BroadcastPkInfoEntry;

  1. (2)

    Define the constants required by REER

#define MAX_BPIE_NUM 8             /*array element count of BroadcastPkInfoEntry*/ #define QDL 50                                      /*default transmission radius*/ #define TH  40                                        /*threshold for the selection of RN*/ #define TAU  0.0025                              /*Backoff time unit for the selection of RN,  τ  in formula (4)*/ #define MU  0.005                                 /*selection of the RN,  μ  in formula (4)*/ #define MAX_TG_CNS 0.05            /*maximum backoff time for countdown of DBN packet, T max  in formula (5)*/ #define COOP_TIMER  5                    /*determination time of CN*/ #define RE_TRANS_PROB_TIMER 0.3       /*retransmission time of PROB*/ #define RE_TRANS_DATA_TIMER 0.1       /*retransmission time of data packet */ #define RE_TRANS_TIMES  5                      /*numbers of transmission*/ #define NODE_FAILURE_RATIO 0              /*default node failure ratio*/ #define LINK_FAILURE_RATIO 0               /*default link failure ratio*/ #define GOOD_STATUS_TIME 30               /*maximum time duration (s) available to be used by the node */ #define NODE_FAILURE_ANIM 0              /*node animation update flag*/ #define SRC_SEND_DATA_NODE_ANIM_REFRESH 1 /*flag to update node animation when data sending by the source*/

  1. (3)

    Determination of the retransmission time

Assume the three continuous RNs to be A, B, and C. After A broadcasts the PROB message, B is determined to be the next RN, and B rebroadcasts the PROB message to C; A confirms the successful transmission after getting the PROB message broadcast by B.

The time interval from the sending of PROB by A to the sending of PROB by B consists of the following parts:

  1. The PROB broadcast by node A is received by node B.

  2. Countdown of the REP packet of B starts, based on the formula below:

    $$ t_{\text{rnc}} = \tau \times \Delta D + {\text{rand}}\left( {0,\mu } \right) $$

    \( \Delta D \) in the formula is defined as TH at the maximum. The following result can be obtained according to the settings: trnc < TAU × TH + MU = 50 × 0.0025 + 0.005 s = 0.13 s.

  3. Node B sends the REP packet to node A.

  4. Node A broadcasts the SEL packet to node B.

  5. Node B broadcasts PROB.

In this process, the REP packet countdown time of node B accounts for a lot, while the others account for minor (no greater than 0.001 s/step) time periods and can thus be ignored. Therefore, it is reasonable to determine the total interval time to be 0.13 s.

Similarly, it also requires 0.13 s from node B to node C to confirm successful transmission. That is, in 0.26 s from A broadcasting PROB message, the broadcast packet of node B shall be received if everything is OK and thus successful transmission can be confirmed.

Therefore, if node B broadcasts PROB packet but node A fails to receive the same due to link failure; if node A fails to receive the PROB broadcast packet of node B after waiting for 0.26 s, a PROB message can be retransmitted to node B. B receives the packet and finds the transmission is successful, otherwise a message will be transmitted to node A to cancel retransmission.

In the definition above, we set the time constant (RE_TRANS_PROB_TIMER) for PROB retransmission to be 0.3 s.

Similarly, the data packet retransmission consists mainly of the DBN countdown and the retransmission countdown formula is:

$$ t_{\text{b}} = {\text{rand}}\left( {0,T_{ \hbox{max} } } \right) $$

\( T_{ \hbox{max} } \) is defined as MAX_TG_CNS in the above paragraph and it is 0.05 s; therefore, we assume the countdown time for data packet retransmission is twice that of \( T_{ \hbox{max} } \), namely, 0.1 s.

  1. (4)

    Interruption of macro-processing code

The codes to convert the interruption code to corresponding state-machine-processed events are shown below:

#define SRC_SEND_PROB (op_intrpt_type()==OPC_INTRPT_SELF                                               &&op_intrpt_code()==SRC_SEND_PROB_INTRPT_CODE)

If SRC_SEND_PROB_INTRPT_CODE is the transmitted interruption code and the state is self-interruption, the corresponding state-machine-processed event SRC_SEND_PROB enters the SrcSendPROB state. Other interruption codes have similar processing.

  1. (4)

    Process status variable

Click the icon on the process toolbar and add the process status variables as follows:

  1. (1)

    Packet pointer

Add four packet pointers: DATA and PROB packet pointers. The two pointers need caching on the intermediate node.

Packet*   \data_pkptr;     Packet*   \PROB_pkptr; Packet*   \cached_data_pkptr; Packet*   \cached_prob_pkptr;

  1. (2)

    Correlation variables of arrays saving PROB packet

BroadcastPkInfoEntry*\BPIE;         /*array pointer*/ int               \BPIE_index;                 /*array count*/ int               \receive_Prob_num;      /*count of PROB packets received*/ int               \my_RefNodeIndex;     /*array index of the main RN of the CN*/ double        \D_rn_x;                        /*send X-coordinate of the RN of PROB packet*/ double        \D_rn_y;                        /*send Y-coordinate of the RN of PROB packet*/ double        \x_vcr;                           /*virtual X-coordinate of relative RN*/ double        \y_vcr;                           /*virtual X-coordinate of relative RN*/ int               \D_Winner;                   /*number of the node selected to transmit DATA or PROB packet*/

  1. (3)

    Flags to receive packet, used for packet shunting in idle state Boolean

\dataflag;                  /* DATA packet */ Boolean       \probflag;                  /* PROB packet */ Boolean       \repflag;                    /* REP packet */ Boolean       \cdbflag;                    /* CDB packet */ Boolean       \dbnflag;                   /* DBN packet */ Boolean       \selflag;                     /* SEL packet */ Boolean       \sinkdataflag;            /* SINK_DATA packet */ Boolean       \cancelretransflag;    /* CANCEL_RETRANS packet */

  1. (4)

    Receiving flags used for determination of the RN. When a new sequence number is received at ChkSeq, these flags are reset as 0. The codes are as follows:

Boolean      \received_REP_flag;   /*ever received REP packet or not? 1 if received, or otherwise */ Boolean      \received_DBN_flag;   /* ever received DBN packet */ Boolean      \received_Seq_flag;   /* ever received such sequence number packet/

  1. (5)

    Countdown event handlers; keeping such event handlers cancels the time. The codes are as follows:

Evhandle   \ref_timer_evhandle;             /*REF countdown event handler*/ Evhandle   \send_DBN_evhandle;          /*DBN countdown event handler*/ Evhandle   \re_TRANS_Data_Handle;   /*Retransmit DATA packet event handler*/ Evhandle   \re_TRANS_Prob_Handle;   /*Retransmit PROB packet event handler*/  Evhandle   \node_fail_evhandle;             /*node failure event handler*/

  1. (6)

    Retransmission; the codes are as follows:

int            \re_Trans_Data_Num;       /*retransmit DATA packet count*/ int            \re_Trans_Prob_Num;       /*retransmit PROB packet count */ Boolean     \bSendSucceed;               /*Set this flag after canceling transmission*/

  1. (7)

    Variables corresponding to the node and process attributes (omitted).

6.1.2.5 Key Codes

  1. (1)

    Processing and shunting of node to different packets

  1. (1)

    Exit code read packet of the idle state and set corresponding packet flags. Codes are as follows.

/*set a flag at each kind of packet*/ dataflag = 0;   probflag = 0; repflag = 0;  …            /*omit other packet flags; reference can be taken from the model code*/ if (op_intrpt_type()==OPC_INTRPT_STRM)   {      /*read packet format*/      pkptr = op_pk_get(op_intrpt_strm());      op_pk_format(pkptr,pk_format);

     if (strcmp(pk_format,''SENSED_DATA'')!=0){  /*non-statistical information of the application layer*/           if (strcmp(pk_format,''DATA'')==0){  /*data packet*/                dataflag = 1;  /*set data packet flag*/                /*read the field*/                op_pk_nfd_access(pkptr, ''PreviousHop'', &D_PreviousHop);                op_pk_nfd_access(pkptr, ''NextHop'', &D_NextHop);                …                /*read the packet size for statistics*/                data_packet_size_received = op_pk_total_size_get(pkptr);           }else if(strcmp(pk_format,''PROB'')==0){  /*PROB packet */                PROBflag = 1;                …                msg_packet_size_received = op_pk_total_size_get(pkptr);           }           else if(strcmp(pk_format,''REP'')==0){   /*REP packet */                repflag = 1;                …                              /*field code omission of the read packet*/                msg_packet_size_received = op_pk_total_size_get(pkptr);           }else if(…){                   /*other packet omission*/                …   else{                                 /*illegal packet, to be destroyed*                op_pk_destroy(pkptr);           }           /*nodes available for use; make statistics on network layer message if RN or CN*/           if ((NodeFailureFlag !=1)&&(nodeflag!=COMMON_NODE)) {           op_intrpt_schedule_remote(op_sim_time(), m_ALL_DATA_RCVD_INTRPT_CODE,init_pro_id);           } }

  1. (2)

    Set conditions for packet processing

Set new packet processing status after ChkSeq status. For example, PROB has the Handle_PROB processing status and the entry condition of PROBflag ==1, as shown in the entry condition of the Handle-PROB status, Fig. 6.14.

Fig. 6.14
figure 14

Entry condition of the Handle-PROB status

  1. (2)

    Node processing after receiving PROB packet

The processes are shown below:

  1. (1)

    Receive PROB packet and assign memory to arrays

receive_Prob_num++; if(receive_Prob_num == 1){ /*receive PROB packet for the first time*/         /*request to store the PROB array storage space*/         BPIE = (BroadcastPkInfoEntry*)op_prg_mem_alloc(      MAX_BPIE_NUM*sizeof(BroadcastPkInfoEntry));          for (i=0; i< MAX_BPIE_NUM; i++){  /*initialization*/             BPIE[i].PkHopCountToSrc = MAX_VALUE;             BPIE[i].sender_x = MAX_VALUE;             BPIE[i].sender_y = MAX_VALUE;             BPIE[i].PkSenderID  = MAX_VALUE;         }         BPIE_index = 0; /*set initial array index*/         /*send self interruption and starts countdown; COOP_TIMER means after the count-down timer becoming due*/         op_intrpt_schedule_self(op_sim_time()+COOP_TIMER, COOP_TIMER_EXPIRED_INTRPT_CODE); }

  1. (2)

    Insert the new PROB into the array, with the following codes:

bNotInProbList = 0; for(i=0;i<BPIE_index;i++) {  /*check whether ever received PROB*/ if (BPIE[BPIE_index].PkSenderID == D_PreviousHop) bNotInProbList = 1; } if(bNotInProbList == 0){  /*if no, add in the array the RN sending this PROB packet*/      BPIE[BPIE_index].PkHopCountToSrc = D_HopCount; /*hop count from source to RN*/      BPIE[BPIE_index].PkSenderID  = D_PreviousHop;  /*number of the RN*/      BPIE[BPIE_index].sender_x = D_rn_x;              /*X-coordinate of the RN*/      BPIE[BPIE_index].sender_y = D_rn_y;              /*Y-coordinate of the RN*/      BPIE_index++; }

  1. (3)

    If the node satisfies the RN screening condition, it starts the countdown with the following codes:

if(D_PreviousHop!=GlobalSinkID){ /*not transmitted by Sink*/   /*calculate virtual coordinates; convert the coordinates of the node to reference-node-based virtual coordinates (x_vcr, y_vcr)*/ VCR(D_rn_x,D_rn_y);           /*receive PROB message for the first time and other conditions are satisfied; start the screening program of RN*/    if(((receive_Prob_num==1) ||(bSendSucceed==OPC_FALSE))            &&(x_vcr<r_value)            &&(((x_vcr-r_value)*(x_vcr-r_value)+y_vcr*y_vcr)<TH*TH)){       /*calculate count-down t_rnc and set self interruption*/       cached_prob_pkptr = op_pk_copy(pkptr); /*Duplicate PROB packet and continue transmission in the next time*/       t_rnc = sqrt((x_vcr-r_value)*(x_vcr-r_value)+ y_vcr*y_vcr)*TAU + op_dist_uniform(MU);       ref_timer_evhandle = op_intrpt_schedule_self(op_sim_time()+t_rnc, REF_TIMER_EXPIRED_INTRPT_CODE); } }else{  /*if transmitted by Sink*/       if (op_ev_valid(ref_timer_evhandle)){            op_ev_cancel(ref_timer_evhandle);       } }

  1. (4)

    Get PROB packet broadcast by future nodes; cancel the retransmission events after receiving such a packet; the codes are as follows:

/*PROB transmitted by future nodes, cancel retransmission*/ if(op_ev_valid(re_TRANS_Prob_Handle)&&                  (BPIE[my_RefNodeIndex].PkHopCountToSrc < D_HopCount)){               op_ev_cancel(re_TRANS_Prob_Handle);               bSendSucceed=OPC_TRUE; }

  1. (5)

    If the PROB broadcast packet is retransmitted by previous node, the codes are as follows:

/*retransmitted data packet; shall be canceled upon prompt*/ if(bSendSucceed==OPC_TRUE)  /*transmission succeeded*/                       &&(BPIE[my_RefNodeIndex].PkHopCountToSrc == D_HopCount)){        packet_pkptr = op_pk_create_fmt(''CANCEL_RETRANS'');       op_pk_nfd_set(packet_pkptr, ''PreviousHop'', MyID);       …                   /*leave out setting of other field codes*/       op_pk_send(packet_pkptr,NETWORK_TO_MAC_STRM);       …                   /*leave out codes sending statistical break messages*/ }

  1. (3)

    The codes for the sink node to process the PROB packet

if(PROBflag==1){           /*if PROB message*/          cached_PROB_pkptr= op_pk_copy(pkptr);          Send_PROB();     /Sink transmits PROB packet here now is to enable the previous node to cancel retransmission*/ }

  1. (4)

    The processing code after the RN receives the REP packet

if(received_REP_flag==0){               /*Change the flag to be 1 after receiving, so that only the first REP packet can be received*/             received_REP_flag=1;             /*received REP packet and the broadcast and transmit SEL packet*/             packet_pkptr = op_pk_create_fmt(''SEL'');             op_pk_nfd_set(packet_pkptr, ''Winner'', D_PreviousHop);             /*set the broadcast address*/             op_pk_nfd_set(packet_pkptr, ''NextHop'', MAC_BROADCAST_ADDR);             /*transmit packet*/             op_pk_send(packet_pkptr,NETWORK_TO_MAC_STRM);             /*determine the size of packet and transmit message interruption to the result-gathering process.*/             msg_packet_size_transmitted = op_pk_total_size_get(packet_pkptr);             op_intrpt_schedule_remote(op_sim_time(),                                 m_ALL_DATA_TRANS_INTRPT_CODE,init_pro_id);

Tips::

We have introduced the result statistic model in Chap. 3 but only for data packets without control packets. In the REER protocol, apart from DATA packet, the other packets such as PROB, SEL, DBN, and CDB are all control message packets. If you want to carry out statistics on the network layer control messages, you can assign values to msg_packet_size_transmitted and msg_packet_size_received with the size of packets sent and received, and later send the statistic message break to the result statistic process.

  1. (5)

    The SEL packet processing codes received by the node

/*D_Winner is contents of fields corresponding to SEL packet read in the Idle  status*/ if(D_Winner == MyID){      /*if the current node is the node sending the REP packet */                 /*set the node as a RN*/                 nodeflag = REF_NODE;                 BPIE[0].PkHopCountToSrc= D_HopCount+1;                 BPIE[0].PkSenderID = MyID;                 /*initialize the times of sending and send the PROB packet*/                 re_Trans_Prob_Num = 0;                 Send_PROB(); }else{ /*if not, cancel the timer*/                 if (op_ev_valid(ref_timer_evhandle)){ op_ev_cancel(ref_timer_evhandle);                 } }

  1. (6)

    Send_PROB function

The function Send_PROB will be called when future RNs (other than the source node) send the PROB packet. The function codes are as follows:

void Send_PROB() {        FIN(Send_PROB());        /* cached_PROB_pkptr is the caching packet for which you can take reference from codes in passage (3) of the earlier section 2) */        PROB_pkptr =op_pk_copy(cached_PROB_pkptr);        /* set the packet field*/        op_pk_nfd_set(PROB_pkptr, ''PreviousHop'', MyID);        op_pk_nfd_set(PROB_pkptr, ''HopCount'', D_HopCount+1);        op_pk_nfd_set(PROB_pkptr, ''RN_X'', my_x_pos);        op_pk_nfd_set(PROB_pkptr, ''RN_Y'', my_y_pos);        /*set as broadcast */        op_pk_nfd_set(PROB_pkptr, ''NextHop'', MAC_BROADCAST_ADDR);        /*send the packet*/        op_pk_send(PROB_pkptr, NETWORK_TO_MAC_STRM);               …        /*set no retransmission flag to the sink node*/        if(MyID!=GlobalSinkID){               /*accumulation of the times of sending*/               re_Trans_Prob_Num++;               if(re_Trans_Prob_Num< RE_TRANS_TIMES){  /*smaller than the maximum times of retransmission*/                        /*set self break for timing*/ re_TRANS_Prob_Handle = op_intrpt_schedule_self(op_sim_time() + RE_TRANS_PROB_TIMER,RE_TRANS_PROB_INTRPT_CODE);               }else  /*reach the maximum times of sending, simulation ends*/                        op_sim_end(''\r\n Send PROB times to max,fail! \n'','''','''','''');               } } }

  1. (7)

    The codes for the completed countdown of node DBN in the status Send_DBN

if(nodeflag == COOP_NODE){ /*CN*/         packet_pkptr = op_pk_create_fmt(''DBN'');         op_pk_nfd_set(packet_pkptr, ''PreviousHop'', MyID);         op_pk_nfd_set(packet_pkptr, ''NextHop'',                                          BPIE[my_RefNodeIndex].PkSenderID);         …         op_pk_send(packet_pkptr,NETWORK_TO_MAC_STRM); }else if(nodeflag == REF_NODE){ /*RN*/         received_DBN_flag = 1;   /*set the receiving flag and no more receiving of DBN packet */         Send_CDB(MyID);    /*send CDB packet*/         Send_Data();           /*send data packet*/ }

  1. (8)

    The codes for the RN to receive the DBN packet in the status Handle_DBN

/if no receiving and hop counts satisfy*/ if((received_DBN_flag==0)       &&(D_HopCount=BPIE[my_RefNodeIndex].PkHopCountToSrc)){       received_DBN_flag = 1;  /*set receiving flags*/       if (op_ev_valid(send_DBN_evhandle)){ /*cancel the DBN countdown of itself*/            op_ev_cancel(send_DBN_evhandle);       }       /*send CDB packet*/       Send_CDB(D_PreviousHop); }

  1. (9)

    Setting of nodes and link status

The strength of REER lies in its high reliability in an unreliable environment. Thus, failures resulting from an unreliable environment, when simulating such environments, are divided into two categories: node failure and link failure.

Let’s simulate the node status with the Gilbert-Elliot model using two statuses: on and off. “On” represents a normal node working condition, while “off” indicates failure. Letting f represent the node failure ratio, the “off” status duration can be expressed as: Toff = Ton × f/(1 – f).

If the “on” status duration lasts for 30 s and f = 0.2, then Toff = 30 × 0.2/(1 − 0.2) = 7.5 s.

  1. (1)

    As for Implementation of the node failure ratio, the steps are as follows:

Define the good status duration to last for 30 s in the header file.

#define GOOD_STATUS_TIME 30

Calculate the failure time based on GOOD_STATUS_TIME and NodeFailureRatio with the failure time calculation codes in the NodeInit status. NodeFailureRatio is a simulation parameter which can be set at the time of simulation.

/*calculate the time of node failure*/ FailStatusTime = (NodeFailureRatio*GOOD_STATUS_TIME)/(1-NodeFailureRatio); /*set self break and node fails*/ node_fail_evhandle = op_intrpt_schedule_self(           op_sim_time()+op_dist_exponential(10), GOOD_TO_FAIL_INTRPT_CODE); /*node failure flags*/ NodeFailureFlag = 0;

Then, add two statuses: Fail and Good. Set the GOOD_TO_FAIL_INTRPT_CODE as node self-break in “Fail” with the following codes:

/*set node failure*/ NodeFailureFlag = OPC_TRUE; /*set node attributes*/ op_ima_obj_attr_set(node_objid,''NodeFailureFlag'',NodeFailureFlag); if (NODE_FAILURE_ANIM == 1) {  /*directly update node icons*/       op_anim_ime_nobj_update (vid, OPC_ANIM_OBJTYPE_NODE,                 node_name, OPC_ANIM_OBJ_ATTR_ICON,''obj_diff_remove'', OPC_EOL); } /*Set FAIL_TO_GOOD_INTRPT_CODE self break*/ op_intrpt_schedule_self(op_sim_time()                + op_dist_exponential(FailStatusTime), FAIL_TO_GOOD_INTRPT_CODE);

The codes in the “Good” status are similar but have opposite functions. With these codes, we can effect node switching between available and unavailable statuses under designated failure ratios.

  1. (2)

    The implementation of the link failure ratio is easy. Create a random number up to 100 when the node receives the data packet. If the number selected is smaller than LinkFailureRatio×100, abandon the data packet. Here, LinkFailureRatio is a simulation parameter and can be set by the simulation. Abandon the packet if the link failure ratio set is 0.1 and the random number generated up to 100 is less than 10. The codes are as follows:

if ( ((op_dist_uniform(100) < LinkFailureRatio*100)      ||(NodeFailureFlag == OPC_TRUE))&&(sink_flag!=1)){           if (NODE_FAILURE_ANIM){                  op_anim_ime_nobj_update (vid, OPC_ANIM_OBJTYPE_NODE,                                   node_name, OPC_ANIM_OBJ_ATTR_ICON,                                  ''Connector:Bridge.s'', OPC_EOL);           } }

6.1.3 Performance Analysis and Experiment

6.1.3.1 Performance Analysis

  1. (1)

    Transmission success rate

The number of cooperative fields between the source and sink is equal to H − 1. Let f be the failure probability of each link/node. Let p denote the successful delivery probability of the data packet at each hop. Then,

$$ P = p^{H} = \left( {1 - f^{{N_{\text{cf}} }} } \right)^{H} $$
  1. (2)

    Energy expenditure

Let etx and erx be the energy consumption of transmitting and receiving a data packet, respectively. Then, the cumulative energy consumption E involved in successfully forwarding a data packet to the sink is:

$$ E = e_{\text{tx}} \cdot H + e_{\text{rx}} \cdot \left[ {3\left( {H - 2} \right) \cdot N_{\text{cf}} \cdot \left( {1 - f} \right) + 2N_{\text{cf}} \cdot \left( {1 - f} \right) + 1} \right] $$

Note that H − 2 numbers of CFs will listen to the broadcast data three times and only the last CF listens to the data two times.

  1. (3)

    Delay

Let tdata be the time to transmit a data packet; Let \( \overline{{t_{\text{b}} }} \) be the average backoff time before data forwarding. Then, the end-to-end (ETE) latency for a data packet is equal to:

$$ T_{\text{ete}} = t_{\text{data}} \cdot H + \bar{t}_{\text{b}} \cdot \left( {H - 1} \right) $$

Assuming all other parameters are fixed, P, E, and Tete are decreasing functions of r. The smaller r is, the larger will be N and H, and a higher reliability p is achieved. However, for small r values, more energy E is consumed for each data packet, and Tete also becomes larger. Thus, r provides a control knob to balance robustness and energy efficiency (and latency). r should be adaptively selected to achieve the required reliability while meeting the application-specific QoS requirements (e.g., reliability and ETE latency limit).

  1. (4)

    Control overhead

Let ns be the number of sensor nodes in the network. Let ectrl be the energy consumption of transmitting a control message. Let Og be the control overhead for setting up the neighbor information table in GPSR. Let Or be the control overhead for establishing RNs and CNs in REER.

$$ \begin{aligned} O_{g} & = n_{\text{s}} \times e_{\text{ctrl}} \\ O_{r} & = H \times 3 \times e_{\text{ctrl}} \\ \end{aligned} $$

Then, a node’s number of neighbors k is equal to:

$$ k =\uppi \times R \times \rho $$

In GPSR, each node beacons a hello message to set up or update the neighbor information table; In REER, three messages (i.e., PROB, REP, and SEL) per hop are needed to construct the RN and CNs. In general, ns is much larger than 3H. In GPSR, each node needs to store k number of neighbor entries in its local memory, while in REER, the nodes do not require neighbor information except for the RN identifier. Once cooperative fields are established, the RN/CN do not need to store any routing-relevant information, while other nodes can enter sleep mode to save energy. Thus, REER scales well in dense sensor networks, where the sensors have low storage capacity.

6.1.3.2 Simulation Model

The simulation parameters are as shown in Table 6.2.

Table 6.2 Simulation parameters

The simulation animation is shown in Fig. 6.15. This is the screenshot at the end of the first data transmission. It can be seen that the first hop of the source node is the broadcast transmission. The gray nodes in the figure are the normal nodes falling asleep to save energy and the pink nodes are the CNs. The square nodes on the path are RNs. When it comes to the second transmission, the node will not necessarily transmit through the same RNs.

Fig. 6.15
figure 15

Simulation animation screenshot

6.1.3.3 Experimental Design

  1. (1)

    Effect of Normalized Node Density on the REER performance in Unreliable Environments

For a successful packet transmission ratio, examining the per packet energy expenditure and average delay under different node densities proves that the higher the node density is, the higher the successful packet transmission ratio will be. The best node density to get the minimum per packet energy expenditure can be identified for any link failure ratio.

  1. (2)

    Comparison of REER and GPSR with variable link failure rates

In comparisons of successful packet transmission ratio, per packet energy expenditure, and average delay of two routing protocols under different link failure ratios (0–0.9), REER exhibits more consistent and relatively higher reliability, and lower energy consumption than GPSR in unreliable environments. Extensive simulations show that reliability is achieved by sacrificing energy-efficiency and delay performance. Thus, the careful selection of the pertinent parameters is required to achieve reliability with energy efficiency while minimizing delay.

Tips::

REER is already published. One can download the English version from the internet via the link address: http://www.ece.ubc.ca/~minchen/doc/Chen_IJSNET_REER.pdf.

6.2 KCN Routing Protocol

In this section, we propose KCN routing using a novel relaying candidate selection scheme (KCN-selection) at each hop based on geographic information, with the value of k initially determined based on on-demand ETE reliability in the presence of unreliable communication links. Compared to the selection of potential forwarders (PFs) in REER, KCN-selection has the following advantages:

  • The KCN time slots are allocated by RN in a centralized fashion before data dissemination, which is similar to the TDMA approach. In practice, the value of each time slot should be as small as possible, yet long enough that a PF can hear the data packet from another PF with higher priority before its timer expires. In other words, each time slot should be long enough to accommodate the hop delay, the elapsed time from the instant when a sensor node sends a data packet to its farthest neighbor node to that when the neighbor node receives it. By comparison, REER needs three hand-shaking mechanisms to avoid collision. Thus, KCN-delivery exhibits lower delays while guaranteeing the same packet delivery ratio.

  • Since it dynamically schedules CNs’ duty cycles, KCN-delivery can achieve energy efficiency while guaranteeing on-demand ETE reliability. By comparison, REER cannot guarantee energy efficiency since all of the PFs should be awake to be selected.

6.2.1 KCN Protocol

6.2.1.1 Selection of Cooperative Nodes

Given a node m in the CNs search region, let eres be the quantized-energy-level, and let d be the distance from u to the strategic location. Its eligibility (or priority) as the CN for the next hop, denoted by Qu, is defined as:

$$ Q\left( m \right) = \sqrt {\left( {1 - \frac{d}{R}} \right)^{2} + \left( {\frac{{e_{\text{res}} }}{{e_{\text{init}} }}} \right)^{2} } $$

The shorter the distance to fm, the larger Qi becomes. The nodes with the first k largest Qi will be selected as KCN under this criterion.

Among the KCN, the CN with the least distance to the strategic location will be selected as the RN for next hop.

Selection of CNs as shown in Fig. 6.16.

Fig. 6.16
figure 16

Selection of cooperative nodes

Time is divided into epochs, and each epoch is T. In each epoch, the source node will initiate KCN-selection by transmitting a probe message. Then, KCN will be updated at each hop depending on the residual energy and the neighborhood node locations.

6.2.1.2 Data Packet Forwarding

  1. (1)

    Determination of the CN time slot

Assume there are k(pcs) CNs and for each hop the CN requires k(pcs) time slots. Since the Q value of the CN is entered into the array from large to small, the first node Q value in the array is the biggest, with a waiting time of \( \tau \times 1 \), and the minimum waiting time of the Q value of the kth node is \( k \times \tau \).

The first node has the largest Q value and thus is the first to be able to forward the data packet. At the end of forwarding, its energy drops and the Q value of such node shall be recalculated and the CN array shall be reordered.

  1. (2)

    Forward the data packet

The node with the time slot coming due first will forward the data packet and notify other nodes of the current hop to cancel the data packet.

6.2.2 KCN Code Implementation

6.2.2.1 Header File

Add the following codes in wsn_global.h. In the following, the structure CNEntry is used to save the CN.

typedef  struct   {          int               ID;                  /*node number*/        double            x;             /*X-coordinate*/        double            y;             /*Y-coordinate*/        double            energy;    /*residual energy*/ }CNEntry; /*the following global variable is used to save the temporary exchange area of the CN information.*/ CNEntry* GlobalCNListTmp;     /*array pointer of this group of CNs*/ int GlobalCNHopCountTmp;      /*hop count of the CN*/

Add break codes as follows in wsn_intrpt_code.h.

#define SRC_SEND_PROB_INTRPT_CODE              1201       /*the source code sends  PROB self break*/ #define COOP_TIMER_EXPIRED_INTRPT_CODE    1202       /*CN countdown comes due*/ #define CN_CANCEL_TIMER_INTRPT_CODE          1203       /*cancel count-down of other CNs*/

Add the packet transmission interval constant in wsn_constant.h. The codes are as follows:

#define T_DATA   0.5          /*KCN application layer packet interval*/

6.2.2.2 Node Attributes

Add two attributes to the node in the node model. See Fig. 6.17 for details.

Fig. 6.17
figure 17

Add node attributes

CooperativeNodeFlag is a normal node if the attribute is 0, or a CN if the attribute is 1. It is used to update the node icons. Normal nodes other than CNs will go to sleep and will wake up at regular intervals to join in the CN selection. DataCountPerPROB is the parameter for the number of DATA packets transmitted between PROB packets.

6.2.2.3 Packet Format

In the KCN protocol, you only need to add a PROB package. The packet structure is shown in Fig. 6.18. The specific package field description refers to the REER protocol section.

Fig. 6.18
figure 18

PROB packet format

6.2.2.4 Network Layer Process Model

  1. (1)

    Figures and explanations of process model

The network layer process model is as shown in Fig. 6.19. Here, only statuses different from the base model are marked. See Table 6.3 for more details about the status.

Fig. 6.19
figure 19

Network layer process model

Table 6.3 Process states
  1. (2)

    Process attributes

Add following attributes to the process as shown in Fig. 6.20.

Fig. 6.20
figure 20

Process attributes

CN_Num: count of CNs per hop.

HopDistanceFactor: Range: 0–1; distance factor used as a condition when choosing the CN. It requires that the virtual coordinate x_i of the CN shall be greater than MaxTxRange×HopDistanceFactor to guarantee that CNs of the same hop can be distributed within not so big a range.

LinkFailureRatio: Link failure ratio.

  1. (3)

    Header module

Add the following codes into the header module.

#define TAU                               0.02     /*time slot of the cooperative  node*/ #define INFORM_CN_INTRPT                 3055    /*notify the next hop CN*/ #define INFORM_CN_NEXHHOP_INTRPT        3056    /*notify this hop CN*/ #define INFORM_CN_CANCEL_TIMER_INTRPT    3057    /*notify the CN to cancel count-down*/

  1. (4)

    Process status variables

  1. (1)

    Save the status variables of the CN message. The codes are as follows:

CNEntry*    \MyCNList;             /*save the structure array pointer of all  the CNs of this hop*/ CNEntry*    \NextHopCNList;    /*save the structure array pointer of all the CNs of the next hop*/ int                 \CNHopCount;       /*hop count where the CN is located*/

  1. (2)

    Corresponding simulation attribute variables. The codes are as follows:

int             \CN_Num;                 /*count of CNs, obtained  through simulation attributes*/ double      \HopDistanceFactor;    /*distance factor*/ double      \LinkFailureRatio;     /*link failure ratio*/ int             \DataCountPerPROB;      /*count of DATA packet between PROB packets*/

  1. (3)

    Other variable codes are as follows:

int               \D_ProbSeqNum;      /*PROB packet sequence number*/  Boolean      \MyNextHopIsSink;    /*whether one-hop nodes near to Sink*/  Boolean      \CooperativeNodeFlag;  /*whether this node flagged as a CN*/ /*whether new data packet? If do, starts link failure judging*/ Boolean      \bNewDataPacketFlag;   int             \dataFlag;            /*DATA packet flag*/ int             \probFlag;            /*PROB packet flag*/ Evhandle    \COOP_TIMER_evHandle;  /*start self break handler of CN count-down*/ double        \myEnergy;          /*residual energy of node*/ 

6.2.2.5 Key Codes

  1. (1)

    Determination of PROB transmission period

  1. (1)

    Transmission period analysis

Assuming that the generation cycle between two PROB messages is T_PROB, the application layer data packet is transmitted at regular intervals and the transmission interval is T_DATA, the relationship between the two is as shown in Fig. 6.21. Take T_DATA cycle as a basic cycle and insert 1 Idle before and after PROB, respectively to identify DATA and PROB packets.

Fig. 6.21
figure 21

Send PROB periodically

Firstly, let’s determine a parameter, that is, how many DATA packets shall be sent every time a PROB packet is sent, and express this parameter as x. Then we obtain the formula:

$$ {\text{T}}\_{\text{PROB}} = {\text{T}}\_{\text{DATA}} \times \left( {x + 3} \right) $$

In the formula, make T_DATA = 0.5 s and define x as a node attribute. If x = 17, then T_PROB=10 s.

Assigning numbers to PROB and DATA jointly and assuming the sequence number of PROB is S, then S + x + 1 is the sequence number of the next PROB packet.

The CN saves the sequence number of the PROB packet it has received and the sequence number (assumed to be “D”) of the DATA packet it receives every time. D – S ≤ x means forwarding of data packet can be continued; while D – S > x indicates the CN is not functional as such and has become a normal node.

  1. (2)

    Code modification of the application layer process model

The application layer process model mainly determines the DATA packet transmission. It can be seen from the analysis above that 3 waiting cycles are required every time x(pcs) packets are transmitted. Code modification of the application layer is shown below:

  1. Add two integral status variables: DataCountPerPROB and pk_num.

  2. Add the following codes in the status “Init”.

/*read simulation attribute*/ if (op_ima_sim_attr_exists(''Campus Network.*.DataCountPerPROB'')) {      op_ima_sim_attr_get_int32(''Campus Network.*.DataCountPerPROB'',                                                           &DataCountPerPROB); }else {      DataCountPerPROB = 18; } pk_num = 0; /*Initialization of packet sequence number*/

  1. Start packet transmission schedule in the status “Generate.”

m_generate_packet ();/*generate packet and transmit''/ pk_num++;  /send packet counts*/ if(pk_num == DataCountPerPROB){   /*if DataCountPerPROB(pcs) of data packet have been sent sufficiently*/        pk_num=0;                  /*start calculation again from ''0''*/        pkt_gen_event = op_intrpt_schedule_self (op_sim_time()+4*pkt_interval,                                                                      PKT_GEN_CODE); }else        pkt_gen_event = op_intrpt_schedule_self (op_sim_time()+pkt_interval,                                                               PKT_GEN_CODE);

  1. (3)

    Code modification of the network layer

  1. The codes of the break setting for the next PROB in the SrcSendPROB status after sending the PROB packet are as follows:

op_intrpt_schedule_self(op_sim_time()+T_DATA*(DataCountPerPROB+3),                                                 SRC_SEND_PROB_INTRPT_CODE);

  1. Extract the packet sequence number in the idle status involving the DATA packet and PROB packet. The codes are as follows:

if (strcmp(pk_format,''DATA'')==0)    {      … op_pk_nfd_access(pkptr, ''SeqNum'', &D_SeqNum);      … }else if (strcmp(pk_format,''PROB'')==0)    {      … op_pk_nfd_access(pkptr, ''SeqNum'', &D_ProbSeqNum);      … }

  1. Determination of invalid packet in the ChkSeq status.

/*if the difference between the DATA packet number and the PROB packet number is greater than DataCountPerPROB, reset the previously selected cooperative node*/ if(D_SeqNum-D_ProbSeqNum>DataCountPerPROB){        CooperativeNodeFlag = OPC_FALSE;       op_ima_obj_attr_set(node_objid,''CooperativeNodeFlag'', CooperativeNodeFlag); }

  1. (2)

    Determination of CNs

The determination of the CN is the most important part of the KCN routing scheme. The function determining the CN is as follows:

/*Entry parameters: Sink coordinates, count of CN; the entry is the next hop which returns the number of the first CN*/ int CooperativeNodeSelection(double destination_x,                                                  double destination_y, int cn_num) {      double y_t_o,x_t_o;     /*coordinates of the sink node*/      double y_h_o,x_h_o;   /*coordinates of this node*/      double y_i_o,x_i_o;     /*coordinates of the neighbor node*/      double y_i,x_i,theta;    /*virtual coordinates*/      double dDistance,dEnergy,dMetric;     /*distance, energy, and the comprehensive weight of distance and energy*/      double MaxDMetric,MaxEnergy;        /*the maximum comprehensive weight and energy*/      int        bInSearchField;                        /*is the node reachable to all the CNs*/      FIN (int CooperativeNodeSelection(double destination_x,                                                                double destination_y, int cn_num));      /*initialized CN array*/      for(i=0;i< cn_num;i++){           NextHopCNList[i].ID=-1;           NextHopCNList[i].x=-1;           NextHopCNList[i].y=-1;           NextHopCNList[i].energy= -1;      }      /*reset the cooperative flag of all the neighbor nodes*/      for (k = 0;k< MAX_NEIGHBOR_NUMBER; k++){            NeighborAsCooperativeNodeFlag[k] = OPC_FALSE;      }

     /*begin to get cn_num pieces of CNs*/      for (i = 0; i < cn_num; i++)      {            MaxDMetric = 0; NextHopIdx=-1;  /*initialized comprehensive weight and neighbor table index and subscript*/            for (k = 0;k < NeighborNumber; k++){ /*cycle to all the neighbor nodes*/                  /*energy of the source node (number 2) is greater than that of normal nodes; excluded from selection */                  if (NeighborList[k]==2) continue;

                 /*determine whether the neighbor node is reachable to all the CNs*/                  bInSearchField = 1;                  if(source_flag == 0) { /*the source node has no MyCNList; do not determine*/                        for(m=0;m<cn_num;m++){                              if(MyID!=MyCNList[m].ID){  /*this node don’t determine*/                              dDistance = sqrt(pow(MyCNList[m].x- NeighborListX[k],2)                                                     +pow(MyCNList[m].y- NeighborListY[k],2));                                     if (dDistance > MaxTxRange){ /*unreachable, reset the flag*/                                             bInSearchField = 0;                                            break;                                     }                              }                        }                  }                  if ((bInSearchField==1)  /*node is reachable and not selected to act the CN*/                        &&(NeighborAsCooperativeNodeFlag[k]== OPC_FALSE))                  {                        /*virtual coordinates calculation*/                        y_t_o = destination_y;           x_t_o = destination_x;                         y_h_o = my_y_pos;               x_h_o = my_x_pos;                        y_i_o = NeighborListY[k];    x_i_o = NeighborListX[k];                        theta = atan((y_t_o - y_h_o)/(x_t_o - x_h_o));                        x_i = cos(theta)*(x_i_o - x_h_o) + sin(theta)*(y_i_o - y_h_o);                        y_i = cos(theta)*(y_i_o - y_h_o) - sin(theta)*(x_i_o - x_h_o);                        if(x_i<0) continue; /*filter neighbor nodes in reverse direction with Sink*/                        /*distance from the ideal node*/                        dDistance = sqrt((MaxTxRange - x_i)*(MaxTxRange - x_i)                                                     + y_i*y_i);                        /*the function GetNodeEnergy returns node energy*/                        dEnergy=GetNodeEnergy(NeighborList[k]);                        /*comprehensive weight of distance and energy*/                        dMetric = sqrt( pow(1-dDistance/MaxTxRange,2)                                               + pow(dEnergy/NODE_INIT_ENERGY,2) );                        /*size of x_i is constrained in conditions below, which guarantees the CN be at a range*/                        if((x_i>MaxTxRange*HopDistanceFactor)                               &&(dMetric > MaxDMetric)){                             MaxDMetric = dMetric;                             NextHopIdx = k;                             MaxEnergy = dEnergy;                        }                  }         }         if(NextHopIdx!=-1){ /*if a neighbor node is found, save such neighbor node*/               NextHopCNList[i].ID = NeighborList[NextHopIdx];               NextHopCNList[i].x = NeighborListX[NextHopIdx];               NextHopCNList[i].y = NeighborListY[NextHopIdx];               NextHopCNList[i].energy = MaxEnergy;               op_anim_ime_nobj_update (vid, OPC_ANIM_OBJTYPE_NODE,                                      other_node_name, OPC_ANIM_OBJ_ATTR_ICON,                                          ''tree_node_expand_windows'', OPC_EOL);         Else{ /*do not cycle as below if not found*/               break;         }      }      FRET(NextHopCNList[0].ID); }

Reminder::

The CN at the front of the array has greater weight and is thus selected first for data forwarding.

  1. (3)

    CN message transmission

When the hth hop CN determines k(pcs) CNs at the (h + 1)th hop, it is necessary to notify the message of this kth CN to the k(pcs) CNs at the (h + 1)th hop and other CNs at the hth hop.

In the process of program implementation, these k CNs in the model are saved in a temporary global array, and later a break is sent to the notification node. The notification node will, after getting the break, read the message of these k CNs.

  1. (1)

    In the Handle_PROB status, the codes notifying CNs of this hop and the next hop are as follows:

GlobalCNHopCountTmp = D_HopCount+1; for (i = 0; i < CN_Num; i++){  /*copy the information into the global variables*/      GlobalCNListTmp[i] = NextHopCNList[i]; } for (i = 0; i < CN_Num; i++){  /*notify all the next hop CNs*/      if(NextHopCNList[i].ID==-1) continue;  /*invalid node if -1*/      sprintf(other_node_name,''%d'',NextHopCNList[i].ID);      /*to get the network layer process ID of the node*/      network_pro_id = op_id_from_name(                                            op_id_from_name(op_topo_parent(node_objid),                                                              OPC_OBJTYPE_NODE_MOB,other_node_name),                                            OPC_OBJTYPE_QUEUE,''network'');      /*send message to the network layer process of the CN*/      op_intrpt_schedule_remote(op_sim_time(), INFORM_CN_INTRPT,                                                       network_pro_id); } for (i = 0; i < CN_Num; i++){ /*notify other CN of this hop*/      if(MyCNList [i].ID==-1) continue;      sprintf(other_node_name,''%d'', MyCNList [i].ID);      network_pro_id = op_id_from_name(                                            op_id_from_name(op_topo_parent(node_objid),                                                              OPC_OBJTYPE_NODE_MOB,other_node_name),                                            OPC_OBJTYPE_QUEUE,''network'');      op_intrpt_schedule_remote(op_sim_time(), INFORM_CN_NEXHHOP_INTRPT ,                                                       network_pro_id); }

  1. (2)

    Handle INFORM_CN_INTRPT interruption in the status Inform_MyCN. The codes are as follows:

CooperativeNodeFlag = OPC_TRUE;  /*set this node as a CN*/ /*update node attributes; used to display animation*/ op_ima_obj_attr_set(node_objid,''CooperativeNodeFlag'',                                    CooperativeNodeFlag); /*read hop count*/ CNHopCount = GlobalCNHopCountTmp; /*the (h+1)th hop CN receives the message of saving this array as this hop cooperative table*/ for (i = 0; i < CN_Num; i++){       MyCNList[i] = GlobalCNListTmp[i]; }

  1. (3)

    Handle INFORM_CN_NEXHHOP_INTRPT interruption at status Inform_NextHOP_CN codes are as follows:

/ *other CNs of the hth hop receives the message of saving the array as the next hop CN*/ for (i = 0; i < CN_Num; i++){        NextHopCNList[i]= GlobalCNListTmp[i]; }

  1. (4)

    Determination of the CN to send the data packet

The next step after determination of the CN is to send the data packet. After broadcasting and sending the packet data, each CN determines its countdown time according to the array location.

  1. (1)

    In GPSR status, KCN handling starts when scheme_idx is 4. The codes are as follows:

/*is CN with consistent hop count */ if((CooperativeNodeFlag == OPC_TRUE)&&(D_HopCount==CNHopCount)){       for(i=0;i<CN_Num;i++){  /*firstly find its location in the array*/             if(MyID==MyCNList[i].ID){                    break;             }       }       /*calculate the count-down time according to location in the data; the bold part represents the count-down time*/       COOP_TIMER_evHandle = op_intrpt_schedule_self(op_sim_time()+ (i+1)*TAU ,                                                                       COOP_TIMER_EXPIRED_INTRPT_CODE);       /*icon changes after message broadcasting, recover the original icon*/        op_anim_ime_nobj_update (vid, OPC_ANIM_OBJTYPE_NODE, node_name,                                                          OPC_ANIM_OBJ_ATTR_ICON,                                                          ''tree_node_expand_windows'', OPC_EOL);       }       packet_pkptr=op_pk_copy(pkptr); /*save the packet, send when the count time comes due*/       op_pk_destroy(pkptr);

  1. (2)

    Codes when the count time of the CN comes due:

/*set the packed fields, broadcast and send data packet*/ op_pk_nfd_set(packet_pkptr, ''PreviousHop'', MyID); op_pk_nfd_set(packet_pkptr, ''NextHop'', MAC_BROADCAST_ADDR); op_pk_nfd_set(packet_pkptr, ''HopCount'', D_HopCount+1); op_pk_send(packet_pkptr, NETWORK_TO_MAC_STRM); /*notify the result-gathering process, collect and send packet data*/ data_packet_size_transmitted = op_pk_total_size_get(packet_pkptr); msg_packet_size_transmitted = 0; op_intrpt_schedule_remote(op_sim_time(),                                           m_ALL_DATA_TRANS_INTRPT_CODE,init_pro_id); /*update and send node icon*/ op_anim_ime_nobj_update (vid, OPC_ANIM_OBJTYPE_NODE, node_name, OPC_ANIM_OBJ_ATTR_ICON, ''adw_error'', OPC_EOL); /*notify other nodes to cancel countdown*/ InformCooperativeNodeCancelTimer(); /*reorder the array subject to residual energy*/ UpdateMyList();

  1. (3)

    Reorder the array subject to energy. Put the CN with the greatest residual energy in the front of the array as such nodes have the smallest countdown time. When the next data packet comes, this node will be selected as the forwarding node. The codes of the function UpdateMyList() for reordering the CNs are as follows:

void UpdateMyList() {        double dMax;        CNEntry CNEntryTmp;        FIN(void UpdateMyList())        for(i=0;i<CN_Num;i++){ /*update residual energy of the CN*/             if(MyCNList[i].ID !=-1)                   MyCNList[i].energy=GetNodeEnergy(MyCNList[i].ID);        }        /*selection sort*/        for(i=0;i<CN_Num-1;i++){             dMax=MyCNList[i].energy;  k=i; /*initial setting*/             for(j=i+1;j<CN_Num;j++){                   if(MyCNList[j].energy>dMax){                          dMax=MyCNList[j].energy;  /*remember the greatest energy*/                          k=j;                                         /*remember the array subscript of the greatest energy*/                   }             }             /*exchange location of the subscript of the greatest energy and the i th  element*/             CNEntryTmp=MyCNList[i];             MyCNList[i]=MyCNList[k];             MyCNList[k]=CNEntryTmp;        }        FOUT; }

6.2.2.6 Simulation Animation

Run the simulation and set 4 CNs. See the screenshot of CN animation as shown in Fig. 6.22.

Fig. 6.22
figure 22

Screenshot of cooperative node animation in KCN protocol