init

Dependencies:   aconno_I2C Lis2dh12 WatchdogTimer

Revision:
45:6c7f5b556d74
Parent:
44:061509d1b38c
Child:
46:b95fe3484d88
--- a/main.cpp	Sun Jan 20 12:50:31 2019 +0000
+++ b/main.cpp	Sun Jan 20 21:40:53 2019 +0000
@@ -3,7 +3,8 @@
 //------------------------------------------------------------------------------
 //FUNCTION PROTOTYPES - NEED TO ADD ALL OF THE MISSING ONES
 //------------------------------------------------------------------------------ 
-//should really add these
+//should really add these - will just add as and when needed for now
+void event_activity_tx(uint8_t activity_mode);
 
 //------------------------------------------------------------------------------
 // GLOBALS
@@ -29,6 +30,7 @@
 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;
@@ -53,17 +55,19 @@
 bool             RET_setupInProgress;
 bool             RET_force2G;
 bool             RET_watchdogfired;
+bool             RET_receivedNewSettings;
 //MOTION STATE
 bool             RET_motionTriggeredinFrame;
-bool             RET_motionTriggeredInTXInterval;
+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;
-char             RET_activityData[140];
+char             RET_activityData[ACTIVITY_BUFFERSIZE];
 //IMPACT
 bool             RET_impactTriggered;
 //EVENTS LOGGING
@@ -108,7 +112,6 @@
     RET_state_prev = RET_state;
     RET_state = state;
 }
-
 void dumpSettings() {    
     if(DEBUG_ON){
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_RTCunixtime:%u", RET_RTCunixtime);debug_exe();
@@ -121,6 +124,7 @@
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_location_tx_failsafe_hrs:%d", RET_setting_location_tx_failsafe_hrs);debug_exe();
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_location_timeout:%d", RET_setting_location_timeout);debug_exe();
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_activity_tx_interval_hrs:%d", RET_setting_activity_tx_interval_hrs);debug_exe();
+        debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_activity_mode:%d", RET_setting_activity_mode);debug_exe();        
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_environmental_tx_interval_mins:%d", RET_setting_environmental_tx_interval_mins);debug_exe();
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_motion_g:%d", RET_setting_motion_g);debug_exe();
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_motion_start_seconds:%d", RET_setting_motion_start_seconds);debug_exe();
@@ -132,6 +136,23 @@
         debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "RET_setting_beacon_scan:%d", RET_setting_beacon_scan);debug_exe();
     }
 }
+void recordFirmwareAsValid() {
+    read_app_data_from_flash(&app_data);
+    bool write_app_data_to_flash_execute = false;
+    if(get_flag(&app_data, app_execution_flag) == true) {
+        clr_flag(&app_data, app_execution_flag);
+        clr_flag(&app_data, first_run_flag);
+        write_app_data_to_flash_execute = true;
+    }
+    if(app_data.current_firmware_version != FW_VERSION) {
+        app_data.current_firmware_version = FW_VERSION;
+        app_data.target_firmware_version = FW_VERSION;
+        write_app_data_to_flash_execute = true;
+    }
+    if (write_app_data_to_flash_execute) {
+        write_app_data_to_flash(&app_data);
+    }   
+}
 float getBatteryV() {
     NRF52_SAADC batteryIn;
     batteryIn.addChannel(9); // vdd for battery
@@ -167,7 +188,9 @@
     return temperature;  
 }
 void addToExceptionString(char* value) {
-    snprintf(GLOBAL_exceptionString+strlen(GLOBAL_exceptionString),sizeof(GLOBAL_exceptionString),"%s.",value);
+    if(strstr(GLOBAL_exceptionString, value) == false){
+        snprintf(GLOBAL_exceptionString+strlen(GLOBAL_exceptionString),sizeof(GLOBAL_exceptionString),"%s.",value);
+    }
 }
 //------------------------------------------------------------------------------
 // USER BUTTON HANDLING
@@ -289,6 +312,7 @@
     RET_force2G = DEFAULT_FORCE2G;
     RET_watchdogfired = false;
     RET_setupInProgress = false;
+    RET_receivedNewSettings = false;
     //SETTINGS
     RET_setting_firmware = 0;
     RET_setting_minimumupdate_hrs = 0;
@@ -298,6 +322,7 @@
     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;
@@ -311,14 +336,15 @@
     RET_buttonPressTime = 0;
     RET_buttonHoldTime = 0;
     //MOTION STATE
-    RET_motionTriggeredinFrame = 0;
-    RET_motionTriggeredInTXInterval = 0;
+    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
@@ -402,30 +428,35 @@
     //calculate motion state
     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(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MOT:%d s",inMotionForSeconds);debug_exe();}
+        time_t inMotionForSeconds = ((RET_RTCunixtime - RET_motionStartTime) + (DEFAULT_SLEEP_FRAME / 1000)); //Plus DEFAULT_SLEEP_FRAME as it should include frame time
+        if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MOT:%u s",inMotionForSeconds);debug_exe();}
         if (inMotionForSeconds >= RET_setting_motion_start_seconds && RET_motionState == false) {
             RET_motionState = true;
-            RET_motionTriggeredInTXInterval = true;
+            RET_motionTriggeredInLocTXInterval = true;
             //if (GLOBAL_debugLED) LED1blink(1,50);
-            if (RET_setting_location_tx_failsafe_hrs > 0) {
-                time_t epochOffsetMins = ((RET_RTCunixtime - RET_motionFrameStart) / 60);
-                sprintf(RET_activityData+strlen(RET_activityData),"1.%u!",epochOffsetMins);
+            if (RET_setting_activity_mode == 2) {
+                if (RET_setting_location_tx_failsafe_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(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MOTLESS:%d s",noMotionForSeconds);debug_exe();}
+        time_t noMotionForSeconds = ((RET_RTCunixtime - RET_motionStopTime) + (DEFAULT_SLEEP_FRAME / 1000)); //Plus DEFAULT_SLEEP_FRAME as it should include frame time
+        if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "MOTLESS:%u s",noMotionForSeconds);debug_exe();}
         if (noMotionForSeconds >= RET_setting_motion_stop_seconds && RET_motionState == true) {
             //if (GLOBAL_debugLED) LED1blink(2,50);
             RET_motionPendingOffState = false;
             RET_motionState = false;
             GLOBAL_motionStopFlagTriggered = true;
             if (RET_setting_location_tx_failsafe_hrs > 0) {
-                RET_motionTotalActivityHours += ((float(RET_motionStopTime)-float(RET_motionStartTime)) / 3600.0f);
-                time_t epochOffsetMins = ((RET_RTCunixtime - RET_motionFrameStart) / 60);
-                sprintf(RET_activityData+strlen(RET_activityData),"0.%u!",epochOffsetMins);
+                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);
+                }
             }
         }
     }
@@ -438,11 +469,12 @@
     int matchCount = 0;
     int critical_fail_count = 0;
     int TEMP_a = -1; time_t TEMP_b = 0; int TEMP_c = -1; int TEMP_d = -1; int TEMP_e = -1; int TEMP_f = -1; int TEMP_g = -1; int TEMP_h = -1; int TEMP_i = -1; int TEMP_j = -1; 
-    int TEMP_k = -1; int TEMP_l = -1; int TEMP_m = -1; int TEMP_n = -1; int TEMP_o = -1; int TEMP_p = -1; int TEMP_q = -1; int TEMP_r = -1; int TEMP_s = -1;
-    if ( (matchCount = sscanf(settingsBuffer,"a:%d,b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d",
-    &TEMP_a,&TEMP_b,&TEMP_c,&TEMP_d,&TEMP_e,&TEMP_f,&TEMP_g,&TEMP_h,&TEMP_i,&TEMP_j,&TEMP_k,&TEMP_l,&TEMP_m,&TEMP_n,&TEMP_o,&TEMP_p,&TEMP_q,&TEMP_r,&TEMP_s) ) > 0 ) {
-        if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "FROMSERVER: a:%d,b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d\n",
-        TEMP_a,TEMP_b,TEMP_c,TEMP_d,TEMP_e,TEMP_f,TEMP_g,TEMP_h,TEMP_i,TEMP_j,TEMP_k,TEMP_l,TEMP_m,TEMP_n,TEMP_o,TEMP_p,TEMP_q,TEMP_r,TEMP_s);debug_exe();}
+    int TEMP_k = -1; int TEMP_l = -1; int TEMP_m = -1; int TEMP_n = -1; int TEMP_o = -1; int TEMP_p = -1; int TEMP_q = -1; int TEMP_r = -1; int TEMP_s = -1; int TEMP_t = -1;
+    int varTotal = 19; //change this if var number changes!!!!!!!!
+    if ( (matchCount = sscanf(settingsBuffer,"a:%d,b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d,t:%d",
+    &TEMP_a,&TEMP_b,&TEMP_c,&TEMP_d,&TEMP_e,&TEMP_f,&TEMP_g,&TEMP_h,&TEMP_i,&TEMP_j,&TEMP_k,&TEMP_l,&TEMP_m,&TEMP_n,&TEMP_o,&TEMP_p,&TEMP_q,&TEMP_r,&TEMP_s,&TEMP_t) ) > 0 ) {
+        if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "FROMSERVER: a:%d,b:%u,c:%d,d:%d,e:%d,f:%d,g:%d,h:%d,i:%d,j:%d,k:%d,l:%d,m:%d,n:%d,o:%d,p:%d,q:%d,r:%d,s:%d,t:%d\n",
+        TEMP_a,TEMP_b,TEMP_c,TEMP_d,TEMP_e,TEMP_f,TEMP_g,TEMP_h,TEMP_i,TEMP_j,TEMP_k,TEMP_l,TEMP_m,TEMP_n,TEMP_o,TEMP_p,TEMP_q,TEMP_r,TEMP_s,TEMP_t);debug_exe();}
         
         if(TEMP_a != -1) { RET_setting_minimumupdate_hrs = TEMP_a;                      }
         if(TEMP_b != 0)  { RET_RTCunixtime = TEMP_b;                                    } else { critical_fail_count++; }
@@ -469,8 +501,10 @@
             if(RET_setting_connection_timeout < 60 || RET_setting_connection_timeout > 240) { RET_setting_connection_timeout = DEFAULT_CONNECTION_TIMEOUT; }
         if(TEMP_r != -1) { RET_setting_beacon_interval_seconds = TEMP_r;                }
         if(TEMP_s != -1) { RET_setting_beacon_scan = TEMP_s;                            }
-        
+        if(TEMP_t != -1) { RET_setting_activity_mode = TEMP_t;                          }
+
         if (critical_fail_count == 0) { 
+            RET_receivedNewSettings = true;
             if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "SETTINGS OK");debug_exe();}
             dumpSettings();
             RET_haveSettings = true;
@@ -479,6 +513,9 @@
             //check for firmware update
             if (RET_setting_firmware > 0 && RET_setting_firmware != FW_VERSION) {
                 read_app_data_from_flash(&app_data);
+                clr_flag(&app_data, app_execution_flag);
+                clr_flag(&app_data, first_run_flag);
+                app_data.current_firmware_version = FW_VERSION;
                 app_data.target_firmware_version = RET_setting_firmware;
                 write_app_data_to_flash(&app_data);
                 if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "OTA\n");debug_exe();}
@@ -559,23 +596,25 @@
     float temperature = getTemperature();
     float voltage = getBatteryV();
     bool selftestresult = selfTest();
-    if (selftestresult == false) { LED1errorCode(4,20); } //ERROR 4
+    if (selftestresult == false) { LED1errorCode(4,10); } //ERROR 4
+    int connectionStartTime = RET_RTCunixtime;
     if (modem.on(RET_force2G)) {
         char locString[70];
+        int gpsStartTime = RET_RTCunixtime;
         memcpy(locString, modem.getLocation(1, RET_setting_location_timeout), 70);
+        int timetaken_gps = (RET_RTCunixtime - gpsStartTime);
         if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,(RET_setting_connection_timeout*1000))) {
-            int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for ussd response time.
+            int timetaken_total = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for ussd response time.
+            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,z:SETUP-%s,k:%s,m:%s,c:1,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,voltage,temperature,timetaken,GLOBAL_exceptionString,SKU,HW_MAJORREVISION,locString);
+            snprintf(bytestosend,sizeof(bytestosend),"(%s,a:setup,f:%d,v:%.2f,t:%.1f,e:%d,y:%d,x:%d,z:SETUP-%s,k:%s,m:%s,c:1,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,voltage,temperature,timetaken_total,timetaken_connection,timetaken_gps,GLOBAL_exceptionString,SKU,HW_MAJORREVISION,locString);
             char result[200];
             snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, true, 2, GLOBAL_defaultApi));
             if (strcmp(result, "err") != 0) {
                 if (saveSettings(result) == false) {
                     //something went critically wrong getting settings 
                     pass = false;
-                    modem.off(true);
-                    if(GLOBAL_debugLED) LED1errorCode(5,10); //ERROR 5
                     sendErrorLog("ERR:SU-IR");
                 }                      
             } else {
@@ -594,10 +633,12 @@
         if(GLOBAL_debugLED) LED1errorCode(2,10); //ERROR 2
         pass = false;
     }
+    //SEND ANY ACTIVITY DATA
+    event_activity_tx(RET_setting_activity_mode);
     modem.off(true);
+    
     //LOG RUN TIME - THIS MUST GO AT END AFTER WE HAVE GOT SERVER TIMESTAMP
     RET_SetupRunAt = RET_RTCunixtime;
-    //SET ALL EVENT TIMES
     setEventTimes();
     RET_setupInProgress = false; //this turns off the flashing led
     //RESULT
@@ -607,16 +648,20 @@
 void event_turnonofflog_tx(bool turnon) {
     float temperature = getTemperature();
     float voltage = getBatteryV();
+    int connectionStartTime = RET_RTCunixtime;
     if (modem.on(RET_force2G)) {
         char locString[70];
+        int gpsStartTime = RET_RTCunixtime;
         memcpy(locString, modem.getLocation(1, RET_setting_location_timeout), 70);
+        int timetaken_gps = (RET_RTCunixtime - gpsStartTime);
         if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,(RET_setting_connection_timeout*1000))) {
-            int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for ussd response time.;
+            int timetaken_total = (RET_RTCunixtime - GLOBAL_wakeTime);
+            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,c:1,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,temperature,voltage,timetaken,locString);
+                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,temperature,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,c:1,s:1%s)\0",GLOBAL_defaultApi,FW_VERSION,temperature,voltage,timetaken,locString);
+                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,temperature,voltage,timetaken_total,timetaken_connection,timetaken_gps,locString);
             }
             char result[180];
             snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytestosend, false, 2, GLOBAL_defaultApi));
@@ -627,25 +672,29 @@
         modem.off(true);
     }
     modem.off(true);
-    //RESETS
-    RET_motionTriggeredInTXInterval = 0;
 }
 
 void event_location_tx() {
     float temperature = getTemperature();
     float voltage = getBatteryV();
     int selfTestResult = selfTest();
+    int connectionStartTime = RET_RTCunixtime;
+    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), 70);
+        int timetaken_gps = (RET_RTCunixtime - gpsStartTime);
         //SEND DATA
         if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,(RET_setting_connection_timeout*1000))) {
-            int timetaken = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for ussd response time 
+            int timetaken_total = (RET_RTCunixtime - GLOBAL_wakeTime) + 10; //add 10 for ussd response time.
+            int timetaken_connection = (RET_RTCunixtime - connectionStartTime);
             //Check if we should wait for settings back
             bool getSettings = true;
-            if (  ((RET_RTCunixtime - RET_SettingsGotAt)/3600) < RET_setting_minimumupdate_hrs  ) { getSettings = false; timetaken -= 10;} //remove the extra 10 seconds from times
+            //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
             char bytesToSend[160];
-            snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:loc,f:%d,t:%.1f,v:%.2f,z:LOC-%s,e:%d,c:1,s:%d%s)\0",GLOBAL_defaultApi,FW_VERSION,temperature,voltage,GLOBAL_exceptionString,timetaken,getSettings,locString);
+            snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:loc,f:%d,t:%.1f,v:%.2f,z:LOC-%s,e:%d,y:%d,x:%d,c:1,s:%d%s)\0",GLOBAL_defaultApi,FW_VERSION,temperature,voltage,GLOBAL_exceptionString,timetaken_total,timetaken_connection,timetaken_gps,getSettings,locString);
             char result[180];
             snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytesToSend, getSettings, 2, GLOBAL_defaultApi));
             if (result != "err") {
@@ -665,37 +714,44 @@
     }
     modem.off(true);
     //RESETS
-    RET_motionTriggeredInTXInterval = 0;
+    RET_motionTriggeredInLocTXInterval = false;
     setEventTime_Location();
 }
 
-void event_activity_tx() {
-    float temperature = getTemperature();
-    float voltage = getBatteryV();
-    if (modem.on(RET_force2G)) {
-        //SEND DATA
-        if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,(RET_setting_connection_timeout*1000))) {
-            char bytesToSend[160];
-            snprintf(bytesToSend,sizeof(bytesToSend),"(%s,a:act,e:%s,t:%u,r:%.2f,c:1)\0",GLOBAL_defaultApi,RET_activityData,RET_motionFrameStart,RET_motionTotalActivityHours);
-            char result[180];
-            bool getResponse = false;
-            snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytesToSend, getResponse, 2, GLOBAL_defaultApi));
-            if (result != "err") {
-                //RESET ACTIVITY FRAME
-                memset(RET_activityData,0,sizeof(RET_activityData));
-                if (RET_haveSettings) { RET_motionFrameStart = RET_RTCunixtime; }
+void event_activity_tx(uint8_t activity_mode) {
+    //SEND ACTIVITY DATA
+    //check we have something to send...
+    if (RET_motionTotalActivityHoursSincePost > 0.0 && activity_mode > 0) {
+        float temperature = getTemperature();
+        float voltage = getBatteryV();
+        if (modem.on(RET_force2G)) {
+            //SEND DATA
+            if (modem.registerOnNetwork(DEFAULT_CONNECTION_ATTEMPTS,(RET_setting_connection_timeout*1000))) {
+                char bytesToSend[160];
+                if (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 (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);
+                }
+                char result[180];
+                bool getResponse = false;
+                snprintf(result,sizeof(result),"%s",modem.USSDmessage(bytesToSend, getResponse, 2, GLOBAL_defaultApi));
+                if (result != "err") {
+                    //RESET ACTIVITY FRAME
+                    memset(RET_activityData,0,sizeof(RET_activityData));
+                    if (RET_haveSettings) { RET_motionFrameStart = RET_RTCunixtime; }
+                }
+            } else {
+                modem.off(true);
+                if(GLOBAL_debugLED) LED1errorCode(3,10); //ERROR 3
             }
         } else {
             modem.off(true);
-            if(GLOBAL_debugLED) LED1errorCode(3,10); //ERROR 3
+            if(GLOBAL_debugLED) LED1errorCode(2,10); //ERROR 3
         }
-    } else {
         modem.off(true);
-        if(GLOBAL_debugLED) LED1errorCode(2,10); //ERROR 3
     }
-    modem.off(true);
     //RESETS
-    RET_motionTriggeredInTXInterval = 0;
     setEventTime_Activity();
 }
 
@@ -733,7 +789,7 @@
                     break;
                 case 2: //INTERVAL POST WITH MOTION CHECK
                     if(RET_RTCunixtime >= RET_eventTime_location_tx && RET_eventTime_location_tx > 0) { 
-                        if (RET_motionTriggeredInTXInterval) {
+                        if (RET_motionTriggeredInLocTXInterval == true) {
                             run_location_tx = true;
                         } else {
                              if(DEBUG_ON){debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "Skip TX no mot\n");debug_exe();}
@@ -750,11 +806,17 @@
             
             //ACTIVITY EVENT
             bool run_activity_tx = false;
-            if(RET_RTCunixtime >= RET_eventTime_activity_tx && RET_eventTime_activity_tx > 0 && strlen(RET_activityData) > 1) { 
-                run_activity_tx = true;
+            if(RET_RTCunixtime >= RET_eventTime_activity_tx && RET_eventTime_activity_tx > 0) {
+                if (RET_setting_activity_mode == 1 && RET_motionTotalActivityHoursSincePost > 0.0) {
+                    run_activity_tx = true;
+                }
+                if (RET_setting_activity_mode == 2 && strlen(RET_activityData) > 1) {
+                    run_activity_tx = true;
+                }
             }
-            if (strlen(RET_activityData) > 8) { run_activity_tx = true; } //was 130
-            if (run_activity_tx) { event_activity_tx();}
+            //If in sendevent mode, check if buffer is close to full, if so send
+            if (RET_setting_activity_mode == 2 && strlen(RET_activityData) > (ACTIVITY_BUFFERSIZE-20)) { run_activity_tx = true; }
+            if (run_activity_tx) { event_activity_tx(RET_setting_activity_mode); }
             break;
         }
         case STATE_DORMANT :
@@ -910,8 +972,8 @@
         //MAIN LOGIC
         if(DEBUG_ON){
             if (RET_state != 99) {
-                debug_prep();snprintf(GLOBAL_debug_buffer, sizeof(GLOBAL_debug_buffer), "F:%d,S:%d, SET:%d, MF:%d, MS: %d, %u, L:%u, LFS:%u, A:%u", FW_VERSION, RET_state, RET_haveSettings, RET_motionTriggeredinFrame, RET_motionState, 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:%s\n",RET_activityData);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_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), "ACT M:%d, HsP:%.2f, Ht:%.2f D:%s\n",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();
             }
@@ -930,31 +992,17 @@
                 
         //LOG FIRST RUN - BOOTLOADER COMMS
         if (RET_coldBoot) {
-            read_app_data_from_flash(&app_data);
-            bool write_app_data_to_flash_execute = false;
-            if(get_flag(&app_data, app_execution_flag) == true) {
-                clr_flag(&app_data, app_execution_flag);
-                clr_flag(&app_data, first_run_flag);
-                write_app_data_to_flash_execute = true;
-            }
-            if(app_data.current_firmware_version != FW_VERSION) {
-                app_data.current_firmware_version = FW_VERSION;
-                app_data.target_firmware_version = FW_VERSION;
-                write_app_data_to_flash_execute = true;
-            }
-            if (write_app_data_to_flash_execute) {
-                write_app_data_to_flash(&app_data);
-            }
+            recordFirmwareAsValid();
             RET_coldBoot = 0;
         }
         
         //PRE-SLEEP ACTIONS
+        LED1off();
+        modem.off(false);
         RET_motionTriggeredinFrame = false;
-        LED1off();
         if (GLOBAL_needToConfigureLis3dh) { lis3dh_configureForSleep(RET_setting_motion_g,RET_setting_impact_g); }
-        modem.off(false);
+        nrf_configureGPIOForSleep();
         NRFuart_uninit();
-        nrf_configureGPIOForSleep();
         watchdogKick();
         
         //SLEEP