* companion: FIRMWARE_VER_CODE now bumped to 3.

* companion: new RESP_CODE_CONTACT_MSG_RECV_V3, and _CHANNEL_MSG_RECV_V3. (now with packet SNR included)
This commit is contained in:
Scott Powell
2025-03-07 14:17:37 +11:00
parent 544adec2b6
commit e534e1b529
4 changed files with 48 additions and 31 deletions

View File

@@ -117,7 +117,7 @@ static uint32_t _atoi(const char* sp) {
/*------------ Frame Protocol --------------*/ /*------------ Frame Protocol --------------*/
#define FIRMWARE_VER_CODE 2 #define FIRMWARE_VER_CODE 3
#ifndef FIRMWARE_BUILD_DATE #ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "3 Mar 2025" #define FIRMWARE_BUILD_DATE "3 Mar 2025"
@@ -165,8 +165,8 @@ static uint32_t _atoi(const char* sp) {
#define RESP_CODE_END_OF_CONTACTS 4 // last reply to CMD_GET_CONTACTS #define RESP_CODE_END_OF_CONTACTS 4 // last reply to CMD_GET_CONTACTS
#define RESP_CODE_SELF_INFO 5 // reply to CMD_APP_START #define RESP_CODE_SELF_INFO 5 // reply to CMD_APP_START
#define RESP_CODE_SENT 6 // reply to CMD_SEND_TXT_MSG #define RESP_CODE_SENT 6 // reply to CMD_SEND_TXT_MSG
#define RESP_CODE_CONTACT_MSG_RECV 7 // a reply to CMD_SYNC_NEXT_MESSAGE #define RESP_CODE_CONTACT_MSG_RECV 7 // a reply to CMD_SYNC_NEXT_MESSAGE (ver < 3)
#define RESP_CODE_CHANNEL_MSG_RECV 8 // a reply to CMD_SYNC_NEXT_MESSAGE #define RESP_CODE_CHANNEL_MSG_RECV 8 // a reply to CMD_SYNC_NEXT_MESSAGE (ver < 3)
#define RESP_CODE_CURR_TIME 9 // a reply to CMD_GET_DEVICE_TIME #define RESP_CODE_CURR_TIME 9 // a reply to CMD_GET_DEVICE_TIME
#define RESP_CODE_NO_MORE_MESSAGES 10 // a reply to CMD_SYNC_NEXT_MESSAGE #define RESP_CODE_NO_MORE_MESSAGES 10 // a reply to CMD_SYNC_NEXT_MESSAGE
#define RESP_CODE_EXPORT_CONTACT 11 #define RESP_CODE_EXPORT_CONTACT 11
@@ -174,6 +174,8 @@ static uint32_t _atoi(const char* sp) {
#define RESP_CODE_DEVICE_INFO 13 // a reply to CMD_DEVICE_QEURY #define RESP_CODE_DEVICE_INFO 13 // a reply to CMD_DEVICE_QEURY
#define RESP_CODE_PRIVATE_KEY 14 // a reply to CMD_EXPORT_PRIVATE_KEY #define RESP_CODE_PRIVATE_KEY 14 // a reply to CMD_EXPORT_PRIVATE_KEY
#define RESP_CODE_DISABLED 15 #define RESP_CODE_DISABLED 15
#define RESP_CODE_CONTACT_MSG_RECV_V3 16 // a reply to CMD_SYNC_NEXT_MESSAGE (ver >= 3)
#define RESP_CODE_CHANNEL_MSG_RECV_V3 17 // a reply to CMD_SYNC_NEXT_MESSAGE (ver >= 3)
// these are _pushed_ to client app at any time // these are _pushed_ to client app at any time
#define PUSH_CODE_ADVERT 0x80 #define PUSH_CODE_ADVERT 0x80
@@ -471,11 +473,18 @@ protected:
return checkConnectionsAck(data); return checkConnectionsAck(data);
} }
void queueMessage(const ContactInfo& from, uint8_t txt_type, uint8_t path_len, uint32_t sender_timestamp, const uint8_t* extra, int extra_len, const char *text) { 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) {
int i = 0; int i = 0;
out_frame[i++] = RESP_CODE_CONTACT_MSG_RECV; if (app_target_ver >= 3) {
out_frame[i++] = RESP_CODE_CONTACT_MSG_RECV_V3;
out_frame[i++] = (int8_t)(pkt->getSNR() * 4);
out_frame[i++] = 0; // reserved1
out_frame[i++] = 0; // reserved2
} else {
out_frame[i++] = RESP_CODE_CONTACT_MSG_RECV;
}
memcpy(&out_frame[i], from.id.pub_key, 6); i += 6; // just 6-byte prefix memcpy(&out_frame[i], from.id.pub_key, 6); i += 6; // just 6-byte prefix
out_frame[i++] = path_len; uint8_t path_len = out_frame[i++] = pkt->isRouteFlood() ? pkt->path_len : 0xFF;
out_frame[i++] = txt_type; out_frame[i++] = txt_type;
memcpy(&out_frame[i], &sender_timestamp, 4); i += 4; memcpy(&out_frame[i], &sender_timestamp, 4); i += 4;
if (extra_len > 0) { if (extra_len > 0) {
@@ -500,27 +509,35 @@ protected:
#endif #endif
} }
void onMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { void onMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override {
markConnectionActive(from); // in case this is from a server, and we have a connection markConnectionActive(from); // in case this is from a server, and we have a connection
queueMessage(from, TXT_TYPE_PLAIN, path_len, sender_timestamp, NULL, 0, text); queueMessage(from, TXT_TYPE_PLAIN, pkt, sender_timestamp, NULL, 0, text);
} }
void onCommandDataRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { void onCommandDataRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override {
markConnectionActive(from); // in case this is from a server, and we have a connection markConnectionActive(from); // in case this is from a server, and we have a connection
queueMessage(from, TXT_TYPE_CLI_DATA, path_len, sender_timestamp, NULL, 0, text); queueMessage(from, TXT_TYPE_CLI_DATA, pkt, sender_timestamp, NULL, 0, text);
} }
void onSignedMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { void onSignedMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override {
markConnectionActive(from); markConnectionActive(from);
saveContacts(); // from.sync_since change needs to be persisted saveContacts(); // from.sync_since change needs to be persisted
queueMessage(from, TXT_TYPE_SIGNED_PLAIN, path_len, sender_timestamp, sender_prefix, 4, text); queueMessage(from, TXT_TYPE_SIGNED_PLAIN, pkt, sender_timestamp, sender_prefix, 4, text);
} }
void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) override { void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) override {
int i = 0; int i = 0;
out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV; if (app_target_ver >= 3) {
out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV_V3;
out_frame[i++] = (int8_t)(pkt->getSNR() * 4);
out_frame[i++] = 0; // reserved1
out_frame[i++] = 0; // reserved2
} else {
out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV;
}
out_frame[i++] = 0; // FUTURE: channel_idx (will just be 'public' for now) out_frame[i++] = 0; // FUTURE: channel_idx (will just be 'public' for now)
out_frame[i++] = in_path_len < 0 ? 0xFF : in_path_len; uint8_t path_len = out_frame[i++] = pkt->isRouteFlood() ? pkt->path_len : 0xFF;
out_frame[i++] = TXT_TYPE_PLAIN; out_frame[i++] = TXT_TYPE_PLAIN;
memcpy(&out_frame[i], &timestamp, 4); i += 4; memcpy(&out_frame[i], &timestamp, 4); i += 4;
int tlen = strlen(text); // TODO: UTF-8 ?? int tlen = strlen(text); // TODO: UTF-8 ??
@@ -538,7 +555,7 @@ protected:
soundBuzzer(); soundBuzzer();
} }
#ifdef DISPLAY_CLASS #ifdef DISPLAY_CLASS
ui_task.showMsgPreview(in_path_len < 0 ? 0xFF : in_path_len, "Public", text); ui_task.showMsgPreview(path_len, "Public", text);
#endif #endif
} }

View File

@@ -254,8 +254,8 @@ protected:
return false; return false;
} }
void onMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { void onMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override {
Serial.printf("(%s) MSG -> from %s\n", path_len == 0xFF ? "DIRECT" : "FLOOD", from.name); Serial.printf("(%s) MSG -> from %s\n", pkt->isRouteDirect() ? "DIRECT" : "FLOOD", from.name);
Serial.printf(" %s\n", text); Serial.printf(" %s\n", text);
if (strcmp(text, "clock sync") == 0) { // special text command if (strcmp(text, "clock sync") == 0) { // special text command
@@ -263,16 +263,16 @@ protected:
} }
} }
void onCommandDataRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const char *text) override { void onCommandDataRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) override {
} }
void onSignedMessageRecv(const ContactInfo& from, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override { void onSignedMessageRecv(const ContactInfo& from, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) override {
} }
void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) override { void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) override {
if (in_path_len < 0) { if (pkt->isRouteDirect()) {
Serial.printf("PUBLIC CHANNEL MSG -> (Direct!)\n"); Serial.printf("PUBLIC CHANNEL MSG -> (Direct!)\n");
} else { } else {
Serial.printf("PUBLIC CHANNEL MSG -> (Flood) hops %d\n", in_path_len); Serial.printf("PUBLIC CHANNEL MSG -> (Flood) hops %d\n", pkt->path_len);
} }
Serial.printf(" %s\n", text); Serial.printf(" %s\n", text);
} }

View File

@@ -105,7 +105,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
data[len] = 0; // need to make a C string again, with null terminator data[len] = 0; // need to make a C string again, with null terminator
if (flags == TXT_TYPE_PLAIN) { if (flags == TXT_TYPE_PLAIN) {
onMessageRecv(from, packet->isRouteFlood() ? packet->path_len : 0xFF, timestamp, (const char *) &data[5]); // let UI know onMessageRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know
uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it
mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE); mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE);
@@ -126,7 +126,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
} }
} }
} else if (flags == TXT_TYPE_CLI_DATA) { } else if (flags == TXT_TYPE_CLI_DATA) {
onCommandDataRecv(from, packet->isRouteFlood() ? packet->path_len : 0xFF, timestamp, (const char *) &data[5]); // let UI know onCommandDataRecv(from, packet, timestamp, (const char *) &data[5]); // let UI know
// NOTE: no ack expected for CLI_DATA replies // NOTE: no ack expected for CLI_DATA replies
if (packet->isRouteFlood()) { if (packet->isRouteFlood()) {
@@ -138,7 +138,7 @@ void BaseChatMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender
if (timestamp > from.sync_since) { // make sure 'sync_since' is up-to-date if (timestamp > from.sync_since) { // make sure 'sync_since' is up-to-date
from.sync_since = timestamp; from.sync_since = timestamp;
} }
onSignedMessageRecv(from, packet->isRouteFlood() ? packet->path_len : 0xFF, timestamp, &data[5], (const char *) &data[9]); // let UI know onSignedMessageRecv(from, packet, timestamp, &data[5], (const char *) &data[9]); // let UI know
uint32_t ack_hash; // calc truncated hash of the message timestamp + text + OUR pub_key, to prove to sender that we got it uint32_t ack_hash; // calc truncated hash of the message timestamp + text + OUR pub_key, to prove to sender that we got it
mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 9 + strlen((char *)&data[9]), self_id.pub_key, PUB_KEY_SIZE); mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 9 + strlen((char *)&data[9]), self_id.pub_key, PUB_KEY_SIZE);
@@ -266,7 +266,7 @@ void BaseChatMesh::onGroupDataRecv(mesh::Packet* packet, uint8_t type, const mes
data[len] = 0; // need to make a C string again, with null terminator data[len] = 0; // need to make a C string again, with null terminator
// notify UI of this new message // notify UI of this new message
onChannelMessageRecv(channel, packet->isRouteFlood() ? packet->path_len : -1, timestamp, (const char *) &data[5]); // let UI know onChannelMessageRecv(channel, packet, timestamp, (const char *) &data[5]); // let UI know
} }
} }

View File

@@ -100,13 +100,13 @@ protected:
virtual void onDiscoveredContact(ContactInfo& contact, bool is_new) = 0; virtual void onDiscoveredContact(ContactInfo& contact, bool is_new) = 0;
virtual bool processAck(const uint8_t *data) = 0; virtual bool processAck(const uint8_t *data) = 0;
virtual void onContactPathUpdated(const ContactInfo& contact) = 0; virtual void onContactPathUpdated(const ContactInfo& contact) = 0;
virtual void onMessageRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const char *text) = 0; virtual void onMessageRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) = 0;
virtual void onCommandDataRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const char *text) = 0; virtual void onCommandDataRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const char *text) = 0;
virtual void onSignedMessageRecv(const ContactInfo& contact, uint8_t path_len, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) = 0; virtual void onSignedMessageRecv(const ContactInfo& contact, mesh::Packet* pkt, uint32_t sender_timestamp, const uint8_t *sender_prefix, const char *text) = 0;
virtual uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const = 0; virtual uint32_t calcFloodTimeoutMillisFor(uint32_t pkt_airtime_millis) const = 0;
virtual uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const = 0; virtual uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const = 0;
virtual void onSendTimeout() = 0; virtual void onSendTimeout() = 0;
virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) = 0; virtual void onChannelMessageRecv(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t timestamp, const char *text) = 0;
virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0; virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
virtual void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) = 0; virtual void onContactTraceRecv(const ContactInfo& contact, uint32_t sender_timestamp, const uint8_t hash[], int8_t snr[], uint8_t path_len) = 0;