You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
4.1 KiB

  1. #include "Core.h"
  2. #include "Config.h"
  3. #include "Flash.h"
  4. #include "Alerts.h"
  5. #define LOGGER_NAME "Core"
  6. #define SMS_BUFFER_SIZE 140
  7. #define NO_ALERTS_NOTIFIED 0
  8. using namespace utils;
  9. namespace core {
  10. uint16_t sleepTime = SLEEP_DEFAULT_TIME_SECONDS;
  11. uint8_t stoppedInARow = SLEEP_DEFAULT_STOPPED_THRESHOLD - 1;
  12. namespace details {
  13. void appendToSmsBuffer(char * buffer, const char * fmt, ...) {
  14. va_list args;
  15. va_start(args, fmt);
  16. size_t bufferLeft = SMS_BUFFER_SIZE - strlen(buffer);
  17. char * p = buffer + strlen(buffer);
  18. vsnprintf_P(p, bufferLeft, fmt, args);
  19. va_end(args);
  20. }
  21. }
  22. void main() {
  23. bool forceBackup = false;
  24. bool acquired = false;
  25. PositionEntryMetadata metadata;
  26. positions::prepareBackup();
  27. acquired = positions::acquire(metadata);
  28. if (acquired) {
  29. positions::appendLast(metadata);
  30. forceBackup = updateSleepTime();
  31. gps::preserveCurrentCoordinates();
  32. }
  33. alerts::add(notifyFailures(metadata));
  34. alerts::clear(metadata);
  35. positions::doBackup(forceBackup);
  36. if (acquired) updateRtcTime();
  37. mainunit::deepSleep(sleepTime);
  38. }
  39. uint8_t notifyFailures(PositionEntryMetadata &metadata) {
  40. SIM808RegistrationStatus networkStatus;
  41. char buffer[SMS_BUFFER_SIZE];
  42. const __FlashStringHelper * backupFailureString = F(" Backup battery failure ?");
  43. bool notified = false;
  44. uint8_t triggered = alerts::getTriggered(metadata);
  45. if (!triggered) return NO_ALERTS_NOTIFIED;
  46. NOTICE_FORMAT("notifyFailures", "triggered : %B", triggered);
  47. network::powerOn();
  48. networkStatus = network::waitForRegistered(NETWORK_DEFAULT_TOTAL_TIMEOUT_MS);
  49. if (network::isAvailable(networkStatus.stat)) {
  50. strncpy_P(buffer, PSTR("Alerts !"), SMS_BUFFER_SIZE);
  51. if (bitRead(triggered, ALERT_BATTERY_LEVEL_1) || bitRead(triggered, ALERT_BATTERY_LEVEL_2)) {
  52. details::appendToSmsBuffer(buffer, PSTR("\n- Battery at %d%%."), metadata.batteryLevel);
  53. }
  54. if (bitRead(triggered, ALERT_RTC_TEMPERATURE_FAILURE)) {
  55. details::appendToSmsBuffer(buffer, PSTR("\n- Temperature is %dC.%S"), static_cast<uint16_t>(metadata.temperature * 100), backupFailureString);
  56. }
  57. if (bitRead(triggered, ALERT_RTC_CLOCK_FAILURE)) {
  58. details::appendToSmsBuffer(buffer, PSTR("\n- RTC was stopped.%S"), backupFailureString);
  59. }
  60. notified = network::sendSms(buffer);
  61. if (!notified) NOTICE_MSG("notifyFailure", "SMS not sent !");
  62. }
  63. network::powerOff();
  64. return notified ? triggered : NO_ALERTS_NOTIFIED; //If not notified, the alerts state should not be persisted (so we can retry to notify them)
  65. }
  66. void updateRtcTime() {
  67. tmElements_t time;
  68. gps::getTime(time);
  69. rtc::setTime(time);
  70. }
  71. bool updateSleepTime() {
  72. uint8_t velocity = gps::getVelocity();
  73. uint16_t result = mapSleepTime(velocity);
  74. bool goingLongSleep = false;
  75. if (velocity < SLEEP_TIMING_MIN_MOVING_VELOCITY) {
  76. float distance = gps::getDistanceFromPrevious(); //did we missed positions because we were sleeping ?
  77. if (distance > GPS_DEFAULT_MISSED_POSITION_GAP_KM) stoppedInARow = 0;
  78. else stoppedInARow = min(stoppedInARow + 1, SLEEP_DEFAULT_STOPPED_THRESHOLD + 1); //avoid overflow on REALLY long stops
  79. if (stoppedInARow < SLEEP_DEFAULT_STOPPED_THRESHOLD) {
  80. result = SLEEP_DEFAULT_PAUSING_TIME_SECONDS;
  81. }
  82. else if (stoppedInARow == SLEEP_DEFAULT_STOPPED_THRESHOLD) goingLongSleep = true;
  83. }
  84. else stoppedInARow = 0;
  85. sleepTime = result;
  86. NOTICE_FORMAT("updateSleepTime", "%dkmh => %d seconds", velocity, sleepTime);
  87. return goingLongSleep;
  88. }
  89. uint16_t mapSleepTime(uint8_t velocity) {
  90. uint16_t result;
  91. uint16_t currentTime = 0xFFFF;
  92. if (rtc::isAccurate()) {
  93. tmElements_t time;
  94. rtc::getTime(time);
  95. currentTime = SLEEP_TIMING_TIME(time.Hour, time.Minute);
  96. }
  97. for (uint8_t i = flash::getArraySize(config::defaultSleepTimings); i--;) {
  98. sleepTimings_t timing;
  99. flash::read(&config::defaultSleepTimings[i], timing);
  100. if (velocity < timing.speed) continue;
  101. if (currentTime != 0xFFFF && (currentTime < timing.timeMin || currentTime > timing.timeMax)) continue;
  102. result = timing.seconds;
  103. break;
  104. }
  105. VERBOSE_FORMAT("computeSleepTime", "%d,%d", velocity, result);
  106. return result;
  107. }
  108. }