battery-minus

Pebble activity tracker that records battery events
git clone https://git.instinctive.eu/battery-minus.git
Log | Files | Refs | README | LICENSE

battery-minus_worker.c (3988B)


      1 /*
      2  * Copyright (c) 2015, Natacha Porté
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <pebble_worker.h>
     18 
     19 #include "../src/storage.h"
     20 
     21 static struct event current_page[PAGE_LENGTH];
     22 static unsigned index;
     23 static BatteryChargeState previous;
     24 
     25 /******************************
     26  * LOW LEVEL EVENT MANAGEMENT *
     27  ******************************/
     28 
     29 static void
     30 append_event(struct event *event) {
     31 	int ret;
     32 
     33 	if (index >= PAGE_LENGTH) {
     34 		APP_LOG(APP_LOG_LEVEL_ERROR,
     35 		    "invalid value %u for index", index);
     36 		return;
     37 	}
     38 
     39 	current_page[index] = *event;
     40 	index = (index + 1) % PAGE_LENGTH;
     41 
     42 	ret = persist_write_data(1, current_page, sizeof current_page);
     43 	if (ret < 0 || (unsigned)ret != sizeof current_page)
     44 		APP_LOG(APP_LOG_LEVEL_ERROR,
     45 		    "unexpected return value %d for persist_wride_data",
     46 		    ret);
     47 }
     48 
     49 static uint8_t
     50 convert_state(BatteryChargeState *state) {
     51 	if (state->charge_percent > 100) return ANOMALOUS_VALUE;
     52 	return state->charge_percent | (state->is_charging ? 0x80 : 0);
     53 }
     54 
     55 /*********************
     56  * HIGH LEVEL EVENTS *
     57  *********************/
     58 
     59 static void
     60 new_event(uint8_t before, uint8_t after) {
     61 	struct event event;
     62 
     63 	event.time = time(0);
     64 	event.before = before;
     65 	event.after = after;
     66 	append_event(&event);
     67 }
     68 
     69 static void
     70 app_started(void) {
     71 	uint8_t current = convert_state(&previous);
     72 
     73 	if (current == ANOMALOUS_VALUE) {
     74 		new_event(APP_STARTED, UNKNOWN);
     75 		new_event(ANOMALOUS_VALUE, previous.charge_percent);
     76 	} else
     77 		new_event(APP_STARTED, current);
     78 }
     79 
     80 static void
     81 app_stopped(void) {
     82 	uint8_t current = convert_state(&previous);
     83 
     84 	new_event(APP_CLOSED, current == ANOMALOUS_VALUE ? UNKNOWN : current);
     85 }
     86 
     87 static void
     88 battery_update(BatteryChargeState *before, BatteryChargeState *after) {
     89 	uint8_t i_before = convert_state(before);
     90 	uint8_t i_after = convert_state(after);
     91 
     92 	if (i_after == ANOMALOUS_VALUE)
     93 		new_event(ANOMALOUS_VALUE, after->charge_percent);
     94 	else
     95 		new_event(i_before == ANOMALOUS_VALUE ? UNKNOWN : i_before,
     96 		    i_after);
     97 }
     98 
     99 /*****************
    100  * EVENT HANDLER *
    101  *****************/
    102 
    103 static void
    104 battery_handler(BatteryChargeState charge) {
    105 	if (charge.charge_percent == previous.charge_percent
    106 	    && charge.is_charging == previous.is_charging)
    107 		return;
    108 
    109 	battery_update(&previous, &charge);
    110 	previous = charge;
    111 }
    112 
    113 /***********************************
    114  * INITIALIZATION AND FINALIZATION *
    115  ***********************************/
    116 
    117 static bool
    118 init(void) {
    119 	int ret = persist_read_data(1, current_page, sizeof current_page);
    120 
    121 	if (ret == E_DOES_NOT_EXIST) {
    122 		APP_LOG(APP_LOG_LEVEL_INFO,
    123 		    "no configuration found, initializing to zero");
    124 		memset(current_page, 0, sizeof current_page);
    125 	} else if (ret != sizeof current_page) {
    126 		APP_LOG(APP_LOG_LEVEL_ERROR,
    127 		    "unexpected return value %d for persist_read_data",
    128 		    ret);
    129 		return false;
    130 	} else if (current_page[0].time) {
    131 		for (index = 1;
    132 		    index < PAGE_LENGTH
    133 		    && current_page[index - 1].time < current_page[index].time;
    134 		    index += 1);
    135 	} else
    136 		index = 0;
    137 
    138 	previous = battery_state_service_peek();
    139 	app_started();
    140 
    141 	battery_state_service_subscribe(&battery_handler);
    142 
    143 	return true;
    144 }
    145 
    146 static void
    147 deinit(void) {
    148 	battery_state_service_unsubscribe();
    149 	app_stopped();
    150 }
    151 
    152 int
    153 main(void) {
    154 	if (!init()) return 1;
    155 	worker_event_loop();
    156 	deinit();
    157 	return 0;
    158 }