diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index eb8cec1c9f..ce5b18af82 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -611,7 +611,7 @@ int32_t GPS::runOnce() return 2000; // Setup failed, re-run in two seconds // We have now loaded our saved preferences from flash - if (config.position.gps_enabled == false && config.position.fixed_position == false) { + if (config.position.gps_enabled == false) { return disable(); } // ONCE we will factory reset the GPS for bug #327 @@ -703,8 +703,8 @@ int32_t GPS::runOnce() // If state has changed do a publish publishUpdate(); - if (config.position.gps_enabled == false) // This should trigger if GPS is disabled but fixed_position is true - return disable(); + if (config.position.fixed_position == true && hasValidLocation) + return disable(); // This should trigger when we have a fixed position, and get that first position // 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms // if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake. diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index d7fd84fb7f..3b6168f270 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -687,8 +687,8 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou LOG_INFO("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i, p.longitude_i, p.altitude); + setLocalPosition(p); info->position = ConvertToPositionLite(p); - localPosition = p; } else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) { // FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO // (stop-gap fix for issue #900) diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index f906acd589..22d5a77800 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -131,6 +131,13 @@ class NodeDB meshtastic_NodeInfoLite *getMeshNode(NodeNum n); size_t getNumMeshNodes() { return *numMeshNodes; } + void setLocalPosition(meshtastic_Position position) + { + LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i\n", position.latitude_i, position.longitude_i, + position.time); + localPosition = position; + } + private: /// Find a node in our DB, create an empty NodeInfoLite if missing meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n); diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index a7beeda282..445bde42b5 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -44,10 +44,11 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes // FIXME this can in fact happen with packets sent from EUD (src=RX_SRC_USER) // to set fixed location, EUD-GPS location or just the time (see also issue #900) + bool isLocal = false; if (nodeDB.getNodeNum() == getFrom(&mp)) { LOG_DEBUG("Incoming update from MYSELF\n"); - // LOG_DEBUG("Ignored an incoming update from MYSELF\n"); - // return false; + isLocal = true; + nodeDB.setLocalPosition(p); } // Log packet size and data fields @@ -64,7 +65,8 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes tv.tv_sec = secs; tv.tv_usec = 0; - perhapsSetRTC(RTCQualityFromNet, &tv); + // Set from phone RTC Quality to RTCQualityNTP since it should be approximately so + perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv); } nodeDB.updatePosition(getFrom(&mp), p); @@ -94,8 +96,9 @@ meshtastic_MeshPacket *PositionModule::allocReply() // Populate a Position struct with ONLY the requested fields meshtastic_Position p = meshtastic_Position_init_default; // Start with an empty structure + // if localPosition is totally empty, put our last saved position (lite) in there if (localPosition.latitude_i == 0 && localPosition.longitude_i == 0) { - localPosition = ConvertToPosition(node->position); + nodeDB.setLocalPosition(ConvertToPosition(node->position)); } localPosition.seq_number++; @@ -184,6 +187,8 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha } } +#define RUNONCE_INTERVAL 5000; + int32_t PositionModule::runOnce() { if (sleepOnNextExecution == true) { @@ -199,60 +204,58 @@ int32_t PositionModule::runOnce() uint32_t now = millis(); uint32_t intervalMs = getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs); uint32_t msSinceLastSend = now - lastGpsSend; + // Only send packets if the channel util. is less than 25% utilized or we're a tracker with less than 40% utilized. + if (!airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) { + return RUNONCE_INTERVAL; + } if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) { - // Only send packets if the channel is less than 40% utilized. - if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) { - if (hasValidPosition(node)) { - lastGpsSend = now; + if (hasValidPosition(node)) { + lastGpsSend = now; - lastGpsLatitude = node->position.latitude_i; - lastGpsLongitude = node->position.longitude_i; + lastGpsLatitude = node->position.latitude_i; + lastGpsLongitude = node->position.longitude_i; + + // If we changed channels, ask everyone else for their latest info + bool requestReplies = currentGeneration != radioGeneration; + currentGeneration = radioGeneration; + + LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies); + sendOurPosition(NODENUM_BROADCAST, requestReplies); + } + } else if (config.position.position_broadcast_smart_enabled) { + const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position - // If we changed channels, ask everyone else for their latest info + if (hasValidPosition(node2)) { + // The minimum time (in seconds) that would pass before we are able to send a new position packet. + const uint32_t minimumTimeThreshold = + getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30); + + auto smartPosition = getDistanceTraveledSinceLastSend(node->position); + + if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) { bool requestReplies = currentGeneration != radioGeneration; currentGeneration = radioGeneration; - LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies); + LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, " + "minTimeInterval=%ims)\n", + localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, + msSinceLastSend, minimumTimeThreshold); sendOurPosition(NODENUM_BROADCAST, requestReplies); - } - } - } else if (config.position.position_broadcast_smart_enabled) { - // Only send packets if the channel is less than 25% utilized or we're a tracker. - if (airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER)) { - const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position - - if (hasValidPosition(node2)) { - // The minimum time (in seconds) that would pass before we are able to send a new position packet. - const uint32_t minimumTimeThreshold = - getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30); - - auto smartPosition = getDistanceTraveledSinceLastSend(node->position); - - if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) { - bool requestReplies = currentGeneration != radioGeneration; - currentGeneration = radioGeneration; - - LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, " - "minTimeInterval=%ims)\n", - localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, - msSinceLastSend, minimumTimeThreshold); - sendOurPosition(NODENUM_BROADCAST, requestReplies); - - // Set the current coords as our last ones, after we've compared distance with current and decided to send - lastGpsLatitude = node->position.latitude_i; - lastGpsLongitude = node->position.longitude_i; - - /* Update lastGpsSend to now. This means if the device is stationary, then - getPref_position_broadcast_secs will still apply. - */ - lastGpsSend = now; - } + + // Set the current coords as our last ones, after we've compared distance with current and decided to send + lastGpsLatitude = node->position.latitude_i; + lastGpsLongitude = node->position.longitude_i; + + /* Update lastGpsSend to now. This means if the device is stationary, then + getPref_position_broadcast_secs will still apply. + */ + lastGpsSend = now; } } } - return 5000; // to save power only wake for our callback occasionally + return RUNONCE_INTERVAL; // to save power only wake for our callback occasionally } struct SmartPosition PositionModule::getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition) @@ -264,6 +267,23 @@ struct SmartPosition PositionModule::getDistanceTraveledSinceLastSend(meshtastic float distanceTraveledSinceLastSend = GeoCoord::latLongToMeter( lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7, currentPosition.latitude_i * 1e-7, currentPosition.longitude_i * 1e-7); +#ifdef GPS_EXTRAVERBOSE + LOG_DEBUG("--------LAST POSITION------------------------------------\n"); + LOG_DEBUG("lastGpsLatitude=%i, lastGpsLatitude=%i\n", lastGpsLatitude, lastGpsLongitude); + + LOG_DEBUG("--------CURRENT POSITION---------------------------------\n"); + LOG_DEBUG("currentPosition.latitude_i=%i, currentPosition.longitude_i=%i\n", lastGpsLatitude, lastGpsLongitude); + + LOG_DEBUG("--------SMART POSITION-----------------------------------\n"); + LOG_DEBUG("hasTraveledOverThreshold=%i, distanceTraveled=%d, distanceThreshold=% u\n", + abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold, abs(distanceTraveledSinceLastSend), + distanceTravelThreshold); + + if (abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold) { + LOG_DEBUG("\n\n\nSMART SEEEEEEEEENDING\n\n\n"); + } +#endif + return SmartPosition{.distanceTraveled = abs(distanceTraveledSinceLastSend), .distanceThreshold = distanceTravelThreshold, .hasTraveledOverThreshold = abs(distanceTraveledSinceLastSend) >= distanceTravelThreshold}; diff --git a/variants/heltec_wsl_v3/variant.h b/variants/heltec_wsl_v3/variant.h index 240a482f78..417abf34d0 100644 --- a/variants/heltec_wsl_v3/variant.h +++ b/variants/heltec_wsl_v3/variant.h @@ -8,8 +8,6 @@ #define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost #define BUTTON_PIN 0 -#define PIN_GPS_EN 46 // GPS power enable pin - #define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage #define ADC_CHANNEL ADC1_GPIO1_CHANNEL #define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider