Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 32 additions & 19 deletions examples/companion_radio/MyMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@
#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 CONTACTS_SAVE_QUIET_WINDOW_MS 60000 // save after this period (1 minute) of no structural changes
#define CONTACTS_SAVE_MAX_WINDOW_MS 300000 // but never delay beyond this total coalesce window (5 minutes)

#define PUBLIC_GROUP_PSK "izOH6cXN6mrJ5e26oRXNcg=="

Expand Down Expand Up @@ -127,6 +128,15 @@ void MyMesh::writeDisabledFrame() {
_serial->writeFrame(buf, 1);
}

void MyMesh::markContactsChanged() {
unsigned long now = _ms->getMillis();
contacts_last_change = now;
if (!contacts_dirty) {
contacts_dirty = true;
contacts_first_change = now;
}
}

void MyMesh::writeContactRespFrame(uint8_t code, const ContactInfo &contact) {
int i = 0;
out_frame[i++] = code;
Expand Down Expand Up @@ -268,8 +278,6 @@ void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path
p->path_len = path_len;
memcpy(p->path, path, p->path_len);
}

dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
}

static int sort_by_recent(const void *a, const void *b) {
Expand All @@ -290,8 +298,10 @@ void MyMesh::onContactPathUpdated(const ContactInfo &contact) {
out_frame[0] = PUSH_CODE_PATH_UPDATED;
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
}

dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
void MyMesh::onContactDataChanged(const ContactInfo& contact) {
markContactsChanged();
}

bool MyMesh::processAck(const uint8_t *data) {
Expand Down Expand Up @@ -374,8 +384,6 @@ void MyMesh::onCommandDataRecv(const ContactInfo &from, mesh::Packet *pkt, uint3
void MyMesh::onSignedMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp,
const uint8_t *sender_prefix, const char *text) {
markConnectionActive(from);
// 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);
}

Expand Down Expand Up @@ -641,7 +649,8 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
clearPendingReqs();
next_ack_idx = 0;
sign_data = NULL;
dirty_contacts_expiry = 0;
contacts_dirty = false;
contacts_last_change = contacts_first_change = 0;
memset(advert_paths, 0, sizeof(advert_paths));

// defaults
Expand Down Expand Up @@ -940,8 +949,7 @@ void MyMesh::handleCmdFrame(size_t len) {
ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
if (recipient) {
recipient->out_path_len = -1;
// recipient->lastmod = ?? shouldn't be needed, app already has this version of contact
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
markContactsChanged();
writeOKFrame();
} else {
writeErrFrame(ERR_CODE_NOT_FOUND); // unknown contact
Expand All @@ -953,15 +961,15 @@ void MyMesh::handleCmdFrame(size_t len) {
if (recipient) {
updateContactFromFrame(*recipient, last_mod, cmd_frame, len);
recipient->lastmod = last_mod;
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
markContactsChanged();
writeOKFrame();
} else {
ContactInfo contact;
updateContactFromFrame(contact, last_mod, cmd_frame, len);
contact.lastmod = last_mod;
contact.sync_since = 0;
if (addContact(contact)) {
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
markContactsChanged();
writeOKFrame();
} else {
writeErrFrame(ERR_CODE_TABLE_FULL);
Expand All @@ -971,7 +979,7 @@ void MyMesh::handleCmdFrame(size_t len) {
uint8_t *pub_key = &cmd_frame[1];
ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
if (recipient && removeContact(*recipient)) {
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
markContactsChanged();
writeOKFrame();
} else {
writeErrFrame(ERR_CODE_NOT_FOUND); // not found, or unable to remove
Expand Down Expand Up @@ -1116,9 +1124,7 @@ void MyMesh::handleCmdFrame(size_t len) {
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();
}
saveContactsIfDirty();
board.reboot();
} else if (cmd_frame[0] == CMD_GET_BATT_AND_STORAGE) {
uint8_t reply[11];
Expand Down Expand Up @@ -1587,6 +1593,7 @@ void MyMesh::checkCLIRescueCmd() {
}

} else if (strcmp(cli_command, "reboot") == 0) {
saveContactsIfDirty();
board.reboot(); // doesn't return
} else {
Serial.println(" Error: unknown command");
Expand Down Expand Up @@ -1632,10 +1639,16 @@ void MyMesh::loop() {
checkSerialInterface();
}

// is there are pending dirty contacts write needed?
if (dirty_contacts_expiry && millisHasNowPassed(dirty_contacts_expiry)) {
saveContacts();
dirty_contacts_expiry = 0;
// Debounced save
if (contacts_dirty) {
unsigned long now = _ms->getMillis();
bool quiet_met = (now - contacts_last_change) >= CONTACTS_SAVE_QUIET_WINDOW_MS;
bool max_reached = (now - contacts_first_change) >= CONTACTS_SAVE_MAX_WINDOW_MS;
if (quiet_met || max_reached) {
saveContacts();
contacts_dirty = false;
contacts_last_change = contacts_first_change = 0;
}
}

#ifdef DISPLAY_CLASS
Expand Down
19 changes: 18 additions & 1 deletion examples/companion_radio/MyMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {

int getRecentlyHeard(AdvertPath dest[], int max_num);

bool isContactsDirty() const { return contacts_dirty; }
void flushContactsIfDirty() { saveContactsIfDirty(); }

protected:
float getAirtimeBudgetFactor() const override;
int getInterferenceThreshold() const override;
Expand All @@ -112,6 +115,7 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {
bool onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_t in_path_len, uint8_t* out_path, uint8_t out_path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
void onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path_len, const uint8_t* path) override;
void onContactPathUpdated(const ContactInfo &contact) override;
void onContactDataChanged(const ContactInfo& contact) override;
bool processAck(const uint8_t *data) override;
void queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packet *pkt, uint32_t sender_timestamp,
const uint8_t *extra, int extra_len, const char *text);
Expand All @@ -136,6 +140,15 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {
uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const override;
void onSendTimeout() override;

bool hasDirtyContacts() const { return contacts_dirty; }
void saveContactsIfDirty() {
if (contacts_dirty) {
saveContacts();
contacts_dirty = false;
contacts_last_change = contacts_first_change = 0;
}
}

// DataStoreHost methods
bool onContactLoaded(const ContactInfo& contact) override { return addContact(contact); }
bool getContactForSave(uint32_t idx, ContactInfo& contact) override { return getContactByIdx(idx, contact); }
Expand All @@ -147,6 +160,7 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {
}

private:
void markContactsChanged();
void writeOKFrame();
void writeErrFrame(uint8_t err_code);
void writeDisabledFrame();
Expand Down Expand Up @@ -189,7 +203,10 @@ class MyMesh : public BaseChatMesh, public DataStoreHost {
uint8_t app_target_ver;
uint8_t *sign_data;
uint32_t sign_data_len;
unsigned long dirty_contacts_expiry;

bool contacts_dirty;
unsigned long contacts_last_change;
unsigned long contacts_first_change;

uint8_t cmd_frame[MAX_FRAME_SIZE + 1];
uint8_t out_frame[MAX_FRAME_SIZE + 1];
Expand Down
2 changes: 2 additions & 0 deletions examples/companion_radio/ui-new/UITask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,11 @@ void UITask::shutdown(bool restart){
#endif // PIN_BUZZER

if (restart) {
the_mesh.flushContactsIfDirty();
_board->reboot();
} else {
_display->turnOff();
the_mesh.flushContactsIfDirty();
_board->powerOff();
}
}
Expand Down
7 changes: 5 additions & 2 deletions examples/companion_radio/ui-orig/UITask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,13 @@ void UITask::shutdown(bool restart){

#endif // PIN_BUZZER

if (restart)
if (restart) {
the_mesh.flushContactsIfDirty();
_board->reboot();
else
} else {
the_mesh.flushContactsIfDirty();
_board->powerOff();
}
}

void UITask::loop() {
Expand Down
3 changes: 3 additions & 0 deletions src/helpers/BaseChatMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
from->lastmod = getRTCClock()->getCurrentTime();

onDiscoveredContact(*from, is_new, packet->path_len, packet->path); // let UI know
onContactDataChanged(*from);
}

int BaseChatMesh::searchPeersByHash(const uint8_t* hash) {
Expand Down Expand Up @@ -183,6 +184,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
} else if (flags == TXT_TYPE_SIGNED_PLAIN) {
if (timestamp > from.sync_since) { // make sure 'sync_since' is up-to-date
from.sync_since = timestamp;
onContactDataChanged(from);
}
onSignedMessageRecv(from, packet, timestamp, &data[5], (const char *) &data[9]); // let UI know

Expand Down Expand Up @@ -245,6 +247,7 @@ bool BaseChatMesh::onContactPathRecv(ContactInfo& from, uint8_t* in_path, uint8_
from.lastmod = getRTCClock()->getCurrentTime();

onContactPathUpdated(from);
onContactDataChanged(from);

if (extra_type == PAYLOAD_TYPE_ACK && extra_len >= 4) {
// also got an encoded ACK!
Expand Down
1 change: 1 addition & 0 deletions src/helpers/BaseChatMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class BaseChatMesh : public mesh::Mesh {
virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0;
virtual uint8_t onContactRequest(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t* data, uint8_t len, uint8_t* reply) = 0;
virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
virtual void onContactDataChanged(const ContactInfo& contact) { }

// storage concepts, for sub-classes to override/implement
virtual int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) { return 0; } // not implemented
Expand Down