diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 13db88c0..3dadb88d 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -57,6 +57,7 @@ #define FLOOD_SEND_TIMEOUT_FACTOR 16.0f #define DIRECT_SEND_PERHOP_FACTOR 6.0f #define DIRECT_SEND_PERHOP_EXTRA_MILLIS 250 +#define LAZY_CONTACTS_WRITE_DELAY 5000 #define PUBLIC_GROUP_PSK "izOH6cXN6mrJ5e26oRXNcg==" @@ -198,6 +199,7 @@ class MyMesh : public BaseChatMesh { uint8_t app_target_ver; uint8_t* sign_data; uint32_t sign_data_len; + unsigned long dirty_contacts_expiry; uint8_t cmd_frame[MAX_FRAME_SIZE+1]; uint8_t out_frame[MAX_FRAME_SIZE+1]; CayenneLPP telemetry; @@ -524,7 +526,7 @@ protected: #endif } - saveContacts(); + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); } void onContactPathUpdated(const ContactInfo& contact) override { @@ -532,7 +534,7 @@ protected: memcpy(&out_frame[1], contact.id.pub_key, PUB_KEY_SIZE); _serial->writeFrame(out_frame, 1 + PUB_KEY_SIZE); // NOTE: app may not be connected - saveContacts(); + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); } bool processAck(const uint8_t *data) override { @@ -603,7 +605,8 @@ protected: void onSignedMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { markConnectionActive(from); - saveContacts(); // from.sync_since change needs to be persisted + // from.sync_since change needs to be persisted + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); queueMessage(from, TXT_TYPE_SIGNED_PLAIN, pkt, sender_timestamp, sender_prefix, 4, text); } @@ -695,6 +698,7 @@ protected: if (memcmp(&data[4], "OK", 2) == 0) { // legacy Repeater login OK response out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS; out_frame[i++] = 0; // legacy: is_admin = false + memcpy(&out_frame[i], contact.id.pub_key, 6); i += 6; // pub_key_prefix } else if (data[4] == RESP_SERVER_LOGIN_OK) { // new login response uint16_t keep_alive_secs = ((uint16_t)data[5]) * 16; if (keep_alive_secs > 0) { @@ -702,11 +706,13 @@ protected: } out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS; out_frame[i++] = data[6]; // permissions (eg. is_admin) + memcpy(&out_frame[i], contact.id.pub_key, 6); i += 6; // pub_key_prefix + memcpy(&out_frame[i], &tag, 4); i += 4; // NEW: include server timestamp } else { out_frame[i++] = PUSH_CODE_LOGIN_FAIL; out_frame[i++] = 0; // reserved + memcpy(&out_frame[i], contact.id.pub_key, 6); i += 6; // pub_key_prefix } - memcpy(&out_frame[i], contact.id.pub_key, 6); i += 6; // pub_key_prefix _serial->writeFrame(out_frame, i); } else if (len > 4 && // check for status response pending_status && memcmp(&pending_status, contact.id.pub_key, 4) == 0 // legacy matching scheme @@ -794,6 +800,7 @@ public: pending_login = pending_status = pending_telemetry = 0; next_ack_idx = 0; sign_data = NULL; + dirty_contacts_expiry = 0; // defaults memset(&_prefs, 0, sizeof(_prefs)); @@ -1145,7 +1152,7 @@ public: if (recipient) { recipient->out_path_len = -1; //recipient->lastmod = ?? shouldn't be needed, app already has this version of contact - saveContacts(); + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); writeOKFrame(); } else { writeErrFrame(ERR_CODE_NOT_FOUND); // unknown contact @@ -1156,7 +1163,7 @@ public: if (recipient) { updateContactFromFrame(*recipient, cmd_frame, len); //recipient->lastmod = ?? shouldn't be needed, app already has this version of contact - saveContacts(); + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); writeOKFrame(); } else { ContactInfo contact; @@ -1164,7 +1171,7 @@ public: contact.lastmod = getRTCClock()->getCurrentTime(); contact.sync_since = 0; if (addContact(contact)) { - saveContacts(); + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); writeOKFrame(); } else { writeErrFrame(ERR_CODE_TABLE_FULL); @@ -1174,7 +1181,7 @@ public: uint8_t* pub_key = &cmd_frame[1]; ContactInfo* recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE); if (recipient && removeContact(*recipient)) { - saveContacts(); + dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); writeOKFrame(); } else { writeErrFrame(ERR_CODE_NOT_FOUND); // not found, or unable to remove @@ -1293,6 +1300,9 @@ public: savePrefs(); writeOKFrame(); } else if (cmd_frame[0] == CMD_REBOOT && memcmp(&cmd_frame[1], "reboot", 6) == 0) { + if (dirty_contacts_expiry) { // is there are pending dirty contacts write needed? + saveContacts(); + } board.reboot(); } else if (cmd_frame[0] == CMD_GET_BATTERY_VOLTAGE) { uint8_t reply[3]; @@ -1563,6 +1573,12 @@ public: checkConnections(); } + // is there are pending dirty contacts write needed? + if (dirty_contacts_expiry && millisHasNowPassed(dirty_contacts_expiry)) { + saveContacts(); + dirty_contacts_expiry = 0; + } + #ifdef DISPLAY_CLASS ui_task.setHasConnection(_serial->isConnected()); ui_task.loop();