sforkowany z mirror/meshtastic-firmware
add support for network ping testing
rodzic
bf347aad91
commit
b9438357b6
5
TODO.md
5
TODO.md
|
@ -1,6 +1,8 @@
|
||||||
# High priority
|
# High priority
|
||||||
Items to complete before the first alpha release.
|
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
|
* post sample video to signal forum
|
||||||
* support non US frequencies
|
* support non US frequencies
|
||||||
* make an install script to let novices install software on their boards
|
* 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
|
* 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 send our times to other nodes
|
||||||
* don't trust times from other nodes
|
* don't trust times from other nodes
|
||||||
* draw compass rose based off local walking track
|
* draw compass rose based off local walking track
|
||||||
|
* add requestResponse optional bool - use for location broadcasts when sending tests
|
|
@ -58,7 +58,7 @@ lib_deps =
|
||||||
; RadioHead - I now use a custom build of this library
|
; RadioHead - I now use a custom build of this library
|
||||||
; file:///home/kevinh/development/meshtastic/RadioHead
|
; file:///home/kevinh/development/meshtastic/RadioHead
|
||||||
TinyGPSPlus
|
TinyGPSPlus
|
||||||
ESP8266_SSD1306
|
https://github.com/geeksville/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||||
AXP202X_Library
|
AXP202X_Library
|
||||||
SPI
|
SPI
|
||||||
OneButton
|
OneButton
|
||||||
|
|
27
src/GPS.cpp
27
src/GPS.cpp
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
// stuff that really should be in in the instance instead...
|
// stuff that really should be in in the instance instead...
|
||||||
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
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
|
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
|
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
|
bool timeSetFromGPS; // We only reset our time once per wake
|
||||||
|
|
||||||
GPS gps;
|
GPS gps;
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ void GPS::perhapsSetRTC(const struct timeval *tv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
// for the time being we need to rapidly read from the serial port to prevent overruns
|
// for the time being we need to rapidly read from the serial port to prevent overruns
|
||||||
void GPS::loop()
|
void GPS::loop()
|
||||||
{
|
{
|
||||||
|
@ -65,11 +67,20 @@ void GPS::loop()
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
// FIXME, this is a shit not right version of the standard def of unix time!!!
|
/* Convert to unix time
|
||||||
tv.tv_sec = time.second() + time.minute() * 60 + time.hour() * 60 * 60 +
|
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).
|
||||||
24 * 60 * 60 * (date.month() * 31 + date.day() + 365 * (date.year() - 1970));
|
*/
|
||||||
|
struct tm t;
|
||||||
tv.tv_usec = time.centisecond() * (10 / 1000);
|
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);
|
perhapsSetRTC(&tv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,9 @@ void MeshService::handleFromRadio(MeshPacket *mp)
|
||||||
releaseToPool(d);
|
releaseToPool(d);
|
||||||
}
|
}
|
||||||
assert(toPhoneQueue.enqueue(mp, 0) == pdTRUE); // FIXME, instead of failing for full queue, delete the oldest mssages
|
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
|
else
|
||||||
DEBUG_MSG("Dropping vetoed User message\n");
|
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!!!
|
// FIXME, this is a shit not right version of the standard def of unix time!!!
|
||||||
tv.tv_sec = secs;
|
tv.tv_sec = secs;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
gps.perhapsSetRTC(&tv);
|
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...)
|
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)
|
// 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)
|
if (p->has_payload && p->payload.which_variant == SubPacket_position_tag)
|
||||||
p->payload.variant.position.time = 0;
|
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 the phone sent a packet just to us, don't send it out into the network
|
||||||
if (radio.send(p) != ERRNO_OK)
|
if (p->to == nodeDB.getNodeNum())
|
||||||
DEBUG_MSG("Dropped packet because send queue was full!\n");
|
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()
|
MeshPacket *MeshService::allocForSending()
|
||||||
|
@ -257,18 +266,18 @@ MeshPacket *MeshService::allocForSending()
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshService::sendNetworkPing()
|
void MeshService::sendNetworkPing(NodeNum dest)
|
||||||
{
|
{
|
||||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
if (node->has_position)
|
if (node->has_position)
|
||||||
sendOurPosition();
|
sendOurPosition(dest);
|
||||||
else
|
else
|
||||||
sendOurOwner();
|
sendOurOwner(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshService::sendOurPosition()
|
void MeshService::sendOurPosition(NodeNum dest)
|
||||||
{
|
{
|
||||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||||
assert(node);
|
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)
|
// Update our local node info with our position (even if we don't decide to update anyone else)
|
||||||
MeshPacket *p = allocForSending();
|
MeshPacket *p = allocForSending();
|
||||||
|
p->to = dest;
|
||||||
p->payload.which_variant = SubPacket_position_tag;
|
p->payload.which_variant = SubPacket_position_tag;
|
||||||
p->payload.variant.position = node->position;
|
p->payload.variant.position = node->position;
|
||||||
// FIXME - for now we are leaving this in the sent packets (for debugging)
|
// FIXME - for now we are leaving this in the sent packets (for debugging)
|
||||||
|
|
|
@ -61,13 +61,13 @@ public:
|
||||||
MeshPacket *allocForSending();
|
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
|
/// 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
|
/// Send our owner info to a particular node
|
||||||
void sendOurOwner(NodeNum dest = NODENUM_BROADCAST);
|
void sendOurOwner(NodeNum dest = NODENUM_BROADCAST);
|
||||||
private:
|
private:
|
||||||
/// Broadcasts our last known position
|
/// 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.
|
/// 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
|
/// This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb cache
|
||||||
|
|
|
@ -106,6 +106,7 @@ typedef struct _SubPacket {
|
||||||
Data data;
|
Data data;
|
||||||
User user;
|
User user;
|
||||||
} variant;
|
} variant;
|
||||||
|
bool want_response;
|
||||||
} SubPacket;
|
} SubPacket;
|
||||||
|
|
||||||
typedef struct _MeshPacket {
|
typedef struct _MeshPacket {
|
||||||
|
@ -170,7 +171,7 @@ typedef struct _ToRadio {
|
||||||
#define Position_init_default {0, 0, 0, 0, 0, 0}
|
#define Position_init_default {0, 0, 0, 0, 0, 0}
|
||||||
#define Data_init_default {_Data_Type_MIN, {0, {0}}}
|
#define Data_init_default {_Data_Type_MIN, {0, {0}}}
|
||||||
#define User_init_default {"", "", "", {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 MeshPacket_init_default {0, 0, false, SubPacket_init_default, 0}
|
||||||
#define ChannelSettings_init_default {0, 0, _ChannelSettings_ModemConfig_MIN, {0}, ""}
|
#define ChannelSettings_init_default {0, 0, _ChannelSettings_ModemConfig_MIN, {0}, ""}
|
||||||
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default, false, ChannelSettings_init_default}
|
#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 Position_init_zero {0, 0, 0, 0, 0, 0}
|
||||||
#define Data_init_zero {_Data_Type_MIN, {0, {0}}}
|
#define Data_init_zero {_Data_Type_MIN, {0, {0}}}
|
||||||
#define User_init_zero {"", "", "", {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 MeshPacket_init_zero {0, 0, false, SubPacket_init_zero, 0}
|
||||||
#define ChannelSettings_init_zero {0, 0, _ChannelSettings_ModemConfig_MIN, {0}, ""}
|
#define ChannelSettings_init_zero {0, 0, _ChannelSettings_ModemConfig_MIN, {0}, ""}
|
||||||
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero, false, ChannelSettings_init_zero}
|
#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_position_tag 1
|
||||||
#define SubPacket_data_tag 3
|
#define SubPacket_data_tag 3
|
||||||
#define SubPacket_user_tag 4
|
#define SubPacket_user_tag 4
|
||||||
|
#define SubPacket_want_response_tag 5
|
||||||
#define MeshPacket_from_tag 1
|
#define MeshPacket_from_tag 1
|
||||||
#define MeshPacket_to_tag 2
|
#define MeshPacket_to_tag 2
|
||||||
#define MeshPacket_payload_tag 3
|
#define MeshPacket_payload_tag 3
|
||||||
|
@ -273,7 +275,8 @@ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4)
|
||||||
#define SubPacket_FIELDLIST(X, a) \
|
#define SubPacket_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, ONEOF, MESSAGE, (variant,position,variant.position), 1) \
|
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,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_CALLBACK NULL
|
||||||
#define SubPacket_DEFAULT NULL
|
#define SubPacket_DEFAULT NULL
|
||||||
#define SubPacket_variant_position_MSGTYPE Position
|
#define SubPacket_variant_position_MSGTYPE Position
|
||||||
|
@ -396,16 +399,16 @@ extern const pb_msgdesc_t ToRadio_msg;
|
||||||
#define Position_size 48
|
#define Position_size 48
|
||||||
#define Data_size 256
|
#define Data_size 256
|
||||||
#define User_size 72
|
#define User_size 72
|
||||||
#define SubPacket_size 259
|
#define SubPacket_size 261
|
||||||
#define MeshPacket_size 290
|
#define MeshPacket_size 292
|
||||||
#define ChannelSettings_size 50
|
#define ChannelSettings_size 50
|
||||||
#define RadioConfig_size 78
|
#define RadioConfig_size 78
|
||||||
#define RadioConfig_UserPreferences_size 24
|
#define RadioConfig_UserPreferences_size 24
|
||||||
#define NodeInfo_size 157
|
#define NodeInfo_size 157
|
||||||
#define MyNodeInfo_size 24
|
#define MyNodeInfo_size 24
|
||||||
#define DeviceState_size 14971
|
#define DeviceState_size 15037
|
||||||
#define FromRadio_size 299
|
#define FromRadio_size 301
|
||||||
#define ToRadio_size 293
|
#define ToRadio_size 295
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
|
|
@ -320,6 +320,10 @@ float estimatedHeading(double lat, double lon)
|
||||||
return b;
|
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
|
#define COMPASS_DIAM 44
|
||||||
|
|
||||||
/// We will skip one node - the one for us, so we just blindly loop over all nodes
|
/// 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
|
*distStr = 0; // might not have location data
|
||||||
float headingRadian = simRadian;
|
float headingRadian = simRadian;
|
||||||
NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum());
|
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;
|
Position &op = ourNode->position, &p = node->position;
|
||||||
float d = latLongToMeter(p.latitude, p.longitude, op.latitude, op.longitude);
|
float d = latLongToMeter(p.latitude, p.longitude, op.latitude, op.longitude);
|
||||||
|
|
Ładowanie…
Reference in New Issue