LoRa_APRS_Tracker111/src/station_utils.cpp

531 lines
24 KiB
C++

#include <TinyGPS++.h>
#include <SPIFFS.h>
#include "APRSPacketLib.h"
#include "station_utils.h"
#include "configuration.h"
#include "power_utils.h"
#include "lora_utils.h"
#include "bme_utils.h"
#include "display.h"
#include "logger.h"
extern Configuration Config;
extern Beacon *currentBeacon;
extern logging::Logger logger;
extern TinyGPSPlus gps;
extern uint8_t myBeaconsIndex;
extern uint8_t loraIndex;
extern uint32_t lastTx;
extern uint32_t lastTxTime;
extern bool sendUpdate;
extern uint32_t txInterval;
extern double currentHeading;
extern double previousHeading;
extern double lastTxLat;
extern double lastTxLng;
extern double lastTxDistance;
extern bool miceActive;
extern bool smartBeaconValue;
extern uint8_t winlinkStatus;
extern bool winlinkCommentState;
extern int wxModuleType;
bool sendStandingUpdate = false;
uint8_t updateCounter = Config.sendCommentAfterXBeacons;
bool wxRequestStatus = false;
uint32_t wxRequestTime = 0;
uint32_t lastTelemetryTx = 0;
uint32_t telemetryTx = millis();
String firstNearTracker;
String secondNearTracker;
String thirdNearTracker;
String fourthNearTracker;
uint32_t lastDeleteListenedTracker;
namespace STATION_Utils {
const String getFirstNearTracker() {
return String(firstNearTracker.substring(0, firstNearTracker.indexOf(",")));
}
const String getSecondNearTracker() {
return String(secondNearTracker.substring(0, secondNearTracker.indexOf(",")));
}
const String getThirdNearTracker() {
return String(thirdNearTracker.substring(0, thirdNearTracker.indexOf(",")));
}
const String getFourthNearTracker() {
return String(fourthNearTracker.substring(0, fourthNearTracker.indexOf(",")));
}
void deleteListenedTrackersbyTime() {
String firstNearTrackermillis, secondNearTrackermillis, thirdNearTrackermillis, fourthNearTrackermillis;
uint32_t firstTrackermillis, secondTrackermillis, thirdTrackermillis, fourthTrackermillis;
if (firstNearTracker != "") {
firstNearTrackermillis = firstNearTracker.substring(firstNearTracker.indexOf(",") + 1);
firstTrackermillis = firstNearTrackermillis.toInt();
if ((millis() - firstTrackermillis) > Config.rememberStationTime * 60 * 1000) {
firstNearTracker = "";
}
}
if (secondNearTracker != "") {
secondNearTrackermillis = secondNearTracker.substring(secondNearTracker.indexOf(",") + 1);
secondTrackermillis = secondNearTrackermillis.toInt();
if ((millis() - secondTrackermillis) > Config.rememberStationTime * 60 * 1000) {
secondNearTracker = "";
}
}
if (thirdNearTracker != "") {
thirdNearTrackermillis = thirdNearTracker.substring(thirdNearTracker.indexOf(",") + 1);
thirdTrackermillis = thirdNearTrackermillis.toInt();
if ((millis() - thirdTrackermillis) > Config.rememberStationTime * 60 * 1000) {
thirdNearTracker = "";
}
}
if (fourthNearTracker != "") {
fourthNearTrackermillis = fourthNearTracker.substring(fourthNearTracker.indexOf(",") + 1);
fourthTrackermillis = fourthNearTrackermillis.toInt();
if ((millis() - fourthTrackermillis) > Config.rememberStationTime * 60 * 1000) {
fourthNearTracker = "";
}
}
if (thirdNearTracker == "") {
thirdNearTracker = fourthNearTracker;
fourthNearTracker = "";
}
if (secondNearTracker == "") {
secondNearTracker = thirdNearTracker;
thirdNearTracker = fourthNearTracker;
fourthNearTracker = "";
}
if (firstNearTracker == "") {
firstNearTracker = secondNearTracker;
secondNearTracker = thirdNearTracker;
thirdNearTracker = fourthNearTracker;
fourthNearTracker = "";
}
lastDeleteListenedTracker = millis();
}
void checkListenedTrackersByTimeAndDelete() {
if (millis() - lastDeleteListenedTracker > Config.rememberStationTime*60*1000) {
deleteListenedTrackersbyTime();
}
}
void orderListenedTrackersByDistance(const String& callsign, float distance, float course) {
String firstNearTrackerDistance, secondNearTrackerDistance, thirdNearTrackerDistance, fourthNearTrackerDistance, firstNearTrackerCallsign, secondNearTrackerCallsign,thirdNearTrackerCallsign, fourthNearTrackerCallsign;
float firstDistance = 0.0;
float secondDistance = 0.0;
float thirdDistance = 0.0;
float fourthDistance = 0.0;
if (firstNearTracker != "") {
firstNearTrackerCallsign = firstNearTracker.substring(0, firstNearTracker.indexOf(">"));
firstNearTrackerDistance = firstNearTracker.substring(firstNearTracker.indexOf(">") + 1, firstNearTracker.indexOf("km"));
firstDistance = firstNearTrackerDistance.toFloat();
}
if (secondNearTracker != "") {
secondNearTrackerCallsign = secondNearTracker.substring(0, secondNearTracker.indexOf(">"));
secondNearTrackerDistance = secondNearTracker.substring(secondNearTracker.indexOf(">") + 1, secondNearTracker.indexOf("km"));
secondDistance = secondNearTrackerDistance.toFloat();
}
if (thirdNearTracker != "") {
thirdNearTrackerCallsign = thirdNearTracker.substring(0, thirdNearTracker.indexOf(">"));
thirdNearTrackerDistance = thirdNearTracker.substring(thirdNearTracker.indexOf(">") + 1, thirdNearTracker.indexOf("km"));
thirdDistance = thirdNearTrackerDistance.toFloat();
}
if (fourthNearTracker != "") {
fourthNearTrackerCallsign = fourthNearTracker.substring(0, fourthNearTracker.indexOf(">"));
fourthNearTrackerDistance = fourthNearTracker.substring(fourthNearTracker.indexOf(">") + 1, fourthNearTracker.indexOf("km"));
fourthDistance = fourthNearTrackerDistance.toFloat();
}
String newTrackerInfo = callsign;
newTrackerInfo += "> ";
newTrackerInfo += String(distance,2);
newTrackerInfo += "km ";
newTrackerInfo += String(int(course));
newTrackerInfo += ",";
newTrackerInfo += String(millis());
if (firstNearTracker == "" && secondNearTracker == "" && thirdNearTracker == "" && fourthNearTracker == "") {
firstNearTracker = newTrackerInfo;
} else if (firstNearTracker != "" && secondNearTracker == "" && thirdNearTracker == "" && fourthNearTracker == "") {
if (callsign != firstNearTrackerCallsign) {
if (distance < firstDistance) {
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
} else {
secondNearTracker = newTrackerInfo;
}
} else {
if (distance != firstDistance) {
firstNearTracker = newTrackerInfo;
}
}
} else if (firstNearTracker != "" && secondNearTracker != "" && thirdNearTracker == "" && fourthNearTracker == "") {
if (callsign != firstNearTrackerCallsign && callsign != secondNearTrackerCallsign) {
if (distance < firstDistance) {
thirdNearTracker = secondNearTracker;
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
} else if (distance < secondDistance && distance >= firstDistance) {
thirdNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance >= secondDistance) {
thirdNearTracker = newTrackerInfo;
}
} else {
if (callsign == firstNearTrackerCallsign) {
if (distance != firstDistance) {
if (distance > secondDistance) {
firstNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else {
firstNearTracker = newTrackerInfo;
}
}
} else if (callsign == secondNearTrackerCallsign) {
if (distance != secondDistance) {
if (distance < firstDistance) {
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
} else {
secondNearTracker = newTrackerInfo;
}
}
}
}
} else if (firstNearTracker != "" && secondNearTracker != "" && thirdNearTracker != "" && fourthNearTracker == "") {
if (callsign != firstNearTrackerCallsign && callsign != secondNearTrackerCallsign && callsign != thirdNearTrackerCallsign) {
if (distance < firstDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = secondNearTracker;
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
} else if (distance >= firstDistance && distance < secondDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance >= secondDistance && distance < thirdDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance >= thirdDistance) {
fourthNearTracker = newTrackerInfo;
}
} else {
if (callsign == firstNearTrackerCallsign) {
if (distance != firstDistance) {
if (distance > thirdDistance) {
firstNearTracker = secondNearTracker;
secondNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance <= thirdDistance && distance > secondDistance) {
firstNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance <= secondDistance) {
firstNearTracker = newTrackerInfo;
}
}
} else if (callsign == secondNearTrackerCallsign) {
if (distance != secondDistance) {
if (distance > thirdDistance) {
secondNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance <= thirdDistance && distance > firstDistance) {
secondNearTracker = newTrackerInfo;
} else if (distance <= firstDistance) {
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
}
}
} else if (callsign == thirdNearTrackerCallsign) {
if (distance != thirdDistance) {
if (distance <= firstDistance) {
thirdNearTracker = secondNearTracker;
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
} else if (distance > firstDistance && distance <= secondDistance) {
thirdNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance > secondDistance) {
thirdNearTracker = newTrackerInfo;
}
}
}
}
} else if (firstNearTracker != "" && secondNearTracker != "" && thirdNearTracker != "" && fourthNearTracker != "") {
if (callsign != firstNearTrackerCallsign && callsign != secondNearTrackerCallsign && callsign != thirdNearTrackerCallsign && callsign != fourthNearTrackerCallsign) {
if (distance < firstDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = secondNearTracker;
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
} else if (distance < secondDistance && distance >= firstDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance < thirdDistance && distance >= secondDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance < fourthDistance && distance >= thirdDistance) {
fourthNearTracker = newTrackerInfo;
}
} else {
if (callsign == firstNearTrackerCallsign) {
if (distance != firstDistance) {
if (distance > fourthDistance) {
firstNearTracker = secondNearTracker;
secondNearTracker = thirdNearTracker;
thirdNearTracker = fourthNearTracker;
fourthNearTracker = newTrackerInfo;
} else if (distance > thirdDistance && distance <= fourthDistance) {
firstNearTracker = secondNearTracker;
secondNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance > secondDistance && distance <= thirdDistance) {
firstNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance <= secondDistance) {
firstNearTracker = newTrackerInfo;
}
}
} else if (callsign == secondNearTrackerCallsign) {
if (distance != secondDistance) {
if (distance > fourthDistance) {
secondNearTracker = thirdNearTracker;
thirdNearTracker = fourthNearTracker;
fourthNearTracker = newTrackerInfo;
} else if (distance > thirdDistance && distance <= fourthDistance) {
secondNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance > firstDistance && distance <= thirdDistance) {
secondNearTracker = newTrackerInfo;
} else if (distance <= firstDistance) {
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
}
}
} else if (callsign == thirdNearTrackerCallsign) {
if (distance != thirdDistance) {
if (distance > fourthDistance) {
thirdNearTracker = fourthNearTracker;
fourthNearTracker = newTrackerInfo;
} else if (distance > secondDistance && distance <= fourthDistance) {
thirdNearTracker = newTrackerInfo;
} else if (distance > firstDistance && distance <= secondDistance) {
thirdNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance <= firstDistance) {
thirdNearTracker = secondNearTracker;
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
}
}
} else if (callsign == fourthNearTrackerCallsign) {
if (distance != fourthDistance) {
if (distance > thirdDistance) {
fourthNearTracker = newTrackerInfo;
} else if (distance > secondDistance && distance <= thirdDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = newTrackerInfo;
} else if (distance > firstDistance && distance <= secondDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = secondNearTracker;
secondNearTracker = newTrackerInfo;
} else if (distance <= firstDistance) {
fourthNearTracker = thirdNearTracker;
thirdNearTracker = secondNearTracker;
secondNearTracker = firstNearTracker;
firstNearTracker = newTrackerInfo;
}
}
}
}
}
}
void checkSmartBeaconInterval(int speed) {
if (smartBeaconValue) {
if (speed < currentBeacon->slowSpeed) {
txInterval = currentBeacon->slowRate * 1000;
} else if (speed > currentBeacon->fastSpeed) {
txInterval = currentBeacon->fastRate * 1000;
} else {
txInterval = min(currentBeacon->slowRate, currentBeacon->fastSpeed * currentBeacon->fastRate / speed) * 1000;
}
}
}
void checkStandingUpdateTime() {
if (!sendUpdate && lastTx >= Config.standingUpdateTime * 60 * 1000) {
sendUpdate = true;
sendStandingUpdate = true;
}
}
void checkSmartBeaconValue() {
if (wxRequestStatus && (millis() - wxRequestTime) > 20000) {
wxRequestStatus = false;
}
if(winlinkStatus == 0 && !wxRequestStatus) {
smartBeaconValue = currentBeacon->smartBeaconState;
} else {
smartBeaconValue = false;
}
}
void checkSmartBeaconState() {
if (!smartBeaconValue) {
uint32_t lastTxSmartBeacon = millis() - lastTxTime;
if (lastTxSmartBeacon >= Config.nonSmartBeaconRate * 60 * 1000) {
sendUpdate = true;
}
}
}
void sendBeacon(uint8_t type) {
String packet;
if (Config.bme.sendTelemetry && type == 1) { // WX
packet = APRSPacketLib::generateGPSBeaconPacket(currentBeacon->callsign, "APLRT1", Config.path, "/", APRSPacketLib::encodeGPS(gps.location.lat(),gps.location.lng(), gps.course.deg(), gps.speed.knots(), currentBeacon->symbol, Config.sendAltitude, gps.altitude.feet(), sendStandingUpdate, "Wx"));
if (wxModuleType != 0) {
packet += BME_Utils::readDataSensor(0);
} else {
packet += ".../...g...t...r...p...P...h..b.....";
}
} else {
if (miceActive) {
packet = APRSPacketLib::generateMiceGPSBeacon(currentBeacon->micE, currentBeacon->callsign, currentBeacon->symbol, currentBeacon->overlay, Config.path, gps.location.lat(), gps.location.lng(), gps.course.deg(), gps.speed.knots(), gps.altitude.meters());
} else {
packet = APRSPacketLib::generateGPSBeaconPacket(currentBeacon->callsign, "APLRT1", Config.path, currentBeacon->overlay, APRSPacketLib::encodeGPS(gps.location.lat(),gps.location.lng(), gps.course.deg(), gps.speed.knots(), currentBeacon->symbol, Config.sendAltitude, gps.altitude.feet(), sendStandingUpdate, "GPS"));
}
}
String comment;
int sendCommentAfterXBeacons;
if (winlinkCommentState) {
comment = " winlink";
sendCommentAfterXBeacons = 1;
} else {
comment = currentBeacon->comment;
sendCommentAfterXBeacons = Config.sendCommentAfterXBeacons;
}
if (Config.sendBatteryInfo) {
String batteryVoltage = POWER_Utils::getBatteryInfoVoltage();
String batteryChargeCurrent = POWER_Utils::getBatteryInfoCurrent();
#if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268)
comment += " Bat=";
comment += batteryVoltage;
comment += "V (";
comment += batteryChargeCurrent;
comment += "mA)";
#endif
#if defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_2_SX1262) || defined(TTGO_T_Beam_S3_SUPREME_V3)
comment += " Bat=";
comment += String(batteryVoltage.toFloat()/1000,2);
comment += "V (";
comment += batteryChargeCurrent;
comment += "%)";
#endif
#if defined(HELTEC_V3_GPS) || defined(HELTEC_WIRELESS_TRACKER)
comment += " Bat=";
comment += String(batteryVoltage.toFloat(),2);
comment += "V";
#endif
}
if (comment != "") {
updateCounter++;
if (updateCounter >= sendCommentAfterXBeacons) {
packet += comment;
updateCounter = 0;
}
}
#ifdef HAS_TFT
cleanTFT();
#endif
show_display("<<< TX >>>", "", packet,100);
LoRa_Utils::sendNewPacket(packet);
if (smartBeaconValue) {
lastTxLat = gps.location.lat();
lastTxLng = gps.location.lng();
previousHeading = currentHeading;
lastTxDistance = 0.0;
}
lastTxTime = millis();
sendUpdate = false;
}
void checkTelemetryTx() {
if (Config.bme.active && Config.bme.sendTelemetry) {
lastTx = millis() - lastTxTime;
telemetryTx = millis() - lastTelemetryTx;
if ((lastTelemetryTx == 0 || telemetryTx > 10 * 60 * 1000) && lastTx > 10 * 1000) {
sendBeacon(1);
lastTelemetryTx = millis();
}
}
}
void saveIndex(uint8_t type, uint8_t index) {
String filePath;
if (type == 0) {
filePath = "/callsignIndex.txt";
} else {
filePath = "/freqIndex.txt";
}
File fileIndex = SPIFFS.open(filePath, "w");
if(!fileIndex) {
return;
}
String dataToSave = String(index);
if (fileIndex.println(dataToSave)) {
if (type == 0) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Main", "New Callsign Index saved to SPIFFS");
} else {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Main", "New Frequency Index saved to SPIFFS");
}
}
fileIndex.close();
}
void loadIndex(uint8_t type) {
String filePath;
if (type == 0) {
filePath = "/callsignIndex.txt";
} else {
filePath = "/freqIndex.txt";
}
File fileIndex = SPIFFS.open(filePath);
if(!fileIndex) {
return;
} else {
while (fileIndex.available()) {
String firstLine = fileIndex.readStringUntil('\n');
if (type == 0) {
myBeaconsIndex = firstLine.toInt();
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "Main", "Callsign Index: %s", firstLine);
} else {
loraIndex = firstLine.toInt();
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, "LoRa", "LoRa Freq Index: %s", firstLine);
}
}
fileIndex.close();
}
}
}