Upload files to "src/c"
This commit is contained in:
78
src/c/options.c
Normal file
78
src/c/options.c
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#include <pebble.h>
|
||||||
|
#include "options.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "tictoc_wd.h"
|
||||||
|
|
||||||
|
extern Options s_options;
|
||||||
|
|
||||||
|
void init_options() {
|
||||||
|
|
||||||
|
if (persist_exists(KEY_OPTIONS)) {
|
||||||
|
persist_read_data(KEY_OPTIONS, &s_options, sizeof(s_options));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s_options.shake_for_lohi = DEFAULT_SHAKE_FOR_LOHI;
|
||||||
|
s_options.display_weather = DEFAULT_DISPLAY_WEATHER;
|
||||||
|
s_options.use_celsius = DEFAULT_USE_CELSIUS;
|
||||||
|
s_options.weather_use_GPS = DEFAULT_WEATHER_USE_GPS;
|
||||||
|
memset(s_options.weather_location, 0,sizeof(s_options.weather_location));
|
||||||
|
s_options.weather_frequency = DEFAULT_WEATHER_FREQUENCY;
|
||||||
|
s_options.min_since_last_forecast = DEFAULT_MIN_SINCE_WEATHER_UPDATE;
|
||||||
|
s_options.background_color = DEFAULT_BACKGROUND_COLOR;
|
||||||
|
s_options.text_color = DEFAULT_TEXT_COLOR;
|
||||||
|
s_options.hour_hand_color = DEFAULT_HOUR_HAND_COLOR;
|
||||||
|
s_options.minute_hand_color = DEFAULT_MINUTE_HAND_COLOR;
|
||||||
|
s_options.hour_markers_color = DEFAULT_HOUR_MARKERS_COLOR;
|
||||||
|
s_options.minor_markers_color = DEFAULT_MINOR_MARKERS_COLOR;
|
||||||
|
s_options.dots_color = DEFAULT_DOTS_COLOR;
|
||||||
|
s_options.readability = DEFAULT_READABILITY;
|
||||||
|
s_options.condition_code = DEFAULT_CONDITION_CODE;
|
||||||
|
s_options.display_digital_time = DEFAULT_DISPLAY_DIGITAL_TIME;
|
||||||
|
s_options.display_date = DEFAULT_DISPLAY_DATE;
|
||||||
|
s_options.display_month = DEFAULT_DISPLAY_MONTH;
|
||||||
|
s_options.vibrate_bt_status = DEFAULT_VIBRATE_BT_STATUS;
|
||||||
|
s_options.use_thin_hands = DEFAULT_USE_THIN_HANDS;
|
||||||
|
s_options.display_battery = DEFAULT_DISPLAY_BATTERY;
|
||||||
|
s_options.display_minute_lines = DEFAULT_DISPLAY_MINUTE_LINES;
|
||||||
|
memset(s_options.conditions, 0,sizeof(s_options.conditions));
|
||||||
|
snprintf(s_options.last_weather_update12hr, sizeof(s_options.last_weather_update12hr), "--:--");
|
||||||
|
snprintf(s_options.last_weather_update24hr, sizeof(s_options.last_weather_update24hr), "--:--");
|
||||||
|
//persist_write_data(KEY_OPTIONS, &s_options, sizeof(s_options));
|
||||||
|
}
|
||||||
|
#if DEBUG
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.shake_for_lohi: %d", s_options.shake_for_lohi);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempF: %d", s_options.tempF);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempFLo: %d", s_options.tempFLo);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempFHi: %d", s_options.tempFHi);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempC: %d", s_options.tempC);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempCLo: %d", s_options.tempCLo);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.tempCHi: %d", s_options.tempCHi);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_weather: %d", s_options.display_weather);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weather_use_GPS: %d", s_options.weather_use_GPS);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weather_location: %s", s_options.weather_location);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.use_celsius: %d", s_options.use_celsius);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.weather_frequency: %d", s_options.weather_frequency);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.min_since_last_forecast: %d", s_options.min_since_last_forecast);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.background_color: %d", s_options.background_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.text_color: %d", s_options.text_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.hour_hand_color: %d", s_options.hour_hand_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.minute_hand_color: %d", s_options.minute_hand_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.hour_markers_color: %d", s_options.hour_markers_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.minor_markers_color: %d", s_options.minor_markers_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.dots_color: %d", s_options.dots_color);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.readability: %d", s_options.readability);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.condition_code: %d", s_options.condition_code);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.bluetooth_state: %d", s_options.bluetooth_state);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_digital_time: %d", s_options.display_digital_time);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_date: %d", s_options.display_date);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_month: %d", s_options.display_month);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.vibrate_bt_status: %d", s_options.vibrate_bt_status);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.use_thin_hands: %d", s_options.use_thin_hands);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_battery: %d", s_options.display_battery);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.display_minute_lines: %d", s_options.display_minute_lines);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.conditions: %s", s_options.conditions);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.last_weather_update12hr: %s", s_options.last_weather_update12hr);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: s_options.last_weather_update24hr: %s", s_options.last_weather_update24hr);
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "init_options: options sizeof(s_options) %zu", sizeof(s_options));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
5
src/c/options.h
Normal file
5
src/c/options.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define KEY_OPTIONS 99
|
||||||
|
|
||||||
|
void init_options();
|
||||||
572
src/c/tictoc_wd.c
Normal file
572
src/c/tictoc_wd.c
Normal file
@@ -0,0 +1,572 @@
|
|||||||
|
#include <pebble.h>
|
||||||
|
#include "tictoc_wd.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "weather.h"
|
||||||
|
#include "date.h"
|
||||||
|
#include "messaging.h"
|
||||||
|
#include "digital_time.h"
|
||||||
|
#include "battery.h"
|
||||||
|
|
||||||
|
#define SCREEN_SHOT_HR 21
|
||||||
|
#define SCREEN_SHOT_MIN 22
|
||||||
|
|
||||||
|
#define ANTIALIASING true
|
||||||
|
|
||||||
|
#define HAND_MARGIN 18
|
||||||
|
#define FINAL_RADIUS 80
|
||||||
|
|
||||||
|
#define REGULAR_HANDS_WIDTH 7
|
||||||
|
#define THIN_HANDS_WIDTH 5
|
||||||
|
|
||||||
|
#define ANIMATION_DURATION 500
|
||||||
|
#define ANIMATION_DELAY 600
|
||||||
|
|
||||||
|
#define HOUR_BAR_MARGIN 5
|
||||||
|
|
||||||
|
#define HAND_LENGTH_SEC_PBL_ROUND 75
|
||||||
|
#define HAND_LENGTH_SEC 65
|
||||||
|
#define SECONDS_HAND_DISPLAY_TIME_SECS 18
|
||||||
|
int g_display_seconds_hand_count = 0; //stores brief counter to display seconds hand
|
||||||
|
|
||||||
|
Options s_options;
|
||||||
|
|
||||||
|
//stores weather retry counts (incremented in second tick handler).
|
||||||
|
//Stop retry count at DEFAULT_MAX_WEATHER_RETRY_COUNT
|
||||||
|
int g_weather_retry_count = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int hours;
|
||||||
|
int minutes;
|
||||||
|
int seconds;
|
||||||
|
} Time;
|
||||||
|
|
||||||
|
static GPoint s_center;
|
||||||
|
static Time s_last_time, s_anim_time;
|
||||||
|
static int s_radius = 0, s_color_channels[3];
|
||||||
|
static bool s_animating = false;
|
||||||
|
|
||||||
|
void set_text_layers_color(GColor textColor) {
|
||||||
|
text_layer_set_text_color(weather_layer1, textColor);
|
||||||
|
#if defined(PBL_ROUND)
|
||||||
|
text_layer_set_text_color(weather_layer2, textColor);
|
||||||
|
text_layer_set_text_color(weather_layer_center, textColor);
|
||||||
|
#endif
|
||||||
|
text_layer_set_text_color(date_layer_center, textColor);
|
||||||
|
text_layer_set_text_color(battery_layer, textColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_window_background_color(){
|
||||||
|
|
||||||
|
window_set_background_color(s_main_window, GColorBlack);
|
||||||
|
window_set_background_color(s_main_window, GColorFromHEX(s_options.background_color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_static_row(TextLayer *label, GFont font) {
|
||||||
|
|
||||||
|
text_layer_set_background_color(label, GColorClear);
|
||||||
|
text_layer_set_text_color(label, GColorWhite);
|
||||||
|
|
||||||
|
text_layer_set_text_color(label, GColorFromHEX(s_options.text_color));
|
||||||
|
|
||||||
|
if (font) {
|
||||||
|
text_layer_set_font(label, font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************** AnimationImplementation **************************/
|
||||||
|
|
||||||
|
static void animation_started(Animation *anim, void *context) {
|
||||||
|
s_animating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void animation_stopped(Animation *anim, bool stopped, void *context) {
|
||||||
|
s_animating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void animate(int duration, int delay, AnimationImplementation *implementation, bool handlers) {
|
||||||
|
Animation *anim = animation_create();
|
||||||
|
animation_set_duration(anim, duration);
|
||||||
|
animation_set_delay(anim, delay);
|
||||||
|
animation_set_curve(anim, AnimationCurveEaseInOut);
|
||||||
|
animation_set_implementation(anim, implementation);
|
||||||
|
if(handlers) {
|
||||||
|
animation_set_handlers(anim, (AnimationHandlers) {
|
||||||
|
.started = animation_started,
|
||||||
|
.stopped = animation_stopped
|
||||||
|
}, NULL);
|
||||||
|
}
|
||||||
|
animation_schedule(anim);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************ UI **************************************/
|
||||||
|
|
||||||
|
static void bt_handler(bool isConnected) {
|
||||||
|
|
||||||
|
int current_bluetooth_state = 0; //default bluetooth disconnected
|
||||||
|
if (isConnected) {
|
||||||
|
current_bluetooth_state = 1; //bluetooth connected
|
||||||
|
}
|
||||||
|
|
||||||
|
//if bluetooth was previously connected and is now disconnected
|
||||||
|
if (s_options.bluetooth_state == 1 &&
|
||||||
|
current_bluetooth_state == 0) {
|
||||||
|
|
||||||
|
if (s_options.vibrate_bt_status) {
|
||||||
|
vibes_short_pulse(); //vibrate on bt disconnect, if option enabled
|
||||||
|
|
||||||
|
if(s_canvas_layer) {
|
||||||
|
layer_mark_dirty(s_canvas_layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if bluetooth was previously disconnected and is now connected
|
||||||
|
if (s_options.bluetooth_state == 0 &&
|
||||||
|
current_bluetooth_state == 1) {
|
||||||
|
|
||||||
|
//clear weather conditions and reset weather retry count to force weather update
|
||||||
|
memset(s_options.conditions, 0,sizeof(s_options.conditions));
|
||||||
|
s_options.condition_code = DEFAULT_CONDITION_CODE;
|
||||||
|
g_weather_retry_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//store bluetooth state
|
||||||
|
s_options.bluetooth_state = current_bluetooth_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tap_handler(AccelAxisType axis, int32_t direction) {
|
||||||
|
|
||||||
|
if (s_options.display_seconds_hand > 0) {
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm *time_now = localtime(&t);
|
||||||
|
|
||||||
|
s_last_time.seconds = time_now->tm_sec;
|
||||||
|
|
||||||
|
g_display_seconds_hand_count = SECONDS_HAND_DISPLAY_TIME_SECS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_options.shake_for_lohi == 1) {
|
||||||
|
//Display Lo Hi temp info;
|
||||||
|
display_lohi_weather_info();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//every five seconds
|
||||||
|
static void handle_5second_tick(struct tm *tick_time, TimeUnits units_changed) {
|
||||||
|
|
||||||
|
//if conditions blank (no current weather info)
|
||||||
|
if(strlen(s_options.conditions) == 0 &&
|
||||||
|
g_weather_retry_count < DEFAULT_MAX_WEATHER_RETRY_COUNT) {
|
||||||
|
|
||||||
|
//add one to weather retry count - stop trying this app session at DEFAULT_MAX_WEATHER_RETRY_COUNT
|
||||||
|
++g_weather_retry_count;
|
||||||
|
|
||||||
|
//reset time since last forecast timer
|
||||||
|
s_options.min_since_last_forecast = 0;
|
||||||
|
|
||||||
|
//get updated weather
|
||||||
|
send(KEY_GET_WEATHER, 1, KEY_WEATHER_USE_GPS, s_options.weather_use_GPS, KEY_WEATHER_LOCATION, s_options.weather_location);
|
||||||
|
|
||||||
|
//update weather layer
|
||||||
|
update_weather_layer();
|
||||||
|
}
|
||||||
|
//APP_LOG(APP_LOG_LEVEL_DEBUG, "heap_bytes_free:heap_bytes_used %zu: %zu", heap_bytes_free(), heap_bytes_used());
|
||||||
|
}
|
||||||
|
|
||||||
|
//every second
|
||||||
|
static void handle_second_tick(struct tm *tick_time, TimeUnits units_changed) {
|
||||||
|
|
||||||
|
if((s_options.display_seconds_hand == 1 && g_display_seconds_hand_count > 0) ||
|
||||||
|
s_options.display_seconds_hand == 2) {
|
||||||
|
|
||||||
|
s_last_time.seconds = tick_time->tm_sec;
|
||||||
|
|
||||||
|
if(s_canvas_layer) {
|
||||||
|
layer_mark_dirty(s_canvas_layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//every minute
|
||||||
|
static void handle_minute_tick(struct tm *tick_time, TimeUnits units_changed) {
|
||||||
|
|
||||||
|
// Store time
|
||||||
|
s_last_time.hours = tick_time->tm_hour;
|
||||||
|
s_last_time.hours -= (s_last_time.hours > 12) ? 12 : 0;
|
||||||
|
s_last_time.minutes = tick_time->tm_min;
|
||||||
|
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
s_color_channels[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redraw
|
||||||
|
if(s_canvas_layer) {
|
||||||
|
layer_mark_dirty(s_canvas_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (units_changed & HOUR_UNIT) {
|
||||||
|
//vibes_double_pulse(); //hourly vibration
|
||||||
|
}
|
||||||
|
|
||||||
|
update_date_layer(); //check/update date layer
|
||||||
|
update_digital_time_layer(); //check/update digital_time_layer
|
||||||
|
update_battery_layer(); //check/update update_battery_layer
|
||||||
|
|
||||||
|
//get minutes since last weather update
|
||||||
|
time_t t = time(NULL);
|
||||||
|
int min_since_last_update = (difftime(t, s_options.last_update) / 60) + 1;
|
||||||
|
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, " (Last update %s) min_since_last_update:weather_frequency - %d:%d", s_options.last_weather_update24hr, min_since_last_update, s_options.weather_frequency);
|
||||||
|
//APP_LOG(APP_LOG_LEVEL_DEBUG, "handle_minute_tick strlen(s_options.conditions): %zu", strlen(s_options.conditions));
|
||||||
|
//if min_since_last_forecast greater than or equal to weatherUpdateFrequency
|
||||||
|
if(min_since_last_update >= s_options.weather_frequency ||
|
||||||
|
strlen(s_options.conditions) == 0) {
|
||||||
|
|
||||||
|
s_options.min_since_last_forecast = 0;
|
||||||
|
|
||||||
|
//get updated weather
|
||||||
|
send(KEY_GET_WEATHER, 1, KEY_WEATHER_USE_GPS, s_options.weather_use_GPS, KEY_WEATHER_LOCATION, s_options.weather_location);
|
||||||
|
|
||||||
|
//update weather layer
|
||||||
|
update_weather_layer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_tick(struct tm *tick_time, TimeUnits units_changed) {
|
||||||
|
|
||||||
|
if (units_changed & SECOND_UNIT) {
|
||||||
|
handle_second_tick(tick_time, units_changed);
|
||||||
|
|
||||||
|
if (tick_time->tm_sec % 5 == 0) {
|
||||||
|
handle_5second_tick(tick_time, units_changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (units_changed & MINUTE_UNIT) {
|
||||||
|
handle_minute_tick(tick_time, units_changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hours_to_minutes(int hours_out_of_12) {
|
||||||
|
return (int)(float)(((float)hours_out_of_12 / 12.0F) * 60.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_proc(Layer *layer, GContext *ctx) {
|
||||||
|
|
||||||
|
//GRect layer_frame = layer_get_frame(window_get_root_layer(s_main_window));
|
||||||
|
GRect layer_frame = layer_get_bounds(window_get_root_layer(s_main_window));
|
||||||
|
const int16_t width = layer_frame.size.w;
|
||||||
|
const int16_t height = layer_frame.size.h;
|
||||||
|
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorWhite);
|
||||||
|
|
||||||
|
#ifdef PBL_SDK_3
|
||||||
|
graphics_context_set_antialiased(ctx, ANTIALIASING);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************ Minute lines **************************************/
|
||||||
|
|
||||||
|
if (s_options.display_minute_lines) {
|
||||||
|
|
||||||
|
for (int i = 0; i < 60; i++) {
|
||||||
|
// hour bar
|
||||||
|
if (i % 1 == 0 && i / 1 != -1) {
|
||||||
|
GPoint minute_line = (GPoint) {
|
||||||
|
.x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * i / 60) * (int32_t)(s_radius - HOUR_BAR_MARGIN) / TRIG_MAX_RATIO) + s_center.x,
|
||||||
|
.y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * i / 60) * (int32_t)(s_radius - HOUR_BAR_MARGIN) / TRIG_MAX_RATIO) + s_center.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
GPoint line_start = minute_line;
|
||||||
|
|
||||||
|
//12 o'clocl position
|
||||||
|
if (i == 0) {
|
||||||
|
// emphasis
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.dots_color));
|
||||||
|
|
||||||
|
line_start.x += (s_center.x - minute_line.x) * 0.12;
|
||||||
|
line_start.y += (s_center.y - minute_line.y) * 0.12;
|
||||||
|
|
||||||
|
graphics_context_set_stroke_width(ctx, 2);
|
||||||
|
graphics_draw_line(ctx, line_start, minute_line);
|
||||||
|
} //3, 6, 9 o'clock positions
|
||||||
|
else if (i % 15 == 0) {
|
||||||
|
// emphasis
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_markers_color));
|
||||||
|
|
||||||
|
line_start.x += (s_center.x - minute_line.x) * 0.12;
|
||||||
|
line_start.y += (s_center.y - minute_line.y) * 0.12;
|
||||||
|
|
||||||
|
graphics_context_set_stroke_width(ctx, 2);
|
||||||
|
graphics_draw_line(ctx, line_start, minute_line);
|
||||||
|
}
|
||||||
|
else if (i % 5 == 0) { //emphasize 5 minute markers
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_markers_color));
|
||||||
|
|
||||||
|
line_start.x += (s_center.x - minute_line.x) * 0.12;
|
||||||
|
line_start.y += (s_center.y - minute_line.y) * 0.12;
|
||||||
|
|
||||||
|
graphics_context_set_stroke_width(ctx, 2);
|
||||||
|
graphics_draw_line(ctx, line_start, minute_line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.minor_markers_color));
|
||||||
|
//graphics_context_set_text_color(ctx, GColorWhite);
|
||||||
|
|
||||||
|
line_start.x += (s_center.x - minute_line.x) * 0.07;
|
||||||
|
line_start.y += (s_center.y - minute_line.y) * 0.07;
|
||||||
|
|
||||||
|
graphics_context_set_stroke_width(ctx, 1);
|
||||||
|
graphics_draw_line(ctx, line_start, minute_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************ Watch hand width **************************************/
|
||||||
|
|
||||||
|
#ifdef PBL_SDK_3
|
||||||
|
//set watch hand width
|
||||||
|
if (s_options.use_thin_hands) {
|
||||||
|
graphics_context_set_stroke_width(ctx, THIN_HANDS_WIDTH);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
graphics_context_set_stroke_width(ctx, REGULAR_HANDS_WIDTH);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************ Twelve o'clock dot **************************************/
|
||||||
|
|
||||||
|
int chalk_offset = 10;
|
||||||
|
if (!s_options.display_minute_lines) {
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.dots_color));
|
||||||
|
graphics_draw_circle(ctx, GPoint(width / 2, chalk_offset), 1); //twelve
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************ Hour and minute hands **************************************/
|
||||||
|
|
||||||
|
// Don't use current time while animating
|
||||||
|
Time mode_time = (s_animating) ? s_anim_time : s_last_time;
|
||||||
|
|
||||||
|
// Adjust for minutes through the hour
|
||||||
|
float minute_angle = TRIG_MAX_ANGLE * mode_time.minutes / 60;
|
||||||
|
float hour_angle;
|
||||||
|
if(s_animating) {
|
||||||
|
// Hours out of 60 for smoothness
|
||||||
|
hour_angle = TRIG_MAX_ANGLE * mode_time.hours / 60;
|
||||||
|
} else {
|
||||||
|
hour_angle = TRIG_MAX_ANGLE * mode_time.hours / 12;
|
||||||
|
}
|
||||||
|
hour_angle += (minute_angle / TRIG_MAX_ANGLE) * (TRIG_MAX_ANGLE / 12);
|
||||||
|
|
||||||
|
// Plot hands
|
||||||
|
GPoint minute_hand = (GPoint) {
|
||||||
|
.x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * mode_time.minutes / 60) * (int32_t)(s_radius - HAND_MARGIN) / TRIG_MAX_RATIO) + s_center.x,
|
||||||
|
.y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * mode_time.minutes / 60) * (int32_t)(s_radius - HAND_MARGIN) / TRIG_MAX_RATIO) + s_center.y,
|
||||||
|
};
|
||||||
|
GPoint hour_hand = (GPoint) {
|
||||||
|
.x = (int16_t)(sin_lookup(hour_angle) * (int32_t)(s_radius - (1.75 * HAND_MARGIN)) / TRIG_MAX_RATIO) + s_center.x,
|
||||||
|
.y = (int16_t)(-cos_lookup(hour_angle) * (int32_t)(s_radius - (1.75 * HAND_MARGIN)) / TRIG_MAX_RATIO) + s_center.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw hands with positive length only
|
||||||
|
|
||||||
|
if(s_radius > HAND_MARGIN) {
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.minute_hand_color));
|
||||||
|
graphics_draw_line(ctx, s_center, minute_hand);
|
||||||
|
}
|
||||||
|
if(s_radius > 2 * HAND_MARGIN) {
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.hour_hand_color));
|
||||||
|
if (s_options.vibrate_bt_status) {
|
||||||
|
if (s_options.bluetooth_state == 0) {
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorBlue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphics_draw_line(ctx, s_center, hour_hand);
|
||||||
|
|
||||||
|
//center circle
|
||||||
|
graphics_draw_circle(ctx, GPoint(width / 2, height / 2), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************ Seconds hand line **************************************/
|
||||||
|
|
||||||
|
// Draw seconds hand
|
||||||
|
--g_display_seconds_hand_count;
|
||||||
|
if (g_display_seconds_hand_count < 0)
|
||||||
|
g_display_seconds_hand_count = 0;
|
||||||
|
|
||||||
|
if((s_options.display_seconds_hand == 1 && g_display_seconds_hand_count > 0) ||
|
||||||
|
(s_options.display_seconds_hand == 2)) {
|
||||||
|
// Plot seconds hand ends
|
||||||
|
#if defined(PBL_ROUND)
|
||||||
|
GPoint second_hand_long = (GPoint) {
|
||||||
|
.x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * s_last_time.seconds / 60) * (int32_t)HAND_LENGTH_SEC_PBL_ROUND / TRIG_MAX_RATIO) + s_center.x,
|
||||||
|
.y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * s_last_time.seconds / 60) * (int32_t)HAND_LENGTH_SEC_PBL_ROUND / TRIG_MAX_RATIO) + s_center.y,
|
||||||
|
#else
|
||||||
|
GPoint second_hand_long = (GPoint) {
|
||||||
|
.x = (int16_t)(sin_lookup(TRIG_MAX_ANGLE * s_last_time.seconds / 60) * (int32_t)HAND_LENGTH_SEC / TRIG_MAX_RATIO) + s_center.x,
|
||||||
|
.y = (int16_t)(-cos_lookup(TRIG_MAX_ANGLE * s_last_time.seconds / 60) * (int32_t)HAND_LENGTH_SEC / TRIG_MAX_RATIO) + s_center.y,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
graphics_context_set_stroke_width(ctx, 2);
|
||||||
|
graphics_context_set_stroke_color(ctx, GColorFromHEX(s_options.seconds_hand_color));
|
||||||
|
graphics_draw_line(ctx, GPoint(s_center.x, s_center.y), GPoint(second_hand_long.x, second_hand_long.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_load(Window *window) {
|
||||||
|
Layer *window_layer = window_get_root_layer(window);
|
||||||
|
GRect window_bounds = layer_get_bounds(window_layer);
|
||||||
|
s_center = grect_center_point(&window_bounds);
|
||||||
|
s_canvas_layer = layer_create(window_bounds);
|
||||||
|
layer_set_update_proc(s_canvas_layer, update_proc);
|
||||||
|
layer_add_child(window_layer, s_canvas_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void window_unload(Window *window) {
|
||||||
|
layer_destroy(s_canvas_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************** App **************************************/
|
||||||
|
|
||||||
|
static int anim_percentage(AnimationProgress dist_normalized, int max) {
|
||||||
|
return (int)(float)(((float)dist_normalized / (float)ANIMATION_NORMALIZED_MAX) * (float)max);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void radius_update(Animation *anim, AnimationProgress dist_normalized) {
|
||||||
|
int chalkRadiusAdjustment = 0;
|
||||||
|
#if defined(PBL_ROUND)
|
||||||
|
chalkRadiusAdjustment = 12;
|
||||||
|
#endif
|
||||||
|
s_radius = anim_percentage(dist_normalized, FINAL_RADIUS + chalkRadiusAdjustment);
|
||||||
|
|
||||||
|
layer_mark_dirty(s_canvas_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hands_update(Animation *anim, AnimationProgress dist_normalized) {
|
||||||
|
s_anim_time.hours = anim_percentage(dist_normalized, hours_to_minutes(s_last_time.hours));
|
||||||
|
s_anim_time.minutes = anim_percentage(dist_normalized, s_last_time.minutes);
|
||||||
|
|
||||||
|
layer_mark_dirty(s_canvas_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_deinit() {
|
||||||
|
//save watchface options
|
||||||
|
persist_write_data(KEY_OPTIONS, &s_options, sizeof(s_options));
|
||||||
|
|
||||||
|
text_layer_destroy(weather_layer1);
|
||||||
|
text_layer_destroy(weather_layer_center);
|
||||||
|
text_layer_destroy(weather_layer2);
|
||||||
|
text_layer_destroy(digital_time_layer);
|
||||||
|
text_layer_destroy(battery_layer);
|
||||||
|
text_layer_destroy(date_layer1);
|
||||||
|
text_layer_destroy(date_layer2);
|
||||||
|
text_layer_destroy(date_layer_center);
|
||||||
|
|
||||||
|
#ifdef PBL_SDK_2
|
||||||
|
bluetooth_connection_service_unsubscribe();
|
||||||
|
#elif PBL_SDK_3
|
||||||
|
connection_service_unsubscribe();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
accel_tap_service_unsubscribe();
|
||||||
|
tick_timer_service_unsubscribe();
|
||||||
|
|
||||||
|
window_destroy(s_main_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_init() {
|
||||||
|
//light_enable(true); //background light for screen shots
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
|
s_main_window = window_create();
|
||||||
|
window_set_window_handlers(s_main_window, (WindowHandlers) {
|
||||||
|
.load = window_load,
|
||||||
|
.unload = window_unload,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//set-retrieve watchface options
|
||||||
|
init_options();
|
||||||
|
|
||||||
|
init_window_background_color();
|
||||||
|
|
||||||
|
// Prepare animations
|
||||||
|
AnimationImplementation radius_impl = {
|
||||||
|
.update = radius_update
|
||||||
|
};
|
||||||
|
animate(ANIMATION_DURATION, ANIMATION_DELAY, &radius_impl, false);
|
||||||
|
|
||||||
|
AnimationImplementation hands_impl = {
|
||||||
|
.update = hands_update
|
||||||
|
};
|
||||||
|
animate(2 * ANIMATION_DURATION, ANIMATION_DELAY, &hands_impl, true);
|
||||||
|
|
||||||
|
//add weather and date layers
|
||||||
|
GRect layer_frame = layer_get_frame(window_get_root_layer(s_main_window));
|
||||||
|
const int16_t width = layer_frame.size.w;
|
||||||
|
const int16_t height = layer_frame.size.h;
|
||||||
|
|
||||||
|
//add_weatherdate_layers(window_get_root_layer(s_main_window), width, height);
|
||||||
|
add_date_layers(window_get_root_layer(s_main_window), width, height);
|
||||||
|
add_weather_layers(window_get_root_layer(s_main_window), width, height);
|
||||||
|
add_digital_time_layer(window_get_root_layer(s_main_window), width, height);
|
||||||
|
add_battery_layer(window_get_root_layer(s_main_window), width, height);
|
||||||
|
|
||||||
|
app_message_register_inbox_received(inbox_received_callback);
|
||||||
|
app_message_register_inbox_dropped(message_dropped);
|
||||||
|
app_message_register_outbox_sent(message_out_success);
|
||||||
|
app_message_register_outbox_failed(message_out_failed);
|
||||||
|
|
||||||
|
#if defined(PBL_BW)
|
||||||
|
app_message_open(175, 250);
|
||||||
|
#else
|
||||||
|
app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
|
||||||
|
|
||||||
|
update_date_layer(); //update date_layer
|
||||||
|
update_digital_time_layer(); //update digital_time_layer
|
||||||
|
update_battery_layer(); //update update_battery_layer
|
||||||
|
update_weather_layer(); //update weather layer
|
||||||
|
|
||||||
|
tick_timer_service_subscribe(MINUTE_UNIT | SECOND_UNIT, handle_tick);
|
||||||
|
accel_tap_service_subscribe(tap_handler);
|
||||||
|
|
||||||
|
time_t t = time(NULL);
|
||||||
|
struct tm *time_now = localtime(&t);
|
||||||
|
#if DEBUG
|
||||||
|
time_now->tm_hour = SCREEN_SHOT_HR; //for screen shots
|
||||||
|
time_now->tm_min = SCREEN_SHOT_MIN;
|
||||||
|
#endif
|
||||||
|
handle_tick(time_now, MINUTE_UNIT);
|
||||||
|
|
||||||
|
if (s_options.display_seconds_hand > 0)
|
||||||
|
s_last_time.seconds = time_now->tm_sec;
|
||||||
|
|
||||||
|
// Subscribe to Bluetooth updates
|
||||||
|
#ifdef PBL_SDK_2
|
||||||
|
bluetooth_connection_service_subscribe(bt_handler);
|
||||||
|
#elif PBL_SDK_3
|
||||||
|
connection_service_subscribe((ConnectionHandlers) {
|
||||||
|
.pebble_app_connection_handler = bt_handler
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check current bluetooth connection state
|
||||||
|
#ifdef PBL_SDK_2
|
||||||
|
bt_handler(bluetooth_connection_service_peek());
|
||||||
|
#elif PBL_SDK_3
|
||||||
|
bt_handler(connection_service_peek_pebble_app_connection());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const bool animated = true;
|
||||||
|
window_stack_push(s_main_window, animated);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
handle_init();
|
||||||
|
app_event_loop();
|
||||||
|
handle_deinit();
|
||||||
|
}
|
||||||
53
src/c/tictoc_wd.h
Normal file
53
src/c/tictoc_wd.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include <pebble.h>
|
||||||
|
|
||||||
|
TextLayer *weather_layer1, *weather_layer2, *weather_layer_center;
|
||||||
|
TextLayer *date_layer1, *date_layer2, *date_layer_center;
|
||||||
|
TextLayer *digital_time_layer;
|
||||||
|
TextLayer *battery_layer;
|
||||||
|
AppTimer *lohi_display_timer;
|
||||||
|
|
||||||
|
void init_static_row(TextLayer *label, GFont font); //creates/configures static (weather/date) display lines
|
||||||
|
void set_text_layers_color(GColor textColor); //sets color for text (weather, date, digital time) elements
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int shake_for_lohi;
|
||||||
|
int tempF;
|
||||||
|
int tempFLo;
|
||||||
|
int tempFHi;
|
||||||
|
int tempC;
|
||||||
|
int tempCLo;
|
||||||
|
int tempCHi;
|
||||||
|
int display_weather;
|
||||||
|
int weather_use_GPS;
|
||||||
|
char weather_location[64];
|
||||||
|
int use_celsius;
|
||||||
|
int weather_frequency;
|
||||||
|
int min_since_last_forecast;
|
||||||
|
int background_color;
|
||||||
|
int text_color;
|
||||||
|
int hour_hand_color;
|
||||||
|
int minute_hand_color;
|
||||||
|
int seconds_hand_color;
|
||||||
|
int hour_markers_color;
|
||||||
|
int minor_markers_color;
|
||||||
|
int dots_color;
|
||||||
|
int readability;
|
||||||
|
int condition_code;
|
||||||
|
int display_digital_time;
|
||||||
|
int display_date;
|
||||||
|
int display_month;
|
||||||
|
int vibrate_bt_status;
|
||||||
|
int use_thin_hands;
|
||||||
|
int display_battery;
|
||||||
|
int display_minute_lines;
|
||||||
|
int display_seconds_hand;
|
||||||
|
int pebble_js_ready;
|
||||||
|
bool bluetooth_state;
|
||||||
|
time_t last_update;
|
||||||
|
char conditions[32];
|
||||||
|
char last_weather_update12hr[16];
|
||||||
|
char last_weather_update24hr[16];
|
||||||
|
} Options;
|
||||||
|
|
||||||
|
Window *s_main_window;
|
||||||
|
Layer *s_canvas_layer;
|
||||||
245
src/c/weather.c
Normal file
245
src/c/weather.c
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
#include <pebble.h>
|
||||||
|
#include "weather.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "digital_time.h"
|
||||||
|
#include "tictoc_wd.h"
|
||||||
|
|
||||||
|
extern TextLayer *weather_layer1, *weather_layer2, *weather_layer_center;
|
||||||
|
extern AppTimer *lohi_display_timer;
|
||||||
|
|
||||||
|
extern Options s_options;
|
||||||
|
|
||||||
|
//check if need to convert weather condition codes (too long)
|
||||||
|
void convert_conditions(int conditionCode) {
|
||||||
|
|
||||||
|
switch(conditionCode) {
|
||||||
|
case 0: // tornado
|
||||||
|
case 1: // tropical storm
|
||||||
|
case 2: // hurricane
|
||||||
|
case 4: // thunderstorms
|
||||||
|
case 8: //freezing drizzle
|
||||||
|
case 9: //drizzle
|
||||||
|
case 10: //freezing rain
|
||||||
|
case 11: //showers
|
||||||
|
case 12: //showers
|
||||||
|
case 13: //snow flurries
|
||||||
|
case 15: //blowing snow
|
||||||
|
case 16: //snow
|
||||||
|
case 17: //hail
|
||||||
|
case 18: //sleet
|
||||||
|
case 19: //dust
|
||||||
|
case 20: //foggy
|
||||||
|
case 21: //haze
|
||||||
|
case 22: //smoky
|
||||||
|
case 23: //blustery
|
||||||
|
case 24: //windy
|
||||||
|
case 25: //cold
|
||||||
|
case 26: //cloudy
|
||||||
|
case 32: //sunny
|
||||||
|
case 36: //hot
|
||||||
|
case 40: //scattered showers
|
||||||
|
case 41: //heavy snow
|
||||||
|
case 43: //heavy snow
|
||||||
|
case 44: //partly cloudy
|
||||||
|
case 45: //thundershowers
|
||||||
|
case 46: //snow showers
|
||||||
|
//no need to convert, do nothing
|
||||||
|
break;
|
||||||
|
case 3: // severe thunderstorms
|
||||||
|
case 37: //isolated thunderstorms
|
||||||
|
case 38: //scattered thunderstorms
|
||||||
|
case 39: //scattered thunderstorms
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Thunderstorms");
|
||||||
|
break;
|
||||||
|
case 5: //mixed rain and snow
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Rain and Snow");
|
||||||
|
break;
|
||||||
|
case 6: //mixed rain and sleet
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Rain and Sleet");
|
||||||
|
break;
|
||||||
|
case 7: //mixed snow and sleet
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Snow and Sleet");
|
||||||
|
break;
|
||||||
|
case 14: //light snow showers
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Snow Showers");
|
||||||
|
break;
|
||||||
|
case 27: //mostly cloudy (night)
|
||||||
|
case 28: //mostly cloudy (day)
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Mostly Cloudy");
|
||||||
|
break;
|
||||||
|
case 29: //partly cloudy (night)
|
||||||
|
case 30: //partly cloudy (day)
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Partly Cloudy");
|
||||||
|
break;
|
||||||
|
case 31: //clear (night)
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Clear");
|
||||||
|
break;
|
||||||
|
case 33: //fair (night)
|
||||||
|
case 34: //fair (day)
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Fair");
|
||||||
|
break;
|
||||||
|
case 35: //mixed rain and hail
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Rain and Hail");
|
||||||
|
break;
|
||||||
|
case 42: //scattered snow showers
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Snow Showers");
|
||||||
|
break;
|
||||||
|
case 47: //isolated thundershowers
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), "Thundershowers");
|
||||||
|
break;
|
||||||
|
case 3200: //Unknown
|
||||||
|
snprintf(s_options.conditions, sizeof(s_options.conditions), ".....");
|
||||||
|
break;
|
||||||
|
default: //invalid condition code, clear conditions
|
||||||
|
memset(s_options.conditions, 0,sizeof(s_options.conditions));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//adds/configures weather display lines
|
||||||
|
void add_weather_layers(Layer *window_layer, int16_t width, int16_t height) {
|
||||||
|
|
||||||
|
GFont weather_font;
|
||||||
|
int weather_Y_readability_offset = 0;
|
||||||
|
int chalk_weather1_Y_offset = 0;
|
||||||
|
int chalk_weather_center_Y_offset = 0;
|
||||||
|
int chalk_weather2_Y_offset = 0;
|
||||||
|
|
||||||
|
chalk_weather1_Y_offset = DEFAULT_CHALK_WEATHER1_Y_OFFSET;
|
||||||
|
chalk_weather_center_Y_offset = DEFAULT_CHALK_WEATHER_CENTER_Y_OFFSET;
|
||||||
|
chalk_weather2_Y_offset = DEFAULT_CHALK_WEATHER2_Y_OFFSET;
|
||||||
|
|
||||||
|
if (s_options.readability) {
|
||||||
|
weather_Y_readability_offset = DEFAULT_WEATHER_Y_OFFSET_READABILITY;
|
||||||
|
weather_font = fonts_get_system_font(FONT_KEY_GOTHIC_24);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
weather_Y_readability_offset = 0;
|
||||||
|
weather_font = fonts_get_system_font(FONT_KEY_GOTHIC_18);
|
||||||
|
}
|
||||||
|
|
||||||
|
//weather layers
|
||||||
|
weather_layer1 = text_layer_create(GRect(0, 5 - weather_Y_readability_offset + chalk_weather1_Y_offset, width, 28));
|
||||||
|
text_layer_set_text_alignment(weather_layer1, GTextAlignmentCenter);
|
||||||
|
init_static_row(weather_layer1, weather_font);
|
||||||
|
layer_add_child(window_layer, text_layer_get_layer(weather_layer1));
|
||||||
|
|
||||||
|
weather_layer2 = text_layer_create(GRect(0, 5 - weather_Y_readability_offset + chalk_weather2_Y_offset, width, 28));
|
||||||
|
text_layer_set_text_alignment(weather_layer2, GTextAlignmentCenter);
|
||||||
|
init_static_row(weather_layer2, weather_font);
|
||||||
|
layer_add_child(window_layer, text_layer_get_layer(weather_layer2));
|
||||||
|
|
||||||
|
weather_layer_center = text_layer_create(GRect(0, 5 - weather_Y_readability_offset + chalk_weather_center_Y_offset, width, 28));
|
||||||
|
text_layer_set_text_alignment(weather_layer_center, GTextAlignmentCenter);
|
||||||
|
init_static_row(weather_layer_center, weather_font);
|
||||||
|
layer_add_child(window_layer, text_layer_get_layer(weather_layer_center));
|
||||||
|
}
|
||||||
|
|
||||||
|
//checks updates weather display lines
|
||||||
|
void update_weather_layer() {
|
||||||
|
static char weather1_layer_buffer[32];
|
||||||
|
static char weather2_layer_buffer[32];
|
||||||
|
static char weather_center_layer_buffer[32];
|
||||||
|
|
||||||
|
//check if need to convert options (if too long)
|
||||||
|
convert_conditions(s_options.condition_code);
|
||||||
|
|
||||||
|
if (s_options.use_celsius){
|
||||||
|
memset(weather1_layer_buffer, 0,sizeof(weather1_layer_buffer));
|
||||||
|
snprintf(weather_center_layer_buffer, sizeof(weather_center_layer_buffer), "%dC %s", s_options.tempC, s_options.conditions);
|
||||||
|
memset(weather2_layer_buffer, 0,sizeof(weather2_layer_buffer));
|
||||||
|
if (strlen(s_options.conditions) > MAX_CHALK_SINGLE_LINE_CONDITIONS_LEN) {
|
||||||
|
snprintf(weather1_layer_buffer, sizeof(weather1_layer_buffer), "%dC", s_options.tempC);
|
||||||
|
memset(weather_center_layer_buffer, 0,sizeof(weather_center_layer_buffer));
|
||||||
|
snprintf(weather2_layer_buffer, sizeof(weather2_layer_buffer), "%s", s_options.conditions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(weather1_layer_buffer, 0,sizeof(weather1_layer_buffer));
|
||||||
|
snprintf(weather_center_layer_buffer, sizeof(weather_center_layer_buffer), "%dF %s", s_options.tempF, s_options.conditions);
|
||||||
|
memset(weather2_layer_buffer, 0,sizeof(weather2_layer_buffer));
|
||||||
|
if (strlen(s_options.conditions) > MAX_CHALK_SINGLE_LINE_CONDITIONS_LEN) {
|
||||||
|
snprintf(weather1_layer_buffer, sizeof(weather1_layer_buffer), "%dF", s_options.tempF);
|
||||||
|
memset(weather_center_layer_buffer, 0,sizeof(weather_center_layer_buffer));
|
||||||
|
snprintf(weather2_layer_buffer, sizeof(weather2_layer_buffer), "%s", s_options.conditions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//write weather text row
|
||||||
|
if (strlen(s_options.conditions) != 0) {
|
||||||
|
text_layer_set_text(weather_layer1, weather1_layer_buffer);
|
||||||
|
text_layer_set_text(weather_layer_center, weather_center_layer_buffer);
|
||||||
|
text_layer_set_text(weather_layer2, weather2_layer_buffer);
|
||||||
|
#if DEBUG
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "update_weather_layer: Successful weather row information written at %s. ", s_options.last_weather_update12hr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
else { //empty temp & conditions
|
||||||
|
text_layer_set_text(weather_layer1, "");
|
||||||
|
text_layer_set_text(weather_layer_center, DEFAULT_ERROR_WEATHER_UPDATE);
|
||||||
|
text_layer_set_text(weather_layer2, "");
|
||||||
|
#if DEBUG
|
||||||
|
APP_LOG(APP_LOG_LEVEL_DEBUG, "update_weather_layer: Error displaying weather %s. ", s_options.last_weather_update12hr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_timer(void *data) {
|
||||||
|
update_weather_layer();
|
||||||
|
update_digital_time_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
//temporarily sets and displays Lo/Hi temp and last updates info on weather/date lines
|
||||||
|
void display_lohi_weather_info() {
|
||||||
|
static char weather1_layer_buffer[32];
|
||||||
|
static char weather2_layer_buffer[32];
|
||||||
|
static char weather_center_layer_buffer[32];
|
||||||
|
|
||||||
|
if (s_options.use_celsius){
|
||||||
|
if (s_options.display_minute_lines) {
|
||||||
|
snprintf(weather1_layer_buffer, sizeof(weather1_layer_buffer), "Lo %dC", s_options.tempCLo);
|
||||||
|
snprintf(weather2_layer_buffer, sizeof(weather2_layer_buffer), "Hi %dC", s_options.tempCHi);
|
||||||
|
memset(weather_center_layer_buffer, 0,sizeof(weather_center_layer_buffer));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(weather1_layer_buffer, 0,sizeof(weather1_layer_buffer));
|
||||||
|
snprintf(weather_center_layer_buffer, sizeof(weather_center_layer_buffer), "Lo %dC - Hi %dC", s_options.tempCLo, s_options.tempCHi);
|
||||||
|
memset(weather2_layer_buffer, 0,sizeof(weather2_layer_buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (s_options.display_minute_lines) {
|
||||||
|
snprintf(weather1_layer_buffer, sizeof(weather1_layer_buffer), "Lo %dF", s_options.tempFLo);
|
||||||
|
snprintf(weather2_layer_buffer, sizeof(weather2_layer_buffer), "Hi %dF", s_options.tempFHi);
|
||||||
|
memset(weather_center_layer_buffer, 0,sizeof(weather_center_layer_buffer));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(weather1_layer_buffer, 0, sizeof(weather1_layer_buffer));
|
||||||
|
snprintf(weather_center_layer_buffer, sizeof(weather_center_layer_buffer), "Lo %dF - Hi %dF", s_options.tempFLo, s_options.tempFHi);
|
||||||
|
memset(weather2_layer_buffer, 0, sizeof(weather2_layer_buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//write weather text row
|
||||||
|
if (strlen(s_options.conditions) != 0) {
|
||||||
|
if (clock_is_24h_style()) {
|
||||||
|
text_layer_set_text(digital_time_layer, s_options.last_weather_update24hr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
text_layer_set_text(digital_time_layer, s_options.last_weather_update12hr);
|
||||||
|
}
|
||||||
|
text_layer_set_text(weather_layer1, weather1_layer_buffer);
|
||||||
|
text_layer_set_text(weather_layer_center, weather_center_layer_buffer);
|
||||||
|
text_layer_set_text(weather_layer2, weather2_layer_buffer);
|
||||||
|
}
|
||||||
|
else { //empty temp & conditions
|
||||||
|
text_layer_set_text(digital_time_layer, s_options.last_weather_update12hr);
|
||||||
|
text_layer_set_text(digital_time_layer, s_options.last_weather_update24hr);
|
||||||
|
text_layer_set_text(weather_layer1, "");
|
||||||
|
text_layer_set_text(weather_layer_center, DEFAULT_ERROR_WEATHER_UPDATE);
|
||||||
|
text_layer_set_text(weather_layer2, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
lohi_display_timer = app_timer_register(DEFAULT_DISPLAY_LOHI_TIMER, handle_timer, NULL);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user