diff options
author | Mattias Andrée <maandree@operamail.com> | 2014-03-27 23:26:06 +0100 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2014-03-27 23:26:06 +0100 |
commit | bb5dfcd19312932113b678d78d2d1d34c70db3c1 (patch) | |
tree | 27356e10adeb4fee0795af6a491bd2c4416bb9cd | |
parent | update todo (diff) | |
download | blueshift-bb5dfcd19312932113b678d78d2d1d34c70db3c1.tar.gz blueshift-bb5dfcd19312932113b678d78d2d1d34c70db3c1.tar.bz2 blueshift-bb5dfcd19312932113b678d78d2d1d34c70db3c1.tar.xz |
doc + make it possible to select download command for weather
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r-- | DEPENDENCIES | 2 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | dist/archlinux/stable/PKGBUILD | 2 | ||||
-rw-r--r-- | examples/comprehensive | 9 | ||||
-rw-r--r-- | examples/weather | 7 | ||||
-rw-r--r-- | info/blueshift.texinfo | 21 | ||||
-rw-r--r-- | src/weather.py | 43 |
7 files changed, 72 insertions, 13 deletions
diff --git a/DEPENDENCIES b/DEPENDENCIES index 7469f77..8585b54 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -20,7 +20,7 @@ RUNTIME DEPENDENCIES: For permission-hasslefree backlight adjustments via sysfs wget (optional) - For weather conditions + For weather conditions, default command MAKE DEPENDENCIES: @@ -8,7 +8,6 @@ Medium priority: Low priority: Raw ramp applying functions with precalcuated interpolation, polynomial - Add support for proxies such as Tor in weather Add support for temporarily closing DRM connection so that multiple users can run in DRM Add multi-display support (for example operating on two X display) diff --git a/dist/archlinux/stable/PKGBUILD b/dist/archlinux/stable/PKGBUILD index bd1f3f7..39d6fe2 100644 --- a/dist/archlinux/stable/PKGBUILD +++ b/dist/archlinux/stable/PKGBUILD @@ -10,7 +10,7 @@ license=('AGPL3' 'GPL3' 'custom:GFDL1.3') depends=(python3 argparser libxcb libxxf86vm libx11 libdrm) optdepends=('adjbacklight: for backlight adjustments without root requirements' 'linux: for backlight support' - 'wget: for weather support') + 'wget: for weather support, default command') makedepends=(cython gcc python3 libxcb libxxf86vm libx11 libdrm make coreutils sed zip texinfo auto-auto-complete) install=blueshift.install source=($url/archive/$pkgver.tar.gz) diff --git a/examples/comprehensive b/examples/comprehensive index b164212..96e3d96 100644 --- a/examples/comprehensive +++ b/examples/comprehensive @@ -82,6 +82,13 @@ def by_time(): return 1 # Error in `time_alpha` (probably) + +# Command used to download a file at an HTTP URL +download_command = None +# This is what if used if `None` is selected: +# download_command = lambda url : ['wget', url, '-O', '-'] + + # Method for applying colour curves. apply_curves = randr #apply_curves = vidmode @@ -318,7 +325,7 @@ def periodically(year, month, day, hour, minute, second, weekday, fade): (metar, last_time) = (None, None) if last_metar is None else last_metar now_time = minute if (metar is None) or (now_time < last_time) or (last_time < now_time + 5): - metar = weather(airport) + metar = weather(airport, download_command) last_metar = (metar, now_time) # Account for weather. diff --git a/examples/weather b/examples/weather index 78b826e..3fac3e4 100644 --- a/examples/weather +++ b/examples/weather @@ -26,6 +26,11 @@ latitude, longitude = 59.3326, 18.0652 # (Stockholm Bromma Airport in this example.) airport = 'ESSB' +# Command used to download a file at an HTTP URL +download_command = None +# This is what if used if `None` is selected: +# download_command = lambda url : ['wget', url, '-O', '-'] + # The colour temperature at day and at night. temperature_day, temperature_night = 6500, 3700 @@ -47,7 +52,7 @@ visibility_max = 4 dayness = sun(latitude, longitude) # Get weather report. -metar = weather(airport) +metar = weather(airport, download_command) # Account for weather. if metar is not None: diff --git a/info/blueshift.texinfo b/info/blueshift.texinfo index 7984afc..27c9dd8 100644 --- a/info/blueshift.texinfo +++ b/info/blueshift.texinfo @@ -1332,9 +1332,16 @@ astronomical twilight, measured in degrees. Blueshift includes the function @code{whether} which gives a brief weather report. @code{whether} -takes one argument: the International Civil Aviation -Organization (ICAO) code of your closest airport. -If Blueshift is unable to download the latest METAR +takes one manditory argument: the International +Civil Aviation Organization (ICAO) code of your +closest airport. It also takes one optional argument, +@code{downloader}: an function that takes an URL +to download as its only parameter and returns a +command, as a list of arguments, that downloads +the file at the given URL to standard output. +The default @code{downloader} is +@code{lambda url : ['wget', url, '-O', '-']}. If +Blueshift is unable to download the latest METAR (Meteorological Aerodrome Report) @code{whether} will return @code{None}. If successful it will return the sky conditions (assumed clear if not @@ -1363,6 +1370,14 @@ approximate. The weather is reported as an string list, that can and often is empty. +Airports should publish METAR (Meteorological +Aerodrome Report) reports at XX:20 and XX:50, +it can presumable take some time before the +collection server we use (weather.noaa.gov) have +received it. Additionally some airports do not +update while closed, and updates while closed +are less accurate. + @node Running without X diff --git a/src/weather.py b/src/weather.py index 33e58ac..f0f0de3 100644 --- a/src/weather.py +++ b/src/weather.py @@ -18,11 +18,19 @@ from subprocess import Popen, PIPE -def weather(station): +def weather(station, downloader = None): ''' Get a brief weather report - @param station:str The station's International Civil Aviation Organization airport code + Airports should publish METAR (Meteorological Aerodrome Report) reports at XX:20 and XX:50, + it can presumable take some time before the collection server we use (weather.noaa.gov) have + received it. Additionally some airports do not update while closed, and updates while closed + are less accurate. + + @param station:str The station's International Civil Aviation + Organization airport code + @param downloader:(url:str)?→list<str> A function that, with an URL as input, returns + a command to download the file at the URL to stdout @return :(sky:str, visiblity:(:int, :float)?, weather:list<str>)? The sky condition, visiblity and weather. Sky condition values include ‘clear’, ‘mostly clear’, ‘partly cloudy’, ‘mostly cloudy’, ‘overcast’ @@ -33,42 +41,67 @@ def weather(station): be `None`. The weather is a list that can, and often is, empty. `None` is return if observation data cannot be downloaded. ''' + ## URI of METAR url = 'http://weather.noaa.gov/pub/data/observations/metar/decoded/%s.TXT' url %= station.upper() - proc = Popen(['wget', url, '-O', '-'], stdout = PIPE, stderr = PIPE) + ## Download METAR + # Use wget if not specified + if downloader is None: + downloader = lambda u : ['wget', u, '-O', '-'] + proc = Popen(downloader(url), stdout = PIPE, stderr = PIPE) + ## Wait for download to finish and fetch output output = proc.communicate()[0] + # Ignore output if it was not successful if not proc.returncode == 0: return None + ## Create field table from output = output.decode('utf-8', 'replace').split('\n') output = [line.lower().split(': ') for line in output if ': ' in line] output = dict([(line[0], ': '.join(line[1:])) for line in output]) + ## Get sky condition, assume clear (although often not) if omitted sky_conditions = 'clear' if 'sky conditions' not in output else output['sky conditions'] + ## Get visibility range visibility = None try: if 'visibility' in output: + # Remove tail digit visibility = output['visibility'].split(':')[0] + # Remove unit, it is always miles the decoded part visibility = visibility.replace(' mile(s)', '') visibility = visibility.replace(' miles', '') visibility = visibility.replace(' mile', '') + # Range is assumed approximate if not specified visibility_eq = 0 if visibility.startswith('greater than '): + # Range is a lower bound visibility_eq = 1 visibility = visibility[len('greater than '):] if visibility.startswith('less than '): + # Range is an upper bound visibility_eq = -1 visibility = visibility[len('less than '):] - if len(list(filter(lambda c : not (('0' <= c <= '9') or (c in ' /')), visibility))) == 0: + if len(list(filter(lambda c : not (('0' <= c <= '9') or (c in ' /.')), visibility))) == 0: + # Parse mixed numeral or decimal form visibility = sum([eval(v) for v in visibility.split(' ')]) + # Pack boundary information and range (converted to kilometers) visibility = (visibility_eq, visibility * 1.609) else: visibility = None except: + ## `eval` failed (probably) visibility = None + ## Get weather weather = '' if 'weather' not in output else output['weather'] + ## Unify conjnuctions weather = weather.replace(',', ';').replace(' with ', ';') + ## Remove undesired details + # Not important as we are not pilots, we are probably far away weather = weather.replace(' in the vicinity', '') - weather = weather.replace(' observed', '') + # Duration is not important for use either weather = weather.replace(' during the past hour', '') + # Unimportant detail + weather = weather.replace(' observed', '') + ## Split at conjunction weather = [w.replace(';', '').strip() for w in weather.split(';') if not w == ''] return (sky_conditions, visibility, weather) |