def uvindex_history_around_coords(self, lat, lon, start, end=None): """ Queries for UV index historical values in the surroundings of the provided geocoordinates and in the specified time frame. If the end of the time frame is not provided, that is intended to be the current datetime. :param lat: the location's latitude, must be between -90.0 and 90.0 :type lat: int/float :param lon: the location's longitude, must be between -180.0 and 180.0 :type lon: int/float :param start: the object conveying the time value for the start query boundary :type start: int, ``datetime.datetime`` or ISO8601-formatted string :param end: the object conveying the time value for the end query boundary (defaults to ``None``, in which case the current datetime will be used) :type end: int, ``datetime.datetime`` or ISO8601-formatted string :return: a list of *UVIndex* instances or empty list if data is not available :raises: *ParseResponseException* when OWM UV Index API responses' data cannot be parsed, *APICallException* when OWM UV Index API can not be reached, *ValueError* for wrong input values """ geo.assert_is_lon(lon) geo.assert_is_lat(lat) assert start is not None start = formatting.timeformat(start, 'unix') if end is None: end = timestamps.now(timeformat='unix') else: end = formatting.timeformat(end, 'unix') params = {'lon': lon, 'lat': lat, 'start': start, 'end': end} json_data = self.uv_client.get_uvi_history(params) uvindex_list = [uvindex.UVIndex.from_dict(item) for item in json_data] return uvindex_list
def forecast(city: str, timestamp: str): time_to_start = time.time() global programMetrics global processing_time_of_the_request_forecast_weather programMetrics[2] += 1 mgr = owm.weather_manager() observation = mgr.forecast_at_place( city, "3h" ) #данной командой стягивается прогноз погоды на ближайшие 5 дней с частотой 3 часа if timestamp == "1h": timest = timestamps.next_hour() elif timestamp == "3h": timest = timestamps.next_three_hours() elif timestamp == "tomorrow": timest = timestamps.tomorrow() elif timestamp == "yesterday": timest = timestamps.yesterday() else: timest = timestamps.now() w = observation.get_weather_at(timest) temp = w.temperature('celsius')['temp'] #вывод в консоль print(" request: " + city + "\ttime: " + str(timest) + "\t" + w.detailed_status + "\t" + str(temp)) processing_time_of_the_request_forecast_weather.append(time.time() - time_to_start) return json.dumps({ "city": city, "unit": "celsius", "temperature": temp, "id_service": my_id })
def from_dict(cls, the_dict): """ Parses a *COIndex* instance out of a data dictionary. Only certain properties of the data dictionary are used: if these properties are not found or cannot be parsed, an exception is issued. :param the_dict: the input dictionary :type the_dict: `dict` :returns: a *COIndex* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: # -- reference time (strip away Z and T on ISO8601 format) t = the_dict['time'].replace('Z', '+00:00').replace('T', ' ') reference_time = formatting.ISO8601_to_UNIXtime(t) # -- reception time (now) reception_time = timestamps.now('unix') # -- location lon = float(the_dict['location']['longitude']) lat = float(the_dict['location']['latitude']) place = location.Location(None, lon, lat, None) # -- CO samples co_samples = the_dict['data'] except KeyError: raise exceptions.ParseAPIResponseError( ''.join([__name__, ': impossible to parse COIndex'])) return COIndex(reference_time, place, None, co_samples, reception_time)
def from_dict(cls, the_dict): """ Parses an *UVIndex* instance out of raw JSON data. Only certain properties of the data are used: if these properties are not found or cannot be parsed, an error is issued. :param the_dict: the input dict :type the_dict: dict :returns: an *UVIndex* instance or ``None`` if no data is available :raises: *ParseAPIResponseError* if it is impossible to find or parse the data needed to build the result, *APIResponseError* if the input dict embeds an HTTP status error """ if the_dict is None: raise exceptions.ParseAPIResponseError('Data is None') try: # -- reference time reference_time = the_dict['date'] # -- reception time (now) reception_time = timestamps.now('unix') # -- location lon = float(the_dict['lon']) lat = float(the_dict['lat']) place = location.Location(None, lon, lat, None) # -- UV intensity uv_intensity = float(the_dict['value']) except KeyError: raise exceptions.ParseAPIResponseError(''.join( [__name__, ': impossible to parse UV Index'])) return UVIndex(reference_time, place, uv_intensity, reception_time)
def actualize(self): """ Removes from this forecast all the *Weather* objects having a reference timestamp in the past with respect to the current timestamp """ current_time = timestamps.now(timeformat='unix') actualized_weathers = filter(lambda x: x.reference_time(timeformat='unix') >= current_time, self.weathers) self.weathers = list(actualized_weathers)
def is_forecast(self): """ Tells if the current CO observation refers to the future with respect to the current date :return: bool """ return timestamps.now(timeformat='unix') < \ self.reference_time(timeformat='unix')
def test_now(self): expected = datetime.now() result = timestamps.now() self.assertEquals(result.year, expected.year) self.assertEquals(result.month, expected.month) self.assertEquals(result.day, expected.day) self.assertEquals(result.hour, expected.hour) self.assertEquals(result.minute, expected.minute) self.assertEquals(result.second, expected.second)
def test_now(self): expected = datetime.now(timezone.utc) result = timestamps.now() self.assertEqual(result.year, expected.year) self.assertEqual(result.month, expected.month) self.assertEqual(result.day, expected.day) self.assertEqual(result.hour, expected.hour) self.assertEqual(result.minute, expected.minute) self.assertEqual(result.second, expected.second) self.is_timezone_aware(result)
async def weather_slash( self, inter: discord.CommandInteraction, where: str = commands.Param(description="Place where show weather"), when: str = commands.Param( autocomplete=when_autocomplete, default="UTC Now", description="UTC Time offset of weather prediction")): when = when.lower() if when == "utc now": time = timestamps.now() elif when == "utc tomorrow": time = timestamps.tomorrow() else: if when.isnumeric(): when = int(when) else: if when[-1] != "h": return await inter.send( embed=general_util.generate_error_message( Strings.weather_slash_invalid_when_format), delete_after=Config.base_error_duration) when = int(when[:-1]) time = timestamps.now() + timestamps.timedelta(hours=when) try: weather = self.get_time_specific_weather(where, time) except commands.CommandOnCooldown: return await inter.send(embed=general_util.generate_error_message( Strings.weather_api_reached_minute_limit), delete_after=Config.base_error_duration) if weather is None: return await inter.send(embed=general_util.generate_error_message( Strings.populate_string("weather_failed_to_get_weather", place=where)), delete_after=Config.base_error_duration) embed = generate_weather_embed(weather, where) general_util.add_author_footer(embed, inter.author) await inter.send(embed=embed)
def forecast_weather(city: str, timestamp: str): #обращение к внешнему сервису mgr = owm.weather_manager() observation = mgr.forecast_at_place(city, "3h") #данной командой стягивается прогноз погоды на ближайшие 5 дней с частотой 3 часа if timestamp == "1h": time = timestamps.next_hour() elif timestamp == "3h": time = timestamps.next_three_hours() else: time = timestamps.now(); w = observation.get_weather_at(time) temp = w.temperature('celsius')['temp'] #занесение в бд данных (не совсем корректно, ведь у нас прогноз погоды...) rc.set(city, temp, ex=time_storage) #возвращение текущей погоды return temp
async def weather_now(self, ctx: commands.Context, *, place: str): await general_util.delete_message(self.bot, ctx) try: weather = self.get_time_specific_weather(place, timestamps.now()) except commands.CommandOnCooldown: return await ctx.send(embed=general_util.generate_error_message( Strings.weather_api_reached_minute_limit), delete_after=Config.base_error_duration) if weather is None: return await ctx.send(embed=general_util.generate_error_message( Strings.populate_string("weather_failed_to_get_weather", place=place)), delete_after=Config.base_error_duration) embed = generate_weather_embed(weather, place) general_util.add_author_footer(embed, ctx.author) await ctx.send(embed=embed)
def forecast(city: str, timestamp: str): mgr = owm.weather_manager() observation = mgr.forecast_at_place( city, "3h" ) #данной командой стягивается прогноз погоды на ближайшие 5 дней с частотой 3 часа if timestamp == "1h": time = timestamps.next_hour() elif timestamp == "3h": time = timestamps.next_three_hours() elif timestamp == "tomorrow": time = timestamps.tomorrow() elif timestamp == "yesterday": time = timestamps.yesterday() else: time = timestamps.now() w = observation.get_weather_at(time) temp = w.temperature('celsius')['temp'] #вывод в консоль print(" request: " + city + "\ttime: " + str(time) + "\t" + w.detailed_status + "\t" + str(temp)) return json.dumps({"city": city, "unit": "celsius", "temperature": temp})
def air_quality_history_at_coords(self, lat, lon, start, end=None): """ Queries the OWM AirPollution API for available forecasted air quality indicators around the specified coordinates. :param lat: the location's latitude, must be between -90.0 and 90.0 :type lat: int/float :param lon: the location's longitude, must be between -180.0 and 180.0 :type lon: int/float :param start: the object conveying the start value of the search time window :type start: int, ``datetime.datetime`` or ISO8601-formatted string :param end: the object conveying the end value of the search time window. Values in the future will be clipped to the current timestamp. Defaults to the current UNIX timestamp. :type end: int, ``datetime.datetime`` or ISO8601-formatted string :return: a `list` of *AirStatus* instances or an empty `list` if data is not available :raises: *ParseResponseException* when OWM AirPollution API responses' data cannot be parsed, *APICallException* when OWM AirPollution API can not be reached, *ValueError* for wrong input values """ geo.assert_is_lon(lon) geo.assert_is_lat(lat) now = timestamps.now(timeformat='unix') assert start is not None start = formatting.timeformat(start, 'unix') if end is None: end = now else: end = formatting.timeformat(end, 'unix') if end > now: end = now params = {'lon': lon, 'lat': lat, 'start': start, 'end': end} json_data = self.new_ap_client.get_historical_air_pollution(params) try: return airstatus.AirStatus.from_dict(json_data) except: return []
def create_trigger(self, start, end, conditions, area, alert_channels=None): """ Create a new trigger on the Alert API with the given parameters :param start: time object representing the time when the trigger begins to be checked :type start: int, ``datetime.datetime`` or ISO8601-formatted string :param end: time object representing the time when the trigger ends to be checked :type end: int, ``datetime.datetime`` or ISO8601-formatted string :param conditions: the `Condition` objects representing the set of checks to be done on weather variables :type conditions: list of `pyowm.utils.alertapi30.Condition` instances :param area: the geographic are over which conditions are checked: it can be composed by multiple geoJSON types :type area: list of geoJSON types :param alert_channels: the alert channels through which alerts originating from this `Trigger` can be consumed. Defaults to OWM API polling :type alert_channels: list of `pyowm.utils.alertapi30.AlertChannel` instances :returns: a *Trigger* instance :raises: *ValueError* when start or end epochs are `None` or when end precedes start or when conditions or area are empty collections """ assert start is not None assert end is not None # prepare time period unix_start = formatting.to_UNIXtime(start) unix_end = formatting.to_UNIXtime(end) unix_current = timestamps.now(timeformat='unix') if unix_start >= unix_end: raise ValueError( "The start timestamp must precede the end timestamp") delta_millis_start = timestamps.millis_offset_between_epochs( unix_current, unix_start) delta_millis_end = timestamps.millis_offset_between_epochs( unix_current, unix_end) the_time_period = { "start": { "expression": "after", "amount": delta_millis_start }, "end": { "expression": "after", "amount": delta_millis_end } } assert conditions is not None if len(conditions) == 0: raise ValueError( 'A trigger must contain at least one condition: you provided none' ) the_conditions = [ dict(name=c.weather_param, expression=c.operator, amount=c.amount) for c in conditions ] assert area is not None if len(area) == 0: raise ValueError( 'The area for a trigger must contain at least one geoJSON type: you provided none' ) the_area = [a.to_dict() for a in area] # >>> for the moment, no specific handling for alert channels status, payload = self.http_client.post( TRIGGERS_URI, params={'appid': self.API_key}, data=dict(time_period=the_time_period, conditions=the_conditions, area=the_area), headers={'Content-Type': 'application/json'}) return Trigger.from_dict(payload)
def send_echo(message): try: mgr = owm.weather_manager() observation = mgr.weather_at_place(message.text) w = observation.weather temperature = w.temperature('celsius')['temp'] wind = w.wind()['speed'] current_time = timestamps.now('iso') status = w.status thunderstorm = u'\U0001F4A8' drizzle = u'\U0001F4A7' rain = u'\U00002614' snowflake = u'\U00002744' snowman = u'\U000026C4' atmosphere = u'\U0001F301' clearSky = u'\U00002600' fewClouds = u'\U000026C5' clouds = u'\U00002601' hot = u'\U0001F525' defaultEmoji = u'\U0001F60A' def set_emojo (weather_status): try: if str(weather_status) == "Thunderstorm": return thunderstorm elif str(weather_status) == "Drizzle": return drizzle elif str(weather_status) == "Rain": return rain elif str(weather_status) == "Snowflake": return snowflake elif str(weather_status) == "Snowman": return snowman elif str(weather_status) == "Atmosphere": return atmosphere elif str(weather_status) == "ClearSky" or "Clear": return clearSky elif str(weather_status) == "FewClouds": return fewClouds elif str(weather_status) == "Clouds": return clouds elif str(weather_status) == "Hot": return hot else: return defaultEmoji except Exception as e: print(e) answer = "Сейчас: " + str(current_time) + "\n\n" answer += "Температура в " + message.text + ": " + str(temperature) + " ℃" + "\n" answer += "Ветер: " + str(wind) + " м/с " + "\n" answer += "В общем - " + w.detailed_status + set_emojo(status) + "\n\n" if temperature < 10: answer += "Сейчас очень холодно, одевайся!" elif temperature < 20: answer += "Сейчас холодно, оденься теплее." else: answer += "Сейчас тепло, одевай что хочешь." bot.send_message(message.chat.id, answer) print(status) except Exception as e: error = str(e) bot.send_message(message.chat.id, error + ". Please try again!")
def __init__(self, station_id): assert station_id is not None self.station_id = station_id self.created_at = timestamps.now(timeformat='unix') self.measurements = []
def download_satellite_image(self, metaimage, x=None, y=None, zoom=None, palette=None): """ Downloads the satellite image described by the provided metadata. In case the satellite image is a tile, then tile coordinates and zoom must be provided. An optional palette ID can be provided, if supported by the downloaded preset (currently only NDVI is supported) :param metaimage: the satellite image's metadata, in the form of a `MetaImage` subtype instance :type metaimage: a `pyowm.agroapi10.imagery.MetaImage` subtype :param x: x tile coordinate (only needed in case you are downloading a tile image) :type x: int or `None` :param y: y tile coordinate (only needed in case you are downloading a tile image) :type y: int or `None` :param zoom: zoom level (only needed in case you are downloading a tile image) :type zoom: int or `None` :param palette: ID of the color palette of the downloaded images. Values are provided by `pyowm.agroapi10.enums.PaletteEnum` :type palette: str or `None` :return: a `pyowm.agroapi10.imagery.SatelliteImage` instance containing both image's metadata and data """ if palette is not None: assert isinstance(palette, str) params = dict(paletteid=palette) else: palette = PaletteEnum.GREEN params = {} # polygon PNG if isinstance(metaimage, MetaPNGImage): prepared_url = metaimage.url status, data = self.png_downloader_http_client.get_png( prepared_url, params=params) img = Image(data, metaimage.image_type) return SatelliteImage( metaimage, img, downloaded_on=timestamps.now(timeformat='unix'), palette=palette) # GeoTIF elif isinstance(metaimage, MetaGeoTiffImage): prepared_url = metaimage.url status, data = self.geotiff_downloader_http_client.get_geotiff( prepared_url, params=params) img = Image(data, metaimage.image_type) return SatelliteImage( metaimage, img, downloaded_on=timestamps.now(timeformat='unix'), palette=palette) # tile PNG elif isinstance(metaimage, MetaTile): assert x is not None assert y is not None assert zoom is not None prepared_url = self._fill_url(metaimage.url, x, y, zoom) status, data = self.http_client.get_png(prepared_url, params=params) img = Image(data, metaimage.image_type) tile = Tile(x, y, zoom, None, img) return SatelliteImage( metaimage, tile, downloaded_on=timestamps.now(timeformat='unix'), palette=palette) else: raise ValueError("Cannot download: unsupported MetaImage subtype")
def search_satellite_imagery(self, polygon_id, acquired_from, acquired_to, img_type=None, preset=None, min_resolution=None, max_resolution=None, acquired_by=None, min_cloud_coverage=None, max_cloud_coverage=None, min_valid_data_coverage=None, max_valid_data_coverage=None): """ Searches on the Agro API the metadata for all available satellite images that contain the specified polygon and acquired during the specified time interval; and optionally matching the specified set of filters: - image type (eg. GeoTIF) - image preset (eg. false color, NDVI, ...) - min/max acquisition resolution - acquiring satellite - min/max cloud coverage on acquired scene - min/max valid data coverage on acquired scene :param polygon_id: the ID of the reference polygon :type polygon_id: str :param acquired_from: lower edge of acquisition interval, UNIX timestamp :type acquired_from: int :param acquired_to: upper edge of acquisition interval, UNIX timestamp :type acquired_to: int :param img_type: the desired file format type of the images. Allowed values are given by `pyowm.commons.enums.ImageTypeEnum` :type img_type: `pyowm.commons.databoxes.ImageType` :param preset: the desired preset of the images. Allowed values are given by `pyowm.agroapi10.enums.PresetEnum` :type preset: str :param min_resolution: minimum resolution for images, px/meters :type min_resolution: int :param max_resolution: maximum resolution for images, px/meters :type max_resolution: int :param acquired_by: short symbol of the satellite that acquired the image (eg. "l8") :type acquired_by: str :param min_cloud_coverage: minimum cloud coverage percentage on acquired images :type min_cloud_coverage: int :param max_cloud_coverage: maximum cloud coverage percentage on acquired images :type max_cloud_coverage: int :param min_valid_data_coverage: minimum valid data coverage percentage on acquired images :type min_valid_data_coverage: int :param max_valid_data_coverage: maximum valid data coverage percentage on acquired images :type max_valid_data_coverage: int :return: a list of `pyowm.agro10.imagery.MetaImage` subtypes instances """ assert polygon_id is not None assert acquired_from is not None assert acquired_to is not None assert acquired_from <= acquired_to, 'Start timestamp of acquisition window must come before its end' if min_resolution is not None: assert min_resolution > 0, 'Minimum resolution must be positive' if max_resolution is not None: assert max_resolution > 0, 'Maximum resolution must be positive' if min_resolution is not None and max_resolution is not None: assert min_resolution <= max_resolution, 'Mininum resolution must be lower than maximum resolution' if min_cloud_coverage is not None: assert min_cloud_coverage >= 0, 'Minimum cloud coverage must be non negative' if max_cloud_coverage is not None: assert max_cloud_coverage >= 0, 'Maximum cloud coverage must be non negative' if min_cloud_coverage is not None and max_cloud_coverage is not None: assert min_cloud_coverage <= max_cloud_coverage, 'Minimum cloud coverage must be lower than maximum cloud coverage' if min_valid_data_coverage is not None: assert min_valid_data_coverage >= 0, 'Minimum valid data coverage must be non negative' if max_valid_data_coverage is not None: assert max_valid_data_coverage >= 0, 'Maximum valid data coverage must be non negative' if min_valid_data_coverage is not None and max_valid_data_coverage is not None: assert min_valid_data_coverage <= max_valid_data_coverage, 'Minimum valid data coverage must be lower than maximum valid data coverage' # prepare params params = dict(appid=self.API_key, polyid=polygon_id, start=acquired_from, end=acquired_to) if min_resolution is not None: params['resolution_min'] = min_resolution if max_resolution is not None: params['resolution_max'] = max_resolution if acquired_by is not None: params['type'] = acquired_by if min_cloud_coverage is not None: params['clouds_min'] = min_cloud_coverage if max_cloud_coverage is not None: params['clouds_max'] = max_cloud_coverage if min_valid_data_coverage is not None: params['coverage_min'] = min_valid_data_coverage if max_valid_data_coverage is not None: params['coverage_max'] = max_valid_data_coverage # call API status, data = self.http_client.get_json(SATELLITE_IMAGERY_SEARCH_URI, params=params) result_set = SatelliteImagerySearchResultSet( polygon_id, data, timestamps.now(timeformat='unix')) # further filter by img_type and/or preset (if specified) if img_type is not None and preset is not None: return result_set.with_img_type_and_preset(img_type, preset) elif img_type is not None: return result_set.with_img_type(img_type) elif preset is not None: return result_set.with_preset(preset) else: return result_set.all()