diff --git a/platformio.ini b/platformio.ini index 644195500..aead63d98 100644 --- a/platformio.ini +++ b/platformio.ini @@ -51,6 +51,7 @@ build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/n ; the default is esptool ; upload_protocol = esp-prog +; monitor_speed = 115200 monitor_speed = 921600 # debug_tool = esp-prog diff --git a/proto b/proto index 3bf195cb2..bc3ecd97e 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 3bf195cb2d60f1d877a89bca87d0c70ea2d01177 +Subproject commit bc3ecd97e381b724c1a28acce0d12c688de73ba3 diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 992144b82..5f4b51bab 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -93,7 +93,7 @@ void MeshService::sendOurOwner(NodeNum dest, bool wantReplies) MeshPacket *p = allocForSending(); p->to = dest; p->decoded.want_response = wantReplies; - p->decoded.has_user = true; + p->decoded.which_payload = SubPacket_user_tag; User &u = p->decoded.user; u = owner; DEBUG_MSG("sending owner %s/%s/%s\n", u.id, u.long_name, u.short_name); @@ -143,7 +143,7 @@ const MeshPacket *MeshService::handleFromRadioUser(const MeshPacket *mp) void MeshService::handleIncomingPosition(const MeshPacket *mp) { - if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.has_position) { + if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.which_payload == SubPacket_position_tag) { DEBUG_MSG("handled incoming position time=%u\n", mp->decoded.position.time); if (mp->decoded.position.time) { @@ -171,7 +171,7 @@ int MeshService::handleFromRadio(const MeshPacket *mp) DEBUG_MSG("Ignoring incoming time, because we have a GPS\n"); } - if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.has_user) { + if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.which_payload == SubPacket_user_tag) { mp = handleFromRadioUser(mp); } @@ -257,7 +257,7 @@ void MeshService::sendToMesh(MeshPacket *p) // Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other // nodes shouldn't trust it anyways) Note: for now, we allow a device with a local GPS to include the time, so that gpsless // devices can get time. - if (p->which_payload == MeshPacket_decoded_tag && p->decoded.has_position) { + if (p->which_payload == MeshPacket_decoded_tag && p->decoded.which_payload == SubPacket_position_tag) { if (!gps->isConnected) { DEBUG_MSG("Stripping time %u from position send\n", p->decoded.position.time); p->decoded.position.time = 0; @@ -312,7 +312,7 @@ void MeshService::sendOurPosition(NodeNum dest, bool wantReplies) // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = allocForSending(); p->to = dest; - p->decoded.has_position = true; + p->decoded.which_payload = SubPacket_position_tag; p->decoded.position = node->position; p->decoded.want_response = wantReplies; p->decoded.position.time = getValidTime(); // This nodedb timestamp might be stale, so update it if our clock is valid. @@ -325,7 +325,7 @@ int MeshService::onGPSChanged(void *unused) // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = allocForSending(); - p->decoded.has_position = true; + p->decoded.which_payload = SubPacket_position_tag; Position &pos = p->decoded.position; // !zero or !zero lat/long means valid diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 8fe82b822..5d2e8ecd3 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -296,16 +296,18 @@ void NodeDB::updateFrom(const MeshPacket &mp) info->snr = mp.rx_snr; // keep the most recent SNR we received for this node. - if (p.has_position) { + switch (p.which_payload) { + case SubPacket_position_tag: { // we carefully preserve the old time, because we always trust our local timestamps more uint32_t oldtime = info->position.time; info->position = p.position; info->position.time = oldtime; info->has_position = true; updateGUIforNode = info; + break; } - if (p.has_data) { + case SubPacket_data_tag: { // Keep a copy of the most recent text message. if (p.data.typ == Data_Type_CLEAR_TEXT) { DEBUG_MSG("Received text msg from=0x%0x, id=%d, msg=%.*s\n", mp.from, mp.id, p.data.payload.size, @@ -318,9 +320,10 @@ void NodeDB::updateFrom(const MeshPacket &mp) powerFSM.trigger(EVENT_RECEIVED_TEXT_MSG); } } + break; } - if (p.has_user) { + case SubPacket_user_tag: { DEBUG_MSG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name); bool changed = memcmp(&info->user, &p.user, @@ -338,6 +341,8 @@ void NodeDB::updateFrom(const MeshPacket &mp) // We just changed something important about the user, store our DB // saveToDisk(); } + break; + } } } } diff --git a/src/mesh/PacketHistory.h b/src/mesh/PacketHistory.h index 3a182caeb..22470f4fc 100644 --- a/src/mesh/PacketHistory.h +++ b/src/mesh/PacketHistory.h @@ -1,7 +1,10 @@ #pragma once #include "Router.h" -#include +#include +#include + +using namespace std; /** * A record of a recent message broadcast @@ -10,6 +13,34 @@ struct PacketRecord { NodeNum sender; PacketId id; uint32_t rxTimeMsec; // Unix time in msecs - the time we received it + + bool operator==(const PacketRecord &p) const { return sender == p.sender && id == p.id; } +}; + +class PacketRecordHashFunction +{ + public: + size_t operator()(const PacketRecord &p) const { return (hash()(p.sender)) ^ (hash()(p.id)); } +}; + +/// Order packet records by arrival time, we want the oldest packets to be in the front of our heap +class PacketRecordOrderFunction +{ + public: + size_t operator()(const PacketRecord &p1, const PacketRecord &p2) const + { + // If the timer ticks have rolled over the difference between times will be _enormous_. Handle that case specially + uint32_t t1 = p1.rxTimeMsec, t2 = p2.rxTimeMsec; + + if (abs(t1 - t2) > + UINT32_MAX / + 2) { // time must have rolled over, swap them because the new little number is 'bigger' than the old big number + t1 = t2; + t2 = p1.rxTimeMsec; + } + + return t1 > t2; + } }; /** @@ -21,7 +52,9 @@ class PacketHistory /** FIXME: really should be a std::unordered_set with the key being sender,id. * This would make checking packets in wasSeenRecently faster. */ - std::vector recentPackets; + vector recentPackets; + // priority_queue, PacketRecordOrderFunction> arrivalTimes; + // unordered_set recentPackets; public: PacketHistory(); diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index d8a2e1fd5..d193d38ee 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -116,18 +116,15 @@ typedef struct _RadioConfig { } RadioConfig; typedef struct _SubPacket { - bool has_position; - Position position; - bool has_data; - Data data; - bool has_user; - User user; - bool want_response; - pb_size_t which_route; + pb_size_t which_payload; union { + Position position; + Data data; + User user; RouteDiscovery request; RouteDiscovery reply; - } route; + }; + bool want_response; uint32_t dest; pb_size_t which_ack; union { @@ -211,7 +208,7 @@ typedef struct _ToRadio { #define Data_init_default {_Data_Type_MIN, {0, {0}}} #define User_init_default {"", "", "", {0}} #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_default {false, Position_init_default, false, Data_init_default, false, User_init_default, 0, 0, {RouteDiscovery_init_default}, 0, 0, {0}} +#define SubPacket_init_default {0, {Position_init_default}, 0, 0, 0, {0}} #define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, ""} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} @@ -226,7 +223,7 @@ typedef struct _ToRadio { #define Data_init_zero {_Data_Type_MIN, {0, {0}}} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_zero {false, Position_init_zero, false, Data_init_zero, false, User_init_zero, 0, 0, {RouteDiscovery_init_zero}, 0, 0, {0}} +#define SubPacket_init_zero {0, {Position_init_zero}, 0, 0, 0, {0}} #define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, ""} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} @@ -285,13 +282,13 @@ typedef struct _ToRadio { #define NodeInfo_next_hop_tag 5 #define RadioConfig_preferences_tag 1 #define RadioConfig_channel_settings_tag 2 -#define SubPacket_success_id_tag 10 -#define SubPacket_fail_id_tag 11 -#define SubPacket_request_tag 6 -#define SubPacket_reply_tag 7 #define SubPacket_position_tag 1 #define SubPacket_data_tag 3 #define SubPacket_user_tag 4 +#define SubPacket_request_tag 6 +#define SubPacket_reply_tag 7 +#define SubPacket_success_id_tag 10 +#define SubPacket_fail_id_tag 11 #define SubPacket_want_response_tag 5 #define SubPacket_dest_tag 9 #define MeshPacket_decoded_tag 3 @@ -352,22 +349,22 @@ X(a, STATIC, REPEATED, INT32, route, 2) #define RouteDiscovery_DEFAULT NULL #define SubPacket_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, position, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, data, 3) \ -X(a, STATIC, OPTIONAL, MESSAGE, user, 4) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,position,position), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,data,data), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,user,user), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,request,request), 6) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,reply,reply), 7) \ X(a, STATIC, SINGULAR, BOOL, want_response, 5) \ -X(a, STATIC, ONEOF, MESSAGE, (route,request,route.request), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (route,reply,route.reply), 7) \ X(a, STATIC, SINGULAR, UINT32, dest, 9) \ X(a, STATIC, ONEOF, UINT32, (ack,success_id,ack.success_id), 10) \ X(a, STATIC, ONEOF, UINT32, (ack,fail_id,ack.fail_id), 11) #define SubPacket_CALLBACK NULL #define SubPacket_DEFAULT NULL -#define SubPacket_position_MSGTYPE Position -#define SubPacket_data_MSGTYPE Data -#define SubPacket_user_MSGTYPE User -#define SubPacket_route_request_MSGTYPE RouteDiscovery -#define SubPacket_route_reply_MSGTYPE RouteDiscovery +#define SubPacket_payload_position_MSGTYPE Position +#define SubPacket_payload_data_MSGTYPE Data +#define SubPacket_payload_user_MSGTYPE User +#define SubPacket_payload_request_MSGTYPE RouteDiscovery +#define SubPacket_payload_reply_MSGTYPE RouteDiscovery #define MeshPacket_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, from, 1) \ @@ -527,17 +524,17 @@ extern const pb_msgdesc_t ToRadio_msg; #define Data_size 256 #define User_size 72 #define RouteDiscovery_size 88 -#define SubPacket_size 478 -#define MeshPacket_size 515 +#define SubPacket_size 273 +#define MeshPacket_size 310 #define ChannelSettings_size 60 #define RadioConfig_size 136 #define RadioConfig_UserPreferences_size 72 #define NodeInfo_size 132 #define MyNodeInfo_size 85 -#define DeviceState_size 21720 +#define DeviceState_size 14955 #define DebugString_size 258 -#define FromRadio_size 524 -#define ToRadio_size 518 +#define FromRadio_size 319 +#define ToRadio_size 313 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/screen.cpp b/src/screen.cpp index c60907aa8..dd2f99c07 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -94,7 +94,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state // the max length of this buffer is much longer than we can possibly print static char tempBuf[96]; - assert(mp.decoded.has_data); + assert(mp.decoded.which_payload == SubPacket_data_tag); snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.data.payload.bytes); display->drawStringMaxWidth(4 + x, 10 + y, 128, tempBuf);