Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Waybar/weather #254

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 129 additions & 55 deletions Configs/.local/lib/hyde/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,93 @@
import os


def load_env_file(filepath):
with open(filepath) as f:
for line in f:
if line.strip() and not line.startswith('#'):
if line.startswith('export '):
line = line[len('export '):]
key, value = line.strip().split('=', 1)
os.environ[key] = value.strip('"')

# Load environment variables from the specified files
load_env_file(os.path.expanduser('~/.local/state/hyde/staterc'))
load_env_file(os.path.expanduser('~/.local/state/hyde/config'))


### Constants ###
WEATHER_CODES = {
**dict.fromkeys(['113'], '☀️ '),
**dict.fromkeys(['116'], '⛅ '),
**dict.fromkeys(['119', '122', '143', '248', '260'], '☁️ '),
**dict.fromkeys(['176', '179', '182', '185', '263', '266', '281', '284', '293', '296', '299', '302', '305', '308', '311', '314', '317', '350', '353', '356', '359', '362', '365', '368', '392'], '🌧️'),
**dict.fromkeys(['176', '179', '182', '185', '263', '266', '281', '284', '293', '296', '299', '302', '305', '308', '311', '314', '317', '350', '353', '356', '359', '362', '365', '368', '392'], '🌧️ '),
**dict.fromkeys(['200'], '⛈️ '),
**dict.fromkeys(['227', '230', '320', '323', '326', '374', '377', '386', '389'], '🌨️'),
**dict.fromkeys(['227', '230', '320', '323', '326', '374', '377', '386', '389'], '🌨️ '),
**dict.fromkeys(['329', '332', '335', '338', '371', '395'], '❄️ ')
}
data = {}


get_location = os.getenv('WAYBAR_WEATHER_LOC', 'True')

if get_location.lower() in ('false', '0', 'f', 'n', 'no'):
set_location = False
weather = requests.get("https://wttr.in/?format=j1").json()
else:
set_location = True
if get_location == 'True':
get_location = ''
### Functions ###
def load_env_file(filepath):
with open(filepath) as f:
for line in f:
if line.strip() and not line.startswith('#'):
if line.startswith('export '):
line = line[len('export '):]
key, value = line.strip().split('=', 1)
os.environ[key] = value.strip('"')

weather = requests.get(f"https://wttr.in/{get_location}?format=j1", timeout=10).json() # timeout is 10 seconds
def get_weather_icon(weatherinstance):
return WEATHER_CODES[weatherinstance['weatherCode']]

def get_description(weatherinstance):
return weatherinstance['weatherDesc'][0]['value']

def get_temperature(weatherinstance):
if temp_unit == 'c':
return weatherinstance['temp_C'] + "°C"
else:
return weatherinstance['temp_F'] + "°F"

def get_temperature_hour(weatherinstance):
if temp_unit == 'c':
return weatherinstance['tempC'] + "°C"
else:
return weatherinstance['tempF'] + "°F"

def get_feels_like(weatherinstance):
if temp_unit == 'c':
return weatherinstance['FeelsLikeC'] + "°C"
else:
return weatherinstance['FeelsLikeF'] + "°F"

def get_wind_speed(weatherinstance):
if windspeed_unit == 'km/h':
return weatherinstance['windspeedKmph'] + "Km/h"
else:
return weatherinstance['windspeedMiles'] + "Mph"

def get_max_temp(day):
if temp_unit == 'c':
return day['maxtempC'] + "°C"
else:
return day['maxtempF'] + "°F"

def get_min_temp(day):
if temp_unit == 'c':
return day['mintempC'] + "°C"
else:
return day['mintempF'] + "°F"

def get_sunrise(day):
return get_timestamp(day['astronomy'][0]['sunrise'])

def get_sunset(day):
return get_timestamp(day['astronomy'][0]['sunset'])

def get_city_name(weather):
return weather['nearest_area'][0]['areaName'][0]['value']

def get_country_name(weather):
return weather['nearest_area'][0]['country'][0]['value']

def format_time(time):
return time.replace("00", "").zfill(2)

return (time.replace("00", "")).ljust(3)

def format_temp(temp):
return (hour['FeelsLikeC']+"°").ljust(3)
if temp[0] != "-": temp = " " + temp
return temp.ljust(5)

def get_timestamp(time_str):
if time_format == '24h':
return datetime.strptime(time_str, '%I:%M %p').strftime('%H:%M')
else:
return time_str

def format_chances(hour):
chances = {
Expand All @@ -69,41 +112,72 @@ def format_chances(hour):
conditions.append(chances[event]+" "+hour[event]+"%")
return ", ".join(conditions)

tempint = int(weather['current_condition'][0]['FeelsLikeC'])
extrachar = ''
if tempint > 0 and tempint < 10:
extrachar = '+'


if set_location is True :
data['text'] = ' '+WEATHER_CODES[weather['current_condition'][0]['weatherCode']] + \
" "+extrachar+weather['current_condition'][0]['FeelsLikeC']+"°" +" | "+ weather['nearest_area'][0]['areaName'][0]['value']+\
", " + weather['nearest_area'][0]['country'][0]['value']

if set_location is False:
data['text'] = ' '+WEATHER_CODES[weather['current_condition'][0]['weatherCode']] + \
" "+extrachar+weather['current_condition'][0]['FeelsLikeC']+"°"

### Variables ###
# Load environment variables from the specified files
load_env_file(os.path.expanduser('~/.local/state/hyde/staterc'))
load_env_file(os.path.expanduser('~/.local/state/hyde/config'))

data['tooltip'] = f"<b>{weather['current_condition'][0]['weatherDesc'][0]['value']} {weather['current_condition'][0]['temp_C']}°</b>\n"
data['tooltip'] += f"Feels like: {weather['current_condition'][0]['FeelsLikeC']}°\n"
data['tooltip'] += f"Location: {weather['nearest_area'][0]['areaName'][0]['value']}\n"
data['tooltip'] += f"Wind: {weather['current_condition'][0]['windspeedKmph']}Km/h\n"
data['tooltip'] += f"Humidity: {weather['current_condition'][0]['humidity']}%\n"
for i, day in enumerate(weather['weather']):
temp_unit = os.getenv('WEATHER_TEMPERATURE_UNIT', 'c').lower() # c or f (default: c)
time_format = os.getenv('WEATHER_TIME_FORMAT', '12h').lower() # 12h or 24h (default: 12h)
windspeed_unit = os.getenv('WEATHER_WINDSPEED_UNIT', 'km/h').lower() # km/h or mph (default: Km/h)
show_icon = os.getenv('WEATHER_SHOW_ICON', 'True').lower() in ('true', '1', 't', 'y', 'yes') # True or False (default: True)
show_location = os.getenv('WEATHER_SHOW_LOCATION', 'False').lower() in ('true', '1', 't', 'y', 'yes') # True or False (default: False)
show_today_details = os.getenv('WEATHER_SHOW_TODAY_DETAILS', 'True').lower() in ('true', '1', 't', 'y', 'yes') # True or False (default: True)
try:
forecast_days = int(os.getenv('WEATHER_FORECAST_DAYS', '3')) # Number of days to show the forecast for (default: 3)
except ValueError:
forecast_days = 3
get_location = os.getenv('WEATHER_LOC', '') # Name of the location to get the weather from (default: '')

# Check if the variables are set correctly
if temp_unit not in ('c', 'f'):
temp_unit = 'c'
if time_format not in ('12h', '24h'):
time_format = '12h'
if windspeed_unit not in ('km/h', 'mph'):
windspeed_unit = 'km/h'
if forecast_days not in range(4):
forecast_days = 3

### Main Logic ###
data = {}
# Get the weather data
weather = requests.get(f"https://wttr.in/{get_location}?format=j1", timeout=10).json()
current_weather = weather['current_condition'][0]

# Get the data to display
# waybar text
data['text'] = get_temperature(current_weather)
if show_icon:
data['text'] = get_weather_icon(current_weather) + data['text']
if show_location:
data['text'] += f" | {get_city_name(weather)}, {get_country_name(weather)}"

# waybar tooltip
data['tooltip'] = ""
if show_today_details:
data['tooltip'] += f"<b>{get_description(current_weather)} {get_temperature(current_weather)}</b>\n"
data['tooltip'] += f"Feels like: {get_feels_like(current_weather)}\n"
data['tooltip'] += f"Location: {get_city_name(weather)}, {get_country_name(weather)}\n"
data['tooltip'] += f"Wind: {get_wind_speed(current_weather)}\n"
data['tooltip'] += f"Humidity: {current_weather['humidity']}%\n"
# Get the weather forecast for the next 2 days
for i in range(forecast_days):
day = weather['weather'][i]
data['tooltip'] += f"\n<b>"
if i == 0:
data['tooltip'] += "Today, "
if i == 1:
data['tooltip'] += "Tomorrow, "
data['tooltip'] += f"{day['date']}</b>\n"
data['tooltip'] += f"⬆️ {day['maxtempC']}° ⬇️ {day['mintempC']}° "
data['tooltip'] += f"🌅 {day['astronomy'][0]['sunrise']} 🌇 {day['astronomy'][0]['sunset']}\n"
data['tooltip'] += f"⬆️ {get_max_temp(day)} ⬇️ {get_min_temp(day)} "
data['tooltip'] += f"🌅 {get_sunrise(day)} 🌇 {get_sunset(day)}\n"
# Get the hourly forecast for the day
for hour in day['hourly']:
if i == 0:
if int(format_time(hour['time'])) < datetime.now().hour-2:
continue
data['tooltip'] += f"{format_time(hour['time'])} {WEATHER_CODES[hour['weatherCode']]} {format_temp(hour['FeelsLikeC'])} {hour['weatherDesc'][0]['value']}, {format_chances(hour)}\n"
data['tooltip'] += f"{format_time(hour['time'])} {get_weather_icon(hour)} {format_temp(get_temperature_hour(hour))} {get_description(hour)}, {format_chances(hour)}\n"


print(json.dumps(data))
11 changes: 9 additions & 2 deletions Configs/.local/share/hyde/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,15 @@ font = "JetBrainsMono Nerd Font"
scale=30 # total scaling
# output = ["", ""] # Default monitor output for waybar

[waybar.weather]
loc = true # Show location in bar // accepts true or false or location/coordinates string
[weather]
temperature_unit='c' # Temperature unit to °C or °F ('c' or 'f')
time_format='24h' # Time format ('12h or 24h')
windspeed_unit='km/h' # Windpeed unit ('kh/h' or 'mph')
show_icon= true # Show the weather icon in waybar
show_location= false # Show the location in waybar
show_today= true # Detailed description of today in tooltip
forecast_days= 3 # Number of days to show forcast (0-3)
loc = '' # Location/coordinates string for the weather output

[cava.stdout]
# 'cava.sh stdout' configuration
Expand Down