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();
  }
}
Exemple #2
0
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);
	}
}
Exemple #3
0
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);
	}
	*/
}
Exemple #4
0
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;
}
Exemple #5
0
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();
}
Exemple #6
0
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();
}
Exemple #7
0
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;
}
Exemple #8
0
// 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(&current_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);
        }
    }
}