|
- #include "Core.h"
- #include "Config.h"
- #include "Flash.h"
- #include "MainUnit.h"
- #include "Gps.h"
- #include "Network.h"
- #include "Rtc.h"
- #include "Alerts.h"
- #include "Logging.h"
-
- #define SMS_BUFFER_SIZE 140
- #define NO_ALERTS_NOTIFIED 0
-
- using namespace utils;
-
- namespace core {
- #define CURRENT_LOGGER "core"
-
- uint16_t sleepTime = SLEEP_TIME_SECONDS;
- uint8_t stoppedInARow = SLEEP_STOPPED_THRESHOLD - 1;
- TRACKER_MOVING_STATE movingState = TRACKER_MOVING_STATE::MOVING;
-
- namespace details {
-
- void appendToSmsBuffer(char * buffer, const char * fmt, ...) {
- va_list args;
- va_start(args, fmt);
-
- size_t bufferLeft = SMS_BUFFER_SIZE - strlen(buffer);
- char * p = buffer + strlen(buffer);
- vsnprintf_P(p, bufferLeft, fmt, args);
-
- va_end(args);
- }
-
- }
-
- void main() {
- bool acquired = false;
- PositionEntryMetadata metadata;
-
- if(movingState >= TRACKER_MOVING_STATE::ABOUT_TO_STOP) {
- //forcing when the tracker is about to stop (which should result in STOPPED a few lines below)
- positions::prepareBackup(movingState == TRACKER_MOVING_STATE::ABOUT_TO_STOP);
- }
-
- acquired = positions::acquire(metadata);
-
- if (acquired) {
- positions::appendLast(metadata);
-
- movingState = updateSleepTime();
- gps::preserveCurrentCoordinates();
- }
-
- alerts::clear(metadata);
- alerts::add(notifyFailures(metadata));
-
- if(movingState >= TRACKER_MOVING_STATE::STOPPED) {
- positions::doBackup(movingState == TRACKER_MOVING_STATE::STOPPED); //forcing at the moment the tracker stop
- }
-
- if (acquired) updateRtcTime();
-
- hardware::sim808::powerOff(); //forcing power off, regardless of the counts and current use
- mainunit::deepSleep(sleepTime);
- }
-
- uint8_t notifyFailures(PositionEntryMetadata &metadata) {
- #define CURRENT_LOGGER_FUNCTION "notifyFailures"
-
- SIM808_NETWORK_REGISTRATION_STATE networkStatus;
- char buffer[SMS_BUFFER_SIZE];
- const __FlashStringHelper * backupFailureString = F(" Backup battery failure ?");
- bool notified = false;
-
- uint8_t triggered = alerts::getTriggered(metadata);
- NOTICE_FORMAT("triggered : %B", triggered);
-
- if (!triggered) return NO_ALERTS_NOTIFIED;
-
- network::powerOn();
- networkStatus = network::waitForRegistered(NETWORK_TOTAL_TIMEOUT_MS);
-
- if (network::isAvailable(networkStatus)) {
- strncpy_P(buffer, PSTR("Alerts !"), SMS_BUFFER_SIZE);
- if (bitRead(triggered, ALERT_BATTERY_LEVEL_1) || bitRead(triggered, ALERT_BATTERY_LEVEL_2)) {
- details::appendToSmsBuffer(buffer, PSTR("\n- Battery at %d%%."), metadata.batteryLevel);
- }
-
- if (bitRead(triggered, ALERT_RTC_TEMPERATURE_FAILURE)) {
- details::appendToSmsBuffer(buffer, PSTR("\n- Temperature is %dC.%S"), metadata.temperature, backupFailureString);
- }
-
- if (bitRead(triggered, ALERT_RTC_CLOCK_FAILURE)) {
- details::appendToSmsBuffer(buffer, PSTR("\n- RTC was stopped.%S"), backupFailureString);
- }
-
- #if ALERTS_ON_SERIAL
- NOTICE_FORMAT("%s", buffer);
- notified = true;
- #else
- notified = network::sendSms(buffer);
- #endif
- if (!notified) NOTICE_MSG("SMS not sent !");
- }
-
- network::powerOff();
- return notified ? triggered : NO_ALERTS_NOTIFIED; //If not notified, the alerts state should not be persisted (so we can retry to notify them)
- }
-
- void updateRtcTime() {
- tmElements_t time;
- gps::getTime(time);
- rtc::setTime(time);
- }
-
- TRACKER_MOVING_STATE updateSleepTime() {
- #define CURRENT_LOGGER_FUNCTION "updateSleepTime"
-
- TRACKER_MOVING_STATE state = TRACKER_MOVING_STATE::MOVING;
- uint8_t velocity = gps::getVelocity();
-
- sleepTime = mapSleepTime(velocity);
-
- if (velocity < SLEEP_TIMING_MIN_MOVING_VELOCITY) {
- float distance = gps::getDistanceFromPrevious(); //did we missed positions because we were sleeping ?
- if (distance > GPS_MISSED_POSITION_GAP_KM) stoppedInARow = 0;
- else stoppedInARow = min(stoppedInARow + 1, SLEEP_STOPPED_THRESHOLD + 1); //avoid overflow on REALLY long stops
-
- if (stoppedInARow < SLEEP_STOPPED_THRESHOLD) {
- sleepTime = SLEEP_PAUSING_TIME_SECONDS;
- state = stoppedInARow == SLEEP_STOPPED_THRESHOLD - 1 ?
- TRACKER_MOVING_STATE::ABOUT_TO_STOP :
- TRACKER_MOVING_STATE::PAUSED;
- }
- else if (stoppedInARow == SLEEP_STOPPED_THRESHOLD) state = TRACKER_MOVING_STATE::STOPPED;
- else state = TRACKER_MOVING_STATE::STATIC;
- }
- else stoppedInARow = 0;
-
- NOTICE_FORMAT("stop %d, state %d, %dkmh => %ds", stoppedInARow, state, velocity, sleepTime);
- return state;
- }
-
- uint16_t mapSleepTime(uint8_t velocity) {
- #define CURRENT_LOGGER_FUNCTION "mapSleepTime"
-
- uint16_t result;
- uint16_t currentTime = 0xFFFF;
-
- if (rtc::isAccurate()) {
- tmElements_t time;
- rtc::getTime(time);
-
- currentTime = SLEEP_TIMING_TIME(time.hour, time.minute);
- }
-
- for (uint8_t i = flash::getArraySize(config::defaultSleepTimings); i--;) {
- sleepTimings_t timing;
- flash::read(&config::defaultSleepTimings[i], timing);
-
- if (velocity < timing.speed) continue;
- if (currentTime != 0xFFFF && (currentTime < timing.timeMin || currentTime > timing.timeMax)) continue;
-
- result = timing.seconds;
- break;
-
- }
-
- VERBOSE_FORMAT("%d,%d", velocity, result);
- return result;
- }
- }
|