star-mesh LoRa network

Dependencies:   sx12xx_hal

start-mesh

radio chip selection

Radio chip driver is not included, because options are available.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

In this network, devices repeat messages to/from devices out of range of central gateway device. Appropriate for use when slightly larger batteries cost less than extra LoRaWAN gateways. This network uses LoRa transceiver directly and is not LoRaWAN. This network is appropriate for use where extra latency added from store-and-forward is of minimal consequence.

network implementation

Network achieves low-power operation by device waking up at regular intervals to check if LoRa preamble exists. If so, packet is received, otherwise devices sleeps. In this type of operation, trade-off is made between transmitter sending long preamble, and receiver waking up to receive this preamble along with associate message at the end of preamble. This long preamble is only used for request packets: the reply packet will have normal 8-symbol preamble length. This is known as asynchronous low-power operation, permitting an arbitrary number of devices to operate.

Devices start operation on the network by sending a discovery request to any devices that can hear it. Any devices which hears this discovery request will then send a discovery reply at randomized time offset relative to the request. After a pre-established time limit, the discovering device will decide which device to attach to depending on signal quality and how many hops away from the central gateway the device resides.

After device has attached to network, downlinks and uplinks can be sent to/from device. To facilitate downlinks, the devices closer to central gateway will be sent a new-device-notification to inform all devices between the central gateway and the newly attached device, which devices the new device can be reached via.

All devices have two logical interfaces to the network: An upstream interface, and a downstream interface. However, the central gateway device only has a downstream interface, because the "upstream" is only a UART interface to the user handling the user payloads on central gateway.

All devices on network are programmed with same firmware, except for gateway. In main.h #define GATEWAY is commented-out for devices on network, or is defined for central gateway device. Only one central gateway must exist on this network. The unique identifying address of device is derived from CPU unique ID registers, of which 4 byte ID number is used on this network. Using this CPU serial number permits the same binary file to be programmed into any number of devices.

network configuration

Network is configured in main.h

define in main.h
spreading factorSPREADING_FACTOR
bandwidthBW_KHZ
operating radio frequencyCF_MHZ
gateway or deviceGATEWAY
transmit powerTX_DBM

MAC layer timing scales according to LoRa symbol period. When spreading factor and/or bandwidth is changed, all network timing is scaled accordingly by MAC layer.
The transceivers used with the project operate at one datarate. This datarate is fixed, and must be defined at compile time for all devices and gateway.

low power operation

This MAC layer uses mbed eventqueue for scheduling. To enable low power operation, events.use-lowpower-timer-ticker is defined in mbed_app.json. This requires bare-metal operation to have eventqueue use low power timer, permitting deep sleep. LoRa applications such as this do not require RTOS: bare-metal mode is preferred for typical LoRa use.

application layer

User payloads are handled in app_endDevice.cpp. Uplinks are send from application layer by calling uplink(uint8_t *buffer_ptr, uint8_t length) Downlinks are handled in callback function app_downlink()

For gateway, app_gateway.cpp handles user payloads. For downlinks, an example is provided in cmd_downlink() where destination and payload is entered on serial port. All uplinks are handled in callback function gateway_uplink().

Header file app.h contains definitions common to application layer on both network central control and end device.

Note

This page describes how to use the network, for more detailed description of implementation, see details page.

serial terminal user interface

The STDIO UART is used to send and receive user-payload on the gateway, but is also available on end-devices. This serial port is configured at 115200 : 8,N,1.

commandargumentsdescription
?list commands
dldestID byte0 byte1 etcsend downlink to device (from gateway)
lslist downstream devices attached
opdBmmanually change transmit power

For the list of downstream devices, on start each row is printed directly attached device. If devices are attached further downstream, they will be subsequently printed on the same row.

testing / evaluation

Use 3 devices for testing: one gateway and two devices.
Three devices required for checking message repeating (relaying) function. The gateway device must be installed at some distance to prevent both devices from connecting directly to gateway.
Gateway needs to be located far enough away, so signal strength preference overrides hop count from gateway.

Committer:
Wayne Roberts
Date:
Tue Dec 03 09:48:53 2019 -0800
Revision:
0:6015834e4279
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:6015834e4279 1 /* upstream: interface towards gateway 36m cyan */
Wayne Roberts 0:6015834e4279 2 #include "main.h"
Wayne Roberts 0:6015834e4279 3
Wayne Roberts 0:6015834e4279 4 #ifndef GATEWAY
Wayne Roberts 0:6015834e4279 5 struct {
Wayne Roberts 0:6015834e4279 6 int preference;
Wayne Roberts 0:6015834e4279 7 uint32_t id;
Wayne Roberts 0:6015834e4279 8 uint8_t hfg;
Wayne Roberts 0:6015834e4279 9 } best_upstream;
Wayne Roberts 0:6015834e4279 10
Wayne Roberts 0:6015834e4279 11 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 12
Wayne Roberts 0:6015834e4279 13
Wayne Roberts 0:6015834e4279 14 /* packets received from upstream */
Wayne Roberts 0:6015834e4279 15 void upstream_req_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd)
Wayne Roberts 0:6015834e4279 16 {
Wayne Roberts 0:6015834e4279 17 if (cmd == CMD_REMOVE_DEVICE_REQ) {
Wayne Roberts 0:6015834e4279 18 uint32_t remove_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
Wayne Roberts 0:6015834e4279 19 *Idx += 4;
Wayne Roberts 0:6015834e4279 20 if (!remove_directlyAttached_device(remove_id)) {
Wayne Roberts 0:6015834e4279 21 /* wasnt found locally, check child devices */
Wayne Roberts 0:6015834e4279 22 uint32_t removedFrom;
Wayne Roberts 0:6015834e4279 23 remove_childDevice(remove_id, &removedFrom);
Wayne Roberts 0:6015834e4279 24 if (removedFrom != ID_NONE) {
Wayne Roberts 0:6015834e4279 25 /* forward this remove down */
Wayne Roberts 0:6015834e4279 26 downRemove.destID = removedFrom;
Wayne Roberts 0:6015834e4279 27 downRemove.removeID = remove_id;
Wayne Roberts 0:6015834e4279 28 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 29 } else
Wayne Roberts 0:6015834e4279 30 reqFlags.bits.txAns = ANSWER_BUSY;
Wayne Roberts 0:6015834e4279 31 } else
Wayne Roberts 0:6015834e4279 32 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 33
Wayne Roberts 0:6015834e4279 34 } else if (cmd == CMD_DISCOVERY_ANS) {
Wayne Roberts 0:6015834e4279 35 #ifdef GATEWAY
Wayne Roberts 0:6015834e4279 36 *Idx += 6;
Wayne Roberts 0:6015834e4279 37 #else
Wayne Roberts 0:6015834e4279 38 int my_sq, peer_sq;
Wayne Roberts 0:6015834e4279 39 uint8_t idxCpy = *Idx;
Wayne Roberts 0:6015834e4279 40 uint8_t hfg;
Wayne Roberts 0:6015834e4279 41 float signal_preference;
Wayne Roberts 0:6015834e4279 42 int hops_preference, preference;
Wayne Roberts 0:6015834e4279 43 /* everything is upstream when we arent associated on network */
Wayne Roberts 0:6015834e4279 44
Wayne Roberts 0:6015834e4279 45 // signal quality is negative: rss + snr
Wayne Roberts 0:6015834e4279 46 peer_sq = Radio::radio.rx_buf[idxCpy++] - 0x100;
Wayne Roberts 0:6015834e4279 47 my_sq = rssi + snr;
Wayne Roberts 0:6015834e4279 48 signal_preference = (peer_sq + my_sq) / 2; // round-trip signal quality
Wayne Roberts 0:6015834e4279 49 hfg = Radio::radio.rx_buf[idxCpy++];
Wayne Roberts 0:6015834e4279 50 if (hfg != HFG_UNATTACHED) {
Wayne Roberts 0:6015834e4279 51 hops_preference = 1 - hfg; // lower number preferable
Wayne Roberts 0:6015834e4279 52 preference = signal_preference + (hops_preference * 10);
Wayne Roberts 0:6015834e4279 53 if (preference > best_upstream.preference) {
Wayne Roberts 0:6015834e4279 54 best_upstream.preference = preference;
Wayne Roberts 0:6015834e4279 55 best_upstream.id = sendingID;
Wayne Roberts 0:6015834e4279 56 best_upstream.hfg = hfg;
Wayne Roberts 0:6015834e4279 57 }
Wayne Roberts 0:6015834e4279 58 }
Wayne Roberts 0:6015834e4279 59
Wayne Roberts 0:6015834e4279 60 *Idx += 2;
Wayne Roberts 0:6015834e4279 61 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 62 } else if (cmd == CMD_USER_PAYLOAD_DN_REQ) { // rxDone callback, pkt from upstream
Wayne Roberts 0:6015834e4279 63 uint8_t len;
Wayne Roberts 0:6015834e4279 64 #ifndef GATEWAY
Wayne Roberts 0:6015834e4279 65 uint32_t final_dest_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
Wayne Roberts 0:6015834e4279 66 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 67 *Idx += 4;
Wayne Roberts 0:6015834e4279 68 len = Radio::radio.rx_buf[*Idx];
Wayne Roberts 0:6015834e4279 69 (*Idx)++;
Wayne Roberts 0:6015834e4279 70 #ifdef GATEWAY
Wayne Roberts 0:6015834e4279 71 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 72 #else
Wayne Roberts 0:6015834e4279 73 if (final_dest_id == my_id) {
Wayne Roberts 0:6015834e4279 74 app_downlink(len, &Radio::radio.rx_buf[*Idx]);
Wayne Roberts 0:6015834e4279 75 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 76 } else {
Wayne Roberts 0:6015834e4279 77 if (attUp.id == ID_NONE) {
Wayne Roberts 0:6015834e4279 78 reqFlags.bits.txAns = ANSWER_UNATTACHED;
Wayne Roberts 0:6015834e4279 79 } else {
Wayne Roberts 0:6015834e4279 80 if (fwd.len == -1) {
Wayne Roberts 0:6015834e4279 81 fwd.len = len;
Wayne Roberts 0:6015834e4279 82 fwd.A_id = final_dest_id;
Wayne Roberts 0:6015834e4279 83 fwd.tx_dest_id = find_dest_id(final_dest_id);
Wayne Roberts 0:6015834e4279 84 memcpy(fwd.buf, &Radio::radio.rx_buf[*Idx], len);
Wayne Roberts 0:6015834e4279 85 reqFlags.bits.currentOp = CMD_USER_PAYLOAD_DN_REQ; // this is downlink
Wayne Roberts 0:6015834e4279 86 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 87 } else
Wayne Roberts 0:6015834e4279 88 reqFlags.bits.txAns = ANSWER_BUSY;
Wayne Roberts 0:6015834e4279 89 }
Wayne Roberts 0:6015834e4279 90 }
Wayne Roberts 0:6015834e4279 91 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 92 (*Idx) += len;
Wayne Roberts 0:6015834e4279 93 }
Wayne Roberts 0:6015834e4279 94
Wayne Roberts 0:6015834e4279 95 } // ..upstream_req_rxDoneCB()
Wayne Roberts 0:6015834e4279 96
Wayne Roberts 0:6015834e4279 97 #ifndef GATEWAY
Wayne Roberts 0:6015834e4279 98
Wayne Roberts 0:6015834e4279 99 upstream_t attUp;
Wayne Roberts 0:6015834e4279 100 upstream_t prospect;
Wayne Roberts 0:6015834e4279 101 uint32_t id_newDeviceNotification;
Wayne Roberts 0:6015834e4279 102
Wayne Roberts 0:6015834e4279 103 void upstream_ans_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd)
Wayne Roberts 0:6015834e4279 104 {
Wayne Roberts 0:6015834e4279 105 if (reqFlags.bits.currentOp == CMD_ATTACH_REQ) {
Wayne Roberts 0:6015834e4279 106 if (sendingID == best_upstream.id) {
Wayne Roberts 0:6015834e4279 107 attUp.id = best_upstream.id;
Wayne Roberts 0:6015834e4279 108 attUp.preference = best_upstream.preference;
Wayne Roberts 0:6015834e4279 109 attUp.hfg = best_upstream.hfg;
Wayne Roberts 0:6015834e4279 110 hops_from_gateway = best_upstream.hfg + 1;
Wayne Roberts 0:6015834e4279 111 prospect.id = ID_NONE;
Wayne Roberts 0:6015834e4279 112 }
Wayne Roberts 0:6015834e4279 113
Wayne Roberts 0:6015834e4279 114 reqFlags.bits.currentOp = CMD_UNUSED;
Wayne Roberts 0:6015834e4279 115 } else if (reqFlags.bits.currentOp == CMD_USER_PAYLOAD_UP_REQ) {
Wayne Roberts 0:6015834e4279 116 app_uplink_complete();
Wayne Roberts 0:6015834e4279 117 reqFlags.bits.currentOp = CMD_UNUSED;
Wayne Roberts 0:6015834e4279 118 } else if (reqFlags.bits.currentOp == CMD_NEW_DEVICE_ATTACHED_REQ) {
Wayne Roberts 0:6015834e4279 119 id_newDeviceNotification = ID_NONE;
Wayne Roberts 0:6015834e4279 120 reqFlags.bits.currentOp = CMD_UNUSED;
Wayne Roberts 0:6015834e4279 121 }
Wayne Roberts 0:6015834e4279 122
Wayne Roberts 0:6015834e4279 123 } // ..upstream_ans_rxDoneCB()
Wayne Roberts 0:6015834e4279 124
Wayne Roberts 0:6015834e4279 125 void upstream_print_status()
Wayne Roberts 0:6015834e4279 126 {
Wayne Roberts 0:6015834e4279 127 pc.printf("attUp.id:%lx ", attUp.id);
Wayne Roberts 0:6015834e4279 128 if (hops_from_gateway == HFG_UNATTACHED) {
Wayne Roberts 0:6015834e4279 129 pc.printf("best_upstream %lx, %d hfg:%u\r\n", best_upstream.id, best_upstream.preference, best_upstream.hfg);
Wayne Roberts 0:6015834e4279 130 }
Wayne Roberts 0:6015834e4279 131 }
Wayne Roberts 0:6015834e4279 132
Wayne Roberts 0:6015834e4279 133 void upstream_new_device_notify() /* called from txDone */
Wayne Roberts 0:6015834e4279 134 {
Wayne Roberts 0:6015834e4279 135 txBuf[txBuf_idx++] = CMD_NEW_DEVICE_ATTACHED_REQ;
Wayne Roberts 0:6015834e4279 136 putu32ToBuf(&txBuf[txBuf_idx], id_newDeviceNotification);
Wayne Roberts 0:6015834e4279 137 txBuf_idx += 4;
Wayne Roberts 0:6015834e4279 138 tx_dest_id = attUp.id;
Wayne Roberts 0:6015834e4279 139 queue.call_in(500, txBuf_send, true);
Wayne Roberts 0:6015834e4279 140 reqFlags.bits.currentOp = CMD_NEW_DEVICE_ATTACHED_REQ;
Wayne Roberts 0:6015834e4279 141 //mdbg_printf("newDeviceNotify_tx ");
Wayne Roberts 0:6015834e4279 142 }
Wayne Roberts 0:6015834e4279 143
Wayne Roberts 0:6015834e4279 144 void discovery_rx_end()
Wayne Roberts 0:6015834e4279 145 {
Wayne Roberts 0:6015834e4279 146 Radio::Sleep();
Wayne Roberts 0:6015834e4279 147 //mdbg_printf("discoveryAnsRxEnd ");
Wayne Roberts 0:6015834e4279 148
Wayne Roberts 0:6015834e4279 149 if (best_upstream.preference == INT_MIN) {
Wayne Roberts 0:6015834e4279 150 /* nothing received, try discoverying again */
Wayne Roberts 0:6015834e4279 151 queue.call_in(1000, txBuf_send, true);
Wayne Roberts 0:6015834e4279 152 pc.printf("discoveredNothing\r\n");
Wayne Roberts 0:6015834e4279 153 } else {
Wayne Roberts 0:6015834e4279 154 /* best gateway heard, attach to it */
Wayne Roberts 0:6015834e4279 155 txBuf_idx = 0; // squash discovery request, no longer needed
Wayne Roberts 0:6015834e4279 156 txBuf[txBuf_idx++] = CMD_ATTACH_REQ;
Wayne Roberts 0:6015834e4279 157 tx_dest_id = best_upstream.id;
Wayne Roberts 0:6015834e4279 158 queue.call_in(500, txBuf_send, true);
Wayne Roberts 0:6015834e4279 159 pc.printf("attach-to-%lx\r\n", best_upstream.id);
Wayne Roberts 0:6015834e4279 160 reqFlags.bits.currentOp = CMD_ATTACH_REQ;
Wayne Roberts 0:6015834e4279 161 }
Wayne Roberts 0:6015834e4279 162 } // ..discovery_rx_end()
Wayne Roberts 0:6015834e4279 163
Wayne Roberts 0:6015834e4279 164 void upstream_init()
Wayne Roberts 0:6015834e4279 165 {
Wayne Roberts 0:6015834e4279 166 pc.printf("txDiscoverReq:%u ", txBuf_idx);
Wayne Roberts 0:6015834e4279 167 txBuf[txBuf_idx++] = CMD_DISCOVERY_REQ;
Wayne Roberts 0:6015834e4279 168 tx_dest_id = ANY_ID;
Wayne Roberts 0:6015834e4279 169 txBuf_send(true);
Wayne Roberts 0:6015834e4279 170
Wayne Roberts 0:6015834e4279 171 best_upstream.preference = INT_MIN;
Wayne Roberts 0:6015834e4279 172 init_attached_upstream();
Wayne Roberts 0:6015834e4279 173 hops_from_gateway = HFG_UNATTACHED;
Wayne Roberts 0:6015834e4279 174 reqFlags.bits.currentOp = CMD_DISCOVERY_REQ;
Wayne Roberts 0:6015834e4279 175 }
Wayne Roberts 0:6015834e4279 176
Wayne Roberts 0:6015834e4279 177 int uplink(const uint8_t* userPayload, uint8_t userPayloadSize)
Wayne Roberts 0:6015834e4279 178 {
Wayne Roberts 0:6015834e4279 179 unsigned n;
Wayne Roberts 0:6015834e4279 180 //mdbg_printf("uplink_tx%u ", userPayloadSize);
Wayne Roberts 0:6015834e4279 181 if (reqFlags.bits.currentOp == CMD_USER_PAYLOAD_UP_REQ) {
Wayne Roberts 0:6015834e4279 182 //mdbg_printf("busy\r\n");
Wayne Roberts 0:6015834e4279 183 return -1;
Wayne Roberts 0:6015834e4279 184 }
Wayne Roberts 0:6015834e4279 185
Wayne Roberts 0:6015834e4279 186 reqFlags.bits.currentOp = CMD_USER_PAYLOAD_UP_REQ;
Wayne Roberts 0:6015834e4279 187
Wayne Roberts 0:6015834e4279 188 txBuf[txBuf_idx++] = CMD_USER_PAYLOAD_UP_REQ;
Wayne Roberts 0:6015834e4279 189
Wayne Roberts 0:6015834e4279 190 // originating ID, to be preserved all the way up to gateway
Wayne Roberts 0:6015834e4279 191 putu32ToBuf(&txBuf[txBuf_idx], my_id);
Wayne Roberts 0:6015834e4279 192 txBuf_idx += 4;
Wayne Roberts 0:6015834e4279 193
Wayne Roberts 0:6015834e4279 194 txBuf[txBuf_idx++] = userPayloadSize;
Wayne Roberts 0:6015834e4279 195 for (n = 0; n < userPayloadSize; n++)
Wayne Roberts 0:6015834e4279 196 txBuf[txBuf_idx++] = userPayload[n];
Wayne Roberts 0:6015834e4279 197
Wayne Roberts 0:6015834e4279 198 tx_dest_id = attUp.id;
Wayne Roberts 0:6015834e4279 199 flags.CallTXRequest = 1; // transmit will occur in idle-rxsingle cycle
Wayne Roberts 0:6015834e4279 200
Wayne Roberts 0:6015834e4279 201 return 0;
Wayne Roberts 0:6015834e4279 202 }
Wayne Roberts 0:6015834e4279 203
Wayne Roberts 0:6015834e4279 204 void upstream_attached_check(uint32_t sending_id)
Wayne Roberts 0:6015834e4279 205 {
Wayne Roberts 0:6015834e4279 206 if (sending_id != attUp.id)
Wayne Roberts 0:6015834e4279 207 return;
Wayne Roberts 0:6015834e4279 208
Wayne Roberts 0:6015834e4279 209 cmd_e cmd = (cmd_e)Radio::radio.rx_buf[9];
Wayne Roberts 0:6015834e4279 210 Mdbg_printf("upAttCmd:%s? ", cmdStrs[cmd]);
Wayne Roberts 0:6015834e4279 211 if (cmd == CMD_ATTACH_REQ) {
Wayne Roberts 0:6015834e4279 212 pc.printf("\e[31muppreattach\e[0m ");
Wayne Roberts 0:6015834e4279 213 /* TODO appropriate action when upstream path changes */
Wayne Roberts 0:6015834e4279 214 }
Wayne Roberts 0:6015834e4279 215 }
Wayne Roberts 0:6015834e4279 216
Wayne Roberts 0:6015834e4279 217 void init_attached_upstream()
Wayne Roberts 0:6015834e4279 218 {
Wayne Roberts 0:6015834e4279 219 attUp.id = ID_NONE;
Wayne Roberts 0:6015834e4279 220 attUp.cnt = 0;
Wayne Roberts 0:6015834e4279 221 attUp.preference = INT_MIN;
Wayne Roberts 0:6015834e4279 222
Wayne Roberts 0:6015834e4279 223 prospect.id = ID_NONE;
Wayne Roberts 0:6015834e4279 224 prospect.cnt = 0;
Wayne Roberts 0:6015834e4279 225 prospect.preference = INT_MIN;
Wayne Roberts 0:6015834e4279 226 }
Wayne Roberts 0:6015834e4279 227
Wayne Roberts 0:6015834e4279 228 void upstream_signal_check(float rssi, float snr, uint8_t rx_hfg, uint32_t rx_id)
Wayne Roberts 0:6015834e4279 229 {
Wayne Roberts 0:6015834e4279 230 float signal_preference;
Wayne Roberts 0:6015834e4279 231 int this_preference, my_sq, hops_preference = 1 - rx_hfg;
Wayne Roberts 0:6015834e4279 232 my_sq = rssi + snr;
Wayne Roberts 0:6015834e4279 233 signal_preference = my_sq;
Wayne Roberts 0:6015834e4279 234 this_preference = signal_preference + (hops_preference * 10);
Wayne Roberts 0:6015834e4279 235 if (rx_id == attUp.id) {
Wayne Roberts 0:6015834e4279 236 /* how much has path to upstream changed ? */
Wayne Roberts 0:6015834e4279 237 Rx_log_printf("attachedChange initial:%d vs this:%d ", attUp.preference, this_preference);
Wayne Roberts 0:6015834e4279 238 if (attUp.preference > this_preference) {
Wayne Roberts 0:6015834e4279 239 attUp.cnt++;
Wayne Roberts 0:6015834e4279 240 } else
Wayne Roberts 0:6015834e4279 241 attUp.cnt = 0;
Wayne Roberts 0:6015834e4279 242 } else {
Wayne Roberts 0:6015834e4279 243 /* check for better upstream */
Wayne Roberts 0:6015834e4279 244 Rx_log_printf("attached:%d vs this:%d ", attUp.preference, this_preference);
Wayne Roberts 0:6015834e4279 245 if ((this_preference-10) > attUp.preference) { // -10: significantly better
Wayne Roberts 0:6015834e4279 246 Rx_log_printf("better");
Wayne Roberts 0:6015834e4279 247 if (prospect.id == ID_NONE) {
Wayne Roberts 0:6015834e4279 248 prospect.cnt = 1;
Wayne Roberts 0:6015834e4279 249 prospect.id = rx_id;
Wayne Roberts 0:6015834e4279 250 Rx_log_printf("Init");
Wayne Roberts 0:6015834e4279 251 } else {
Wayne Roberts 0:6015834e4279 252 prospect.cnt++;
Wayne Roberts 0:6015834e4279 253 Rx_log_printf("Inc%u", prospect.cnt);
Wayne Roberts 0:6015834e4279 254 if (prospect.cnt > 3) {
Wayne Roberts 0:6015834e4279 255 init_attached_upstream();
Wayne Roberts 0:6015834e4279 256 hops_from_gateway = HFG_UNATTACHED;
Wayne Roberts 0:6015834e4279 257 queue.call_in(2000, upstream_init);
Wayne Roberts 0:6015834e4279 258 Rx_log_printf("\e[33mreattach\e[0m ");
Wayne Roberts 0:6015834e4279 259 }
Wayne Roberts 0:6015834e4279 260 }
Wayne Roberts 0:6015834e4279 261 } else if (this_preference < attUp.preference) {
Wayne Roberts 0:6015834e4279 262 Rx_log_printf("worse");
Wayne Roberts 0:6015834e4279 263 if (prospect.id == rx_id) {
Wayne Roberts 0:6015834e4279 264 prospect.id = ID_NONE;
Wayne Roberts 0:6015834e4279 265 prospect.cnt = 0;
Wayne Roberts 0:6015834e4279 266 Rx_log_printf("Clear");
Wayne Roberts 0:6015834e4279 267 }
Wayne Roberts 0:6015834e4279 268 }
Wayne Roberts 0:6015834e4279 269
Wayne Roberts 0:6015834e4279 270 Rx_log_printf(" ");
Wayne Roberts 0:6015834e4279 271 } // ..rx from other-than-attached
Wayne Roberts 0:6015834e4279 272 }
Wayne Roberts 0:6015834e4279 273
Wayne Roberts 0:6015834e4279 274 #endif /* !GATEWAY */