1414import time
1515import xml .etree .cElementTree as etree
1616from datetime import datetime
17+ from typing import Optional , Callable , Any
1718from urllib .request import urlopen
1819
1920from homeassistant .components .weather import (
@@ -124,9 +125,11 @@ def current(self):
124125
125126 def _http_request (self , url , cache_fname = None ):
126127 """Request to API and cache results."""
128+ _LOGGER .debug ("Requesting URL %s" , url )
127129 if self ._cache and cache_fname is not None :
128130 cache_fname += ".xml"
129131 if self ._cache .is_cached (cache_fname ):
132+ _LOGGER .debug ("Cached response used" )
130133 return self ._cache .read_cache (cache_fname )
131134
132135 try :
@@ -142,6 +145,16 @@ def _http_request(self, url, cache_fname=None):
142145
143146 return response
144147
148+ @staticmethod
149+ def _get (var : dict , ind : str , func : Optional [Callable ] = None ) -> Any :
150+ res = var .get (ind )
151+ if func is not None :
152+ try :
153+ res = func (res )
154+ except ValueError :
155+ return None
156+ return res
157+
145158 def _get_city_id (self , lat , lng ):
146159 """Return the nearest city ID."""
147160 url = (BASE_URL + "/cities/?lat={}&lng={}&count=1&lang=en" ).format (lat , lng )
@@ -154,7 +167,7 @@ def _get_city_id(self, lat, lng):
154167
155168 xml = etree .fromstring (response )
156169 item = xml .find ("item" )
157- return int ( item . get ( "id" ) )
170+ return self . _get ( item , "id" , int )
158171
159172 @staticmethod
160173 def _is_day (testing_time , sunrise_time , sunset_time ):
@@ -325,84 +338,73 @@ def update(self):
325338 current = xml .find ("location/fact" )
326339 current_v = current .find ("values" )
327340
328- pr_amount = current_v .get ("prflt" )
329- if pr_amount is not None :
330- pr_amount = float (pr_amount )
331-
332341 self ._current = {
333- ATTR_SUNRISE : int ( current . get ( "sunrise" ) ),
334- ATTR_SUNSET : int ( current . get ( "sunset" ) ),
335- ATTR_WEATHER_CONDITION : current_v . get ( "descr" ),
336- ATTR_WEATHER_TEMPERATURE : float ( current_v . get ( "tflt" ) ),
337- ATTR_WEATHER_PRESSURE : int ( current_v . get ( "p" ) ),
338- ATTR_WEATHER_HUMIDITY : int ( current_v . get ( "hum" ) ),
339- ATTR_WEATHER_WIND_SPEED : int ( current_v . get ( "ws" ) ),
340- ATTR_WEATHER_WIND_BEARING : int ( current_v . get ( "wd" ) ),
341- ATTR_WEATHER_CLOUDINESS : int ( current_v . get ( "cl" ) ),
342- ATTR_WEATHER_PRECIPITATION_TYPE : int ( current_v . get ( "pt" ) ),
343- ATTR_WEATHER_PRECIPITATION_AMOUNT : pr_amount ,
344- ATTR_WEATHER_PRECIPITATION_INTENSITY : int ( current_v . get ( "pr" ) ),
345- ATTR_WEATHER_STORM : (current_v . get ( "ts" ) == 1 ),
346- ATTR_WEATHER_GEOMAGNETIC_FIELD : int ( current_v . get ( "grade" ) ),
347- ATTR_WEATHER_PHENOMENON : int ( current_v . get ( "ph" ) ),
342+ ATTR_SUNRISE : self . _get ( current , "sunrise" , int ),
343+ ATTR_SUNSET : self . _get ( current , "sunset" , int ),
344+ ATTR_WEATHER_CONDITION : self . _get ( current_v , "descr" ),
345+ ATTR_WEATHER_TEMPERATURE : self . _get ( current_v , "tflt" , float ),
346+ ATTR_WEATHER_PRESSURE : self . _get ( current_v , "p" , int ),
347+ ATTR_WEATHER_HUMIDITY : self . _get ( current_v , "hum" , int ),
348+ ATTR_WEATHER_WIND_SPEED : self . _get ( current_v , "ws" , int ),
349+ ATTR_WEATHER_WIND_BEARING : self . _get ( current_v , "wd" , int ),
350+ ATTR_WEATHER_CLOUDINESS : self . _get ( current_v , "cl" , int ),
351+ ATTR_WEATHER_PRECIPITATION_TYPE : self . _get ( current_v , "pt" , int ),
352+ ATTR_WEATHER_PRECIPITATION_AMOUNT : self . _get ( current_v , "prflt" , float ) ,
353+ ATTR_WEATHER_PRECIPITATION_INTENSITY : self . _get ( current_v , "pr" , int ),
354+ ATTR_WEATHER_STORM : (self . _get ( current_v , "ts" ) == 1 ),
355+ ATTR_WEATHER_GEOMAGNETIC_FIELD : self . _get ( current_v , "grade" , int ),
356+ ATTR_WEATHER_PHENOMENON : self . _get ( current_v , "ph" , int ),
348357 }
349358
350359 self ._forecast = []
351360 if self ._mode == FORECAST_MODE_HOURLY :
352361 for day in xml .findall ("location/day" ):
353- sunrise = int ( day . get ( "sunrise" ) )
354- sunset = int ( day . get ( "sunset" ) )
362+ sunrise = self . _get ( day , "sunrise" , int )
363+ sunset = self . _get ( day , "sunset" , int )
355364
356365 for i in day .findall ("forecast" ):
357366 fc_v = i .find ("values" )
358-
359- pr_amount = fc_v .get ("prflt" )
360- if pr_amount is not None :
361- pr_amount = float (pr_amount )
362-
363367 data = {
364368 ATTR_SUNRISE : sunrise ,
365369 ATTR_SUNSET : sunset ,
366370 ATTR_FORECAST_TIME : self ._get_utime (i .get ("valid" ), tzone ),
367- ATTR_FORECAST_CONDITION : fc_v .get ("descr" ),
368- ATTR_FORECAST_TEMP : int (fc_v .get ("t" )),
369- ATTR_FORECAST_PRESSURE : int (fc_v .get ("p" )),
370- ATTR_FORECAST_HUMIDITY : int (fc_v .get ("hum" )),
371- ATTR_FORECAST_WIND_SPEED : int (fc_v .get ("ws" )),
372- ATTR_FORECAST_WIND_BEARING : int (fc_v .get ("wd" )),
373- ATTR_FORECAST_CLOUDINESS : int (fc_v .get ("cl" )),
374- ATTR_FORECAST_PRECIPITATION_TYPE : int (fc_v .get ("pt" )),
375- ATTR_FORECAST_PRECIPITATION_AMOUNT : pr_amount ,
376- ATTR_FORECAST_PRECIPITATION_INTENSITY : int (fc_v .get ("pr" )),
371+ ATTR_FORECAST_CONDITION : self ._get (fc_v , "descr" ),
372+ ATTR_FORECAST_TEMP : self ._get (fc_v , "t" , int ),
373+ ATTR_FORECAST_PRESSURE : self ._get (fc_v , "p" , int ),
374+ ATTR_FORECAST_HUMIDITY : self ._get (fc_v , "hum" , int ),
375+ ATTR_FORECAST_WIND_SPEED : self ._get (fc_v , "ws" , int ),
376+ ATTR_FORECAST_WIND_BEARING : self ._get (fc_v , "wd" , int ),
377+ ATTR_FORECAST_CLOUDINESS : self ._get (fc_v , "cl" , int ),
378+ ATTR_FORECAST_PRECIPITATION_TYPE : self ._get (fc_v , "pt" , int ),
379+ ATTR_FORECAST_PRECIPITATION_AMOUNT : self ._get (
380+ fc_v , "prflt" , float
381+ ),
382+ ATTR_FORECAST_PRECIPITATION_INTENSITY : self ._get (
383+ fc_v , "pr" , int
384+ ),
377385 ATTR_FORECAST_STORM : (fc_v .get ("ts" ) == 1 ),
378- ATTR_FORECAST_GEOMAGNETIC_FIELD : int ( fc_v . get ( "grade" ) ),
386+ ATTR_FORECAST_GEOMAGNETIC_FIELD : self . _get ( fc_v , "grade" , int ),
379387 }
380-
381388 self ._forecast .append (data )
382389
383390 else : # self._mode == FORECAST_MODE_DAILY
384391 for day in xml .findall ("location/day[@descr]" ):
385- pr_amount = day .get ("prflt" )
386- if pr_amount is not None :
387- pr_amount = float (pr_amount )
388-
389392 data = {
390- ATTR_SUNRISE : int ( day . get ( "sunrise" ) ),
391- ATTR_SUNSET : int ( day . get ( "sunset" ) ),
393+ ATTR_SUNRISE : self . _get ( day , "sunrise" , int ),
394+ ATTR_SUNSET : self . _get ( day , "sunset" , int ),
392395 ATTR_FORECAST_TIME : self ._get_utime (day .get ("date" ), tzone ),
393- ATTR_FORECAST_CONDITION : day . get ( "descr" ),
394- ATTR_FORECAST_TEMP : int ( day . get ( "tmax" ) ),
395- ATTR_FORECAST_TEMP_LOW : int ( day . get ( "tmin" ) ),
396- ATTR_FORECAST_PRESSURE : int ( day . get ( "p" ) ),
397- ATTR_FORECAST_HUMIDITY : int ( day . get ( "hum" ) ),
398- ATTR_FORECAST_WIND_SPEED : int ( day . get ( "ws" ) ),
399- ATTR_FORECAST_WIND_BEARING : int ( day . get ( "wd" ) ),
400- ATTR_FORECAST_CLOUDINESS : int ( day . get ( "cl" ) ),
401- ATTR_FORECAST_PRECIPITATION_TYPE : int ( day . get ( "pt" ) ),
402- ATTR_FORECAST_PRECIPITATION_AMOUNT : pr_amount ,
403- ATTR_FORECAST_PRECIPITATION_INTENSITY : int ( day . get ( "pr" ) ),
404- ATTR_FORECAST_STORM : (day . get ( "ts" ) == 1 ),
405- ATTR_FORECAST_GEOMAGNETIC_FIELD : int ( day . get ( "grademax" ) ),
396+ ATTR_FORECAST_CONDITION : self . _get ( day , "descr" ),
397+ ATTR_FORECAST_TEMP : self . _get ( day , "tmax" , int ),
398+ ATTR_FORECAST_TEMP_LOW : self . _get ( day , "tmin" , int ),
399+ ATTR_FORECAST_PRESSURE : self . _get ( day , "p" , int ),
400+ ATTR_FORECAST_HUMIDITY : self . _get ( day , "hum" , int ),
401+ ATTR_FORECAST_WIND_SPEED : self . _get ( day , "ws" , int ),
402+ ATTR_FORECAST_WIND_BEARING : self . _get ( day , "wd" , int ),
403+ ATTR_FORECAST_CLOUDINESS : self . _get ( day , "cl" , int ),
404+ ATTR_FORECAST_PRECIPITATION_TYPE : self . _get ( day , "pt" , int ),
405+ ATTR_FORECAST_PRECIPITATION_AMOUNT : self . _get ( day , "prflt" , float ) ,
406+ ATTR_FORECAST_PRECIPITATION_INTENSITY : self . _get ( day , "pr" , int ),
407+ ATTR_FORECAST_STORM : (self . _get ( day , "ts" ) == 1 ),
408+ ATTR_FORECAST_GEOMAGNETIC_FIELD : self . _get ( day , "grademax" , int ),
406409 }
407-
408410 self ._forecast .append (data )
0 commit comments