diff --git a/src/Config.h b/src/Config.h index 6d7c0a4..e165fc2 100644 --- a/src/Config.h +++ b/src/Config.h @@ -1,112 +1,33 @@ -#pragma once - -#include - -#define BACKUP_ENABLE_SDCARD 0 -#define BACKUP_ENABLE_NETWORK 1 - -#if BACKUP_ENABLE_NETWORK -#include "NetworkPositionsConfig.h" -#endif - -#define SIM808_BAUDRATE 4800 - -#define CONFIG_ADDR 0 -#define CONFIG_RESERVED_SIZE 128 -#define CONFIG_SEED 14 -#define VERSION "1.20" - -#define SLEEP_TIMING_TIME(hours, minutes) hours * 60 + minutes - -#pragma region Default configuration values - -#define MENU_TIMEOUT 10000 -/** - \def SLEEP_DEFAULT_TIME_SECONDS - Hard coded value for default sleep time between position acquisitions. - Exprimed in seconds -*/ - -#define CONFIG_DEFAULT_BATTERY_ALERT_LEVEL1 45 -#define CONFIG_DEFAULT_BATTERY_ALERT_LEVEL2 38 -#define CONFIG_DEFAULT_BATTERY_ALERT_CLEAR 60 -#define CONFIG_DEFAULT_ACTIVE_ALERTS 0 -#define CONFIG_DEFAULT_CONTACT_PHONE "+642568452" - -#define SLEEP_DEFAULT_TIME_SECONDS 1800 -#define SLEEP_DEFAULT_STOPPED_THRESHOLD 5 -#define SLEEP_DEFAULT_PAUSING_TIME_SECONDS 270 - -#define SLEEP_TIMING_MIN SLEEP_TIMING_TIME(0, 0) -#define SLEEP_TIMING_MAX SLEEP_TIMING_TIME(23, 59) -#define SLEEP_TIMING_MIN_MOVING_VELOCITY 5 - -#define GPS_DEFAULT_INTERMEDIATE_TIMEOUT_MS 10000L -#define GPS_DEFAULT_TOTAL_TIMEOUT_MS 80000L -#define GPS_DEFAULT_MISSED_POSITION_GAP_KM 2 - -#define NETWORK_DEFAULT_INTERMEDIATE_TIMEOUT_MS 10000L -#define NETWORK_DEFAULT_TOTAL_TIMEOUT_MS 80000L -#define NETWORK_DEFAULT_NO_NETWORK_QUALITY_THRESHOLD 8 -#define NETWORK_DEFAULT_NO_NETWORK_TRIES 5 - -#define ALERTS_ON_SERIAL_IF_AVAILABLE 1 -/** - \def ALERTS_ON_SERIAL_IF_AVAILABLE - Display alerts on serial when connected rather than sending an SMS. - Useful for debugging purpose and avoid costs related to SMS sending. -*/ -#define ALERT_SUSPICIOUS_RTC_TEMPERATURE 0 - -#pragma endregion - -struct sleepTimings_t { - uint8_t speed; - uint16_t timeMin; - uint16_t timeMax; - uint16_t seconds; -}; - -struct config_t { - uint8_t seed; //sizeof = 1 - char version[5]; //sizeof = 5 - uint16_t firstEntry; //sizeof = 2 - uint16_t lastEntry; //sizeof = 2 -#if BACKUP_ENABLE_NETWORK - networkConfig_t network; //sizeof = 73 -#else - char reserved[73]; -#endif - uint8_t alertBatteryLevel1; //sizeof = 1 - uint8_t alertBatteryLevel2; //sizeof = 1 - uint8_t alertBatteryLevelClear; //sizeof = 1 - uint8_t activeAlerts; //sizeof = 1 - char contactPhone[15]; //sizeof = 15 -}; //sizeof = 29 + 73 = 102 - -namespace config { - - static const sleepTimings_t defaultSleepTimings[] PROGMEM = { - { 0, SLEEP_TIMING_TIME(16, 00), SLEEP_TIMING_TIME(19, 59), 3600 }, - { 0, SLEEP_TIMING_TIME(20, 00), SLEEP_TIMING_MAX, SLEEP_DEFAULT_TIME_SECONDS }, - { 0, SLEEP_TIMING_MIN, SLEEP_TIMING_TIME(8, 29), SLEEP_DEFAULT_TIME_SECONDS }, - { 0, SLEEP_TIMING_TIME(8, 30), SLEEP_TIMING_TIME(15, 59), 10800 }, - - { SLEEP_TIMING_MIN_MOVING_VELOCITY, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 540 }, - { 10, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 270 }, - { 20, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 225 }, - { 30, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 240 }, - { 45, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 280 }, - { 65, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 276 }, - { 85, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 225 } - }; - - namespace main { - extern config_t value; - - void setup(); - void save(); - - void reset(); - } +#pragma once + +#include +#include "config/Main.h" + +struct config_t { + uint8_t seed; //sizeof = 1 + char version[5]; //sizeof = 5 + uint16_t firstEntry; //sizeof = 2 + uint16_t lastEntry; //sizeof = 2 +#if BACKUP_ENABLE_NETWORK + networkConfig_t network; //sizeof = 73 +#else + char reserved[73]; +#endif + uint8_t alertBatteryLevel1; //sizeof = 1 + uint8_t alertBatteryLevel2; //sizeof = 1 + uint8_t alertBatteryLevelClear; //sizeof = 1 + uint8_t activeAlerts; //sizeof = 1 + char contactPhone[15]; //sizeof = 15 +}; //sizeof = 29 + 73 = 102 + +namespace config { + + namespace main { + extern config_t value; + + void setup(); + void save(); + + void reset(); + } } \ No newline at end of file diff --git a/src/Core.h b/src/Core.h index 7afbe4e..3f61206 100644 --- a/src/Core.h +++ b/src/Core.h @@ -1,29 +1,29 @@ -#pragma once - -#include - -#include "Debug.h" -#include "Gps.h" -#include "MainUnit.h" -#include "Network.h" -#include "Rtc.h" -#include "Pins.h" -#include "Positions.h" - -enum class TRACKER_MOVING_STATE : uint8_t { - MOVING = 0, - PAUSED = 1, - STOPPED = 2, - STATIC = 3 -}; - -namespace core { - extern uint16_t sleepTime; - - void main(); - void updateRtcTime(); - TRACKER_MOVING_STATE updateSleepTime(); - uint16_t mapSleepTime(uint8_t velocity); - - uint8_t notifyFailures(PositionEntryMetadata &metadata); +#pragma once + +#include + +#include "Debug.h" +#include "Gps.h" +#include "MainUnit.h" +#include "Network.h" +#include "Rtc.h" +#include "config/Pins.h" +#include "Positions.h" + +enum class TRACKER_MOVING_STATE : uint8_t { + MOVING = 0, + PAUSED = 1, + STOPPED = 2, + STATIC = 3 +}; + +namespace core { + extern uint16_t sleepTime; + + void main(); + void updateRtcTime(); + TRACKER_MOVING_STATE updateSleepTime(); + uint16_t mapSleepTime(uint8_t velocity); + + uint8_t notifyFailures(PositionEntryMetadata &metadata); } \ No newline at end of file diff --git a/src/Hardware.cpp b/src/Hardware.cpp index 35ffc48..3400604 100644 --- a/src/Hardware.cpp +++ b/src/Hardware.cpp @@ -1,159 +1,159 @@ -#include "Config.h" -#include "Hardware.h" -#include "Pins.h" -#include "Debug.h" - -#include -#include -#include - -#include -#include - - -namespace hardware { - -#define LOGGER_NAME "Hardware::sim808" - - namespace sim808 { - SoftwareSerial simSerial = SoftwareSerial(SIM_TX, SIM_RX); - SIM808 device = SIM808(SIM_RST, SIM_PWR, SIM_STATUS); - uint8_t networkPoweredCount = 0; - uint8_t gpsPoweredCount = 0; - - void powerOn() { - VERBOSE("powerOn"); - bool poweredOn = device.powerOnOff(true); - if (!poweredOn) return; - - device.init(); - networkPoweredCount = gpsPoweredCount = 0; - } - - void powerOff() { - VERBOSE("powerOff"); - device.powerOnOff(false); - networkPoweredCount = gpsPoweredCount = 0; - } - - void powerOffIfUnused() { - //does not rely on count for safety - //if there is a bug somewhere, the device will consume more battery, - //but will not fail due to an over aggressive battery saving strategy - bool gpsPowered = false; - - if ((!device.getGpsPowerState(&gpsPowered) || !gpsPowered) && - (device.getPhoneFunctionality() != SIM808_PHONE_FUNCTIONALITY::FULL)) { - powerOff(); - } - } - - void setup() { - NOTICE("setup"); - simSerial.begin(SIM808_BAUDRATE); - device.begin(simSerial); - powerOff(); //ensure powerOff on start - } - - void gpsPowerOn() { - if(gpsPoweredCount) { - gpsPoweredCount++; - return; - } - - VERBOSE("gpsPowerOn"); - powerOn(); - if(!networkPoweredCount) { - //SIM808 turns phone on by default but we don't need it for gps only - device.setPhoneFunctionality(SIM808_PHONE_FUNCTIONALITY::MINIMUM); - } - device.enableGps(); - } - - void gpsPowerOff() { - if (!device.powered()) { - networkPoweredCount = gpsPoweredCount = 0; //just to be sure counts == 0 - return; - } - - if(gpsPoweredCount > 1) { - gpsPoweredCount--; - return; - } - - VERBOSE("gpsPowerOff"); - device.disableGps(); - powerOffIfUnused(); - } - - void networkPowerOn() { - if(networkPoweredCount) { - networkPoweredCount++; - return; - } - - VERBOSE("networkPowerOn"); - powerOn(); - device.setPhoneFunctionality(SIM808_PHONE_FUNCTIONALITY::FULL); - } - - void networkPowerOff() { - if (!device.powered()) { - networkPoweredCount = gpsPoweredCount = 0; //just to be sure counts == 0 - return; - } - - if(networkPoweredCount > 1) { - networkPoweredCount--; - return; - } - - VERBOSE("networkPowerOff"); - device.disableGprs(); - device.setPhoneFunctionality(SIM808_PHONE_FUNCTIONALITY::MINIMUM); - powerOffIfUnused(); - } - } - -#define LOGGER_NAME "Hardware::i2c" - - namespace i2c { - - E24 eeprom = E24(E24Size_t::E24_512K); - uint8_t poweredCount = 0; - - void powerOn() { - if(poweredCount) { - poweredCount++; - return; - } - - VERBOSE("powerOn"); - digitalWrite(I2C_PWR, HIGH); - pinMode(I2C_PWR, OUTPUT); - - Wire.begin(); - poweredCount = 1; - } - - void powerOff(bool forced = false) { - if(poweredCount > 1 && !forced) { - poweredCount--; - return; - } - - VERBOSE("powerOff"); - pinMode(I2C_PWR, INPUT); - digitalWrite(I2C_PWR, LOW); - - //turn off i2c - TWCR &= ~(bit(TWEN) | bit(TWIE) | bit(TWEA)); - - //disable i2c internal pull ups - digitalWrite(A4, LOW); - digitalWrite(A5, LOW); - - poweredCount = 0; - } - } -} +#include "Config.h" +#include "Hardware.h" +#include "config/Pins.h" +#include "Debug.h" + +#include +#include +#include + +#include +#include + + +namespace hardware { + +#define LOGGER_NAME "Hardware::sim808" + + namespace sim808 { + SoftwareSerial simSerial = SoftwareSerial(SIM_TX, SIM_RX); + SIM808 device = SIM808(SIM_RST, SIM_PWR, SIM_STATUS); + uint8_t networkPoweredCount = 0; + uint8_t gpsPoweredCount = 0; + + void powerOn() { + VERBOSE("powerOn"); + bool poweredOn = device.powerOnOff(true); + if (!poweredOn) return; + + device.init(); + networkPoweredCount = gpsPoweredCount = 0; + } + + void powerOff() { + VERBOSE("powerOff"); + device.powerOnOff(false); + networkPoweredCount = gpsPoweredCount = 0; + } + + void powerOffIfUnused() { + //does not rely on count for safety + //if there is a bug somewhere, the device will consume more battery, + //but will not fail due to an over aggressive battery saving strategy + bool gpsPowered = false; + + if ((!device.getGpsPowerState(&gpsPowered) || !gpsPowered) && + (device.getPhoneFunctionality() != SIM808_PHONE_FUNCTIONALITY::FULL)) { + powerOff(); + } + } + + void setup() { + NOTICE("setup"); + simSerial.begin(SIM808_BAUDRATE); + device.begin(simSerial); + powerOff(); //ensure powerOff on start + } + + void gpsPowerOn() { + if(gpsPoweredCount) { + gpsPoweredCount++; + return; + } + + VERBOSE("gpsPowerOn"); + powerOn(); + if(!networkPoweredCount) { + //SIM808 turns phone on by default but we don't need it for gps only + device.setPhoneFunctionality(SIM808_PHONE_FUNCTIONALITY::MINIMUM); + } + device.enableGps(); + } + + void gpsPowerOff() { + if (!device.powered()) { + networkPoweredCount = gpsPoweredCount = 0; //just to be sure counts == 0 + return; + } + + if(gpsPoweredCount > 1) { + gpsPoweredCount--; + return; + } + + VERBOSE("gpsPowerOff"); + device.disableGps(); + powerOffIfUnused(); + } + + void networkPowerOn() { + if(networkPoweredCount) { + networkPoweredCount++; + return; + } + + VERBOSE("networkPowerOn"); + powerOn(); + device.setPhoneFunctionality(SIM808_PHONE_FUNCTIONALITY::FULL); + } + + void networkPowerOff() { + if (!device.powered()) { + networkPoweredCount = gpsPoweredCount = 0; //just to be sure counts == 0 + return; + } + + if(networkPoweredCount > 1) { + networkPoweredCount--; + return; + } + + VERBOSE("networkPowerOff"); + device.disableGprs(); + device.setPhoneFunctionality(SIM808_PHONE_FUNCTIONALITY::MINIMUM); + powerOffIfUnused(); + } + } + +#define LOGGER_NAME "Hardware::i2c" + + namespace i2c { + + E24 eeprom = E24(E24Size_t::E24_512K); + uint8_t poweredCount = 0; + + void powerOn() { + if(poweredCount) { + poweredCount++; + return; + } + + VERBOSE("powerOn"); + digitalWrite(I2C_PWR, HIGH); + pinMode(I2C_PWR, OUTPUT); + + Wire.begin(); + poweredCount = 1; + } + + void powerOff(bool forced = false) { + if(poweredCount > 1 && !forced) { + poweredCount--; + return; + } + + VERBOSE("powerOff"); + pinMode(I2C_PWR, INPUT); + digitalWrite(I2C_PWR, LOW); + + //turn off i2c + TWCR &= ~(bit(TWEN) | bit(TWIE) | bit(TWEA)); + + //disable i2c internal pull ups + digitalWrite(A4, LOW); + digitalWrite(A5, LOW); + + poweredCount = 0; + } + } +} diff --git a/src/MainUnit.cpp b/src/MainUnit.cpp index 1d02dff..fe12fdf 100644 --- a/src/MainUnit.cpp +++ b/src/MainUnit.cpp @@ -1,45 +1,45 @@ -#include "MainUnit.h" -#include "Rtc.h" -#include "Pins.h" -#include "Debug.h" - -#define LOGGER_NAME "MainUnit" - -namespace mainunit { - - namespace details { - - void prepareSleep() { - hardware::sim808::simSerial.end(); //avoid woke up by SoftwareSerial interrupt - delay(5); //ensure log messages have been printed out - } - - void wokeUp() { - tmElements_t wokeUpTime; - rtc::getTime(wokeUpTime); - VERBOSE_FORMAT("wokeUp", "%d:%d:%d", wokeUpTime.Hour, wokeUpTime.Minute, wokeUpTime.Second); - - hardware::sim808::simSerial.listen(); - } - - } - - void interrupt() { - detachInterrupt(digitalPinToInterrupt(RTC_WAKE)); - } - - void interruptIn(uint16_t seconds) { - rtc::setAlarm(seconds); - - pinMode(RTC_WAKE, INPUT); - attachInterrupt(digitalPinToInterrupt(RTC_WAKE), interrupt, FALLING); - } - - void deepSleep(uint16_t seconds) { - NOTICE_FORMAT("deepSleep", "%d seconds", seconds); - interruptIn(seconds); - details::prepareSleep(); - LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); - details::wokeUp(); - } +#include "MainUnit.h" +#include "Rtc.h" +#include "config/Pins.h" +#include "Debug.h" + +#define LOGGER_NAME "MainUnit" + +namespace mainunit { + + namespace details { + + void prepareSleep() { + hardware::sim808::simSerial.end(); //avoid woke up by SoftwareSerial interrupt + delay(5); //ensure log messages have been printed out + } + + void wokeUp() { + tmElements_t wokeUpTime; + rtc::getTime(wokeUpTime); + VERBOSE_FORMAT("wokeUp", "%d:%d:%d", wokeUpTime.Hour, wokeUpTime.Minute, wokeUpTime.Second); + + hardware::sim808::simSerial.listen(); + } + + } + + void interrupt() { + detachInterrupt(digitalPinToInterrupt(RTC_WAKE)); + } + + void interruptIn(uint16_t seconds) { + rtc::setAlarm(seconds); + + pinMode(RTC_WAKE, INPUT); + attachInterrupt(digitalPinToInterrupt(RTC_WAKE), interrupt, FALLING); + } + + void deepSleep(uint16_t seconds) { + NOTICE_FORMAT("deepSleep", "%d seconds", seconds); + interruptIn(seconds); + details::prepareSleep(); + LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); + details::wokeUp(); + } } \ No newline at end of file diff --git a/src/NetworkPositionsBackup.h b/src/NetworkPositionsBackup.h index 751a911..dbc9c74 100644 --- a/src/NetworkPositionsBackup.h +++ b/src/NetworkPositionsBackup.h @@ -1,26 +1,26 @@ -#pragma once - -#include "PositionsBackup.h" -#include "Time2.h" -#include "Positions.h" - -namespace positions { - namespace backup { - namespace net { - - class NetworkPositionsBackup : public PositionsBackup { - private: - bool isBackupNeeded(bool forPrepare); - bool appendPosition(PositionEntry &entry); - void appendPositions(); - - public: - void setup(); - - void prepare(); - void backup(bool force); - }; - - } - } +#pragma once + +#include "PositionsBackup.h" +#include "Time2.h" +#include "Positions.h" + +namespace positions { + namespace backup { + namespace net { + + class NetworkPositionsBackup : public PositionsBackup { + private: + bool isBackupNeeded(bool forPrepare); + bool appendPosition(PositionEntry &entry); + void appendPositions(); + + public: + void setup(); + + void prepare(); + void backup(bool force); + }; + + } + } } \ No newline at end of file diff --git a/src/NetworkPositionsConfig.h b/src/NetworkPositionsConfig.h deleted file mode 100644 index 5e56708..0000000 --- a/src/NetworkPositionsConfig.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - - -#define POSITIONS_CONFIG_NET_DEFAULT_SAVE_THRESHOLD 30 -#define POSITIONS_CONFIG_NET_DEFAULT_APN "Vodafone" -#define POSITIONS_CONFIG_NET_DEFAULT_URL "https://yourserver.com/endpoint" -#define POSITIONS_CONFIG_NET_DEFAULT_EXPECTED_RESPONSE 201 -#define POSITIONS_CONFIG_NET_DEFAULT_UNAVAILABLE_NETWORK_POSTPONE_THRESHOLD 5 - - -struct networkConfig_t { - uint8_t saveThreshold; //sizeof = 1 - uint16_t lastSavedEntry; //sizeof = 2 - char apn[20]; //sizeof = 20 - char url[50]; //sizeof = 50 -}; //sizeof = 73 \ No newline at end of file diff --git a/src/Pins.h b/src/Pins.h deleted file mode 100644 index 81796ec..0000000 --- a/src/Pins.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#define SIM_RST 5 -#define SIM_RX 6 -#define SIM_TX 7 -#define SIM_PWR 9 -#define SIM_STATUS 8 - -#define I2C_PWR A0 -#define SD_SS SS - -#define SIM_RI 2 -#define RTC_WAKE 3 diff --git a/src/Rtc.cpp b/src/Rtc.cpp index 2123f37..b02fdd5 100644 --- a/src/Rtc.cpp +++ b/src/Rtc.cpp @@ -1,86 +1,86 @@ -#include "Debug.h" - -#include "Rtc.h" -#include "Pins.h" - -#include -#include - -#define LOGGER_NAME "Rtc" - -using namespace utils; - -namespace rtc { - - void setup() { - VERBOSE("setup"); - hardware::i2c::powerOn(); - RTC.control(DS3231_12H, DS3231_OFF); //24 hours clock - RTC.control(DS3231_A1_INT_ENABLE, DS3231_OFF); //Alarm 1 OFF - RTC.control(DS3231_INT_ENABLE, DS3231_ON); //INTCN ON - hardware::i2c::powerOff(); - } - - int16_t getTemperature() { - hardware::i2c::powerOn(); - float temperature = RTC.readTempRegister(); - hardware::i2c::powerOff(); - - return static_cast(temperature * 100); - } - - bool isAccurate() { - hardware::i2c::powerOn(); - bool accurate = RTC.status(DS3231_HALTED_FLAG) == DS3231_OFF; - hardware::i2c::powerOff(); - - return accurate; - } - - timestamp_t getTime() { - tmElements_t time; - getTime(time); - return time::makeTimestamp(time); - } - - void getTime(tmElements_t &time) { - hardware::i2c::powerOn(); - RTC.readTime(time); - hardware::i2c::powerOff(); - - VERBOSE_FORMAT("getTime", "%d/%d/%d %d:%d:%d", tmYearToCalendar(time.Year), time.Month, time.Day, time.Hour, time.Minute, time.Second); - } - - void setTime(const tmElements_t &time) { - VERBOSE_FORMAT("setTime", "%d/%d/%d %d:%d:%d", tmYearToCalendar(time.Year), time.Month, time.Day, time.Hour, time.Minute, time.Second); - - hardware::i2c::powerOn(); - RTC.writeTime(time); - RTC.control(DS3231_HALTED_FLAG, DS3231_OFF); - hardware::i2c::powerOff(); - } - - void setAlarm(uint16_t seconds) { - tmElements_t currentTime; - tmElements_t alarmTime; - - getTime(currentTime); - time::breakTime(time::makeTimestamp(currentTime) + seconds, alarmTime); - - setAlarm(alarmTime); - } - - void setAlarm(const tmElements_t &time) { - hardware::i2c::powerOn(); - RTC.writeAlarm1(DS3231_ALM_HMS, time); - - RTC.control(DS3231_A1_FLAG, DS3231_OFF); //reset Alarm 1 flag - RTC.control(DS3231_A1_INT_ENABLE, DS3231_ON); //Alarm 1 ON - RTC.control(DS3231_INT_ENABLE, DS3231_ON); //INTCN ON - - NOTICE_FORMAT("setAlarm", "Next alarm : %d:%d:%d", time.Hour, time.Minute, time.Second); - - hardware::i2c::powerOff(); - } - +#include "Debug.h" + +#include "Rtc.h" +#include "config/Pins.h" + +#include +#include + +#define LOGGER_NAME "Rtc" + +using namespace utils; + +namespace rtc { + + void setup() { + VERBOSE("setup"); + hardware::i2c::powerOn(); + RTC.control(DS3231_12H, DS3231_OFF); //24 hours clock + RTC.control(DS3231_A1_INT_ENABLE, DS3231_OFF); //Alarm 1 OFF + RTC.control(DS3231_INT_ENABLE, DS3231_ON); //INTCN ON + hardware::i2c::powerOff(); + } + + int16_t getTemperature() { + hardware::i2c::powerOn(); + float temperature = RTC.readTempRegister(); + hardware::i2c::powerOff(); + + return static_cast(temperature * 100); + } + + bool isAccurate() { + hardware::i2c::powerOn(); + bool accurate = RTC.status(DS3231_HALTED_FLAG) == DS3231_OFF; + hardware::i2c::powerOff(); + + return accurate; + } + + timestamp_t getTime() { + tmElements_t time; + getTime(time); + return time::makeTimestamp(time); + } + + void getTime(tmElements_t &time) { + hardware::i2c::powerOn(); + RTC.readTime(time); + hardware::i2c::powerOff(); + + VERBOSE_FORMAT("getTime", "%d/%d/%d %d:%d:%d", tmYearToCalendar(time.Year), time.Month, time.Day, time.Hour, time.Minute, time.Second); + } + + void setTime(const tmElements_t &time) { + VERBOSE_FORMAT("setTime", "%d/%d/%d %d:%d:%d", tmYearToCalendar(time.Year), time.Month, time.Day, time.Hour, time.Minute, time.Second); + + hardware::i2c::powerOn(); + RTC.writeTime(time); + RTC.control(DS3231_HALTED_FLAG, DS3231_OFF); + hardware::i2c::powerOff(); + } + + void setAlarm(uint16_t seconds) { + tmElements_t currentTime; + tmElements_t alarmTime; + + getTime(currentTime); + time::breakTime(time::makeTimestamp(currentTime) + seconds, alarmTime); + + setAlarm(alarmTime); + } + + void setAlarm(const tmElements_t &time) { + hardware::i2c::powerOn(); + RTC.writeAlarm1(DS3231_ALM_HMS, time); + + RTC.control(DS3231_A1_FLAG, DS3231_OFF); //reset Alarm 1 flag + RTC.control(DS3231_A1_INT_ENABLE, DS3231_ON); //Alarm 1 ON + RTC.control(DS3231_INT_ENABLE, DS3231_ON); //INTCN ON + + NOTICE_FORMAT("setAlarm", "Next alarm : %d:%d:%d", time.Hour, time.Minute, time.Second); + + hardware::i2c::powerOff(); + } + } \ No newline at end of file diff --git a/src/SdCard.cpp b/src/SdCard.cpp index 9a37dd3..88f6aa8 100644 --- a/src/SdCard.cpp +++ b/src/SdCard.cpp @@ -1,18 +1,19 @@ -#include "Config.h" - -#if BACKUP_ENABLE_SDCARD -#include "SdCard.h" - -namespace hardware { - namespace sdcard { - - SdFat filesystem; - bool available = false; - - void setup() { - available = filesystem.begin(SD_SS); - } - - } -} +#include "Config.h" + +#if BACKUP_ENABLE_SDCARD +#include "SdCard.h" +#include "config/Pins.h" + +namespace hardware { + namespace sdcard { + + SdFat filesystem; + bool available = false; + + void setup() { + available = filesystem.begin(SD_SS); + } + + } +} #endif \ No newline at end of file diff --git a/src/SdCard.h b/src/SdCard.h index fde853a..43a948e 100644 --- a/src/SdCard.h +++ b/src/SdCard.h @@ -1,14 +1,13 @@ -#pragma once - -#include -#include "Pins.h" - -namespace hardware { - namespace sdcard { - - extern SdFat filesystem; - extern bool available; - - void setup(); - } +#pragma once + +#include + +namespace hardware { + namespace sdcard { + + extern SdFat filesystem; + extern bool available; + + void setup(); + } } \ No newline at end of file diff --git a/src/config/Alerts.h b/src/config/Alerts.h new file mode 100644 index 0000000..b2122de --- /dev/null +++ b/src/config/Alerts.h @@ -0,0 +1,32 @@ +#pragma once + +/** + * Configure the values used for alerts triggering. + * Note that the battery level percentage are quite high, + * because the reading provided by the SIM808 module are + * not accurate and the device shuts itself off way before reaching 0%. + * The clearance level is also well above the first alert level, because + * the reading is so inaccurate that sometimes the battery can gain 5% + * between readings. Setting a clearance level much higher avoid + * clearing the levels and retriggering them the next time. + */ +#define CONFIG_DEFAULT_BATTERY_ALERT_LEVEL1 45 ///< Battery percentage at which to trigger the first low battery alert. +#define CONFIG_DEFAULT_BATTERY_ALERT_LEVEL2 38 ///< Battery percentage at which to trigger the final low battery alert. +#define CONFIG_DEFAULT_BATTERY_ALERT_CLEAR 60 ///< Battery percentage at which to clear all battery alerts. +#define CONFIG_DEFAULT_ACTIVE_ALERTS 0 ///< Default active alerts +#define CONFIG_DEFAULT_CONTACT_PHONE "+642568452" ///< Default phone number to send the alert SMS to. + + +/** + \def ALERTS_ON_SERIAL_IF_AVAILABLE + Display alerts on serial when connected rather than sending an SMS. + Useful for debugging purpose and avoid costs related to SMS sending. +*/ +#define ALERTS_ON_SERIAL_IF_AVAILABLE 1 +/** + \def ALERT_SUSPICIOUS_RTC_TEMPERATURE + Temperature at which to consider the RTC module as failling. + When the backup battery is dead or nearly dead, the reading + of the temperature fails and returns 0. +*/ +#define ALERT_SUSPICIOUS_RTC_TEMPERATURE 0 \ No newline at end of file diff --git a/src/config/BackupNetwork.h b/src/config/BackupNetwork.h new file mode 100644 index 0000000..4b82e32 --- /dev/null +++ b/src/config/BackupNetwork.h @@ -0,0 +1,24 @@ +/** + * Configure how the positions are backuped with the network + */ + +#pragma once + +#define POSITIONS_CONFIG_NET_DEFAULT_SAVE_THRESHOLD 30 ///< Determines how many positions will be saved before a network backup is needed (only when not moving though). +#define POSITIONS_CONFIG_NET_DEFAULT_APN "Vodafone" ///< APN used for GPRS context +#define POSITIONS_CONFIG_NET_DEFAULT_URL "https://yourserver.com/endpoint" ///< URL to which positions data will be send through an HTTP POST request +#define POSITIONS_CONFIG_NET_DEFAULT_EXPECTED_RESPONSE 201 ///< Expected response code from the server that indicates that the positions has been successfully backuped. +/** + \def POSITIONS_CONFIG_NET_DEFAULT_UNAVAILABLE_NETWORK_POSTPONE_THRESHOLD + Determines how many times to deal with an unreliable network before postponing the backup. + In an area where cell reception isn't good, this avoid to try to backup the positions + every single time, which would rapidly consumes all the batty. +*/ +#define POSITIONS_CONFIG_NET_DEFAULT_UNAVAILABLE_NETWORK_POSTPONE_THRESHOLD 5 + +struct networkConfig_t { + uint8_t saveThreshold; //sizeof = 1 + uint16_t lastSavedEntry; //sizeof = 2 + char apn[20]; //sizeof = 20 + char url[50]; //sizeof = 50 +}; //sizeof = 73 diff --git a/src/config/BackupSd.h b/src/config/BackupSd.h new file mode 100644 index 0000000..7b9637e --- /dev/null +++ b/src/config/BackupSd.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/src/config/Gps.h b/src/config/Gps.h new file mode 100644 index 0000000..a1cfee7 --- /dev/null +++ b/src/config/Gps.h @@ -0,0 +1,17 @@ +/** + * Configure how the system waits for the GPS signal. + */ + +#pragma once + +#define GPS_DEFAULT_INTERMEDIATE_TIMEOUT_MS 10000L ///< Time to sleeps between each GPS signal assessment. +#define GPS_DEFAULT_TOTAL_TIMEOUT_MS 80000L ///< Timeout after which to stop trying to get a GPS signal. + +/** + \def GPS_DEFAULT_MISSED_POSITION_GAP_KM + Gap between the current and previous position above which to consider + that the tracker has moved. Even if stopped, this will trigger a whole + new "cycle" of positions acquisition, and will avoid missing positions + because while moving, the tracker woke up while stopped at a light traffic for instance. +*/ +#define GPS_DEFAULT_MISSED_POSITION_GAP_KM 2 \ No newline at end of file diff --git a/src/config/Main.h b/src/config/Main.h new file mode 100644 index 0000000..392f179 --- /dev/null +++ b/src/config/Main.h @@ -0,0 +1,28 @@ +#pragma once + +#include "System.h" +#include "Sleeps.h" +#include "Gps.h" +#include "Network.h" +#include "Alerts.h" + +/** + \def BACKUP_ENABLE_SDCARD + Enable (1) or disable (0) the backup of positions using an sd card. + Note: This code has never been finished properly because of the lack of space + on the ATMega +*/ +#define BACKUP_ENABLE_SDCARD 0 +/** + \def BACKUP_ENABLE_NETWORK + Enable (1) or disable (0) the backup of positions using the network. +*/ +#define BACKUP_ENABLE_NETWORK 1 + +#if BACKUP_ENABLE_SDCARD +#include "BackupSd.h" +#endif + +#if BACKUP_ENABLE_NETWORK +#include "BackupNetwork.h" +#endif \ No newline at end of file diff --git a/src/config/Network.h b/src/config/Network.h new file mode 100644 index 0000000..a5da437 --- /dev/null +++ b/src/config/Network.h @@ -0,0 +1,10 @@ +/** + * Configure how the system waits for the network. + */ + +#pragma onces + +#define NETWORK_DEFAULT_NO_NETWORK_QUALITY_THRESHOLD 8 ///< Minimum signal quality to consider the cellphone reception as reliable. +#define NETWORK_DEFAULT_NO_NETWORK_TRIES 5 ///< Maximum tries before considering an unreliable cellphone reception as no reception at all. +#define NETWORK_DEFAULT_INTERMEDIATE_TIMEOUT_MS 10000L ///< Intermediate time to sleep between each cellphone reception assessment. +#define NETWORK_DEFAULT_TOTAL_TIMEOUT_MS 80000L ///< Timeout after which to stop trying to register to the network. diff --git a/src/config/Pins.h b/src/config/Pins.h new file mode 100644 index 0000000..fe61a5f --- /dev/null +++ b/src/config/Pins.h @@ -0,0 +1,16 @@ +/** + * Defines Arduino pins number connected to external systems. + */ +#pragma once + +#define SIM_RST 5 ///< SIM808 RESET +#define SIM_RX 6 ///< SIM808 RXD +#define SIM_TX 7 ///< SIM808 TXD +#define SIM_PWR 9 ///< SIM808 PWRKEY +#define SIM_STATUS 8 ///< SIM808 STATUS + +#define I2C_PWR A0 ///< Used to drive I2C power supply +#define SD_SS SS + +#define SIM_RI 2 ///< Interrupt pin connected to SIM RI. +#define RTC_WAKE 3 ///< Interrupt pin connected to DS3231 !INT/SQW diff --git a/src/config/Sleeps.h b/src/config/Sleeps.h new file mode 100644 index 0000000..b728531 --- /dev/null +++ b/src/config/Sleeps.h @@ -0,0 +1,53 @@ +/** + * Controls how and when the device goes to sleep. + */ + +#pragma once + +#define SLEEP_TIMING_TIME(hours, minutes) hours * 60 + minutes + +#define SLEEP_DEFAULT_TIME_SECONDS 1800 ///< Default sleep time +#define SLEEP_TIMING_MIN_MOVING_VELOCITY 5 ///< Speed under which to consider the tracker as not moving +#define SLEEP_DEFAULT_PAUSING_TIME_SECONDS 270 ///< Sleep time to use when not moving +#define SLEEP_DEFAULT_STOPPED_THRESHOLD 5 ///< Number of successive positions acquired as not moving before considering the tracker as stopped + +#define SLEEP_TIMING_MIN SLEEP_TIMING_TIME(0, 0) +#define SLEEP_TIMING_MAX SLEEP_TIMING_TIME(23, 59) + + +/** + * Represents a single entry in a larger parametization + * of how long the tracker will go the sleep based on its speed + * and the time of the day. + */ +struct sleepTimings_t { + uint8_t speed; ///< Minimum speed (NOT maximum, the logic is reversed for code efficiency) + uint16_t timeMin; ///< Minimum time of the day (UTC) + uint16_t timeMax; ///< Maximum time of the day (UTC) + uint16_t seconds; ///< Sleep duration in seconds +}; + +namespace config { + + /** + * Describes for how long the tracker should sleep before the next position + * acquisition based on the sleepTimings_t structure + */ + static const sleepTimings_t defaultSleepTimings[] PROGMEM = { + // Sleep timings when not moving + { 0, SLEEP_TIMING_TIME(16, 00), SLEEP_TIMING_TIME(19, 59), 3600 }, ///< 1 hour between 16:00 and 20:00 UTC (04:00 to 08:00 UTC+12) + { 0, SLEEP_TIMING_TIME(20, 00), SLEEP_TIMING_MAX, SLEEP_DEFAULT_TIME_SECONDS }, ///< default (30 minutes) between 20:00 and 00:00 UTC (08:00 to 12:00 UTC+12) + { 0, SLEEP_TIMING_MIN, SLEEP_TIMING_TIME(8, 29), SLEEP_DEFAULT_TIME_SECONDS }, ///< default (30 minutes) between 00:00 and 8:30 UTC (12:00 to 20:30 UTC+12) + { 0, SLEEP_TIMING_TIME(8, 30), SLEEP_TIMING_TIME(15, 59), 10800 }, ///< 3 hours between 20:30 and 16:00 UTC (20:30 to 04:00 UTC+12) + + // Sleep timings while moving + { SLEEP_TIMING_MIN_MOVING_VELOCITY, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 540 }, ///< 540 seconds when speed > SLEEP_TIMING_MIN_MOVING_VELOCITY (5km/h) + { 10, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 270 }, ///< 270 seconds when speed > 10 km/h + { 20, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 225 }, ///< 225 seconds when speed > 20 km/h + { 30, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 240 }, ///< 240 seconds when speed > 30 km/h + { 45, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 280 }, ///< 280 seconds when speed > 45 km/h + { 65, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 276 }, ///< 276 seconds when speed > 65 km/h + { 85, SLEEP_TIMING_MIN, SLEEP_TIMING_MAX, 225 } ///< 2225 seconds when speed > 85 km/h + }; + +} \ No newline at end of file diff --git a/src/config/System.h b/src/config/System.h new file mode 100644 index 0000000..813afb5 --- /dev/null +++ b/src/config/System.h @@ -0,0 +1,37 @@ +#pragma once + +/** + \def SIM808_BAUDRATE + Control the baudrate use to communicate with the SIM808 module +*/ +#define SIM808_BAUDRATE 4800 + +/** + \def CONFIG_ADDR + Address of the config block in the I2C EEPROM chip. + */ +#define CONFIG_ADDR 0 +/** + \def CONFIG_RESERVED_SIZE + Reserved size for the config block in the I2C EEPROM chip. + */ +#define CONFIG_RESERVED_SIZE 128 +/** + \def CONFIG_SEED + Seed use to detect invalid or outdate configuration data. + Changing this value will reset the configuration block. + */ +#define CONFIG_SEED 14 +/** + \def VERSION + Version string, only used for indicative purpose + */ +#define VERSION "1.20" + + +/** + \def MENU_TIMEOUT + When hooked up on Serial port, determine how much milliseconds + to wait for a user input before proceeding. + */ +#define MENU_TIMEOUT 20000 \ No newline at end of file