static void handle_tick(struct tm *tick_time, TimeUnits units_changed) { if (units_changed & MINUTE_UNIT) { // Update the time - Deal with 12 / 24 format clock_copy_time_string(time_text, sizeof(time_text)); text_layer_set_text(time_layer, time_text); } if (units_changed & DAY_UNIT) { // Update the date - Without a leading 0 on the day of the month char day_text[4]; strftime(day_text, sizeof(day_text), "%a", tick_time); snprintf(date_text, sizeof(date_text), "%s %i", day_text, tick_time->tm_mday); text_layer_set_text(date_layer, date_text); } // Update the bottom half of the screen: icon and temperature static int animation_step = 0; if (weather_data->updated == 0 && weather_data->error == WEATHER_E_OK) { // 'Animate' loading icon until the first successful weather request if (animation_step == 0) { weather_layer_set_icon(weather_layer, WEATHER_ICON_LOADING1); } else if (animation_step == 1) { weather_layer_set_icon(weather_layer, WEATHER_ICON_LOADING2); } else if (animation_step >= 2) { weather_layer_set_icon(weather_layer, WEATHER_ICON_LOADING3); } animation_step = (animation_step + 1) % 3; } else { // Update the weather icon and temperature if (weather_data->error) { weather_layer_set_icon(weather_layer, WEATHER_ICON_PHONE_ERROR); } else { // Show the temperature as 'stale' if it has not been updated in 30 minutes bool stale = false; if (weather_data->updated > time(NULL) + 1800) { stale = true; } weather_layer_set_temperature(weather_layer, weather_data->temperature, stale); // Figure out if it's day or night. Not the best way to do this but the webservice // does not seem to return this info. bool night_time = false; if (tick_time->tm_hour >= 19 || tick_time->tm_hour < 7) night_time = true; weather_layer_set_icon(weather_layer, weather_icon_for_condition(weather_data->condition, night_time)); } } // Refresh the weather info every 15 minutes if (units_changed & MINUTE_UNIT && (tick_time->tm_min % 15) == 0) { request_weather(); } }
void success(int32_t cookie, int http_status, DictionaryIterator* received, void* context) { if(cookie != WEATHER_HTTP_COOKIE) return; Tuple* icon_tuple = dict_find(received, WEATHER_KEY_ICON); if(icon_tuple) { int icon = icon_tuple->value->int8; if(icon >= 0 && icon < 10) { weather_layer_set_icon(&weather_layer, icon); } else { weather_layer_set_icon(&weather_layer, WEATHER_ICON_NO_WEATHER); } } Tuple* temperature_tuple = dict_find(received, WEATHER_KEY_TEMPERATURE); if(temperature_tuple) { weather_layer_set_temperature(&weather_layer, temperature_tuple->value->int16); } }
void success(int32_t cookie, int http_status, DictionaryIterator* received, void* context) { if(cookie != WEATHER_HTTP_COOKIE) return; Tuple* data_tuple = dict_find(received, WEATHER_KEY_CURRENT); if(data_tuple) { // The below bitwise dance is so we can actually fit our precipitation forecast. uint16_t value = data_tuple->value->int16; uint8_t icon = value >> 11; if(icon < 10) { weather_layer_set_icon(&weather_layer, icon); } else { weather_layer_set_icon(&weather_layer, WEATHER_ICON_NO_WEATHER); } int16_t temp = value & 0x3ff; if(value & 0x400) temp = -temp; weather_layer_set_temperature(&weather_layer, temp); } Tuple* forecast_tuple = dict_find(received, WEATHER_KEY_PRECIPITATION); if(forecast_tuple) { // It's going to rain! memset(precip_forecast, 0, 60); memcpy(precip_forecast, forecast_tuple->value->data, forecast_tuple->length > 60 ? 60 : forecast_tuple->length); precip_forecast_index = 0; weather_layer_set_precipitation_forecast(&weather_layer, precip_forecast, 60); } else { weather_layer_clear_precipitation_forecast(&weather_layer); } /* if(cookie != WEATHER_HTTP_COOKIE) return; Tuple* data_tuple = dict_find(received, TEMPERATURE_KEY_CURRENT); if(data_tuple) { weather_layer_set_temperature_str(&weather_layer, data_tuple->value->cstring); } */ }
void success(int32_t cookie, int http_status, DictionaryIterator* received, void* context) { is_stale = false; if(cookie != WEATHER_HTTP_COOKIE) return; Tuple* icon_tuple = dict_find(received, WEATHER_KEY_ICON); if(icon_tuple) { int icon = icon_tuple->value->int8; if(icon >= 0 && icon < 18 && icon != 17) { weather_layer_set_icon(&weather_layer, icon); } } Tuple* temperature_tuple = dict_find(received, WEATHER_KEY_TEMPERATURE); if(temperature_tuple) { last_valid_temperature = temperature_tuple->value->int16; weather_layer_set_temperature(&weather_layer, temperature_tuple->value->int16, is_stale); has_temperature = true; } link_monitor_handle_success(); has_failed = false; phone_disconnected = false; }
void success(int32_t cookie, int http_status, DictionaryIterator* received, void* context) { if(cookie != WEATHER_HTTP_COOKIE) return; Tuple* icon_tuple = dict_find(received, WEATHER_KEY_ICON); if(icon_tuple) { int icon = icon_tuple->value->int8; if(icon >= 0 && icon < 10) { weather_layer_set_icon(&weather_layer, icon); } else { weather_layer_set_icon(&weather_layer, WEATHER_ICON_NO_WEATHER); } } Tuple* temperature_tuple = dict_find(received, WEATHER_KEY_TEMPERATURE); if(temperature_tuple) { weather_layer_set_temperature(&weather_layer, temperature_tuple->value->int16); } Tuple* high_tuple = dict_find(received, WEATHER_KEY_HIGH); if(high_tuple) { weather_layer_set_high(&weather_layer, high_tuple->value->int16); } Tuple* low_tuple = dict_find(received, WEATHER_KEY_LOW); if(low_tuple) { weather_layer_set_low(&weather_layer, low_tuple->value->int16); } Tuple* sh_tuple = dict_find(received, WEATHER_KEY_SH); if(sh_tuple) { weather_layer_set_sh(&weather_layer, sh_tuple->value->int16); } Tuple* sm_tuple = dict_find(received, WEATHER_KEY_SM); if(sm_tuple) { weather_layer_set_sm(&weather_layer, sm_tuple->value->int16); } link_monitor_handle_success(); }
void success(int32_t cookie, int http_status, DictionaryIterator* received, void* context) { if(cookie != WEATHER_HTTP_COOKIE) return; Tuple* icon_tuple = dict_find(received, WEATHER_KEY_ICON); if(icon_tuple) { int icon = -1; char ipng[16]; strcpy(ipng, icon_tuple->value->cstring); // map openweather to futura-weather icons // 01d.png 01n.png sky is clear // 02d.png 02n.png few clouds // 03d.png 03n.png scattered clouds // 04d.png 04n.png broken clouds // 09d.png 09n.png shower rain // 10d.png 10n.png Rain // 11d.png 11n.png Thunderstorm // 13d.png 13n.png snow // 50d.png 50n.png mist if (strcmp(ipng, "01d") == 0) icon = WEATHER_ICON_CLEAR_DAY; if (strcmp(ipng, "01n") == 0) icon = WEATHER_ICON_CLEAR_NIGHT; if (strcmp(ipng, "02d") == 0) icon = WEATHER_ICON_PARTLY_CLOUDY_DAY; if (strcmp(ipng, "02n") == 0) icon = WEATHER_ICON_PARTLY_CLOUDY_NIGHT; if (strcmp(ipng, "03d") == 0) icon = WEATHER_ICON_CLOUDY; if (strcmp(ipng, "03n") == 0) icon = WEATHER_ICON_CLOUDY; if (strcmp(ipng, "04d") == 0) icon = WEATHER_ICON_CLOUDY; if (strcmp(ipng, "04n") == 0) icon = WEATHER_ICON_CLOUDY; if (strcmp(ipng, "09d") == 0) icon = WEATHER_ICON_RAIN; if (strcmp(ipng, "09n") == 0) icon = WEATHER_ICON_RAIN; if (strcmp(ipng, "10d") == 0) icon = WEATHER_ICON_RAIN; if (strcmp(ipng, "10n") == 0) icon = WEATHER_ICON_RAIN; if (strcmp(ipng, "11d") == 0) icon = WEATHER_ICON_RAIN; if (strcmp(ipng, "11n") == 0) icon = WEATHER_ICON_RAIN; if (strcmp(ipng, "13d") == 0) icon = WEATHER_ICON_SNOW; if (strcmp(ipng, "13n") == 0) icon = WEATHER_ICON_SNOW; if (strcmp(ipng, "50d") == 0) icon = WEATHER_ICON_FOG; if (strcmp(ipng, "50n") == 0) icon = WEATHER_ICON_FOG; if(icon >= 0 && icon < 10) { weather_layer_set_icon(&weather_layer, icon); } else { #ifndef ANTONIO weather_layer_set_icon(&weather_layer, WEATHER_ICON_NO_WEATHER); #endif } } int min_temp = -1; int max_temp = -1; static char minmax[32]; Tuple* min_temp_tuple = dict_find(received, WEATHER_KEY_MIN_TEMP); if (min_temp_tuple) { min_temp = min_temp_tuple->value->int16; } Tuple* max_temp_tuple = dict_find(received, WEATHER_KEY_MAX_TEMP); if (max_temp_tuple) { max_temp = max_temp_tuple->value->int16; } strcpy(minmax, itoa(max_temp)); strcat(minmax, "°/ "); strcat(minmax, itoa(min_temp)); strcat(minmax, "°"); if (min_temp_tuple && max_temp_tuple) { text_layer_set_text(&minmax_layer, minmax); } Tuple* temperature_tuple = dict_find(received, WEATHER_KEY_TEMP); if (temperature_tuple) { weather_layer_set_temperature(&weather_layer, temperature_tuple->value->int16); get_time(&updated_tm); set_updated(); // updated last successful wweather event has_temperature = true; } link_monitor_handle_success(); }
void failed(int32_t cookie, int http_status, void* context) { /* This is triggered by invalid responses from the bridge on the phone, * due to e.g. HTTP errors or phone disconnections. */ if(HTTP_INVALID_BRIDGE_RESPONSE) { // Phone can still be reached (assume HTTP error) if (http_time_request() == HTTP_OK) { /* Display 'cloud error' icon if: * - HTTP error is noticed upon inital load * - watch has recovered from a phone disconnection, but has no internet connection */ if (!has_temperature || phone_disconnected) { weather_layer_set_icon(&weather_layer, WEATHER_ICON_CLOUD_ERROR); phone_disconnected = false; } /* Assume that weather information is stale after 1 hour without a successful * weather request. Indicate this by removing the degree symbol. */ else if (has_timed_out || has_temperature || http_request_build_count > 0 || http_request_send_count > 0) { if (fail_count >= 60) { is_stale = true; weather_layer_set_temperature(&weather_layer, last_valid_temperature, is_stale); } } } else { /* Redundant check to make sure that HTTP time-outs are not triggering the * 'phone error' icon. If appearing to be timed out after 1 hour without a * successful weather request, indicate stale weather information by removing * the degree symbol. */ if (fail_count >= 60 && has_timed_out && !phone_disconnected) { is_stale = true; weather_layer_set_temperature(&weather_layer, last_valid_temperature, is_stale); } /* Display 'phone error' icon if: * - watch appears to be disconnected from phone * - watch appears to be disconnected from bridge app on phone * * In case this is triggered by a HTTP time-out, subsequently send a * weather request for a possible quick re-connection. */ else { if (http_status==1008) { phone_disconnected = true; weather_layer_set_icon(&weather_layer, WEATHER_ICON_PHONE_ERROR); link_monitor_handle_failure(http_status); http_location_request(); request_weather(); } } } } // Remove temperature text 30 minutes after a phone/bridge app disconnection if (fail_count >= 30 && phone_disconnected) { text_layer_set_text(weather_layer.temp_layer, " "); has_temperature = false; } // Indicate failure and activate fail counter (see handle_tick() function) has_failed = true; // Re-request the location and subsequently weather on next minute tick located = false; }
// Update the bottom half of the screen: icon and temperature void weather_layer_update(WeatherData *weather_data) { // We have no weather data yet... don't update until we do if (weather_data->updated == 0) { return; } WeatherLayerData *wld = layer_get_data(weather_layer); if (weather_animation_timer && animation_timer_enabled) { app_timer_cancel(weather_animation_timer); // this is only needed to stop the error message when cancelling an already cancelled timer... animation_timer_enabled = false; layer_set_hidden(wld->loading_layer, true); } time_t current_time = time(NULL); bool stale = false; if (current_time - weather_data->updated > WEATHER_STALE_TIMEOUT) { stale = true; } //APP_LOG(APP_LOG_LEVEL_DEBUG, "ct:%i wup:%i, stale:%i", // (int)current_time, (int)weather_data->updated, (int)WEATHER_STALE_TIMEOUT); // Update the weather icon and temperature if (weather_data->error) { // Only update the error icon if the weather data is stale if (stale) { weather_layer_clear_temperature(); switch (weather_data->error) { case WEATHER_E_NETWORK: weather_layer_set_error(); debug_update_message("Network error"); break; case WEATHER_E_DISCONNECTED: case WEATHER_E_PHONE: default: weather_layer_set_error(); debug_update_message("Phone disco / error"); break; } } } else { layer_set_frame(bitmap_layer_get_layer(wld->primary_icon_layer), PRIMARY_ICON_NORMAL_FRAME); // Show the temperature as 'stale' if it has not been updated in WEATHER_STALE_TIMEOUT weather_layer_set_temperature(weather_data->temperature, stale); // Day/night check time_t utc = current_time; // time_t utc = current_time + weather_data->tzoffset; ///////// Change utc value to current_time for SDK3 by ktagjp bool night_time = is_night_time(weather_data->sunrise, weather_data->sunset, utc); /* APP_LOG(APP_LOG_LEVEL_DEBUG, "ct:%i, utc:%i sr:%i, ss:%i, nt:%i", (int)current_time, (int)utc, weather_data->sunrise, weather_data->sunset, night_time); */ if (strcmp(weather_data->service, SERVICE_OPEN_WEATHER) == 0) { weather_layer_set_icon(open_weather_icon_for_condition(weather_data->condition, night_time), AREA_PRIMARY); } else if (strcmp(weather_data->service, SERVICE_YAHOO_WEATHER) == 0) { weather_layer_set_icon(yahoo_weather_icon_for_condition(weather_data->condition, night_time), AREA_PRIMARY); } else { weather_layer_set_icon(wunder_weather_icon_for_condition(weather_data->condition, night_time), AREA_PRIMARY); } if (weather_data->hourly_updated != 0 && weather_data->hourly_enabled) { time_t h1t = weather_data->h1_time; time_t h2t = weather_data->h2_time; // time_t h1t = weather_data->h1_time - weather_data->tzoffset; ///////// Change time value for SDK3 by ktagjp // time_t h2t = weather_data->h2_time - weather_data->tzoffset; ///////// Change time value for SDK3 by ktagjp strftime(time_h1, sizeof(time_h1), "%I%p", localtime(&h1t)); strftime(time_h2, sizeof(time_h2), "%I%p", localtime(&h2t)); if (time_h1[0] == '0') { memmove(time_h1, &time_h1[1], sizeof(time_h1) - 1); } if (time_h2[0] == '0') { memmove(time_h2, &time_h2[1], sizeof(time_h2) - 1); } text_layer_set_text(wld->h1_time_layer, time_h1); text_layer_set_text(wld->h2_time_layer, time_h2); localtime(¤t_time); night_time = is_night_time(weather_data->sunrise, weather_data->sunset, weather_data->h1_time); weather_layer_set_icon(wunder_weather_icon_for_condition(weather_data->h1_cond, night_time), AREA_HOURLY1); night_time = is_night_time(weather_data->sunrise, weather_data->sunset, weather_data->h2_time); weather_layer_set_icon(wunder_weather_icon_for_condition(weather_data->h2_cond, night_time), AREA_HOURLY2); snprintf(wld->h1_temp_str, sizeof(wld->h1_temp_str), "%i%s", weather_data->h1_temp, "°"); snprintf(wld->h2_temp_str, sizeof(wld->h2_temp_str), "%i%s", weather_data->h2_temp, "°"); text_layer_set_text(wld->h1_temp_layer, wld->h1_temp_str); text_layer_set_text(wld->h2_temp_layer, wld->h2_temp_str); } } }