All 4 units, BOB, CY, DAN & ED, are LINKing with the other three. Success.
This commit is contained in:
parent
d8e5cc0a8d
commit
fd96e56410
3 changed files with 227 additions and 30 deletions
|
|
@ -43,18 +43,22 @@ We have 7 units: AMY...GUY. The following command creates identities for use in
|
|||
At boot the OLED shows:
|
||||
|
||||
```text
|
||||
Ex 204 v. <build utc>
|
||||
Exercise 204
|
||||
Build
|
||||
<build utc>
|
||||
<BOARD>
|
||||
<node label>
|
||||
```
|
||||
|
||||
The unit then checks the RTC and `/ex204/clock.txt` on the SD card. If the saved discipline marker is less than 24 hours old according to the RTC, LoRa/microReticulum starts immediately. If not, the OLED shows `Take outside` and serial prints `gps_gate ...` until GPS UTC/fix is available. A successful GPS discipline writes a fresh marker and then starts LoRa.
|
||||
The splash is held for 10 seconds so the full build stamp can be read.
|
||||
|
||||
The unit then checks the RTC and `/ex204/clock.txt` on the SD card. If the saved discipline marker is less than 24 hours old according to the RTC, LoRa/microReticulum starts immediately. If not, the OLED shows `Take outside` and serial prints `gps_gate ...` until GPS UTC/fix is available. A successful GPS discipline writes a fresh marker and then starts LoRa. Marker writes replace the old file, and marker reads use the last valid line so stale appended clock data cannot keep forcing GPS discipline.
|
||||
|
||||
All units run with `reticulum.transport_enabled(true)`. Path learning remains enabled, but `RNS_PERSIST_PATHS` is intentionally not defined for this exercise. Live announces are sufficient for the single-hop field test, and disabling persistent paths avoids ESP32 LittleFS `/path_store_*.dat` compaction errors during dense multi-unit announce traffic.
|
||||
|
||||
Each unit tracks up to six peers, so a full seven-unit field run can form one Link per ordered pair. The lexicographically lower node initiates each pair to avoid both ends opening duplicate Links at the same time; for example `Bob` initiates to `Cy`, `Dan`, `Ed`, `Flo`, and `Guy`, while `Amy` initiates to everyone. If an outbound link request is sent but no link becomes active, the initiator retries after 30 seconds. This matters in field use because the first request can be missed while units are being moved, reset, or connected to monitors.
|
||||
Each unit tracks up to six peers, so a full seven-unit field run can form one Link per ordered pair. The lexicographically lower node initiates each pair to avoid both ends opening duplicate Links at the same time; for example `Bob` initiates to `Cy`, `Dan`, `Ed`, `Flo`, and `Guy`, while `Amy` initiates to everyone. If an outbound link request is sent but no link becomes active, the initiator retries after 90 seconds. This matters in field use because the first request can be missed while units are being moved, reset, or connected to monitors.
|
||||
|
||||
Application traffic is scheduled from the RTC so all nodes do not transmit at once:
|
||||
Announces and application traffic are scheduled from the RTC so all nodes do not transmit at once. Announces run once per minute at `02,06,10,14,18,22,26` for `Amy..Guy`; Link payloads run twice per minute:
|
||||
|
||||
```text
|
||||
Amy: 04,34 Bob: 08,38 Cy: 12,42 Dan: 16,46
|
||||
|
|
|
|||
|
|
@ -22,3 +22,9 @@ I have a 3 minute set of logs with the lastest code at: ~/logs/20260528_1707. O
|
|||
jlpoole@jp ~/logs/20260528_1707 $
|
||||
|
||||
Are we hitting some bugs in microreticulum?
|
||||
|
||||
When you are ready to compile, please compile only 1 unit, if that compiles, then so will all the rest. Notify me and I can run a bash script that will compile the others -- it takes about 4 minutes to complete.
|
||||
|
||||
Please leave all uploading of newly compiled firmware to me.
|
||||
|
||||
I am trying to maximize your time within my 5 Hour allowance and which recently has been consumed at a rapid rate and I think having you monitor units and wait for compiles and upload may be eating into the budget. I've developed a logging system that isolates logs from a run into its own directory, e.g. ~/logs/20260528_1707, so we can use that to efficiently evaluate what is going on.
|
||||
|
|
@ -44,6 +44,9 @@ static constexpr uint32_t GPS_STATUS_PERIOD_MS = 2000;
|
|||
static constexpr uint32_t PPS_WAIT_MS = 1500;
|
||||
//static constexpr uint32_t LINK_RETRY_MS = 30000;
|
||||
static constexpr uint32_t LINK_RETRY_MS = 90000;
|
||||
static constexpr uint32_t LINK_RX_STALE_MS = 75000;
|
||||
static constexpr uint32_t LINK_REOPEN_DELAY_MS = 5000;
|
||||
static constexpr uint8_t LINK_MESSAGES_PER_CYCLE = 5;
|
||||
|
||||
struct DateTime {
|
||||
uint16_t year = 0;
|
||||
|
|
@ -92,7 +95,12 @@ struct PeerState {
|
|||
bool outbound_active = false;
|
||||
bool inbound_active = false;
|
||||
uint32_t last_link_attempt_ms = 0;
|
||||
uint32_t last_link_active_ms = 0;
|
||||
uint32_t next_link_open_ms = 0;
|
||||
uint32_t last_rx_ms = 0;
|
||||
uint32_t last_tx_ms = 0;
|
||||
uint32_t tx_iter = 0;
|
||||
uint8_t tx_since_link_open = 0;
|
||||
uint8_t last_tx_second = 255;
|
||||
};
|
||||
|
||||
|
|
@ -256,10 +264,17 @@ static int64_t read_clock_marker() {
|
|||
if (!f) {
|
||||
return 0;
|
||||
}
|
||||
int64_t marker_epoch = 0;
|
||||
while (f.available()) {
|
||||
String line = f.readStringUntil('\n');
|
||||
f.close();
|
||||
line.trim();
|
||||
return (int64_t)strtoll(line.c_str(), nullptr, 10);
|
||||
const int64_t value = (int64_t)strtoll(line.c_str(), nullptr, 10);
|
||||
if (value > 0) {
|
||||
marker_epoch = value;
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
return marker_epoch;
|
||||
}
|
||||
|
||||
static bool write_clock_marker(int64_t epoch) {
|
||||
|
|
@ -267,6 +282,9 @@ static bool write_clock_marker(int64_t epoch) {
|
|||
return false;
|
||||
}
|
||||
SD.mkdir("/ex204");
|
||||
if (SD.exists(CLOCK_MARKER_PATH)) {
|
||||
SD.remove(CLOCK_MARKER_PATH);
|
||||
}
|
||||
File f = SD.open(CLOCK_MARKER_PATH, FILE_WRITE);
|
||||
if (!f) {
|
||||
return false;
|
||||
|
|
@ -281,7 +299,7 @@ static void show_status(const char* left, const char* right = nullptr, const cha
|
|||
}
|
||||
|
||||
static void show_splash() {
|
||||
oled_display.showLines("Ex 204 v. " FW_BUILD_UTC, BOARD_ID, NODE_LABEL, "established ids", "transport");
|
||||
oled_display.showLines("Exercise 204", "Build", FW_BUILD_UTC, BOARD_ID, NODE_LABEL, "transport");
|
||||
}
|
||||
|
||||
static bool hex_nibble(char c, uint8_t& out) {
|
||||
|
|
@ -426,6 +444,13 @@ static bool saved_clock_is_fresh() {
|
|||
Serial.println("RTC invalid; GPS discipline required");
|
||||
return false;
|
||||
}
|
||||
char iso[32];
|
||||
format_iso(rtc_now, iso, sizeof(iso));
|
||||
if (!sd_ready) {
|
||||
Serial.printf("Clock holdover accepted without SD marker: rtc=%s reason=sd_unavailable\r\n", iso);
|
||||
show_status("Clock OK", "RTC only", iso);
|
||||
return true;
|
||||
}
|
||||
const int64_t marker_epoch = read_clock_marker();
|
||||
if (marker_epoch <= 0) {
|
||||
Serial.println("No saved clock marker; GPS discipline required");
|
||||
|
|
@ -436,9 +461,8 @@ static bool saved_clock_is_fresh() {
|
|||
Serial.printf("Saved clock stale: age_s=%lld\r\n", (long long)age);
|
||||
return false;
|
||||
}
|
||||
char iso[32];
|
||||
format_iso(rtc_now, iso, sizeof(iso));
|
||||
Serial.printf("Clock holdover accepted: rtc=%s age_s=%lld\r\n", iso, (long long)age);
|
||||
(void)write_clock_marker(rtc_epoch);
|
||||
show_status("Clock OK", "holdover", iso);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -497,6 +521,45 @@ static bool should_initiate_link_to(const String& label) {
|
|||
return strcmp(NODE_LABEL, label.c_str()) < 0;
|
||||
}
|
||||
|
||||
static int8_t node_index_for_label(const String& label) {
|
||||
if (label == "Amy") {
|
||||
return 0;
|
||||
}
|
||||
if (label == "Bob") {
|
||||
return 1;
|
||||
}
|
||||
if (label == "Cy") {
|
||||
return 2;
|
||||
}
|
||||
if (label == "Dan") {
|
||||
return 3;
|
||||
}
|
||||
if (label == "Ed") {
|
||||
return 4;
|
||||
}
|
||||
if (label == "Flo") {
|
||||
return 5;
|
||||
}
|
||||
if (label == "Guy") {
|
||||
return 6;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint8_t pair_link_open_second(const String& label) {
|
||||
int8_t a = node_index_for_label(String(NODE_LABEL));
|
||||
int8_t b = node_index_for_label(label);
|
||||
if (a < 0 || b < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (a > b) {
|
||||
const int8_t tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
return (uint8_t)(1U + (uint8_t)(((uint8_t)a * 7U + (uint8_t)b) % 29U) * 2U);
|
||||
}
|
||||
|
||||
static uint8_t node_send_slot_second() {
|
||||
if (strcmp(NODE_LABEL, "Amy") == 0) {
|
||||
return 4;
|
||||
|
|
@ -522,6 +585,10 @@ static uint8_t node_send_slot_second() {
|
|||
return (uint8_t)(4U + ((uint8_t)NODE_SLOT_INDEX * 4U));
|
||||
}
|
||||
|
||||
static uint8_t node_announce_slot_second() {
|
||||
return (uint8_t)(2U + ((uint8_t)NODE_SLOT_INDEX * 4U));
|
||||
}
|
||||
|
||||
static int find_peer_by_label(const String& label) {
|
||||
for (uint8_t i = 0; i < MAX_PEERS; ++i) {
|
||||
if (peers[i].label == label) {
|
||||
|
|
@ -552,6 +619,26 @@ static int first_free_peer_slot() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void clear_peer_slot(uint8_t index) {
|
||||
peers[index].label = "";
|
||||
peers[index].destination_hash.clear();
|
||||
peers[index].destination = {RNS::Type::NONE};
|
||||
peers[index].outbound_link = {RNS::Type::NONE};
|
||||
peers[index].inbound_link = {RNS::Type::NONE};
|
||||
peers[index].announced = false;
|
||||
peers[index].outbound_attempted = false;
|
||||
peers[index].outbound_active = false;
|
||||
peers[index].inbound_active = false;
|
||||
peers[index].last_link_attempt_ms = 0;
|
||||
peers[index].last_link_active_ms = 0;
|
||||
peers[index].next_link_open_ms = 0;
|
||||
peers[index].last_rx_ms = 0;
|
||||
peers[index].last_tx_ms = 0;
|
||||
peers[index].tx_iter = 0;
|
||||
peers[index].tx_since_link_open = 0;
|
||||
peers[index].last_tx_second = 255;
|
||||
}
|
||||
|
||||
static int ensure_peer_for_label(const String& label) {
|
||||
int index = find_peer_by_label(label);
|
||||
if (index >= 0) {
|
||||
|
|
@ -577,6 +664,19 @@ static String parse_sender_label(const String& text) {
|
|||
return text.substring(start, end);
|
||||
}
|
||||
|
||||
static String parse_recipient_label(const String& text) {
|
||||
const int to_pos = text.indexOf("to=");
|
||||
if (to_pos < 0) {
|
||||
return "";
|
||||
}
|
||||
const int start = to_pos + 3;
|
||||
int end = text.indexOf(' ', start);
|
||||
if (end < 0) {
|
||||
end = text.length();
|
||||
}
|
||||
return text.substring(start, end);
|
||||
}
|
||||
|
||||
static void attach_link_callbacks(RNS::Link& link) {
|
||||
link.set_packet_callback(on_link_packet);
|
||||
link.set_link_closed_callback(on_link_closed);
|
||||
|
|
@ -590,10 +690,26 @@ static void on_link_packet(const RNS::Bytes& data, const RNS::Packet& packet) {
|
|||
}
|
||||
String text = data.toString().c_str();
|
||||
String sender = parse_sender_label(text);
|
||||
String recipient = parse_recipient_label(text);
|
||||
if (sender == NODE_LABEL || (recipient.length() > 0 && recipient != NODE_LABEL)) {
|
||||
Serial.printf("RX LINK ignored: self_or_wrong_recipient text=%s\r\n", text.c_str());
|
||||
return;
|
||||
}
|
||||
if (peer_index >= 0 && peers[peer_index].label.length() == 0 &&
|
||||
sender.length() > 0 && sender != NODE_LABEL) {
|
||||
const int existing_index = find_peer_by_label(sender);
|
||||
if (existing_index >= 0 && existing_index != peer_index) {
|
||||
if (packet.link()) {
|
||||
peers[existing_index].inbound_link = packet.link();
|
||||
peers[existing_index].inbound_active = true;
|
||||
attach_link_callbacks(peers[existing_index].inbound_link);
|
||||
}
|
||||
clear_peer_slot((uint8_t)peer_index);
|
||||
peer_index = existing_index;
|
||||
} else {
|
||||
peers[peer_index].label = sender;
|
||||
}
|
||||
}
|
||||
if (peer_index < 0) {
|
||||
if (sender.length() > 0 && sender != NODE_LABEL) {
|
||||
peer_index = ensure_peer_for_label(sender);
|
||||
|
|
@ -606,6 +722,7 @@ static void on_link_packet(const RNS::Bytes& data, const RNS::Packet& packet) {
|
|||
}
|
||||
if (peer_index >= 0) {
|
||||
peer = peers[peer_index].label;
|
||||
peers[peer_index].last_rx_ms = millis();
|
||||
}
|
||||
float rssi = lora_impl ? lora_impl->last_rssi() : 0.0f;
|
||||
float snr = lora_impl ? lora_impl->last_snr() : 0.0f;
|
||||
|
|
@ -615,22 +732,34 @@ static void on_link_packet(const RNS::Bytes& data, const RNS::Packet& packet) {
|
|||
}
|
||||
|
||||
static void on_link_closed(RNS::Link& link) {
|
||||
int peer_index = find_peer_by_link_hash(link.hash());
|
||||
if (!link) {
|
||||
Serial.println("LINK CLOSED: null link callback");
|
||||
show_status("LINK CLOSED", "null");
|
||||
return;
|
||||
}
|
||||
|
||||
const RNS::Bytes link_hash = link.hash();
|
||||
const String link_hash_hex = link_hash.toHex().c_str();
|
||||
int peer_index = find_peer_by_link_hash(link_hash);
|
||||
const char* label = "(unknown)";
|
||||
if (peer_index >= 0) {
|
||||
label = peers[peer_index].label.c_str();
|
||||
if (peers[peer_index].outbound_link && peers[peer_index].outbound_link.hash() == link.hash()) {
|
||||
if (peers[peer_index].outbound_link && peers[peer_index].outbound_link.hash() == link_hash) {
|
||||
peers[peer_index].outbound_link = {RNS::Type::NONE};
|
||||
peers[peer_index].outbound_active = false;
|
||||
peers[peer_index].outbound_attempted = false;
|
||||
peers[peer_index].last_link_attempt_ms = 0;
|
||||
peers[peer_index].last_link_active_ms = 0;
|
||||
peers[peer_index].tx_since_link_open = 0;
|
||||
}
|
||||
if (peers[peer_index].inbound_link && peers[peer_index].inbound_link.hash() == link.hash()) {
|
||||
if (peers[peer_index].inbound_link && peers[peer_index].inbound_link.hash() == link_hash) {
|
||||
peers[peer_index].inbound_link = {RNS::Type::NONE};
|
||||
peers[peer_index].inbound_active = false;
|
||||
peers[peer_index].last_link_active_ms = 0;
|
||||
peers[peer_index].tx_since_link_open = 0;
|
||||
}
|
||||
}
|
||||
Serial.printf("LINK CLOSED: %s hash=%s\r\n", label, link.hash().toHex().c_str());
|
||||
Serial.printf("LINK CLOSED: %s hash=%s\r\n", label, link_hash_hex.c_str());
|
||||
show_status("LINK CLOSED", label);
|
||||
}
|
||||
|
||||
|
|
@ -642,6 +771,8 @@ static void on_outbound_link_established(RNS::Link& link) {
|
|||
peers[peer_index].outbound_active = true;
|
||||
peers[peer_index].outbound_attempted = true;
|
||||
peers[peer_index].last_link_attempt_ms = 0;
|
||||
peers[peer_index].last_link_active_ms = millis();
|
||||
peers[peer_index].tx_since_link_open = 0;
|
||||
Serial.printf("LINK ACTIVE: initiator link established to %s hash=%s\r\n",
|
||||
peers[peer_index].label.c_str(), link.hash().toHex().c_str());
|
||||
show_status("LINK ACTIVE", peers[peer_index].label.c_str(), "initiator");
|
||||
|
|
@ -660,6 +791,8 @@ static void on_inbound_link_established(RNS::Link& link) {
|
|||
peers[peer_index].inbound_link = link;
|
||||
attach_link_callbacks(peers[peer_index].inbound_link);
|
||||
peers[peer_index].inbound_active = true;
|
||||
peers[peer_index].last_link_active_ms = millis();
|
||||
peers[peer_index].tx_since_link_open = 0;
|
||||
}
|
||||
Serial.printf("RX LINK: inbound link established hash=%s\r\n", link.hash().toHex().c_str());
|
||||
show_status("LINK ACTIVE", "inbound", link.hash().toHex().c_str());
|
||||
|
|
@ -723,7 +856,7 @@ static void send_announce() {
|
|||
inbound_destination.announce(RNS::bytesFromString(NODE_LABEL));
|
||||
}
|
||||
|
||||
static void maybe_open_link() {
|
||||
static void maybe_open_link(const DateTime& rtc_now, bool have_rtc_now) {
|
||||
const uint32_t now = millis();
|
||||
static uint32_t last_open_ms = 0;
|
||||
if (!clock_ready) {
|
||||
|
|
@ -734,6 +867,37 @@ static void maybe_open_link() {
|
|||
if (!peer.announced || !peer.destination || !should_initiate_link_to(peer.label)) {
|
||||
continue;
|
||||
}
|
||||
uint32_t stale_reference_ms = peer.last_rx_ms;
|
||||
if (stale_reference_ms == 0) {
|
||||
stale_reference_ms = peer.last_tx_ms;
|
||||
}
|
||||
if (stale_reference_ms == 0) {
|
||||
stale_reference_ms = peer.last_link_active_ms;
|
||||
}
|
||||
if (stale_reference_ms == 0) {
|
||||
stale_reference_ms = peer.last_link_attempt_ms;
|
||||
}
|
||||
if ((peer.outbound_link || peer.inbound_link) && stale_reference_ms != 0 &&
|
||||
(uint32_t)(now - stale_reference_ms) >= LINK_RX_STALE_MS) {
|
||||
Serial.printf("LINK STALE: no RX from %s after %lu ms ref=%lu; clearing link state\r\n",
|
||||
peer.label.c_str(),
|
||||
(unsigned long)LINK_RX_STALE_MS,
|
||||
(unsigned long)stale_reference_ms);
|
||||
peer.outbound_link = {RNS::Type::NONE};
|
||||
peer.inbound_link = {RNS::Type::NONE};
|
||||
peer.outbound_active = false;
|
||||
peer.inbound_active = false;
|
||||
peer.outbound_attempted = false;
|
||||
peer.last_link_attempt_ms = 0;
|
||||
peer.last_link_active_ms = 0;
|
||||
peer.last_rx_ms = 0;
|
||||
peer.last_tx_ms = 0;
|
||||
peer.tx_since_link_open = 0;
|
||||
peer.next_link_open_ms = now + LINK_REOPEN_DELAY_MS;
|
||||
}
|
||||
if (peer.next_link_open_ms != 0 && (int32_t)(now - peer.next_link_open_ms) < 0) {
|
||||
continue;
|
||||
}
|
||||
if (peer.outbound_active || (peer.outbound_link && peer.outbound_link.status() == RNS::Type::Link::ACTIVE)) {
|
||||
peer.outbound_active = true;
|
||||
continue;
|
||||
|
|
@ -750,11 +914,17 @@ static void maybe_open_link() {
|
|||
if (peer.outbound_attempted || peer.outbound_link) {
|
||||
continue;
|
||||
}
|
||||
const uint8_t open_second = pair_link_open_second(peer.label);
|
||||
if (!have_rtc_now || rtc_now.second != open_second) {
|
||||
continue;
|
||||
}
|
||||
if (last_open_ms != 0 && (uint32_t)(now - last_open_ms) < 1500U) {
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("TX LINKREQUEST: opening link to %s\r\n", peer.label.c_str());
|
||||
Serial.printf("TX LINKREQUEST: opening link to %s slot=%u\r\n",
|
||||
peer.label.c_str(),
|
||||
(unsigned)open_second);
|
||||
show_status("TX LINKREQ", peer.label.c_str());
|
||||
peer.outbound_link = RNS::Link(peer.destination);
|
||||
peer.outbound_link.set_packet_callback(on_link_packet);
|
||||
|
|
@ -835,7 +1005,7 @@ void setup() {
|
|||
display_config.powerSave = false;
|
||||
oled_display.begin(display_config);
|
||||
show_splash();
|
||||
delay(1200);
|
||||
delay(10000);
|
||||
|
||||
print_config();
|
||||
mount_sd();
|
||||
|
|
@ -856,26 +1026,23 @@ void setup() {
|
|||
void loop() {
|
||||
reticulum.loop();
|
||||
|
||||
static uint32_t next_announce_ms = 0;
|
||||
static uint32_t last_rtc_poll_ms = 0;
|
||||
static DateTime rtc_now{};
|
||||
static bool have_rtc_now = false;
|
||||
static uint8_t last_announce_minute = 255;
|
||||
uint32_t now = millis();
|
||||
|
||||
if (next_announce_ms == 0) {
|
||||
next_announce_ms = now + 700U + ((uint32_t)NODE_SLOT_INDEX * 350U);
|
||||
}
|
||||
if ((int32_t)(now - next_announce_ms) >= 0) {
|
||||
next_announce_ms = now + 15000;
|
||||
send_announce();
|
||||
}
|
||||
|
||||
maybe_open_link();
|
||||
|
||||
if ((uint32_t)(now - last_rtc_poll_ms) >= 200U) {
|
||||
last_rtc_poll_ms = now;
|
||||
have_rtc_now = read_rtc(rtc_now);
|
||||
}
|
||||
maybe_open_link(rtc_now, have_rtc_now);
|
||||
|
||||
if (have_rtc_now && rtc_now.second == node_announce_slot_second() &&
|
||||
last_announce_minute != rtc_now.minute) {
|
||||
last_announce_minute = rtc_now.minute;
|
||||
send_announce();
|
||||
}
|
||||
const uint8_t send_slot = node_send_slot_second();
|
||||
const uint8_t second_slot = (uint8_t)((send_slot + 30U) % 60U);
|
||||
if (have_rtc_now && (rtc_now.second == send_slot || rtc_now.second == second_slot)) {
|
||||
|
|
@ -898,10 +1065,30 @@ void loop() {
|
|||
}
|
||||
|
||||
peer.last_tx_second = rtc_now.second;
|
||||
peer.last_tx_ms = now;
|
||||
String message = String("Hi from ") + NODE_LABEL + " iter=" + String(peer.tx_iter++) + " to=" + peer.label;
|
||||
Serial.printf("TX LINK: %s\r\n", message.c_str());
|
||||
show_status("TX LINK", peer.label.c_str(), message.c_str());
|
||||
RNS::Packet(*link, RNS::bytesFromString(message.c_str())).send();
|
||||
++peer.tx_since_link_open;
|
||||
if (peer.tx_since_link_open >= LINK_MESSAGES_PER_CYCLE) {
|
||||
Serial.printf("LINK CYCLE: sent %u messages to %s; tearing down for reopen\r\n",
|
||||
(unsigned)peer.tx_since_link_open,
|
||||
peer.label.c_str());
|
||||
show_status("LINK CYCLE", peer.label.c_str(), "teardown");
|
||||
link->teardown();
|
||||
peer.outbound_link = {RNS::Type::NONE};
|
||||
peer.inbound_link = {RNS::Type::NONE};
|
||||
peer.outbound_active = false;
|
||||
peer.inbound_active = false;
|
||||
peer.outbound_attempted = false;
|
||||
peer.last_link_attempt_ms = 0;
|
||||
peer.last_link_active_ms = 0;
|
||||
peer.last_rx_ms = 0;
|
||||
peer.last_tx_ms = 0;
|
||||
peer.tx_since_link_open = 0;
|
||||
peer.next_link_open_ms = now + LINK_REOPEN_DELAY_MS;
|
||||
}
|
||||
delay(120);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue