init
Dependencies: aconno_I2C Lis2dh12 WatchdogTimer
Diff: main.cpp
- Revision:
- 52:bd7678eade77
- Parent:
- 51:9078e6928412
- Child:
- 53:c6942af186d7
--- a/main.cpp Thu May 23 11:39:28 2019 +0000 +++ b/main.cpp Wed May 29 22:59:12 2019 +0000 @@ -6,109 +6,143 @@ • Ensure APP DATA address is correct */ - /* TO DO STOP FRASH WRITE FROM CRASHING IF THERE IS A PROBLEM - */ - //------------------------------------------------------------------------------ //FUNCTION PROTOTYPES - NEED TO ADD ALL OF THE MISSING ONES //------------------------------------------------------------------------------ //should really add these - will just add as and when needed for now void event_activity_tx(); void event_location_tx(bool failsafe); +#if BLE_ENABLED + void bleShutdown(); +#endif //------------------------------------------------------------------------------ // GLOBALS //------------------------------------------------------------------------------ -bool GLOBAL_debugLED = false; -char* GLOBAL_defaultApi = "b:gps2"; -bool GLOBAL_accel_healthy = false; -bool GLOBAL_motionStopFlagTriggered = false; -bool GLOBAL_needToConfigureLis3dh = false; -bool GLOBAL_registeredOnNetwork = false; -bool GLOBAL_modemOn = false; -bool GLOBAL_LEDSequenceinProgress = false; -time_t GLOBAL_wakeTime = 0; +char* GLOBAL_defaultApi = "b:gps2"; +bool GLOBAL_accel_healthy = false; +bool GLOBAL_motionStopFlagTriggered = false; +bool GLOBAL_needToConfigureLis3dh = false; +bool GLOBAL_registeredOnNetwork = false; +bool GLOBAL_modemOn = false; +bool GLOBAL_LEDSequenceinProgress = false; +time_t GLOBAL_wakeTime = 0; char GLOBAL_exceptionString[30]; -char GLOBAL_debug_buffer[200]; +char GLOBAL_debug_buffer[DEBUG_BUFFERSIZE]; char GLOBAL_failed_broadcasts[10][160]; bool GLOBAL_failed_broadcast_slots[10]; +char GLOBAL_GPSlocString_prev[70]; +bool GLOBAL_have_GPSlocString_prev = false; //SETTINGS -int RET_setting_firmware; -uint32_t RET_setting_minimumupdate_hrs; -uint8_t RET_setting_location_mode; -uint8_t RET_setting_location_accuracy; -uint32_t RET_setting_location_tx_interval_mins; -uint32_t RET_setting_location_tx_failsafe_hrs; -uint16_t RET_setting_location_timeout; -uint32_t RET_setting_activity_tx_interval_hrs; -uint8_t RET_setting_activity_mode; -uint32_t RET_setting_environmental_tx_interval_mins; -uint16_t RET_setting_motion_g; -time_t RET_setting_motion_start_seconds; -time_t RET_setting_motion_stop_seconds; -uint16_t RET_setting_impact_g; -uint8_t RET_setting_impact_alert; -uint16_t RET_setting_connection_timeout; -uint16_t RET_setting_beacon_interval_seconds; -uint16_t RET_setting_beacon_scan; +int RET_setting_firmware = 0; +uint32_t RET_setting_minimumupdate_hrs = 0; +uint8_t RET_setting_location_mode = DEFAULT_LOCATION_MODE; +uint8_t RET_setting_location_accuracy = DEFAULT_LOCATION_ACCURACY; +uint32_t RET_setting_location_tx_interval_mins = DEFAULT_LOCATION_TX_INTERVAL_MINS; +uint32_t RET_setting_location_tx_failsafe_hrs = DEFAULT_LOCATION_TX_FAILSAFE_HRS; +uint16_t RET_setting_location_timeout = DEFAULT_LOCATION_TIMEOUT; +uint32_t RET_setting_activity_tx_interval_hrs = 0; +uint8_t RET_setting_activity_mode = 1; +uint32_t RET_setting_environmental_tx_interval_mins = 0; +uint16_t RET_setting_motion_g = DEFAULT_MOTION_G; +time_t RET_setting_motion_start_seconds = DEFAULT_MOTION_START_SECONDS; +time_t RET_setting_motion_stop_seconds = DEFAULT_MOTION_STOP_SECONDS; +uint16_t RET_setting_impact_g = 0; +uint8_t RET_setting_impact_alert = 0; +uint16_t RET_setting_connection_timeout = DEFAULT_CONNECTION_TIMEOUT; +uint16_t RET_setting_beacon_interval_seconds = 0; +uint8_t RET_setting_beacon_scan = 0; //STATE char RET_pf_identifier[7]; -uint8_t RET_coldBoot = 1; -bool RET_asleep = false; -bool RET_busy = false; -time_t RET_RTCunixtime; -bool RET_haveSettings; -uint8_t RET_state; -uint8_t RET_state_prev; -uint8_t RET_buttonPressCount; -time_t RET_buttonPressTime; -time_t RET_buttonReleaseTime; -time_t RET_buttonReleaseTime_prev; -time_t RET_buttonHoldTime; -time_t RET_SetupRunAt; -time_t RET_SettingsGotAt; -bool RET_setupInProgress; -bool RET_force2G; -bool RET_watchdogfired; -bool RET_receivedNewSettings; -uint32_t RET_GPSFailCount; -uint32_t RET_NetworkFailCount; -bool RET_debug = true; -time_t RET_debug_offat; -float RET_voltage; -float RET_temperature; -float RET_temperature_max = -999.0; //Within broadcast frame. Set inital value to low -float RET_temperature_min = 999.0; //Within broadcase frame. Set inital value to high +uint8_t RET_coldBoot = 1; +bool RET_asleep = false; +bool RET_busy = false; +time_t RET_RTCunixtime = 0; +bool RET_haveSettings = false; +uint8_t RET_state = STATE_SETUP; +uint8_t RET_state_prev = RET_state; +uint8_t RET_buttonPressCount = 0; +time_t RET_buttonPressTime = 0; +time_t RET_buttonReleaseTime = 0; +time_t RET_buttonReleaseTime_prev = 0; +time_t RET_buttonHoldTime = 0; +time_t RET_SetupRunAt = 0; +time_t RET_SettingsGotAt = 0; +bool RET_setupInProgress = false; +bool RET_force2G = DEFAULT_FORCE2G; +bool RET_watchdogfired = false; +bool RET_receivedNewSettings = false; +uint32_t RET_GPSFailCount = 0; +uint32_t RET_NetworkFailCount = 0; +bool RET_debug = true; +time_t RET_debug_offat = 0; +float RET_voltage = 0.0; +float RET_temperature = 0.0; +float RET_temperature_max = -999.0; //Within broadcast frame. Set inital value to low +float RET_temperature_min = 999.0; //Within broadcase frame. Set inital value to high +uint32_t RET_modemBrownOutCountInSession = 0; //MOTION STATE -bool RET_motionTriggeredinFrame; -bool RET_motionTriggeredInLocTXInterval; -time_t RET_motionStartTime; -time_t RET_motionStopTime; -bool RET_motionPendingOnState; -bool RET_motionPendingOffState; -bool RET_motionState; -float RET_motionTotalActivityHours; -float RET_motionTotalActivityHoursSincePost; -time_t RET_motionFrameStart; +bool RET_motionTriggeredinFrame = false; +bool RET_motionStateOnInLocTXInterval = false; +time_t RET_motionStartTime = 0; +time_t RET_motionStopTime = 0; +bool RET_motionPendingOnState = false; +bool RET_motionPendingOffState = false; +bool RET_motionState = false; +float RET_motionTotalActivityHours = 0.0f; +float RET_motionTotalActivityHoursSincePost = 0.0f; +time_t RET_motionFrameStart = 0; char RET_activityData[ACTIVITY_BUFFERSIZE]; //IMPACT -bool RET_impactTriggered; +bool RET_impactTriggered = 0; //EVENTS LOGGING -time_t RET_eventTime_location_log; -time_t RET_eventTime_environmental_log; +time_t RET_eventTime_location_log = 0; +time_t RET_eventTime_environmental_log = 0; //EVENTS TX -time_t RET_eventTime_location_tx; -time_t RET_eventTime_location_failsafe_tx; -time_t RET_eventTime_environmental_tx; -time_t RET_eventTime_activity_tx; -time_t RET_eventTime_wakeFromDormant; - +time_t RET_eventTime_location_tx = 0; +time_t RET_eventTime_location_failsafe_tx = 0; +time_t RET_eventTime_environmental_tx = 0; +time_t RET_eventTime_activity_tx = 0; +time_t RET_eventTime_wakeFromDormant = 0; +//BLE +#if BLE_ENABLED + bool RET_bleBroadcasting = false; + uint8_t RET_bleAdv_flags = 0; + char RET_closestLocationTag_id[17]; + int RET_closestLocationTag_rssi = 999; + bool RET_locationTag_present = false; + bool RET_detector_present = false; + const uint8_t bleAdv_motionTriggeredinFrame_flag = 0b01000000; + const uint8_t bleAdv_motionState_flag = 0b00100000; + const uint8_t bleAdv_impact_flag = 0b00010000; + #pragma pack(1) + struct bleData_t { + uint16_t applicationSpecificId; + uint8_t firmware; + uint8_t flags; + uint16_t voltage; + uint8_t buttonpresses; + int16_t temperature; + uint8_t humidity; + uint8_t lux; + int8_t accel_x; + int8_t accel_y; + int8_t accel_z; + /*char id_1; //cant use this and local name as it pushes us over size limit + char id_2; + char id_3; + char id_4; + char id_5; + char id_6;*/ + }; + #pragma pack() +#endif //------------------------------------------------------------------------------ //GPIO //------------------------------------------------------------------------------ @@ -117,22 +151,27 @@ //------------------------------------------------------------------------------ //PERIPHERALS //------------------------------------------------------------------------------ -WatchdogTimer watchdog; //Do not set to less than 4500ms or can cause issues with softdevice -void watchdogKick() { watchdog.kick();} -//SI7060 si7060(PN_I2C_SDA, PN_I2C_SCL); +#if BLE_ENABLED + BLE myble; +#endif +WatchdogTimer watchdog; LIS3DH lis3dh(PN_SPI_MOSI, PN_SPI_MISO, PN_SPI_CS0, PN_SPI_CLK); +SI7060 si7060(PN_I2C_SDA, PN_I2C_SCL); Modem modem(PN_GSM_PWR_KEY, PN_VREG_EN, PN_GSM_WAKE_DISABLE); LowPowerTicker RTCticker; LowPowerTimer LPtimer; //------------------------------------------------------------------------------ -//THREAD SEMAPHORES +//SEMAPHORES //------------------------------------------------------------------------------ Semaphore mainthread; //------------------------------------------------------------------------------ // LOW LEVEL FUNCS //------------------------------------------------------------------------------ +void watchdogKick() { + watchdog.kick(); +} void set_8bit_flag(uint8_t& flags, uint8_t flag) { flags |= flag; } @@ -152,20 +191,16 @@ nrf_gpio_cfg_input(PN_GSM_PWR_KEY, NRF_GPIO_PIN_NOPULL); nrf_gpio_cfg_input(PN_GSM_WAKE_DISABLE, NRF_GPIO_PIN_NOPULL); - /* - //ERRATA 89, shut down i2c channels properly //TWI0 - //NRF_TWI0->ENABLE=0;//TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; - //NRF_TWI0->ENABLE=1;//TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; + NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; *(volatile uint32_t *)0x40003FFC = 0; *(volatile uint32_t *)0x40003FFC; *(volatile uint32_t *)0x40003FFC = 1; //TWI1 - //NRF_TWI1->ENABLE=TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; + NRF_TWI1->ENABLE=TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; *(volatile uint32_t *)0x40004FFC = 0; *(volatile uint32_t *)0x40004FFC; *(volatile uint32_t *)0x40004FFC = 1; - */ } void setState(uint8_t state) { RET_state_prev = RET_state; @@ -197,6 +232,9 @@ } } void recordFirmwareAsValid() { + #if BLE_ENABLED + bleShutdown(); + #endif debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RECORD FW %d AS VALID...", FW_VERSION);debug_exe(); read_app_data_from_flash(&app_data); bool write_app_data_to_flash_execute = false; @@ -237,54 +275,22 @@ } RET_voltage = (voltage_accumulator / (float)readings); } -float nrfTemperature() { - float temperature = 0.0; - - //INTERNAL NRF52 TEMP SENSOR - uint32_t safetycounter = 0; - NRF_TEMP->TASKS_START=1; - while (NRF_TEMP->EVENTS_DATARDY==0 && safetycounter < 10000) { - safetycounter ++; - }; - NRF_TEMP->EVENTS_DATARDY=0; - temperature = nrf_temp_read()/4.0; - NRF_TEMP->TASKS_STOP=1; - - //SOFTDEVICE METHOD - To use this method you need to include #include "nrf_soc.h" - //THIS GAVE SOME INTERMITENT ODD RESULTS AND DOESNT SEEM AS RELIABLE - /* - int32_t t; - sd_temp_get(&t); - temperature = t/4.0; - */ - - return temperature; -} +//------------------------------------------------------------------------------ +// TEMPERATURE +//------------------------------------------------------------------------------ float getTemperature() { - float temperature; - if (USE_NRF_TEMP_SENSOR) { - temperature = nrfTemperature(); - } else { - //temperature = si7060.getTemperature(); //currently disabled because its causing a high current 450ua sleep, most likely due to sensor not sleeping correctly, or i2c sleep issue - } - return temperature; + return si7060.getTemperature(); } void updateTemperatures() { - //RET_temperature = getTemperature(); //not smoothed - if (RET_temperature == 0.0f) {RET_temperature = getTemperature();} + if (RET_temperature == 0.0) {RET_temperature = getTemperature();} RET_temperature = (RET_temperature + (getTemperature() - RET_temperature) * 0.25f); //smoothed - - if (RET_temperature < RET_temperature_min) { - RET_temperature_min = RET_temperature; - } - if (RET_temperature > RET_temperature_max) { - RET_temperature_max = RET_temperature; - } + if (RET_temperature < RET_temperature_min) {RET_temperature_min = RET_temperature;} + if (RET_temperature > RET_temperature_max) {RET_temperature_max = RET_temperature;} if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "Temp:%.1f Min:%.1f Max:%.1f",RET_temperature,RET_temperature_min,RET_temperature_max);debug_exe();} } void addToExceptionString(char* value) { if(strstr(GLOBAL_exceptionString, value) == false){ - snprintf(GLOBAL_exceptionString+strlen(GLOBAL_exceptionString),sizeof(GLOBAL_exceptionString),"%s.",value); + snprintf(GLOBAL_exceptionString+strlen(GLOBAL_exceptionString),sizeof(GLOBAL_exceptionString),".%s",value); } } void resetTemperatures() { @@ -305,7 +311,7 @@ RET_buttonHoldTime = (RET_buttonReleaseTime - RET_buttonPressTime); //temporarily enable debugging and dump settings RET_debug = true; - RET_debug_offat = (RET_RTCunixtime + 600); //debug on for 10 mins + RET_debug_offat = (RET_RTCunixtime + 3600); //debug on for 1hr } RET_buttonReleaseTime_prev = RET_buttonReleaseTime; } @@ -365,11 +371,22 @@ RET_buttonPressCount = 0; } } + + if(RET_debug && GLOBAL_LEDSequenceinProgress == false){ + if (RET_motionState) { + led1 = 0; + } else { + led1 = 1; + } + } } - -void resetGlobals() { +//------------------------------------------------------------------------------ +// GLOBALS +//------------------------------------------------------------------------------ +void resetSessionVars() { GLOBAL_accel_healthy = false; - GLOBAL_motionStopFlagTriggered = false; + RET_motionTriggeredinFrame = false; + RET_modemBrownOutCountInSession = 0; memset(GLOBAL_exceptionString,0x00,sizeof(GLOBAL_exceptionString)); } void healthCheck() { @@ -404,69 +421,6 @@ setState(STATE_SETUP); } } -void setDefaults() { - //STATE - RET_asleep = false; - RET_busy = false; - RET_haveSettings = false; - RET_state = STATE_SETUP; - RET_state_prev = RET_state; - RET_RTCunixtime = 0; - RET_SetupRunAt = 0; - RET_SettingsGotAt = 0; - RET_force2G = DEFAULT_FORCE2G; - RET_watchdogfired = false; - RET_setupInProgress = false; - RET_receivedNewSettings = false; - RET_GPSFailCount = 0; - RET_NetworkFailCount = 0; - //SETTINGS - RET_setting_firmware = 0; - RET_setting_minimumupdate_hrs = 0; - RET_setting_location_mode = DEFAULT_LOCATION_MODE; - RET_setting_location_accuracy = DEFAULT_LOCATION_ACCURACY; - RET_setting_location_tx_interval_mins = DEFAULT_LOCATION_TX_INTERVAL_MINS; - RET_setting_location_tx_failsafe_hrs = DEFAULT_LOCATION_TX_FAILSAFE_HRS; - RET_setting_location_timeout = DEFAULT_LOCATION_TIMEOUT; - RET_setting_activity_tx_interval_hrs = 0; - RET_setting_activity_mode = 1; - RET_setting_environmental_tx_interval_mins = 0; - RET_setting_motion_g = DEFAULT_MOTION_G; - RET_setting_motion_start_seconds = DEFAULT_MOTION_START_SECONDS; - RET_setting_motion_stop_seconds = DEFAULT_MOTION_STOP_SECONDS; - RET_setting_impact_g = 0; - RET_setting_impact_alert = 0; - RET_setting_connection_timeout = DEFAULT_CONNECTION_TIMEOUT; - RET_setting_beacon_scan = 0; - RET_buttonPressCount = 0; - RET_buttonPressTime = 0; - RET_buttonReleaseTime = 0; - RET_buttonHoldTime = 0; - //MOTION STATE - RET_motionTriggeredinFrame = false; - RET_motionTriggeredInLocTXInterval = false; - RET_motionStartTime = 0; - RET_motionStopTime = 0; - RET_motionPendingOnState = 0; - RET_motionPendingOffState = 0; - RET_motionState = 0; - RET_motionTotalActivityHours = 0.0; - RET_motionTotalActivityHoursSincePost = 0.0; - RET_motionFrameStart = 0; - memset(RET_activityData,0x00,sizeof(RET_activityData)); - //IMPACT - RET_impactTriggered = 0; - //EVENT HANDLING - RET_eventTime_location_log = 0; - RET_eventTime_location_tx = 0; - RET_eventTime_location_failsafe_tx = 0; - RET_eventTime_environmental_log = 0; - RET_eventTime_environmental_tx = 0; - RET_eventTime_activity_tx = 0; - RET_eventTime_wakeFromDormant = 0; - //PERIPHERAL RESET - lis3dh_configureForSleep(DEFAULT_MOTION_G,DEFAULT_IMPACT_G); -} bool selfTest() { int test_count = 0; @@ -481,17 +435,224 @@ test_pass ++; } else { GLOBAL_accel_healthy = false; - addToExceptionString("A"); + addToExceptionString("AF"); } //Result if (test_count == test_pass) { return true; } else { - addToExceptionString("HF"); + //addToExceptionString("HF"); return false; } } +//------------------------------------------------------------------------------ +// BLE FUNCS +//------------------------------------------------------------------------------ +#if BLE_ENABLED +void bleBuildData(bleData_t &bleData) +{ + bleData.applicationSpecificId = BLE_SERVICEID_GPSPLUS; + bleData.firmware = FW_VERSION; + //set flags + if (RET_motionTriggeredinFrame) { + set_8bit_flag(RET_bleAdv_flags, bleAdv_motionTriggeredinFrame_flag); + } else { + clr_8bit_flag(RET_bleAdv_flags, bleAdv_motionTriggeredinFrame_flag); + } + if (RET_motionState) { + set_8bit_flag(RET_bleAdv_flags, bleAdv_motionState_flag); + } else { + clr_8bit_flag(RET_bleAdv_flags, bleAdv_motionState_flag); + } + clr_8bit_flag(RET_bleAdv_flags, bleAdv_impact_flag); + bleData.flags = RET_bleAdv_flags; + bleData.voltage = uint16_t(RET_voltage * 100); + bleData.temperature = uint16_t(getTemperature() * 10); + bleData.humidity = 0xFF; + bleData.lux = 0xFF; + bleData.accel_x = 0xFF; + bleData.accel_y = 0xFF; + bleData.accel_z = 0xFF; + /* + bleData.id_1 = RET_pf_identifier[0]; //dont use this just stick it in the local name + bleData.id_2 = RET_pf_identifier[1]; + bleData.id_3 = RET_pf_identifier[2]; + bleData.id_4 = RET_pf_identifier[3]; + bleData.id_5 = RET_pf_identifier[4]; + bleData.id_6 = RET_pf_identifier[5]; + */ +} +void bleUpdateAndAdvertise(void) +{ + int AdvertisingInterval = (RET_setting_beacon_interval_seconds * 1000); + bleData_t bleData; + bleBuildData(bleData); + myble.gap().stopAdvertising(); + myble.gap().setTxPower(DEFAULT_BEACON_POWER); // set tx power,valid values are -40, -20, -16, -12, -8, -4, 0, 4 + myble.gap().accumulateAdvertisingPayloadTxPower(DEFAULT_BEACON_POWER); // (accepted values are -40, -30, -20, -16, -12, -8, -4, 0, and 4 dBm) + myble.gap().setAdvertisingInterval(AdvertisingInterval); + myble.gap().updateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)&bleData, sizeof(bleData_t)); + //myble.gap().updateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&bleData, sizeof(bleData_t)); + myble.gap().startAdvertising(); + RET_bleBroadcasting = true; + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "BLE Adv Start");debug_exe();} +} +void bleSetupAdvertising(BLE::InitializationCompleteCallbackContext *params) +{ + if (RET_pf_identifier[0] != 0x00 && RET_pf_identifier[1] != 0x00 && RET_pf_identifier[2] != 0x00) { + bleData_t bleData; + bleBuildData(bleData); + char localname[6]; + memcpy(localname,RET_pf_identifier,6); + myble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE ); + myble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)localname, sizeof(localname)); + myble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, (uint8_t *)&bleData, sizeof(bleData_t)); + //myble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, (uint8_t *)&bleData, sizeof(bleData_t)); + myble.gap().setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED); + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "BLE Setup...");debug_exe();} + } +} +void bleStopAdvertising(void) +{ + myble.gap().stopAdvertising(); + RET_bleBroadcasting = false; + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "BLE Adv Stop");debug_exe();} +} +void bleAdvertisementCallback(const Gap::AdvertisementCallbackParams_t *params) { + struct AdvertisingData_t { + uint8_t length; + GapAdvertisingData::DataType_t dataType; + uint8_t data[0]; + } PACKED; + struct bleData_t { + uint16_t applicationSpecificId; + } PACKED; + + //LOOKING FOR (SIAEC BETA) + //14f64b977c250854 + //442ce31996801546 + + char beta_location_tag_0[17] = {'4','1','1','7','6','9','0','5','6','4','6','8','3','f','6','8',0x00}; //bens + char beta_location_tag_1[17] = {'1','4','f','6','4','b','9','7','7','c','2','5','0','8','5','4',0x00}; //singapore + char beta_location_tag_2[17] = {'4','4','2','c','e','3','1','9','9','6','8','0','1','5','4','6',0x00}; //singapore + + //Portal demos + char beta_location_tag_3[17] = {'1','5','f','c','6','d','d','5','c','3','7','f','1','f','4','a',0x00}; + char beta_location_tag_4[17] = {'b','a','a','e','c','d','6','8','b','d','7','e','e','a','6','5',0x00}; + char beta_location_tag_5[17] = {'7','e','4','b','7','8','e','0','f','a','3','3','0','8','a','0',0x00}; + char beta_location_tag_6[17] = {'e','1','1','3','c','d','e','a','a','e','f','f','1','4','d','9',0x00}; + char beta_location_tag_7[17] = {'8','c','9','2','4','5','f','f','0','c','f','a','b','9','2','f',0x00}; + char beta_location_tag_8[17] = {'0','7','e','9','9','1','d','3','b','e','b','6','4','0','4','8',0x00}; + char beta_location_tag_9[17] = {'9','5','6','3','a','0','8','6','2','1','e','8','e','c','1','4',0x00}; + + //Search for the manufacturer specific data with matching application-ID + AdvertisingData_t *pAdvData; + for (size_t index = 0; index < params->advertisingDataLen; index += (pAdvData->length + 1)) { + pAdvData = (AdvertisingData_t *)¶ms->advertisingData[index]; + const bleData_t *pbleData = (const bleData_t *)pAdvData->data; + + //ESTIMOTE BEACON + //example data 020104 0303 9afe1716 9afe 22 02c887042a33f9f0 00efebc60146f8ffffffff //spaces just to show identifier + + //BLE TYPE SWITCH + switch(pbleData->applicationSpecificId) { + case BLE_SERVICEID_PFBEACON1 : + { + char beacon_identifier[17]; + snprintf(beacon_identifier, sizeof(beacon_identifier), "%02x%02x%02x%02x%02x%02x%02x%02x", + params->advertisingData[12], + params->advertisingData[13], + params->advertisingData[14], + params->advertisingData[15], + params->advertisingData[16], + params->advertisingData[17], + params->advertisingData[18], + params->advertisingData[19]); + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), " Mac: [%02x%02x%02x%02x%02x%02x], rssi: %d, AType: %u, S: %04x, Id: %s",params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],params->rssi, params->type, pbleData->applicationSpecificId, beacon_identifier);debug_exe();} + //check to see if its one of the two location beta beacons we are looking for... + if (strcmp(beacon_identifier, beta_location_tag_0) == 0 + || strcmp(beacon_identifier, beta_location_tag_1) == 0 + || strcmp(beacon_identifier, beta_location_tag_2) == 0 + || strcmp(beacon_identifier, beta_location_tag_3) == 0 + || strcmp(beacon_identifier, beta_location_tag_4) == 0 + || strcmp(beacon_identifier, beta_location_tag_5) == 0 + || strcmp(beacon_identifier, beta_location_tag_6) == 0 + || strcmp(beacon_identifier, beta_location_tag_7) == 0 + || strcmp(beacon_identifier, beta_location_tag_8) == 0 + || strcmp(beacon_identifier, beta_location_tag_9) == 0 + ) { + //dump advertising data + //for (unsigned index = 0; index < params->advertisingDataLen; index++) { if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "%02x",params->advertisingData[index]);debug_exe(false);}} + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), " MATCH");debug_exe();} + int tag_rssi = params->rssi * -1; //to convert to positive number + if (tag_rssi < RET_closestLocationTag_rssi) { + RET_closestLocationTag_rssi = tag_rssi; + memcpy(RET_closestLocationTag_id, beacon_identifier, sizeof(RET_closestLocationTag_id)); + RET_locationTag_present = true; + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "Location Tag Present: %s, rssi: %d",closestLocationTag_id, closestLocationTag_rssi);debug_exe();} + } + } + break; + } + case BLE_SERVICEID_BT04 : + { + //nothing yet + break; + } + case BLE_SERVICEID_PFDETECTOR1 : + { + char ble_advdata[100]; + snprintf(ble_advdata, sizeof(ble_advdata), "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + params->advertisingData[0], + params->advertisingData[1], + params->advertisingData[2], + params->advertisingData[3], + params->advertisingData[4], + params->advertisingData[5], + params->advertisingData[6], + params->advertisingData[7], + params->advertisingData[8], + params->advertisingData[9], + params->advertisingData[10], + params->advertisingData[11], + params->advertisingData[12], + params->advertisingData[13], + params->advertisingData[14], + params->advertisingData[15], + params->advertisingData[16], + params->advertisingData[17], + params->advertisingData[18], + params->advertisingData[19], + params->advertisingData[20]); + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), " Mac: [%02x%02x%02x%02x%02x%02x], rssi: %d, AType: %u, Id: %s",params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0],params->rssi, pAdvData->dataType, ble_advdata);debug_exe();} + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "Detector @rssi: %d",params->rssi);debug_exe();} + if (params->rssi >= -75) { + RET_detector_present = true; + } + break; + } + } + } +} +void bleConfigureScan(void) +{ + //configure scan + //myble.gap().setScanParams(60,30); //scan interval //scan window + myble.gap().setScanParams(100,100); //scan interval //scan window + myble.gap().startScan(bleAdvertisementCallback); +} +void bleStopScan(void) +{ + myble.gap().stopScan(); +} +void bleShutdown(void) +{ + bleStopScan(); + bleStopAdvertising(); + myble.shutdown(); +} +#endif //------------------------------------------------------------------------------ // MOTION FUNCS @@ -501,6 +662,9 @@ if (lis3dh_int2) { RET_motionTriggeredinFrame = true; GLOBAL_needToConfigureLis3dh = true; //interrupt has fire so need to clear it + if(RET_debug) { + LED1on(100); + } if (!RET_motionPendingOnState) { RET_motionPendingOnState = true; RET_motionPendingOffState = false; @@ -521,29 +685,35 @@ if (RET_motionPendingOnState) { //check if above threshold time_t inMotionForSeconds = ((RET_RTCunixtime - RET_motionStartTime) + (DEFAULT_SLEEP_FRAME / 1000)); //Plus DEFAULT_SLEEP_FRAME as it should include frame time - if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MOT:%u s",inMotionForSeconds);debug_exe();} - if (inMotionForSeconds >= (RET_setting_motion_start_seconds + 15) && RET_motionState == false) { + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "M:%u",inMotionForSeconds);debug_exe();} + if (inMotionForSeconds >= RET_setting_motion_start_seconds) { + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MotionOn");debug_exe();} RET_motionState = true; - RET_motionTriggeredInLocTXInterval = true; - if (RET_setting_activity_mode == 2 && RET_setting_activity_tx_interval_hrs > 0) { - time_t epochOffsetMins = ((RET_RTCunixtime - RET_motionFrameStart) / 60); - sprintf(RET_activityData+strlen(RET_activityData),"1.%u!",epochOffsetMins); + RET_motionStateOnInLocTXInterval = true; + if (RET_motionState == false) { //If this is first after motionState 0 + if (RET_setting_activity_mode == 2 && RET_setting_activity_tx_interval_hrs > 0) { + time_t epochOffsetMins = ((RET_RTCunixtime - RET_motionFrameStart) / 60); + sprintf(RET_activityData+strlen(RET_activityData),"1.%u!",epochOffsetMins); + } } } } if (RET_motionPendingOffState) { time_t noMotionForSeconds = ((RET_RTCunixtime - RET_motionStopTime) + (DEFAULT_SLEEP_FRAME / 1000)); //Plus DEFAULT_SLEEP_FRAME as it should include frame time - if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MOTLESS:%u s",noMotionForSeconds);debug_exe();} - if (noMotionForSeconds >= (RET_setting_motion_stop_seconds + 15) && RET_motionState == true) { - RET_motionPendingOffState = false; - RET_motionState = false; - GLOBAL_motionStopFlagTriggered = true; - if (RET_setting_activity_mode > 0 && RET_setting_activity_tx_interval_hrs > 0) { - RET_motionTotalActivityHoursSincePost += ((float(RET_motionStopTime)-float(RET_motionStartTime)) / 3600.0f); - RET_motionTotalActivityHours += RET_motionTotalActivityHoursSincePost; - if (RET_setting_activity_mode == 2) { - time_t epochOffsetMins = ((RET_RTCunixtime - RET_motionFrameStart) / 60); - sprintf(RET_activityData+strlen(RET_activityData),"0.%u!",epochOffsetMins); + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "NM:%u",noMotionForSeconds);debug_exe();} + if (noMotionForSeconds >= RET_setting_motion_stop_seconds) { + if (RET_motionState == true) { + RET_motionPendingOffState = false; + RET_motionState = false; + GLOBAL_motionStopFlagTriggered = true; + //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MotionStop");debug_exe();} + if (RET_setting_activity_mode > 0 && RET_setting_activity_tx_interval_hrs > 0) { + RET_motionTotalActivityHoursSincePost += ((float(RET_motionStopTime)-float(RET_motionStartTime)) / 3600.0f); + RET_motionTotalActivityHours += RET_motionTotalActivityHoursSincePost; + if (RET_setting_activity_mode == 2) { + time_t epochOffsetMins = ((RET_RTCunixtime - RET_motionFrameStart) / 60); + sprintf(RET_activityData+strlen(RET_activityData),"0.%u!",epochOffsetMins); + } } } } @@ -595,7 +765,7 @@ if(TEMP_c != -1) { RET_setting_firmware = TEMP_c; } else { RET_setting_firmware = -1;} if(TEMP_d != -1) { setState(TEMP_d); } else { setState(STATE_NORMAL);} if(TEMP_e != -1) { RET_setting_location_mode = TEMP_e; } - if(RET_setting_location_mode > 3) {RET_setting_location_mode = DEFAULT_LOCATION_MODE;} + if(RET_setting_location_mode > 4) {RET_setting_location_mode = DEFAULT_LOCATION_MODE;} if(TEMP_f != -1) { RET_setting_location_accuracy = TEMP_f; } if(RET_setting_location_accuracy > 3) {RET_setting_location_accuracy = DEFAULT_LOCATION_ACCURACY;} if(TEMP_g != -1) { RET_setting_location_tx_interval_mins = TEMP_g; } @@ -630,6 +800,9 @@ //Broadcast any activity data we have before fw update event_activity_tx(); //prep for FW update + #if BLE_ENABLED + bleShutdown(); + #endif read_app_data_from_flash(&app_data); clr_flag(&app_data, app_execution_flag); clr_flag(&app_data, first_run_flag); @@ -691,7 +864,7 @@ int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime); char bytestosend[100]; memset(bytestosend,0x00,sizeof(bytestosend)); - snprintf(bytestosend,sizeof(bytestosend),"(%s,a:log,f:%d,v:%.2f,e:%d,z:%s.%s,c:1,s:0)\0",GLOBAL_defaultApi,FW_VERSION,RET_voltage,timetaken,error,GLOBAL_exceptionString); + snprintf(bytestosend,sizeof(bytestosend),"(%s,a:log,f:%d,v:%.2f,e:%d,z:%s.%s,s:0)\0",GLOBAL_defaultApi,FW_VERSION,RET_voltage,timetaken,error,GLOBAL_exceptionString); if (modem.on(RET_force2G)) { if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,RET_setting_connection_timeout,RET_NetworkFailCount)) { modem.USSDmessage(bytestosend, false, GLOBAL_defaultApi); @@ -722,6 +895,9 @@ return; } void failed_broadcasts_tx() { + #if BLE_ENABLED + bleStopAdvertising(); + #endif //check we have something to send... int numbertosend = 0; for(int i = 0; i < sizeof(GLOBAL_failed_broadcast_slots); i++) { @@ -751,6 +927,9 @@ } } bool event_setup(bool manualrun) { + #if BLE_ENABLED + bleStopAdvertising(); + #endif bool pass = false; LED1on(0); if (RET_NetworkFailCount > DEFAULT_MAX_FAILED_CONNECTIONS) addToExceptionString("NF"); @@ -767,7 +946,7 @@ int timetaken_connection = (RET_RTCunixtime - connectionStartTime); if (manualrun) addToExceptionString("MAN"); char bytestosend[160]; - snprintf(bytestosend,sizeof(bytestosend),"(%s,a:setup,f:%d,v:%.2f,t:%.1f,e:%d,y:%d,z:SETUP-%s,k:%s,m:%s,c:1,s:1)\0",GLOBAL_defaultApi,FW_VERSION,RET_voltage,RET_temperature,timetaken_total,timetaken_connection,GLOBAL_exceptionString,SKU,HW_MAJORREVISION); + snprintf(bytestosend,sizeof(bytestosend),"(%s,a:setup,f:%d,v:%.2f,t:%.1f,e:%d,y:%d,z:SETUP-%s,k:%s,m:%s,s:1)\0",GLOBAL_defaultApi,FW_VERSION,RET_voltage,RET_temperature,timetaken_total,timetaken_connection,GLOBAL_exceptionString,SKU,HW_MAJORREVISION); char result[200]; snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, true, GLOBAL_defaultApi)); RET_setupInProgress = false; //this turns off the flashing led @@ -796,10 +975,10 @@ if (pass == true) { GLOBAL_wakeTime = RET_RTCunixtime; //lets reset this here so that the following loc and act function have sensible values for total time //GET LOC DATA - uint8_t previous_location_accuracy = RET_setting_location_accuracy; - RET_setting_location_accuracy = 1; //set location mode to CL only + //uint8_t previous_location_accuracy = RET_setting_location_accuracy; + //RET_setting_location_accuracy = 1; //set location mode to CL only event_location_tx(false); - RET_setting_location_accuracy = previous_location_accuracy; //set location mode back to previous + //RET_setting_location_accuracy = previous_location_accuracy; //set location mode back to previous //SEND ANY ACTIVITY DATA event_activity_tx(); LED1blink(4,500); //PASS AND END @@ -809,10 +988,14 @@ RET_SetupRunAt = RET_RTCunixtime; RET_GPSFailCount = 0; RET_NetworkFailCount = 0; + setEventTimes(); //RESULT return pass; } void event_turnonofflog_tx(bool turnon) { + #if BLE_ENABLED + bleStopAdvertising(); + #endif RET_NetworkFailCount = 0; //reset network blocker RET_GPSFailCount = 0; updateBatteryV(); @@ -827,9 +1010,9 @@ int timetaken_connection = (RET_RTCunixtime - connectionStartTime); char bytestosend[160]; if (turnon) { - snprintf(bytestosend,sizeof(bytestosend),"(%s,a:log,f:%d,t:%.1f,v:%.2f,z:TURNON,e:%d,y:%d,x:%d,c:1,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_voltage,timetaken_total,timetaken_connection,timetaken_gps,locString); + snprintf(bytestosend,sizeof(bytestosend),"(%s,a:log,f:%d,t:%.1f,v:%.2f,z:TURNON,e:%d,y:%d,x:%d,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_voltage,timetaken_total,timetaken_connection,timetaken_gps,locString); } else { - snprintf(bytestosend,sizeof(bytestosend),"(%s,a:log,f:%d,t:%.1f,v:%.2f,z:TURNOFF,e:%d,y:%d,x:%d,c:1,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_voltage,timetaken_total,timetaken_connection,timetaken_gps,locString); + snprintf(bytestosend,sizeof(bytestosend),"(%s,a:log,f:%d,t:%.1f,v:%.2f,z:TURNOFF,e:%d,y:%d,x:%d,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_voltage,timetaken_total,timetaken_connection,timetaken_gps,locString); } char result[180]; snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, false, GLOBAL_defaultApi)); @@ -837,57 +1020,111 @@ } } void event_location_tx(bool failsafe) { + #if BLE_ENABLED + bleStopAdvertising(); + #endif //check if we have any outstanding to send failed_broadcasts_tx(); bool selfTestResult = selfTest(); + bool skipTX = false; char bytesToSend[160]; - //see if we are in range of ble detector, if so, no need to get gps and broadcast - //Set any network or GPS fail flags - if (RET_NetworkFailCount > DEFAULT_MAX_FAILED_CONNECTIONS) addToExceptionString("NF"); - if (RET_GPSFailCount > DEFAULT_MAX_FAILED_GPS) addToExceptionString("GF"); - //lets check to see if we've had repeated comms failings in this location, if so dont bother trying. reset by movment and timeout - if (RET_NetworkFailCount <= DEFAULT_MAX_FAILED_CONNECTIONS) { - if (RET_receivedNewSettings) {RET_receivedNewSettings = false; addToExceptionString("SR"); } - if (modem.on(RET_force2G)) { - char locString[70]; - int gpsStartTime = RET_RTCunixtime; - memcpy(locString, modem.getLocation(RET_setting_location_accuracy, RET_setting_location_timeout, RET_GPSFailCount, RET_NetworkFailCount), sizeof(locString)); - int timetaken_gps = (RET_RTCunixtime - gpsStartTime); - - //SEND DATA - int connectionStartTime = RET_RTCunixtime; - if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,RET_setting_connection_timeout,RET_NetworkFailCount)) { - int timetaken_total = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for avg ussd response time. - int timetaken_connection = (RET_RTCunixtime - connectionStartTime); - //Check if we should wait for settings back - bool getSettings = true; - //work out if we need to get settings back - if ( ((RET_RTCunixtime - RET_SettingsGotAt)/3600) < RET_setting_minimumupdate_hrs ) { getSettings = false; timetaken_total -= 10;} //remove the extra 10 seconds from times - snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:loc,f:%d,t:%.1f,v:%.2f,z:LOC-%s,e:%d,y:%d,x:%d,j:%d,c:1,s:%d%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_voltage,GLOBAL_exceptionString,timetaken_total,timetaken_connection,timetaken_gps,RET_motionTriggeredInLocTXInterval,getSettings,locString); - char result[180]; - snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytesToSend, getSettings, GLOBAL_defaultApi)); - if (getSettings == true && strcmp(result, "sendokrecfail") == 0) { - //send ok but receive fail - if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"USSD Send Ok but Rec fail");debug_exe();} - sendErrorLog("ERR-LOC-NR"); - } else if (strcmp(result, "sendok") == 0) { - //do nothing - } else if (strcmp(result, "sendfail") == 0) { - if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"USSD Send Fail");debug_exe();} - //need to log for retry + + //Check for Nearby Location Beacons + #if BLE_ENABLED + memset(RET_closestLocationTag_id, 0x00, sizeof(RET_closestLocationTag_id)); + RET_closestLocationTag_rssi = 999; + RET_locationTag_present = false; + RET_detector_present = false; + if (RET_setting_beacon_scan == 1 && RET_setting_location_mode != LOCATION_MODE_REALTIME) { + LowPowerTimer bleScan_t; + bleScan_t.start(); + uint32_t bleScan_startmillis = bleScan_t.read_ms(); uint32_t bleScan_runtime = 0; + if (!myble.hasInitialized()) { + myble.init(); + while (!myble.hasInitialized() && bleScan_runtime < 1000) { + bleScan_runtime = (bleScan_t.read_ms() - bleScan_startmillis); + } + } + if (myble.hasInitialized()) { + //Scan for 10 seconds + bleConfigureScan(); + bleScan_startmillis = bleScan_t.read_ms(); + while (bleScan_runtime < 10000 && RET_detector_present == false) { + bleScan_runtime = (bleScan_t.read_ms() - bleScan_startmillis); + myble.waitForEvent(); // low power wait for event + } + //if (LocationTag_preset) if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "LocationTag: %s, rssi: %d",closestLocationTag_id, closestLocationTag_rssi);debug_exe();} + } + bleScan_t.stop(); + myble.gap().stopScan(); + } + //see if we are in range of ble detector, if so, no need to get gps and broadcast + if (RET_detector_present == true && RET_setting_beacon_interval_seconds > 0) { + skipTX = true; + } + #endif + + + if (skipTX == false || failsafe == true) { + //Set any network or GPS fail flags + if (RET_NetworkFailCount > DEFAULT_MAX_FAILED_CONNECTIONS) addToExceptionString("NF"); + if (RET_GPSFailCount > DEFAULT_MAX_FAILED_GPS) addToExceptionString("GF"); + //lets check to see if we've had repeated comms failings in this location, if so dont bother trying. reset by movment and timeout + if (RET_NetworkFailCount <= DEFAULT_MAX_FAILED_CONNECTIONS) { + if (RET_receivedNewSettings) {RET_receivedNewSettings = false; addToExceptionString("SR"); } + if (modem.on(RET_force2G)) { + char locString[70]; + int gpsStartTime = RET_RTCunixtime; + + //check if we have moved since last post, if not use same valid gps fix if exists + if (RET_motionStateOnInLocTXInterval == false && GLOBAL_have_GPSlocString_prev == true) { + memcpy(locString, GLOBAL_GPSlocString_prev, sizeof(locString)); + addToExceptionString("P"); } else { - if (getSettings) { - if (saveSettings(result) == false){sendErrorLog("ERR-LOC-IR");} + memcpy(locString, modem.getLocation(RET_setting_location_accuracy, RET_setting_location_timeout, RET_GPSFailCount, RET_NetworkFailCount), sizeof(locString)); + } + + int timetaken_gps = (RET_RTCunixtime - gpsStartTime); + + //SEND DATA + int connectionStartTime = RET_RTCunixtime; + if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,RET_setting_connection_timeout,RET_NetworkFailCount)) { + int timetaken_total = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for avg ussd response time. + int timetaken_connection = (RET_RTCunixtime - connectionStartTime); + //Check if we should wait for settings back + bool getSettings = true; + //work out if we need to get settings back + if ( ((RET_RTCunixtime - RET_SettingsGotAt)/3600) < RET_setting_minimumupdate_hrs ) { getSettings = false; timetaken_total -= 10;} //remove the extra 10 seconds from times + snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:loc,f:%d,t:%.0f,n:%.0f,q:%.0f,v:%.1f,z:L%s,e:%d,y:%d,x:%d,j:%d,s:%d%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_temperature_min,RET_temperature_max,RET_voltage,GLOBAL_exceptionString,timetaken_total,timetaken_connection,timetaken_gps,RET_motionStateOnInLocTXInterval,getSettings,locString); + //snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:loc,f:%d,t:%.0f,v:%.1f,z:L-%s,e:%d,y:%d,x:%d,j:%d,s:%d%s)\0",GLOBAL_defaultApi,FW_VERSION,RET_temperature,RET_voltage,GLOBAL_exceptionString,timetaken_total,timetaken_connection,timetaken_gps,RET_motionStateOnInLocTXInterval,getSettings,locString); + char result[180]; + snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytesToSend, getSettings, GLOBAL_defaultApi)); + if (getSettings == true && strcmp(result, "sendokrecfail") == 0) { + //send ok but receive fail + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"USSD Send Ok but Rec fail");debug_exe();} + //sendErrorLog("ERR-LOC-NR"); + } else if (strcmp(result, "sendok") == 0) { + //do nothing + } else if (strcmp(result, "sendfail") == 0) { + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"USSD Send Fail");debug_exe();} + //need to log for retry + } else { + if (getSettings) { + if (saveSettings(result) == false){sendErrorLog("ERR-LOC-IR");} + } } } } } } //RESETS - RET_motionTriggeredInLocTXInterval = false; + RET_motionStateOnInLocTXInterval = false; setEventTime_Location(); } void event_activity_tx() { + #if BLE_ENABLED + bleStopAdvertising(); + #endif //check if we have any outstanding to send failed_broadcasts_tx(); //check we have something to send... @@ -896,9 +1133,9 @@ //Build data to send char bytesToSend[160]; if (RET_setting_activity_mode == 1) { - snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,t:%u,r:%.2f,h:%.2f,c:1)\0",GLOBAL_defaultApi,RET_motionFrameStart,RET_motionTotalActivityHoursSincePost,RET_motionTotalActivityHours); + snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,t:%u,r:%.2f,h:%.2f)\0",GLOBAL_defaultApi,RET_motionFrameStart,RET_motionTotalActivityHoursSincePost,RET_motionTotalActivityHours); } else if (RET_setting_activity_mode == 2) { - snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,e:%s,t:%u,r:%.2f,c:1)\0",GLOBAL_defaultApi,RET_activityData,RET_motionFrameStart,RET_motionTotalActivityHoursSincePost); + snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,e:%s,t:%u,r:%.2f)\0",GLOBAL_defaultApi,RET_activityData,RET_motionFrameStart,RET_motionTotalActivityHoursSincePost); } if (RET_NetworkFailCount <= DEFAULT_MAX_FAILED_CONNECTIONS) { if (modem.on(RET_force2G)) { @@ -937,48 +1174,6 @@ memset(RET_activityData,0x00,sizeof(RET_activityData)); setEventTime_Activity(); } -/* -void event_activity_tx() { - bool sendok = false; - //check if we have any outstanding to send - failed_broadcasts_tx(); - - //check we have something to send... - if (RET_motionTotalActivityHoursSincePost > 0.0f && RET_setting_activity_mode > 0) { - //Build data to send - char bytesToSend[160]; - if (RET_setting_activity_mode == 1) { - snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,t:%u,r:%.2f,h:%.2f,c:1)\0",GLOBAL_defaultApi,RET_motionFrameStart,RET_motionTotalActivityHoursSincePost,RET_motionTotalActivityHours); - } else if (RET_setting_activity_mode == 2) { - snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,e:%s,t:%u,r:%.2f,c:1)\0",GLOBAL_defaultApi,RET_activityData,RET_motionFrameStart,RET_motionTotalActivityHoursSincePost); - } - if (RET_NetworkFailCount <= DEFAULT_MAX_FAILED_CONNECTIONS) { - if (modem.on(RET_force2G)) { - //SEND DATA - if (modem.registerOnNetwork(2,RET_setting_connection_timeout,RET_NetworkFailCount)) { - char result[100]; - bool getResponse = false; - snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytesToSend, getResponse, GLOBAL_defaultApi)); - if (strcmp(result, "sendok") == 0) { - //sendok = true; - if(!RET_debug) {sendok = true;} - } - } - } - modem.off(true); - } - //If send failed then log it for retry - if (sendok == false) { - failed_broadcast_log(bytesToSend); - } - } - //RESETS - RET_motionTotalActivityHoursSincePost = 0.0f; - memset(RET_activityData,0x00,sizeof(RET_activityData)); - if (RET_haveSettings) { RET_motionFrameStart = RET_RTCunixtime; } //this is now safe to do as we are logging the fails - setEventTime_Activity(); -} -*/ //------------------------------------------------------------------------------ // STATE ENGINE @@ -1018,27 +1213,27 @@ break; case 2: //INTERVAL POST WITH MOTION CHECK if(RET_RTCunixtime >= RET_eventTime_location_tx && RET_eventTime_location_tx > 0) { - if (RET_motionTriggeredInLocTXInterval == true) { + if (RET_motionStateOnInLocTXInterval == true || RET_motionState == true) { run_location_tx = true; } else { - if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "Skip TX no mot\n");debug_exe();} + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "Skip TX no mot\n");debug_exe();} } } break; case 3: //POST ON STOP MOTION - if (GLOBAL_motionStopFlagTriggered) { run_location_tx = true; GLOBAL_motionStopFlagTriggered = false; } + if (GLOBAL_motionStopFlagTriggered) { GLOBAL_motionStopFlagTriggered = false; run_location_tx = true; } break; } if(RET_RTCunixtime >= RET_eventTime_location_failsafe_tx && RET_eventTime_location_failsafe_tx > 0) { RET_NetworkFailCount = 0; //reset to ensure connection RET_GPSFailCount = 0; // reset to ensure gps try + addToExceptionString("FS"); updateBatteryV(); event_location_tx(true); } else { if (run_location_tx) { updateBatteryV(); event_location_tx(false); } } - //ACTIVITY EVENT bool run_activity_tx = false; if(RET_RTCunixtime >= RET_eventTime_activity_tx && RET_eventTime_activity_tx > 0) { @@ -1179,7 +1374,7 @@ //INIT LED1off(); ThisThread::sleep_for(2000); //Initial pause, this is needed for softdevice to init, dont remove!! If we dont have this we get crashes - watchdog.configure(300.0); //5 mins + watchdog.configure(300.0); //5 mins //Do not set to less than 4500ms or can cause issues with softdevice modem.off(false); RTCticker.attach(&RTCtick, 1.0); LPtimer.start(); @@ -1194,54 +1389,42 @@ RET_coldBoot = 1; switch(NRF_POWER->RESETREAS) { case 0x00000001 : - //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:HW\n");debug_exe();} + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:HW\n");debug_exe();} break; case 0x00000002 : - //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:WD\n");debug_exe();} + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:WD\n");debug_exe();} break; case 0x00000004 : - //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:SW\n");debug_exe();} + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:SW\n");debug_exe();} break; case 0x00000008 : - //if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:LU\n");debug_exe();} + if(RET_debug){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer),"RR:LU\n");debug_exe();} break; } NRF_POWER->RESETREAS = 0xffffffff; - } else { - //if its not one of these reasons then its a power-on or a brown-out - //if(get_flag(&app_data, app_execution_flag) == false) { - //THIS is a unexpected reset / brownout??? - //} } //CHECK FOR FIRST BOOT - if (RET_coldBoot == 1) { - setDefaults(); - //check battery + if (RET_coldBoot == 1) { + memset(RET_activityData,0x00,sizeof(RET_activityData)); + lis3dh_configureForSleep(DEFAULT_MOTION_G,DEFAULT_IMPACT_G); updateBatteryV(); - if (RET_voltage < 2.5f) { - //battery low - LED1errorCode(10,2); - } + if (RET_voltage < 2.5f) { LED1errorCode(10,2);} addToExceptionString("FR"); } //MAIN LOOP - while(true) { - //WATCHDOG - watchdogKick(); + while(true) { RET_asleep = false; + watchdogKick(); updateTemperatures(); - - //INIT - resetGlobals(); + resetSessionVars(); healthCheck(); //this must be after resetGlobals GLOBAL_wakeTime = RET_RTCunixtime; //check and log motion if (RET_state == STATE_NORMAL || RET_state == STATE_SETUP) { - if (checkMotion() == true) { - //if motionstate is true, then reset network and gps fail counts, so that they are not skipped + if (checkMotion() == true) { //if motionstate is true, then reset network and gps fail counts, so that they are not skipped RET_NetworkFailCount = 0; RET_GPSFailCount = 0; } @@ -1250,7 +1433,7 @@ //MAIN LOGIC if(RET_debug){ if (RET_state != 99) { - debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "F:%d, S:%d, SET:%d, MF:%d, MS:%d, MTX:%d, %u, L:%u, LFS:%u, A:%u", FW_VERSION, RET_state, RET_haveSettings, RET_motionTriggeredinFrame, RET_motionState, RET_motionTriggeredInLocTXInterval, RET_RTCunixtime,RET_eventTime_location_tx,RET_eventTime_location_failsafe_tx,RET_eventTime_activity_tx);debug_exe(); + debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "F:%d, S:%d, SET:%d, MF:%d, MS:%d, MTX:%d, %u, L:%u, LFS:%u, A:%u", FW_VERSION, RET_state, RET_haveSettings, RET_motionTriggeredinFrame, RET_motionState, RET_motionStateOnInLocTXInterval, RET_RTCunixtime,RET_eventTime_location_tx,RET_eventTime_location_failsafe_tx,RET_eventTime_activity_tx);debug_exe(); debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "ACT M:%d, HsP:%.2f, Ht:%.2f, D:%s",RET_setting_activity_mode,RET_motionTotalActivityHoursSincePost,RET_motionTotalActivityHours,RET_activityData);debug_exe(); } else { debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "F:%d, S:%d, WAKE@:%u\n", FW_VERSION, RET_state, RET_eventTime_wakeFromDormant);debug_exe(); @@ -1270,19 +1453,35 @@ RET_coldBoot = 0; } + //CONFIGURE BLE BEACON BROADCAST + #if BLE_ENABLED + //see if we are in range of ble detector, if so, no need to get gps and broadcast + if (RET_setting_beacon_interval_seconds > 0 && RET_pf_identifier[0] != 0x00 && RET_pf_identifier[1] != 0x00 && RET_pf_identifier[2] != 0x00) { + if (RET_bleBroadcasting == false) { + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "BLE init...");debug_exe();} + myble.init(bleSetupAdvertising); + if (myble.hasInitialized()) { + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "OK");debug_exe();} + bleUpdateAndAdvertise(); + } else { + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "FAIL");debug_exe();} + } + } else { + if(RET_debug) {debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "BLE update");debug_exe();} + bleUpdateAndAdvertise(); + } + } else { + if (RET_bleBroadcasting == true) bleStopAdvertising(); + } + #endif + //PRE-SLEEP ACTIONS LED1off(); - if (GLOBAL_modemOn) { - modem.off(true); //SOFT SHUT DOWN - THIS IS THE ONLY MODEM OFF, DONT REMOVE - } else { - modem.off(false); //HARD SHUT DOWN - THIS IS THE ONLY MODEM OFF, DONT REMOVE - } - RET_motionTriggeredinFrame = false; + modem.off(GLOBAL_modemOn); //HARD OR SOFT SHUT DOWN - DEPENDING ON modemOn state if (GLOBAL_needToConfigureLis3dh) { lis3dh_configureForSleep(RET_setting_motion_g,RET_setting_impact_g); } nrf_configureForSleep(); NRFuart_uninit(); watchdogKick(); - //SLEEP RET_asleep = true; mainthread.wait(DEFAULT_SLEEP_FRAME);