diff --git a/TODO.md b/TODO.md index 15e825f8..e2f3e6c7 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,8 @@ # High priority Items to complete before the first alpha release. +* rx signal measurements -3 marginal, -9 bad, 10 great +* only send 10% of phone gps positions on the network * post sample video to signal forum * support non US frequencies * make an install script to let novices install software on their boards @@ -177,4 +179,5 @@ Items after the first final candidate release. * update local GPS position (but do not broadcast) at whatever rate the GPS is giving it * don't send our times to other nodes * don't trust times from other nodes -* draw compass rose based off local walking track \ No newline at end of file +* draw compass rose based off local walking track +* add requestResponse optional bool - use for location broadcasts when sending tests \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index f0157a76..3a652f73 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,7 +58,7 @@ lib_deps = ; RadioHead - I now use a custom build of this library ; file:///home/kevinh/development/meshtastic/RadioHead TinyGPSPlus - ESP8266_SSD1306 + https://github.com/geeksville/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 AXP202X_Library SPI OneButton diff --git a/src/GPS.cpp b/src/GPS.cpp index c0521508..e59b45c5 100644 --- a/src/GPS.cpp +++ b/src/GPS.cpp @@ -5,9 +5,9 @@ // stuff that really should be in in the instance instead... HardwareSerial _serial_gps(GPS_SERIAL_NUM); -uint32_t timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time -uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock -bool timeSetFromGPS; // We only reset our time once per wake +uint32_t timeStartMsec; // Once we have a GPS lock, this is where we hold the initial msec clock that corresponds to that time +uint64_t zeroOffsetSecs; // GPS based time in secs since 1970 - only updated once on initial lock +bool timeSetFromGPS; // We only reset our time once per wake GPS gps; @@ -50,6 +50,8 @@ void GPS::perhapsSetRTC(const struct timeval *tv) } } +#include + // for the time being we need to rapidly read from the serial port to prevent overruns void GPS::loop() { @@ -65,11 +67,20 @@ void GPS::loop() { struct timeval tv; - // FIXME, this is a shit not right version of the standard def of unix time!!! - tv.tv_sec = time.second() + time.minute() * 60 + time.hour() * 60 * 60 + - 24 * 60 * 60 * (date.month() * 31 + date.day() + 365 * (date.year() - 1970)); - - tv.tv_usec = time.centisecond() * (10 / 1000); + /* Convert to unix time + The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z). + */ + struct tm t; + t.tm_sec = time.second(); + t.tm_min = time.minute(); + t.tm_hour = time.hour(); + t.tm_mday = date.day(); + t.tm_mon = date.month() - 1; + t.tm_year = date.year() - 1900; + t.tm_isdst = false; + time_t res = mktime(&t); + tv.tv_sec = res; + tv.tv_usec = 0; // time.centisecond() * (10 / 1000); perhapsSetRTC(&tv); } diff --git a/src/MeshService.cpp b/src/MeshService.cpp index 17c56bd6..271ed03b 100644 --- a/src/MeshService.cpp +++ b/src/MeshService.cpp @@ -145,6 +145,9 @@ void MeshService::handleFromRadio(MeshPacket *mp) releaseToPool(d); } assert(toPhoneQueue.enqueue(mp, 0) == pdTRUE); // FIXME, instead of failing for full queue, delete the oldest mssages + + if(mp->payload.want_response) + sendNetworkPing(mp->from); } else DEBUG_MSG("Dropping vetoed User message\n"); @@ -206,7 +209,7 @@ void MeshService::handleToRadio(std::string s) // FIXME, this is a shit not right version of the standard def of unix time!!! tv.tv_sec = secs; - tv.tv_usec = 0; + tv.tv_usec = 0; gps.perhapsSetRTC(&tv); } @@ -237,12 +240,18 @@ void MeshService::sendToMesh(MeshPacket *p) nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...) // 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) - if(p->has_payload && p->payload.which_variant == SubPacket_position_tag) - p->payload.variant.position.time = 0; + if (p->has_payload && p->payload.which_variant == SubPacket_position_tag) + p->payload.variant.position.time = 0; - // Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it - if (radio.send(p) != ERRNO_OK) - DEBUG_MSG("Dropped packet because send queue was full!\n"); + // If the phone sent a packet just to us, don't send it out into the network + if (p->to == nodeDB.getNodeNum()) + DEBUG_MSG("Dropping locally processed message\n"); + else + { + // Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it + if (radio.send(p) != ERRNO_OK) + DEBUG_MSG("Dropped packet because send queue was full!\n"); + } } MeshPacket *MeshService::allocForSending() @@ -257,18 +266,18 @@ MeshPacket *MeshService::allocForSending() return p; } -void MeshService::sendNetworkPing() +void MeshService::sendNetworkPing(NodeNum dest) { NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); assert(node); if (node->has_position) - sendOurPosition(); + sendOurPosition(dest); else - sendOurOwner(); + sendOurOwner(dest); } -void MeshService::sendOurPosition() +void MeshService::sendOurPosition(NodeNum dest) { NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum()); assert(node); @@ -276,6 +285,7 @@ void MeshService::sendOurPosition() // 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->payload.which_variant = SubPacket_position_tag; p->payload.variant.position = node->position; // FIXME - for now we are leaving this in the sent packets (for debugging) diff --git a/src/MeshService.h b/src/MeshService.h index cd7c6a87..005e1af0 100644 --- a/src/MeshService.h +++ b/src/MeshService.h @@ -61,13 +61,13 @@ public: MeshPacket *allocForSending(); /// Called when the user wakes up our GUI, normally sends our latest location to the mesh (if we have it), otherwise at least sends our owner - void sendNetworkPing(); + void sendNetworkPing(NodeNum dest = NODENUM_BROADCAST); /// Send our owner info to a particular node void sendOurOwner(NodeNum dest = NODENUM_BROADCAST); private: /// Broadcasts our last known position - void sendOurPosition(); + void sendOurPosition(NodeNum dest = NODENUM_BROADCAST); /// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after sending. /// This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb cache diff --git a/src/mesh.pb.h b/src/mesh.pb.h index b9322f9c..58c58326 100644 --- a/src/mesh.pb.h +++ b/src/mesh.pb.h @@ -106,6 +106,7 @@ typedef struct _SubPacket { Data data; User user; } variant; + bool want_response; } SubPacket; typedef struct _MeshPacket { @@ -170,7 +171,7 @@ typedef struct _ToRadio { #define Position_init_default {0, 0, 0, 0, 0, 0} #define Data_init_default {_Data_Type_MIN, {0, {0}}} #define User_init_default {"", "", "", {0}} -#define SubPacket_init_default {0, {Position_init_default}} +#define SubPacket_init_default {0, {Position_init_default}, 0} #define MeshPacket_init_default {0, 0, false, SubPacket_init_default, 0} #define ChannelSettings_init_default {0, 0, _ChannelSettings_ModemConfig_MIN, {0}, ""} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default} @@ -183,7 +184,7 @@ typedef struct _ToRadio { #define Position_init_zero {0, 0, 0, 0, 0, 0} #define Data_init_zero {_Data_Type_MIN, {0, {0}}} #define User_init_zero {"", "", "", {0}} -#define SubPacket_init_zero {0, {Position_init_zero}} +#define SubPacket_init_zero {0, {Position_init_zero}, 0} #define MeshPacket_init_zero {0, 0, false, SubPacket_init_zero, 0} #define ChannelSettings_init_zero {0, 0, _ChannelSettings_ModemConfig_MIN, {0}, ""} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero} @@ -230,6 +231,7 @@ typedef struct _ToRadio { #define SubPacket_position_tag 1 #define SubPacket_data_tag 3 #define SubPacket_user_tag 4 +#define SubPacket_want_response_tag 5 #define MeshPacket_from_tag 1 #define MeshPacket_to_tag 2 #define MeshPacket_payload_tag 3 @@ -273,7 +275,8 @@ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) #define SubPacket_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (variant,position,variant.position), 1) \ X(a, STATIC, ONEOF, MESSAGE, (variant,data,variant.data), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (variant,user,variant.user), 4) +X(a, STATIC, ONEOF, MESSAGE, (variant,user,variant.user), 4) \ +X(a, STATIC, SINGULAR, BOOL, want_response, 5) #define SubPacket_CALLBACK NULL #define SubPacket_DEFAULT NULL #define SubPacket_variant_position_MSGTYPE Position @@ -396,16 +399,16 @@ extern const pb_msgdesc_t ToRadio_msg; #define Position_size 48 #define Data_size 256 #define User_size 72 -#define SubPacket_size 259 -#define MeshPacket_size 290 +#define SubPacket_size 261 +#define MeshPacket_size 292 #define ChannelSettings_size 50 #define RadioConfig_size 78 #define RadioConfig_UserPreferences_size 24 #define NodeInfo_size 157 #define MyNodeInfo_size 24 -#define DeviceState_size 14971 -#define FromRadio_size 299 -#define ToRadio_size 293 +#define DeviceState_size 15037 +#define FromRadio_size 301 +#define ToRadio_size 295 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/screen.cpp b/src/screen.cpp index bcf3f0b1..65b41626 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -320,6 +320,10 @@ float estimatedHeading(double lat, double lon) return b; } +/// Sometimes we will have Position objects that only have a time, so check for valid lat/lon +bool hasPosition(NodeInfo *n) { + return n->has_position && (n->position.latitude != 0 || n->position.longitude != 0); +} #define COMPASS_DIAM 44 /// We will skip one node - the one for us, so we just blindly loop over all nodes @@ -370,7 +374,7 @@ void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, in *distStr = 0; // might not have location data float headingRadian = simRadian; NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum()); - if (ourNode && ourNode->has_position && node->has_position) + if (ourNode && hasPosition(ourNode) && hasPosition(node)) { Position &op = ourNode->position, &p = node->position; float d = latLongToMeter(p.latitude, p.longitude, op.latitude, op.longitude);