log activity to file
This commit is contained in:
parent
c0514ad39a
commit
af409b82f1
@ -84,7 +84,7 @@ const watch_face_t watch_faces[] = {
|
|||||||
* 6: 2 days
|
* 6: 2 days
|
||||||
* 7: 7 days
|
* 7: 7 days
|
||||||
*/
|
*/
|
||||||
#define MOVEMENT_DEFAULT_LOW_ENERGY_INTERVAL 1
|
#define MOVEMENT_DEFAULT_LOW_ENERGY_INTERVAL 0
|
||||||
|
|
||||||
/* Set the led duration
|
/* Set the led duration
|
||||||
* Valid values are:
|
* Valid values are:
|
||||||
|
|||||||
@ -34,7 +34,7 @@ typedef enum {
|
|||||||
} chirpy_demo_mode_t;
|
} chirpy_demo_mode_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CDP_SCALE = 0,
|
CDP_CLEAR = 0,
|
||||||
CDP_INFO_SHORT,
|
CDP_INFO_SHORT,
|
||||||
CDP_INFO_LONG,
|
CDP_INFO_LONG,
|
||||||
CDP_INFO_NANOSEC,
|
CDP_INFO_NANOSEC,
|
||||||
@ -111,7 +111,7 @@ void chirpy_demo_face_activate(void *context) {
|
|||||||
|
|
||||||
memset(context, 0, sizeof(chirpy_demo_state_t));
|
memset(context, 0, sizeof(chirpy_demo_state_t));
|
||||||
state->mode = CDM_CHOOSE;
|
state->mode = CDM_CHOOSE;
|
||||||
state->program = CDP_SCALE;
|
state->program = CDP_INFO_NANOSEC;
|
||||||
|
|
||||||
// Do we have activity data? Load it.
|
// Do we have activity data? Load it.
|
||||||
int32_t sz = filesystem_get_file_size(ACTIVITY_DATA_FILE_NAME);
|
int32_t sz = filesystem_get_file_size(ACTIVITY_DATA_FILE_NAME);
|
||||||
@ -123,7 +123,7 @@ void chirpy_demo_face_activate(void *context) {
|
|||||||
activity_buffer_size = sz + 2;
|
activity_buffer_size = sz + 2;
|
||||||
activity_buffer = malloc(activity_buffer_size);
|
activity_buffer = malloc(activity_buffer_size);
|
||||||
// First two bytes of prefix, so Chirpy RX can recognize this data type
|
// First two bytes of prefix, so Chirpy RX can recognize this data type
|
||||||
activity_buffer[0] = 0xc0;
|
activity_buffer[0] = 0x41;
|
||||||
activity_buffer[1] = 0x00;
|
activity_buffer[1] = 0x00;
|
||||||
// Read file
|
// Read file
|
||||||
filesystem_read_file(ACTIVITY_DATA_FILE_NAME, (char*)&activity_buffer[2], sz);
|
filesystem_read_file(ACTIVITY_DATA_FILE_NAME, (char*)&activity_buffer[2], sz);
|
||||||
@ -136,16 +136,18 @@ void chirpy_demo_face_activate(void *context) {
|
|||||||
|
|
||||||
static void _cdf_update_lcd(chirpy_demo_state_t *state) {
|
static void _cdf_update_lcd(chirpy_demo_state_t *state) {
|
||||||
watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "CH", "Chirp");
|
watch_display_text_with_fallback(WATCH_POSITION_TOP_LEFT, "CH", "Chirp");
|
||||||
if (state->program == CDP_SCALE)
|
if (state->program == CDP_CLEAR) {
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, " SCALE");
|
movement_force_led_on(255, 0, 0);
|
||||||
else if (state->program == CDP_INFO_SHORT)
|
watch_display_text(WATCH_POSITION_BOTTOM, "CLEAR?");
|
||||||
|
} else if (state->program == CDP_INFO_SHORT) {
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, "SHORT ");
|
watch_display_text(WATCH_POSITION_BOTTOM, "SHORT ");
|
||||||
else if (state->program == CDP_INFO_LONG)
|
} else if (state->program == CDP_INFO_LONG) {
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, " LOng ");
|
watch_display_text(WATCH_POSITION_BOTTOM, " LOng ");
|
||||||
else if (state->program == CDP_INFO_NANOSEC)
|
} else if (state->program == CDP_INFO_NANOSEC) {
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, " ACtIV");
|
watch_display_text(WATCH_POSITION_BOTTOM, " ACtIV");
|
||||||
else
|
} else {
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, "---- ");
|
watch_display_text(WATCH_POSITION_BOTTOM, "---- ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cdf_quit_chirping(chirpy_demo_state_t *state) {
|
static void _cdf_quit_chirping(chirpy_demo_state_t *state) {
|
||||||
@ -207,7 +209,7 @@ static void _cdf_countdown_tick(void *context) {
|
|||||||
tick_state->tick_count = -1;
|
tick_state->tick_count = -1;
|
||||||
tick_state->seq_pos = 0;
|
tick_state->seq_pos = 0;
|
||||||
// We'll be chirping out a scale
|
// We'll be chirping out a scale
|
||||||
if (state->program == CDP_SCALE) {
|
if (false) { // state->program == CDP_CLEAR) {
|
||||||
tick_state->tick_fun = _cdf_scale_tick;
|
tick_state->tick_fun = _cdf_scale_tick;
|
||||||
}
|
}
|
||||||
// We'll be chirping out data
|
// We'll be chirping out data
|
||||||
@ -271,7 +273,7 @@ bool chirpy_demo_face_loop(movement_event_t event, void *context) {
|
|||||||
case EVENT_ALARM_BUTTON_UP:
|
case EVENT_ALARM_BUTTON_UP:
|
||||||
// If in choose mode: select next program
|
// If in choose mode: select next program
|
||||||
if (state->mode == CDM_CHOOSE) {
|
if (state->mode == CDM_CHOOSE) {
|
||||||
if (state->program == CDP_SCALE)
|
if (state->program == CDP_CLEAR)
|
||||||
state->program = CDP_INFO_SHORT;
|
state->program = CDP_INFO_SHORT;
|
||||||
else if (state->program == CDP_INFO_SHORT)
|
else if (state->program == CDP_INFO_SHORT)
|
||||||
state->program = CDP_INFO_LONG;
|
state->program = CDP_INFO_LONG;
|
||||||
@ -279,9 +281,9 @@ bool chirpy_demo_face_loop(movement_event_t event, void *context) {
|
|||||||
if (activity_buffer_size > 0)
|
if (activity_buffer_size > 0)
|
||||||
state->program = CDP_INFO_NANOSEC;
|
state->program = CDP_INFO_NANOSEC;
|
||||||
else
|
else
|
||||||
state->program = CDP_SCALE;
|
state->program = CDP_CLEAR;
|
||||||
} else if (state->program == CDP_INFO_NANOSEC)
|
} else if (state->program == CDP_INFO_NANOSEC)
|
||||||
state->program = CDP_SCALE;
|
state->program = CDP_CLEAR;
|
||||||
_cdf_update_lcd(state);
|
_cdf_update_lcd(state);
|
||||||
}
|
}
|
||||||
// If chirping: stoppit
|
// If chirping: stoppit
|
||||||
@ -292,7 +294,13 @@ bool chirpy_demo_face_loop(movement_event_t event, void *context) {
|
|||||||
case EVENT_ALARM_LONG_PRESS:
|
case EVENT_ALARM_LONG_PRESS:
|
||||||
// If in choose mode: start chirping
|
// If in choose mode: start chirping
|
||||||
if (state->mode == CDM_CHOOSE) {
|
if (state->mode == CDM_CHOOSE) {
|
||||||
_cdm_setup_chirp(state);
|
if (state->program == CDP_CLEAR) {
|
||||||
|
filesystem_write_file("activity.dat", "", 0);
|
||||||
|
movement_force_led_off();
|
||||||
|
movement_move_to_next_face();
|
||||||
|
} else {
|
||||||
|
_cdm_setup_chirp(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_TICK:
|
case EVENT_TICK:
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "activity_logging_face.h"
|
#include "activity_logging_face.h"
|
||||||
|
#include "filesystem.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
#ifdef HAS_ACCELEROMETER
|
#ifdef HAS_ACCELEROMETER
|
||||||
@ -37,14 +38,27 @@ extern uint8_t active_minutes;
|
|||||||
static void _activity_logging_face_log_data(activity_logging_state_t *state) {
|
static void _activity_logging_face_log_data(activity_logging_state_t *state) {
|
||||||
watch_date_time_t date_time = movement_get_local_date_time();
|
watch_date_time_t date_time = movement_get_local_date_time();
|
||||||
size_t pos = state->data_points % ACTIVITY_LOGGING_NUM_DATA_POINTS;
|
size_t pos = state->data_points % ACTIVITY_LOGGING_NUM_DATA_POINTS;
|
||||||
|
activity_logging_data_point_t data_point = {0};
|
||||||
|
|
||||||
|
data_point.bit.day = date_time.unit.day;
|
||||||
|
data_point.bit.month = date_time.unit.month;
|
||||||
|
data_point.bit.hour = date_time.unit.hour;
|
||||||
|
data_point.bit.minute = date_time.unit.minute;
|
||||||
|
data_point.bit.active_minutes = active_minutes;
|
||||||
|
data_point.bit.orientation_changes = orientation_changes;
|
||||||
|
// print size of thing
|
||||||
|
printf("Size of data point: %d\n", sizeof(activity_logging_data_point_t));
|
||||||
|
if (filesystem_append_file("activity.dat", (char *)&data_point, sizeof(activity_logging_data_point_t))) {
|
||||||
|
printf("Data point written\n", state->data_points);
|
||||||
|
} else {
|
||||||
|
printf("Failed to write data point\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
state->data[pos].reg = data_point.reg;
|
||||||
|
state->data_points++;
|
||||||
|
|
||||||
state->data[pos].timestamp.reg = date_time.reg;
|
|
||||||
state->data[pos].active_minutes = active_minutes;
|
|
||||||
state->data[pos].orientation_changes = orientation_changes;
|
|
||||||
active_minutes = 0;
|
active_minutes = 0;
|
||||||
orientation_changes = 0;
|
orientation_changes = 0;
|
||||||
|
|
||||||
state->data_points++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _activity_logging_face_update_display(activity_logging_state_t *state, bool clock_mode_24h) {
|
static void _activity_logging_face_update_display(activity_logging_state_t *state, bool clock_mode_24h) {
|
||||||
@ -63,26 +77,25 @@ static void _activity_logging_face_update_display(activity_logging_state_t *stat
|
|||||||
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
|
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
|
||||||
} else if (state->ts_ticks) {
|
} else if (state->ts_ticks) {
|
||||||
// we are displaying the timestamp in response to a button press
|
// we are displaying the timestamp in response to a button press
|
||||||
watch_date_time_t date_time = state->data[pos].timestamp;
|
|
||||||
watch_set_colon();
|
watch_set_colon();
|
||||||
if (clock_mode_24h) {
|
if (clock_mode_24h) {
|
||||||
watch_set_indicator(WATCH_INDICATOR_24H);
|
watch_set_indicator(WATCH_INDICATOR_24H);
|
||||||
} else {
|
} else {
|
||||||
if (date_time.unit.hour > 11) watch_set_indicator(WATCH_INDICATOR_PM);
|
if (state->data[pos].bit.hour > 11) watch_set_indicator(WATCH_INDICATOR_PM);
|
||||||
date_time.unit.hour %= 12;
|
state->data[pos].bit.hour %= 12;
|
||||||
if (date_time.unit.hour == 0) date_time.unit.hour = 12;
|
if (state->data[pos].bit.hour == 0) state->data[pos].bit.hour = 12;
|
||||||
}
|
}
|
||||||
watch_display_text(WATCH_POSITION_TOP_LEFT, "AT");
|
watch_display_text(WATCH_POSITION_TOP_LEFT, "AT");
|
||||||
sprintf(buf, "%2d", date_time.unit.day);
|
sprintf(buf, "%2d", state->data[pos].bit.day);
|
||||||
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
|
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
|
||||||
sprintf(buf, "%2d%02d%02d", date_time.unit.hour, date_time.unit.minute, date_time.unit.second);
|
sprintf(buf, "%2d%02d%02d", state->data[pos].bit.hour, state->data[pos].bit.minute, 0);
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, buf);
|
watch_display_text(WATCH_POSITION_BOTTOM, buf);
|
||||||
} else {
|
} else {
|
||||||
// we are displaying the number of accelerometer wakeups and orientation changes
|
// we are displaying the number of accelerometer wakeups and orientation changes
|
||||||
watch_display_text(WATCH_POSITION_TOP, "AC");
|
watch_display_text(WATCH_POSITION_TOP, "AC");
|
||||||
sprintf(buf, "%2d", state->display_index);
|
sprintf(buf, "%2d", state->display_index);
|
||||||
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
|
watch_display_text(WATCH_POSITION_TOP_RIGHT, buf);
|
||||||
sprintf(buf, "%-3lu/%2d", state->data[pos].orientation_changes > 999 ? 999 : state->data[pos].orientation_changes, state->data[pos].active_minutes);
|
sprintf(buf, "%-3lu/%2d", state->data[pos].bit.orientation_changes > 999 ? 999 : state->data[pos].bit.orientation_changes, state->data[pos].bit.active_minutes);
|
||||||
watch_display_text(WATCH_POSITION_BOTTOM, buf);
|
watch_display_text(WATCH_POSITION_BOTTOM, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,6 +105,8 @@ void activity_logging_face_setup(uint8_t watch_face_index, void ** context_ptr)
|
|||||||
if (*context_ptr == NULL) {
|
if (*context_ptr == NULL) {
|
||||||
*context_ptr = malloc(sizeof(activity_logging_state_t));
|
*context_ptr = malloc(sizeof(activity_logging_state_t));
|
||||||
memset(*context_ptr, 0, sizeof(activity_logging_state_t));
|
memset(*context_ptr, 0, sizeof(activity_logging_state_t));
|
||||||
|
// create file if it doesn't exist
|
||||||
|
if (!filesystem_file_exists("activity.dat")) filesystem_write_file("activity.dat", "", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,9 +161,8 @@ movement_watch_face_advisory_t activity_logging_face_advise(void *context) {
|
|||||||
(void) context;
|
(void) context;
|
||||||
movement_watch_face_advisory_t retval = { 0 };
|
movement_watch_face_advisory_t retval = { 0 };
|
||||||
|
|
||||||
// this will get called at the top of each minute, so all we check is if we're at the top of the hour as well.
|
// log data every 5 minutes
|
||||||
// if we are, we ask for a background task.
|
retval.wants_background_task = (movement_get_local_date_time().unit.minute % 5) == 0;
|
||||||
retval.wants_background_task = watch_rtc_get_date_time().unit.minute == 0;
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,10 +41,16 @@
|
|||||||
|
|
||||||
#define ACTIVITY_LOGGING_NUM_DATA_POINTS (36)
|
#define ACTIVITY_LOGGING_NUM_DATA_POINTS (36)
|
||||||
|
|
||||||
typedef struct {
|
typedef union {
|
||||||
watch_date_time_t timestamp;
|
struct {
|
||||||
uint8_t active_minutes;
|
uint32_t day: 5;
|
||||||
uint32_t orientation_changes;
|
uint32_t month: 4;
|
||||||
|
uint32_t hour: 5;
|
||||||
|
uint32_t minute: 6;
|
||||||
|
uint32_t active_minutes: 3;
|
||||||
|
uint32_t orientation_changes: 9;
|
||||||
|
} bit;
|
||||||
|
uint32_t reg;
|
||||||
} activity_logging_data_point_t;
|
} activity_logging_data_point_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user