progress on keeping gps off more

1.2-legacy
geeksville 2020-02-19 10:53:09 -08:00
rodzic d9a875082c
commit cd4cd6fe56
8 zmienionych plików z 95 dodań i 40 usunięć

Wyświetl plik

@ -34,4 +34,5 @@ is optional, but highly recommended.
We don't yet distribute prebuilt binaries. But soon (by Feb 22) we will have a file that you can easily install on your radio via USB. Once our software is installed, all future software updates happen over bluetooth from your phone.
For a nice 3D printable case see this [design](https://www.thingiverse.com/thing:3773717) by [bsiege](https://www.thingiverse.com/bsiege).
For a nice TTGO 3D printable case see this [design](https://www.thingiverse.com/thing:3773717) by [bsiege](https://www.thingiverse.com/bsiege).
For a nice Heltec 3D printable case see this [design](https://www.thingiverse.com/thing:3125854) by [ornotermes](https://www.thingiverse.com/ornotermes).

Wyświetl plik

@ -6,7 +6,7 @@
// 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 zeroOffset; // GPS based time in millis 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
GPS gps;
@ -34,7 +34,19 @@ void GPS::readFromRTC()
DEBUG_MSG("Read RTC time as %ld (cur millis %u)\n", tv.tv_sec, now);
timeStartMsec = now;
zeroOffset = tv.tv_sec * 1000LL + tv.tv_usec / 1000LL;
zeroOffsetSecs = tv.tv_sec;
}
}
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
void GPS::perhapsSetRTC(const struct timeval *tv)
{
if (!timeSetFromGPS)
{
timeSetFromGPS = true;
DEBUG_MSG("Setting RTC %ld secs\n", tv->tv_sec);
settimeofday(tv, NULL);
readFromRTC();
}
}
@ -51,8 +63,6 @@ void GPS::loop()
if (!timeSetFromGPS && time.isValid() && date.isValid())
{
timeSetFromGPS = true;
struct timeval tv;
// FIXME, this is a shit not right version of the standard def of unix time!!!
@ -61,16 +71,19 @@ void GPS::loop()
tv.tv_usec = time.centisecond() * (10 / 1000);
DEBUG_MSG("Setting RTC %ld secs\n", tv.tv_sec);
settimeofday(&tv, NULL);
readFromRTC();
perhapsSetRTC(&tv);
}
#endif
}
uint64_t GPS::getTime()
uint32_t GPS::getTime()
{
return ((uint64_t)millis() - timeStartMsec) + zeroOffset;
return ((millis() - timeStartMsec) / 1000) + zeroOffsetSecs;
}
uint32_t GPS::getValidTime()
{
return timeSetFromGPS ? getTime() : 0;
}
void GPS::doTask()

Wyświetl plik

@ -3,6 +3,7 @@
#include <TinyGPS++.h>
#include "PeriodicTask.h"
#include "Observer.h"
#include "sys/time.h"
/**
* A gps class that only reads from the GPS periodically (and FIXME - eventually keeps the gps powered down except when reading)
@ -14,8 +15,11 @@ class GPS : public PeriodicTask, public Observable, public TinyGPSPlus
public:
GPS();
/// Return time since 1970 in msecs. Until we have a GPS lock we will be returning time based at zero
uint64_t getTime();
/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero
uint32_t getTime();
/// Return time since 1970 in secs. If we don't have a GPS lock return zero
uint32_t getValidTime();
String getTimeStr();
@ -25,6 +29,9 @@ public:
virtual void doTask();
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
void perhapsSetRTC(const struct timeval *tv);
private:
void readFromRTC();
};

Wyświetl plik

@ -64,17 +64,18 @@ public:
void onRead(BLECharacteristic *c)
{
DEBUG_MSG("Got nodeinfo read\n");
const NodeInfo *info = nodeDB.readNextInfo();
if (info)
{
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->position.time, info->user.id, info->user.long_name);
size_t numbytes = pb_encode_to_bytes(trBytes, sizeof(trBytes), NodeInfo_fields, info);
c->setValue(trBytes, numbytes);
}
else
{
c->setValue(trBytes, 0); // Send an empty response
DEBUG_MSG("Done sending nodeinfos\n");
}
}

Wyświetl plik

@ -122,7 +122,7 @@ MeshPacket *MeshService::handleFromRadioUser(MeshPacket *mp)
void MeshService::handleFromRadio(MeshPacket *mp)
{
mp->rx_time = gps.getTime() / 1000; // store the arrival timestamp for the phone
mp->rx_time = gps.getValidTime(); // store the arrival timestamp for the phone
if (mp->has_payload && mp->payload.which_variant == SubPacket_user_tag)
{
@ -132,6 +132,7 @@ void MeshService::handleFromRadio(MeshPacket *mp)
// If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it)
if (mp)
{
DEBUG_MSG("Forwarding to phone, from=0x%x, rx_time=%u\n", mp->from, mp->rx_time);
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
fromNum++;
@ -197,6 +198,25 @@ void MeshService::handleToRadio(std::string s)
{
case ToRadio_packet_tag:
{
// If our phone is sending a position, see if we can use it to set our RTC
if (r.variant.packet.has_payload && r.variant.packet.payload.which_variant == SubPacket_position_tag && r.variant.packet.payload.variant.position.time)
{
struct timeval tv;
uint32_t msecs = r.variant.packet.payload.variant.position.time;
// FIXME, this is a shit not right version of the standard def of unix time!!!
tv.tv_sec = msecs / 1000;
tv.tv_usec = (msecs % 1000) * 1000; // scale only the msecs portion of the timestamp (i.e. remainder after dividing by 1s)
gps.perhapsSetRTC(&tv);
// leave in for now FIXME
// r.variant.packet.payload.variant.position.time = 0; // Set it to the default value so that we don't waste bytes broadcasting it (other nodes will use their own time)
}
r.variant.packet.rx_time = gps.getValidTime(); // Record the time the packet arrived from the phone (so we update our nodedb for the local node)
// Send the packet into the mesh
sendToMesh(packetPool.allocCopy(r.variant.packet));
bool loopback = false; // if true send any packet the phone sends back itself (for testing)
@ -220,7 +240,7 @@ void MeshService::sendToMesh(MeshPacket *p)
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
// 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)
if (radio.send(p) != ERRNO_OK)
DEBUG_MSG("Dropped packet because send queue was full!\n");
}
@ -231,7 +251,7 @@ MeshPacket *MeshService::allocForSending()
p->has_payload = true;
p->from = nodeDB.getNodeNum();
p->to = NODENUM_BROADCAST;
p->rx_time = gps.getTime() / 1000; // Just in case we process the packet locally - make sure it has a valid timestamp
p->rx_time = gps.getValidTime(); // Just in case we process the packet locally - make sure it has a valid timestamp
return p;
}
@ -257,6 +277,8 @@ void MeshService::sendOurPosition()
MeshPacket *p = allocForSending();
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)
//p->payload.variant.position.time = 0; // No need to send time, other node won't trust it anyways
sendToMesh(p);
}
@ -270,6 +292,7 @@ void MeshService::onGPSChanged()
pos.altitude = gps.altitude.meters();
pos.latitude = gps.location.lat();
pos.longitude = gps.location.lng();
pos.time = gps.getValidTime();
// We limit our GPS broadcasts to a max rate
static uint32_t lastGpsSend;

Wyświetl plik

@ -76,7 +76,6 @@ void NodeDB::init()
NodeInfo *info = getOrCreateNode(getNodeNum());
info->user = owner;
info->has_user = true;
info->last_seen = 0; // haven't heard a real message yet
if (!FS.begin(true)) // FIXME - do this in main?
{
@ -198,9 +197,10 @@ const NodeInfo *NodeDB::readNextInfo()
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const NodeInfo *n)
{
uint32_t now = gps.getTime() / 1000;
uint32_t now = gps.getTime();
int delta = (int)(now - n->last_seen);
uint32_t last_seen = n->position.time;
int delta = (int)(now - last_seen);
if (delta < 0) // our clock must be slightly off still - not set from GPS yet
delta = 0;
@ -236,16 +236,23 @@ void NodeDB::updateFrom(const MeshPacket &mp)
if (oldNumNodes != *numNodes)
updateGUI = true; // we just created a nodeinfo
if (mp.rx_time) // if the packet has a valid timestamp use it
info->last_seen = mp.rx_time;
if (mp.rx_time)
{ // if the packet has a valid timestamp use it to update our last_seen
info->has_position = true; // at least the time is valid
info->position.time = mp.rx_time;
}
switch (p.which_variant)
{
case SubPacket_position_tag:
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.variant.position;
info->position.time = oldtime;
info->has_position = true;
updateGUIforNode = info;
break;
}
case SubPacket_data_tag:
{

Wyświetl plik

@ -43,8 +43,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Select which board is being used. If the outside build environment has sent a choice, just use that
#if !defined(T_BEAM_V10) && !defined(HELTEC_LORA32)
#define T_BEAM_V10 // AKA Rev1 (second board released)
//#define HELTEC_LORA32
//#define T_BEAM_V10 // AKA Rev1 (second board released)
#define HELTEC_LORA32
#define HW_VERSION_US // We encode the hardware freq range in the hw version string, so sw update can eventually install the correct build
#endif

Wyświetl plik

@ -33,8 +33,8 @@ typedef enum _ChannelSettings_ModemConfig {
typedef enum _DeviceState_Version {
DeviceState_Version_Unset = 0,
DeviceState_Version_Minimum = 13,
DeviceState_Version_Current = 13
DeviceState_Version_Minimum = 15,
DeviceState_Version_Current = 15
} DeviceState_Version;
/* Struct definitions */
@ -64,11 +64,13 @@ typedef struct _Position {
int32_t altitude;
int32_t battery_level;
bool from_hardware;
uint32_t time;
} Position;
typedef struct _RadioConfig_UserPreferences {
uint32_t position_broadcast_secs;
uint32_t send_owner_secs;
uint32_t num_missed_to_fail;
bool keep_all_packets;
bool promiscuous_mode;
} RadioConfig_UserPreferences;
@ -86,7 +88,6 @@ typedef struct _NodeInfo {
User user;
bool has_position;
Position position;
uint32_t last_seen;
int32_t snr;
int32_t frequency_error;
} NodeInfo;
@ -166,28 +167,28 @@ typedef struct _ToRadio {
/* Initializer values for message structs */
#define Position_init_default {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 User_init_default {"", "", "", {0}}
#define SubPacket_init_default {0, {Position_init_default}}
#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}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, 0}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
#define MyNodeInfo_init_default {0, 0, 0}
#define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default}, _DeviceState_Version_MIN, false, MeshPacket_init_default}
#define FromRadio_init_default {0, 0, {MeshPacket_init_default}}
#define ToRadio_init_default {0, {MeshPacket_init_default}}
#define Position_init_zero {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 User_init_zero {"", "", "", {0}}
#define SubPacket_init_zero {0, {Position_init_zero}}
#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}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, 0}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
#define MyNodeInfo_init_zero {0, 0, 0}
#define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero}, _DeviceState_Version_MIN, false, MeshPacket_init_zero}
#define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}}
@ -209,8 +210,10 @@ typedef struct _ToRadio {
#define Position_altitude_tag 3
#define Position_battery_level_tag 4
#define Position_from_hardware_tag 5
#define Position_time_tag 6
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
#define RadioConfig_UserPreferences_send_owner_secs_tag 2
#define RadioConfig_UserPreferences_num_missed_to_fail_tag 3
#define RadioConfig_UserPreferences_keep_all_packets_tag 100
#define RadioConfig_UserPreferences_promiscuous_mode_tag 101
#define User_id_tag 1
@ -220,7 +223,6 @@ typedef struct _ToRadio {
#define NodeInfo_num_tag 1
#define NodeInfo_user_tag 2
#define NodeInfo_position_tag 3
#define NodeInfo_last_seen_tag 4
#define NodeInfo_snr_tag 5
#define NodeInfo_frequency_error_tag 6
#define RadioConfig_preferences_tag 1
@ -249,7 +251,8 @@ X(a, STATIC, SINGULAR, DOUBLE, latitude, 1) \
X(a, STATIC, SINGULAR, DOUBLE, longitude, 2) \
X(a, STATIC, SINGULAR, INT32, altitude, 3) \
X(a, STATIC, SINGULAR, INT32, battery_level, 4) \
X(a, STATIC, SINGULAR, BOOL, from_hardware, 5)
X(a, STATIC, SINGULAR, BOOL, from_hardware, 5) \
X(a, STATIC, SINGULAR, UINT32, time, 6)
#define Position_CALLBACK NULL
#define Position_DEFAULT NULL
@ -306,6 +309,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, channel_settings, 2)
#define RadioConfig_UserPreferences_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \
X(a, STATIC, SINGULAR, UINT32, send_owner_secs, 2) \
X(a, STATIC, SINGULAR, UINT32, num_missed_to_fail, 3) \
X(a, STATIC, SINGULAR, BOOL, keep_all_packets, 100) \
X(a, STATIC, SINGULAR, BOOL, promiscuous_mode, 101)
#define RadioConfig_UserPreferences_CALLBACK NULL
@ -315,7 +319,6 @@ X(a, STATIC, SINGULAR, BOOL, promiscuous_mode, 101)
X(a, STATIC, SINGULAR, INT32, num, 1) \
X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \
X(a, STATIC, SINGULAR, UINT32, last_seen, 4) \
X(a, STATIC, SINGULAR, INT32, snr, 5) \
X(a, STATIC, SINGULAR, INT32, frequency_error, 6)
#define NodeInfo_CALLBACK NULL
@ -390,17 +393,17 @@ extern const pb_msgdesc_t ToRadio_msg;
#define ToRadio_fields &ToRadio_msg
/* Maximum encoded size of messages (where known) */
#define Position_size 42
#define Position_size 48
#define Data_size 256
#define User_size 72
#define SubPacket_size 259
#define MeshPacket_size 290
#define ChannelSettings_size 50
#define RadioConfig_size 72
#define RadioConfig_UserPreferences_size 18
#define RadioConfig_size 78
#define RadioConfig_UserPreferences_size 24
#define NodeInfo_size 157
#define MyNodeInfo_size 24
#define DeviceState_size 14965
#define DeviceState_size 14971
#define FromRadio_size 299
#define ToRadio_size 293