diff options
author | Mattias Andrée <maandree@kth.se> | 2021-06-26 13:18:37 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2021-06-26 13:18:37 +0200 |
commit | 3e21f6d13c0a70db95fec8b5a71b758223ff4293 (patch) | |
tree | 6d6d2eddb243935007ce1e316c61470224f93df0 /xpybar/config/myweather.py | |
parent | Add inputrc for readline + m (diff) | |
download | dotfiles-3e21f6d13c0a70db95fec8b5a71b758223ff4293.tar.gz dotfiles-3e21f6d13c0a70db95fec8b5a71b758223ff4293.tar.bz2 dotfiles-3e21f6d13c0a70db95fec8b5a71b758223ff4293.tar.xz |
Add xpybar
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r-- | xpybar/config/myweather.py | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/xpybar/config/myweather.py b/xpybar/config/myweather.py new file mode 100644 index 0000000..bb90c80 --- /dev/null +++ b/xpybar/config/myweather.py @@ -0,0 +1,420 @@ +# -*- python -*- +from plugins.weather import Weather + +from common import * + +class MyWeather(Entry): + def __init__(self, *args, stations = None, fahrenheit = False, wind = 'm/s', from_wind = False, visibility = 'km', **kwargs): + self.semaphore = threading.Semaphore() + self.stations = [MyWeather.get_metar_station()] if stations is None else [s.upper() for s in stations] + self.reports = [None] * len(self.stations) + self.up_to_date = [False] * len(self.stations) + self.in_deg_f = fahrenheit + self.wind_unit = wind + self.from_wind = from_wind + self.visibility_unit = visibility + self.show_temp = True + self.show_wind_speed = False + self.show_wind_gusts = False + self.show_wind_dir = False + self.show_wind_chill = False + self.show_humidity = False + self.show_dew = False + self.show_pressure = False + self.show_visibility = False + self.show_sky = False + self.show_station = False + self.station = 0 + self.updated = False + self.segments = [] + self.refresh = Sometimes(lambda : xasync(self.refresh_, name = 'weather'), 20 * 60 * 4) + self.refresh() + Entry.__init__(self, *args, **kwargs) + + def action(self, col, button, x, y): + if button == MIDDLE_BUTTON: + self.show_temp = True + self.show_wind_speed = True + self.show_wind_gusts = True + self.show_wind_dir = True + self.show_wind_chill = True + self.show_humidity = True + self.show_dew = True + self.show_pressure = True + self.show_visibility = True + self.show_sky = True + self.show_station = True + self.invalidate() + elif button == RIGHT_BUTTON: + self.refresh.counter = 0 + self.refresh() + elif button in (LEFT_BUTTON, SCROLL_UP, SCROLL_DOWN): + index = None + for i, seg in enumerate(self.segments): + if seg is None: + continue + (x, width) = seg + if 0 <= col - x < width: + index = i + break + if index is None: + return + if index == 0: # station + if button == LEFT_BUTTON: + self.show_station = False + elif button == SCROLL_UP: + station = self.station + if station + 1 < len(self.stations): + self.station = station + 1 + else: + station = self.station + if station > 0: + self.station = station - 1 + elif index == 1: # temperature + if button == LEFT_BUTTON: + self.show_temp = False + else: + self.in_deg_f = button == SCROLL_UP + elif index == 2: # wind speed/gusts + if button == LEFT_BUTTON: + if self.towards is None or col < self.towards: + self.show_wind_speed = False + else: + self.show_wind_gusts = False + else: + if self.wind_unit == 'm/s': + self.wind_unit = 'mph' if button == SCROLL_UP else 'm/s' + elif self.wind_unit == 'mph': + self.wind_unit = 'kn' if button == SCROLL_UP else 'm/s' + elif self.wind_unit in ('kn', 'kt', 'knot', 'knots'): + self.wind_unit = 'km/h' if button == SCROLL_UP else 'mph' + elif self.wind_unit in ('km/h', 'kmph'): + self.wind_unit = 'ft/s' if button == SCROLL_UP else 'kn' + elif self.wind_unit in ('ft/s', 'ftps'): + self.wind_unit = 'b' if button == SCROLL_UP else 'km/h' + else: + self.wind_unit = 'b' if button == SCROLL_UP else 'ft/s' + elif index == 3: # wind direction + if button == LEFT_BUTTON: + self.show_wind_dir = False + else: + self.from_wind = button == SCROLL_UP + elif index == 4: # wind chill + if button == LEFT_BUTTON: + self.show_wind_chill = False + else: + self.in_deg_f = button == SCROLL_UP + elif index == 5: # relative humidity + if button == LEFT_BUTTON: + self.show_humidity = False + else: + return + elif index == 6: # dew point + if button == LEFT_BUTTON: + self.show_dew = False + else: + self.in_deg_f = button == SCROLL_UP + elif index == 7: # pressure + if button == LEFT_BUTTON: + self.show_pressure = False + else: + return + elif index == 8: # visibility + if button == LEFT_BUTTON: + self.show_visibility = False + elif button == SCROLL_UP: + unit = self.visibility_unit + if unit in {'km' : 'm', 'm' : 'mi'}: + self.visibility_unit = {'km' : 'm', 'm' : 'mi'}[unit] + else: + unit = self.visibility_unit + if unit in {'mi' : 'm', 'mile' : 'm', 'm' : 'km'}: + self.visibility_unit = {'mi' : 'm', 'mile' : 'm', 'm' : 'km'}[unit] + elif index == 9: # sky conditions + if button == LEFT_BUTTON: + self.show_sky = False + else: + return + self.invalidate() + + def refresh_(self): + if self.semaphore.acquire(blocking = False): + for index, station in enumerate(self.stations): + try: + self.reports[index] = Weather(station) + self.up_to_date[index] = True + except: + self.up_to_date[index] = False + self.semaphore.release() + self.invalidate() + + def invalidate(self): + self.updated = False + Entry.invalidate(self) + + def get_weather(self, index): + station = self.stations[index] + report = self.reports[index] + up_to_date = self.up_to_date[index] + station = station[0] + station[1:].lower() + + if report is None: + if self.show_station: + return '%s: ?' % station + else: + return '?' + + text = [] + + if self.show_temp and report.temp is not None: + value = report.temp + colour = '34' + if value < -10: colour = '39;44' + if value >= 18: colour = '39' + if value >= 25: colour = '33' + if value >= 30: colour = '31' + if self.in_deg_f: + value = value * 9 / 5 + 32 + value = '\033[%sm%.0f\033[0m%s' % (colour, value, '°F' if self.in_deg_f else '°C') + text.append(value) + else: + text.append(None) + + if self.show_wind_speed and report.wind_speed is not None: + knot = report.wind_speed + kmph = knot * 1.852 # km/h + mps = kmph / 3.6 # m/s + mph = knot * 1.151 # mph + ftps = mps * 3.281 # ft/s + beaufort = (mps / 0.8365) ** (2 / 3) # B + if self.wind_unit in ('kn', 'kt', 'knot', 'knots'): + value, unit = knot, 'kn' + elif self.wind_unit in ('km/h', 'kmph'): + value, unit = kmph, 'km/h' + elif self.wind_unit == 'mph': + value, unit = mph, 'mph' + elif self.wind_unit in ('ft/s', 'ftps'): + value, unit = ftps, 'ft/s' + elif self.wind_unit.lower() in ('beaufort', 'beaufort scale', 'bf', 'bt', 'b'): + value, unit = beaufort, 'B' + else: + value, unit = mps, 'm/s' + beaufort = int(beaufort + 0.5) + colour = '32' + if beaufort >= 1: colour = '39' + if beaufort >= 3: colour = '32' + if beaufort >= 7: colour = '33' + if beaufort >= 10: colour = '31' + if beaufort >= 12: colour = '39;41' + wind = '\033[%sm%.0f\033[0m' % (colour, value) + if self.show_wind_gusts and report.wind_gusts is not None: + knot = report.wind_gusts + kmph = knot * 1.852 # km/h + mps = kmph / 3.6 # m/s + mph = knot * 1.151 # mph + ftps = mps * 3.281 # ft/s + beaufort = (mps / 0.8365) ** (2 / 3) # B + if self.wind_unit in ('kn', 'kt', 'knot', 'knots'): + value = knot + elif self.wind_unit in ('km/h', 'kmph'): + value = kmph + elif self.wind_unit == 'mph': + value = mph + elif self.wind_unit in ('ft/s', 'ftps'): + value = ftps + elif self.wind_unit.lower() in ('beaufort', 'beaufort scale', 'bf', 'bt', 'b'): + value = beaufort + else: + value = mps + beaufort = int(beaufort + 0.5) + colour = '32' + if beaufort >= 1: colour = '39' + if beaufort >= 3: colour = '32' + if beaufort >= 7: colour = '33' + if beaufort >= 10: colour = '31' + if beaufort >= 12: colour = '39;41' + wind += '→\033[%sm%.0f\033[0m' % (colour, value) + wind += unit + text.append(wind) + else: + text.append(None) + + def wind_dir(direction): + if not self.from_wind: + direction += 180 + direction %= 360 + if direction < 0: + direction += 360 + if (direction < 90): + if direction == 0: + return 'N' + if direction <= 45: + return 'N%.0f°E' % direction + return 'E%.0f°N' % (90 - direction) + elif (90 <= direction < 180): + if direction == 90: + return 'E' + direction -= 90 + if direction <= 45: + return 'E%.0f°S' % direction + return 'S%.0f°E' % (90 - direction) + elif (180 <= direction < 270): + if direction == 180: + return 'S' + direction -= 180 + if direction <= 45: + return 'S%.0f°W' % direction + return 'W%.0f°S' % (90 - direction) + else: + if direction == 270: + return 'W' + direction -= 270 + if direction <= 45: + return 'W%.0f°N' % direction + return 'N%.0f°W' % (90 - direction) + if not self.show_wind_dir: + wind = None + elif report.wind_var is not None: + wind = wind_dir(report.wind_var[0]) + '-' + wind_dir(report.wind_var[1]) + elif report.wind_dir is not None: + wind = wind_dir(report.wind_dir) + else: + wind = None + if wind is not None: + if self.from_wind: + wind += '→' + else: + wind = '→' + wind + text.append(wind) + else: + text.append(None) + + if self.show_wind_chill and report.wind_chill is not None: + value = report.wind_chill + # Coloured by frostbite time, however the wind is not taken + # into account so the colour is approximate + colour = '39' + if value <= -28: colour = '33' + if value <= -37: colour = '31' + if value <= -46: colour = '39;41' + if self.in_deg_f: + value = value * 9 / 5 + 32 + value = 'w\033[%sm%.0f\033[0m%s' % (colour, value, '°F' if self.in_deg_f else '°C') + text.append(value) + else: + text.append(None) + + if self.show_humidity and report.humidity is not None: + value = report.humidity + colour = '34' + if value >= 26: colour = '32' + if value >= 31: colour = '39' + if value >= 37: colour = '33' + if value >= 52: colour = '31' + if value >= 73: colour = '39;41' + value = '\033[%sm%.0f\033[0m%%' % (colour, value) + text.append(value) + else: + text.append(None) + + if self.show_dew and report.dew is not None: + value = report.dew + colour = '34' + if value >= 10: colour = '32' + if value >= 13: colour = '39' + if value >= 16: colour = '33' + if value >= 21: colour = '31' + if value >= 26: colour = '39;41' + if self.in_deg_f: + value = value * 9 / 5 + 32 + value = 'd\033[%sm%.0f\033[0m%s' % (colour, value, '°F' if self.in_deg_f else '°C') + text.append(value) + else: + text.append(None) + + if self.show_pressure and report.pressure is not None: + text.append('%.0fhPa' % report.pressure) + else: + text.append(None) + + if self.show_visibility and report.visibility is not None: + mile = report.visibility + km = mile * 1.609344 + m = mile * 1609.344 + if self.visibility_unit in ('mile', 'mi'): + value, unit = mile, 'mi' + elif self.visibility_unit == 'm': + value, unit = m, 'm' + else: + value, unit = km, 'km' + text.append('%.0f%s' % (value, unit)) + else: + text.append(None) + + if self.show_sky and 'Sky conditions' in report.fields: + value = report.fields['Sky conditions'] + if not value == '': + text.append(value) + else: + text.append(None) + else: + text.append(None) + + segments = [] + x = 0 + if self.show_station: + w = len(station) + segments.append((x, w)) + x += w + 2 + else: + segments.append(None) + x -= 1 + self.towards = None + for i, segment in enumerate(text): + if segment is None: + segments.append(None) + else: + if i == 1 and '→' in segment: + self.towards = x + Bar.coloured_length(segment.split('→')[0]) + w = Bar.coloured_length(segment) + x += 1 + segments.append((x, w)) + x += w + self.segments = segments + text = [s for s in text if s is not None] + + if len(text) == 0: + return station + + if not up_to_date: + if len(text) <= 1: + text = ' '.join(text) + '?' + else: + text = ' '.join(text) + ' ?' + else: + text = ' '.join(text) + if self.show_station: + text = '%s: %s' % (station, text) + return text + + def function(self): + if not self.updated: + self.updated = True + self.text = self.get_weather(self.station) + rc = self.text + self.refresh() + return rc + + @staticmethod + def get_metar_station(): + try: + with open(HOME + '/.config/metar', 'rb') as file: + station = file.read() + except: + try: + with open('/etc/metar', 'rb') as file: + station = file.read() + except: + print('~/.config/metar is not set', file = sys.stderr, flush = True) + station = b'ESSA' + return station.decode('utf-8', 'strict').split('\n')[0].upper() |