def get(self, request, *args, **kwargs): json_item = {} json_places = [] context = self.get_context_data(**kwargs) if "q" in request.GET: search_location = request.GET["q"] client = MeteoFranceClient() list_places = client.search_places(search_location) for one_place in list_places: # correct bad json returned my MeteoFrance + admin is not # always there if "name" in one_place.raw_data: one_place.raw_data["name"] = one_place.raw_data[ "name" ].replace("'", " ") if "admin" in one_place.raw_data: one_place.raw_data["admin"] = one_place.raw_data[ "admin" ].replace("'", " ") json_item["value"] = str(one_place.raw_data) json_item["text"] = one_place.__str__() json_places.append(json_item) json_item = {} return JsonResponse(json_places, status=200, safe=False) return render(request, SettingsView.template_name, context=context)
def test_forecast_france(): """Test weather forecast results from API.""" client = MeteoFranceClient() weather_forecast = client.get_forecast(latitude=48.8075, longitude=2.24028) now_ts = int(time.time()) assert type(weather_forecast.position) == dict assert type(weather_forecast.updated_on) == int assert "T" in weather_forecast.daily_forecast[0].keys() assert "humidity" in weather_forecast.daily_forecast[0].keys() assert "rain" in weather_forecast.probability_forecast[0].keys() assert "clouds" in weather_forecast.forecast[0].keys() assert ( type( weather_forecast.timestamp_to_locale_time( weather_forecast.daily_forecast[0]["dt"] ) ) == datetime ) assert abs(weather_forecast.nearest_forecast["dt"] - now_ts) <= 30 * 60 assert now_ts - 3600 <= weather_forecast.current_forecast["dt"] <= now_ts assert ( weather_forecast.today_forecast["dt"] == weather_forecast.daily_forecast[0]["dt"] )
def test_forecast_world(): """Test weather forecast results from API.""" client = MeteoFranceClient() weather_forecast = client.get_forecast(latitude=45.5016889, longitude=73.567256) now_ts = int(time.time()) assert type(weather_forecast.position) == dict assert type(weather_forecast.updated_on) == int assert "T" in weather_forecast.daily_forecast[0].keys() assert "humidity" in weather_forecast.daily_forecast[0].keys() assert not weather_forecast.probability_forecast assert "clouds" in weather_forecast.forecast[0].keys() assert ( type( weather_forecast.timestamp_to_locale_time( weather_forecast.daily_forecast[0]["dt"] ) ) == datetime ) assert abs(weather_forecast.nearest_forecast["dt"] - now_ts) == min( abs(x["dt"] - now_ts) for x in weather_forecast.forecast ) assert ( weather_forecast.current_forecast["dt"] == weather_forecast.nearest_forecast["dt"] ) assert ( weather_forecast.today_forecast["dt"] == weather_forecast.daily_forecast[0]["dt"] )
async def async_step_user(self, user_input=None): """Handle a flow initiated by the user.""" errors = {} if user_input is None: return self._show_setup_form(user_input, errors) city = user_input[CONF_CITY] # Might be a city name or a postal code latitude = user_input.get(CONF_LATITUDE) longitude = user_input.get(CONF_LONGITUDE) if not latitude: client = MeteoFranceClient() self.places = await self.hass.async_add_executor_job( client.search_places, city) _LOGGER.debug("Places search result: %s", self.places) if not self.places: errors[CONF_CITY] = "empty" return self._show_setup_form(user_input, errors) return await self.async_step_cities() # Check if already configured await self.async_set_unique_id(f"{latitude}, {longitude}") self._abort_if_unique_id_configured() return self.async_create_entry( title=city, data={ CONF_LATITUDE: latitude, CONF_LONGITUDE: longitude }, )
def test_workflow(city): """Test classical workflow usage with the Python library.""" # Init client client = MeteoFranceClient() # Search a location from name. list_places = client.search_places(city) my_place = list_places[0] # Fetch weather forecast for the location my_place_weather_forecast = client.get_forecast_for_place(my_place) # Get the daily forecast my_place_daily_forecast = my_place_weather_forecast.daily_forecast # If rain in the hour forecast is available, get it. if my_place_weather_forecast.position["rain_product_available"] == 1: my_place_rain_forecast = client.get_rain(my_place.latitude, my_place.longitude) next_rain_dt = my_place_rain_forecast.next_rain_date_locale() if not next_rain_dt: rain_status = "No rain expected in the following hour." else: rain_status = next_rain_dt.strftime("%H:%M") else: rain_status = "No rain forecast availble." # Fetch weather alerts. my_place_weather_alerts = client.get_warning_current_phenomenoms(my_place.admin2) readable_warnings = readeable_phenomenoms_dict( my_place_weather_alerts.phenomenons_max_colors ) assert type(my_place_daily_forecast) == list assert rain_status assert type(readable_warnings) == dict
def test_places_not_found() -> None: """Test when no places are found.""" client = MeteoFranceClient() list_places = client.search_places("sqdmfkjdsmkf") assert not list_places
def test_no_rain_expected(requests_mock: Mock) -> None: """Test datecomputation when rain is expected within the hour.""" client = MeteoFranceClient() requests_mock.request( "get", f"{METEOFRANCE_API_URL}/rain", json={ "position": { "lat": 48.807166, "lon": 2.239895, "alti": 76, "name": "Meudon", "country": "FR - France", "dept": "92", "timezone": "Europe/Paris", }, "updated_on": 1589995200, "quality": 0, "forecast": [ {"dt": 1589996100, "rain": 1, "desc": "Temps sec"}, {"dt": 1589996400, "rain": 1, "desc": "Temps sec"}, {"dt": 1589996700, "rain": 1, "desc": "Temps sec"}, {"dt": 1589997000, "rain": 1, "desc": "Temps sec"}, {"dt": 1589997300, "rain": 1, "desc": "Temps sec"}, {"dt": 1589997600, "rain": 1, "desc": "Temps sec"}, {"dt": 1589998200, "rain": 1, "desc": "Temps sec"}, {"dt": 1589998800, "rain": 1, "desc": "Temps sec"}, {"dt": 1589999400, "rain": 1, "desc": "Temps sec"}, ], }, ) rain = client.get_rain(latitude=48.8075, longitude=2.24028) assert rain.next_rain_date_locale() is None
def getPluieDansLheureLatLon(lat, lon) : # Init client client = MeteoFranceClient() # Search a location from name. # Fetch weather forecast for the location my_place_weather_forecast = client.get_forecast(lat, lon) # Get the daily forecast my_place_daily_forecast = my_place_weather_forecast.daily_forecast # If rain in the hour forecast is available, get it. print (my_place_weather_forecast.position["rain_product_available"] ) if my_place_weather_forecast.position["rain_product_available"] == 1: my_place_rain_forecast = client.get_rain(lat, lon) next_rain_dt = my_place_rain_forecast.next_rain_date_locale() if not next_rain_dt: rain_status = "Pas de pluie prévu dans l'heure" else: rain_status = next_rain_dt.strftime("%H:%M") else: rain_status = "Absence de données." return rain_status
def test_currentphenomenons_with_coastal_bulletin(dep, res): """Test getting a complete basic bulletin for coastal department.""" client = MeteoFranceClient() current_phenomenoms = client.get_warning_current_phenomenoms( domain=dep, depth=1, with_costal_bulletin=True) has_coastal_phenomenom = any( phenomenom["phenomenon_id"] == 9 for phenomenom in current_phenomenoms.phenomenons_max_colors) assert has_coastal_phenomenom == res
def test_rain(): """Test rain forecast on a covered zone.""" client = MeteoFranceClient() rain = client.get_rain(latitude=48.8075, longitude=2.24028) assert type(rain.position) == dict assert type(rain.updated_on) == int assert type(rain.quality) == int assert "rain" in rain.forecast[0].keys()
def getLatLongFromCityName(ville): client = MeteoFranceClient() list_places = client.search_places(ville) my_place = list_places[0] position = PositionLatLong() position.latitude = my_place.latitude position.longitude = my_place.longitude return position
def test_thumbnail(): """Test getting France status weather alert map.""" client = MeteoFranceClient() thumbnail_url = client.get_warning_thumbnail() assert thumbnail_url == ( "http://webservice.meteofrance.com/warning/thumbnail" "?&token=__Wj7dVSTjV9YGu1guveLyDq0g7S7TfTjaHBTPTpO0kj8__&" "domain=france")
def test_full_with_coastal_bulletint(dep, res): """Test getting a complete advanced bulletin for coastal department.""" client = MeteoFranceClient() full_phenomenoms = client.get_warning_full(domain=dep, with_costal_bulletin=True) has_coastal_phenomenom = any( phenomenom["phenomenon_id"] == 9 for phenomenom in full_phenomenoms.phenomenons_items) assert has_coastal_phenomenom == res
def test_picture_of_the_day() -> None: """Test weather picture of the day results from API.""" client = MeteoFranceClient() potd = client.get_picture_of_the_day() assert "http://" in potd.image_url assert ".jpg" in potd.image_url assert "http://" in potd.image_hd_url assert ".jpg" in potd.image_hd_url assert potd.description
def getWind(ville): client = MeteoFranceClient() my_place = rechercheLatLong.getLatLongFromCityName(ville) jsonObj = client.get_forecast(my_place.latitude, my_place.longitude) premier= jsonObj.forecast[12] test = premier['wind'] dt = premier['dt'] time = datetime.utcfromtimestamp(dt).strftime('%d-%m-%Y %H:%M:%S') return ("la vitesse du vent à " + str(time) + " est de " + str(test['speed']*3600/1000) +" km/h avec une direction de " + str(test['direction']) + " degrée")
def test_currentphenomenons(requests_mock): """Test basic weather alert results from API.""" client = MeteoFranceClient() requests_mock.request( "get", f"{METEOFRANCE_API_URL}/warning/currentphenomenons", json={ "update_time": 1591279200, "end_validity_time": 1591365600, "domain_id": "32", "phenomenons_max_colors": [ { "phenomenon_id": 6, "phenomenon_max_color_id": 1 }, { "phenomenon_id": 4, "phenomenon_max_color_id": 1 }, { "phenomenon_id": 5, "phenomenon_max_color_id": 3 }, { "phenomenon_id": 2, "phenomenon_max_color_id": 1 }, { "phenomenon_id": 1, "phenomenon_max_color_id": 1 }, { "phenomenon_id": 3, "phenomenon_max_color_id": 2 }, ], }, ) current_phenomenoms = client.get_warning_current_phenomenoms(domain="32", depth=1) assert type(current_phenomenoms.update_time) == int assert type(current_phenomenoms.end_validity_time) == int assert type(current_phenomenoms.domain_id) == str assert "phenomenon_id" in current_phenomenoms.phenomenons_max_colors[ 0].keys() assert current_phenomenoms.get_domain_max_color() == 3
def test_places_with_gps() -> None: """Test a place search by specifying a GPS point to search arround.""" client = MeteoFranceClient() list_places = client.search_places("montreal", "45.50884", "-73.58") assert list_places place = list_places[0] assert place.name == "Montréal" assert place.country == "CA" assert place.admin == "Quebec" assert place.admin2 == "06"
def test_fulls(): """Test advanced weather alert results from API.""" client = MeteoFranceClient() warning_full = client.get_warning_full(domain="31") assert type(warning_full.update_time) == int assert type(warning_full.end_validity_time) == int assert type(warning_full.domain_id) == str assert warning_full.domain_id == "31" assert warning_full.color_max in WARNING_COLOR_LIST assert (warning_full.timelaps[0]["timelaps_items"][0]["color_id"] in WARNING_COLOR_LIST) assert (warning_full.phenomenons_items[0]["phenomenon_max_color_id"] in WARNING_COLOR_LIST)
def test_places_print() -> None: """Test different way to print Places class.""" client = MeteoFranceClient() place_in_france = client.search_places("montreal")[0] place_not_in_france = client.search_places("montreal", "45.50884", "-73.58")[0] assert (repr(place_in_france) == "<Place(name=Montréal, country=FR, admin=Languedoc-Roussillon)>") assert str(place_in_france) == "Montréal - Languedoc-Roussillon (11) - FR" assert (repr(place_not_in_france) == "<Place(name=Montréal, country=CA, admin=Quebec)>") assert str(place_not_in_france) == "Montréal - Quebec - CA" assert f"I live in {place_not_in_france}" == "I live in Montréal - Quebec - CA"
def test_forecast_place() -> None: """Test weather forecast results from API.""" client = MeteoFranceClient() weather_forecast = client.get_forecast_for_place( place=Place(MOUNTAIN_CITY)) assert type(weather_forecast.position) == dict assert type(weather_forecast.updated_on) == int assert "T" in weather_forecast.daily_forecast[0].keys() assert "humidity" in weather_forecast.daily_forecast[0].keys() assert "rain" in weather_forecast.probability_forecast[0].keys() assert "clouds" in weather_forecast.forecast[0].keys() assert (type( weather_forecast.timestamp_to_locale_time( weather_forecast.daily_forecast[0]["dt"])) == datetime)
def test_places() -> None: """Test for simple seach of Place.""" client = MeteoFranceClient() list_places = client.search_places("montreal") assert list_places place = list_places[0] assert place.insee assert place.latitude assert place.longitude assert place.postal_code assert place.name == "Montréal" assert place.country == "FR" assert place.admin == "Languedoc-Roussillon" assert place.admin2 == "11"
def test_rain_expected(requests_mock: Mock) -> None: """Test datecomputation when rain is expected within the hour.""" client = MeteoFranceClient() requests_mock.request( "get", f"{METEOFRANCE_API_URL}/rain", json={ "position": { "lat": 48.807166, "lon": 2.239895, "alti": 76, "name": "Meudon", "country": "FR - France", "dept": "92", "timezone": "Europe/Paris", }, "updated_on": 1589995200, "quality": 0, "forecast": [ {"dt": 1589996100, "rain": 1, "desc": "Temps sec"}, {"dt": 1589996400, "rain": 1, "desc": "Temps sec"}, {"dt": 1589996700, "rain": 1, "desc": "Temps sec"}, {"dt": 1589997000, "rain": 2, "desc": "Pluie faible"}, {"dt": 1589997300, "rain": 3, "desc": "Pluie modérée"}, {"dt": 1589997600, "rain": 2, "desc": "Pluie faible"}, {"dt": 1589998200, "rain": 1, "desc": "Temps sec"}, {"dt": 1589998800, "rain": 1, "desc": "Temps sec"}, {"dt": 1589999400, "rain": 1, "desc": "Temps sec"}, ], }, ) rain = client.get_rain(latitude=48.8075, longitude=2.24028) date_rain = rain.next_rain_date_locale() assert str(date_rain) == "2020-05-20 19:50:00+02:00" assert ( str(rain.timestamp_to_locale_time(rain.forecast[3]["dt"])) == "2020-05-20 19:50:00+02:00" )
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up an Meteo-France account from a config entry.""" hass.data.setdefault(DOMAIN, {}) latitude = entry.data.get(CONF_LATITUDE) client = MeteoFranceClient() # Migrate from previous config if not latitude: places = await hass.async_add_executor_job( client.search_places, entry.data[CONF_CITY] ) hass.config_entries.async_update_entry( entry, title=f"{places[0]}", data={ CONF_LATITUDE: places[0].latitude, CONF_LONGITUDE: places[0].longitude, }, ) latitude = entry.data[CONF_LATITUDE] longitude = entry.data[CONF_LONGITUDE] async def _async_update_data_forecast_forecast(): """Fetch data from API endpoint.""" return await hass.async_add_executor_job( client.get_forecast, latitude, longitude ) async def _async_update_data_rain(): """Fetch data from API endpoint.""" return await hass.async_add_executor_job(client.get_rain, latitude, longitude) async def _async_update_data_alert(): """Fetch data from API endpoint.""" return await hass.async_add_executor_job( client.get_warning_current_phenomenoms, department, 0, True ) coordinator_forecast = DataUpdateCoordinator( hass, _LOGGER, name=f"Météo-France forecast for city {entry.title}", update_method=_async_update_data_forecast_forecast, update_interval=SCAN_INTERVAL, ) coordinator_rain = None coordinator_alert = None # Fetch initial data so we have data when entities subscribe await coordinator_forecast.async_refresh() if not coordinator_forecast.last_update_success: raise ConfigEntryNotReady # Check if rain forecast is available. if coordinator_forecast.data.position.get("rain_product_available") == 1: coordinator_rain = DataUpdateCoordinator( hass, _LOGGER, name=f"Météo-France rain for city {entry.title}", update_method=_async_update_data_rain, update_interval=SCAN_INTERVAL_RAIN, ) await coordinator_rain.async_refresh() if not coordinator_rain.last_update_success: raise ConfigEntryNotReady else: _LOGGER.warning( "1 hour rain forecast not available. %s is not in covered zone", entry.title, ) department = coordinator_forecast.data.position.get("dept") _LOGGER.debug( "Department corresponding to %s is %s", entry.title, department, ) if department: if not hass.data[DOMAIN].get(department): coordinator_alert = DataUpdateCoordinator( hass, _LOGGER, name=f"Météo-France alert for department {department}", update_method=_async_update_data_alert, update_interval=SCAN_INTERVAL, ) await coordinator_alert.async_refresh() if not coordinator_alert.last_update_success: raise ConfigEntryNotReady hass.data[DOMAIN][department] = True else: _LOGGER.warning( "Weather alert for department %s won't be added with city %s, as it has already been added within another city", department, entry.title, ) else: _LOGGER.warning( "Weather alert not available: The city %s is not in France or Andorre.", entry.title, ) undo_listener = entry.add_update_listener(_async_update_listener) hass.data[DOMAIN][entry.entry_id] = { COORDINATOR_FORECAST: coordinator_forecast, COORDINATOR_RAIN: coordinator_rain, COORDINATOR_ALERT: coordinator_alert, UNDO_UPDATE_LISTENER: undo_listener, } for platform in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, platform) ) return True
def test_rain_not_covered(): """Test rain forecast result on a non covered zone.""" client = MeteoFranceClient() with pytest.raises(requests.HTTPError, match=r"400 .*"): client.get_rain(latitude=45.508, longitude=-73.58)
def getMeteoMarine(ville): client = MeteoFranceClient() list_places = client.search_places(ville) my_place = list_places[0] url_weather = "http://ws.meteofrance.com/ws//getDetail/france/"+ str(my_place.insee) + "0.json" #url_weather = "http://ws.meteofrance.com/ws//getDetail/france/290190.json" print (url_weather) r_weather = requests.get(url_weather) data = r_weather.json() result =data['result'] res_Ville = result['ville'] nomVille = res_Ville['nom'] bulletinCote = res_Ville['bulletinCote'] print(str(nomVille) + "/" + str(bulletinCote)) # print(result) resume_today = result['resumes']['0_resume'] #print(resume_today) descr = resume_today["description"] print (descr) returnedStr = "" if (bulletinCote == False): returnedStr = "Je ne trouve pas de bulletin cotier pour '"+nomVille + "'. " elif (bulletinCote == True): returnedStr = returnedStr + "Bulletin cotier de '"+nomVille + "', " date = int(resume_today['date']) #timestamp = 1602354456 #dt_object = datetime.fromtimestamp(timestamp) #print("dt_object =", dt_object) tutu = datetime.fromtimestamp((date/1000)) #gros hack... heure = int(tutu.strftime("%H")) if (bulletinCote == True): if heure >= 22 : returnedStr = returnedStr + " Nuit. " elif heure >= 18: returnedStr = returnedStr + " Soir. " elif heure >= 12: returnedStr = returnedStr + " Après-midi. " else: returnedStr = returnedStr + " Matin. " dateStr = tutu.strftime("%A %e %B") print (dateStr) returnedStr = returnedStr + "Prévisions pour la journée du " + dateStr +" ." ventForce = int(resume_today['vitesseVent']) forceRafales = int(resume_today['forceRafales']) directionVent = int(resume_today['directionVent']) if (directionVent > 315) : directionVentStr = " Nord Nord Ouest" elif (directionVent == 315) : directionVentStr = " Nord Ouest" elif (directionVent > 270) : directionVentStr = " Nord Ouest" elif (directionVent == 270) : directionVentStr = " Ouest" elif (directionVent > 225) : directionVentStr = " Ouest Sud Ouest" elif (directionVent == 225) : directionVentStr = " Sud Ouest" elif (directionVent > 180) : directionVentStr = " Sud Sud Ouest" elif (directionVent == 180) : directionVentStr = " Sud" elif (directionVent > 135) : directionVentStr = " Sud Sud Est" elif (directionVent == 135) : directionVentStr = " Sud Est" elif (directionVent > 90) : directionVentStr = " Est Sud Est" elif (directionVent == 90) : directionVentStr = " Est" elif (directionVent > 45) : directionVentStr = " Est Nord Est" elif (directionVent == 45) : directionVentStr = " Nord Est" elif (directionVent > 0 ) : directionVentStr = " Nord Nord Est" elif (directionVent == 0 ) : directionVentStr = " Nord" returnedStr = returnedStr + " VENT, direction " + directionVentStr + " de " + str(ventForce) + " km/h " if (forceRafales > 0) : returnedStr = returnedStr + " avec des rafales à " + str(forceRafales) + " km/h." #" VENT : Nord-Ouest 4 à 5, fraichissant 5 à 6 en Manche l'après-midi. #TODO # MER : agitée. HOULE : Ouest à Nord-Ouest 2 m sur pointe Bretagne. #TODO # TEMPS : Ciel nuageux.. returnedStr = returnedStr + ". " + getConditionCielCourant(nomVille) probaPluie = resume_today['probaPluie'] print (probaPluie) if (probaPluie is int and probaPluie > 0) : returnedStr = returnedStr + " avec probabilité de pluie de " + str(probaPluie) + "%." # VISIBILITE : Bonne." print (returnedStr) return returnedStr
from meteofrance.client import MeteoFranceClient from meteofrance.helpers import readeable_phenomenoms_dict # Init client client = MeteoFranceClient() # Search a location from name. city = "Brest" list_places = client.search_places(city) my_place = list_places[0] # Fetch weather forecast for the location my_place_weather_forecast = client.get_forecast_for_place(my_place) # Get the daily forecast my_place_daily_forecast = my_place_weather_forecast.daily_forecast # If rain in the hour forecast is available, get it. if my_place_weather_forecast.position["rain_product_available"] == 1: my_place_rain_forecast = client.get_rain(my_place.latitude, my_place.longitude) next_rain_dt = my_place_rain_forecast.next_rain_date_locale() if not next_rain_dt: rain_status = "No rain expected in the following hour." else: rain_status = next_rain_dt.strftime("%H:%M") else: rain_status = "No rain forecast availble." print (rain_status) # Fetch weather alerts.