Skip to content

Commit

Permalink
Merge pull request #54 from amit9838/dev
Browse files Browse the repository at this point in the history
New features and fixes
  • Loading branch information
amit9838 authored Jan 30, 2024
2 parents d7239da + 1c82121 commit 0b106f1
Show file tree
Hide file tree
Showing 20 changed files with 166 additions and 115 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
<div align="center">
<img src="data/icons/hicolor/scalable/apps/io.github.amit9838.weather.svg?raw=true" width="120">
<h1>Weather</h1>
<p>Beautiful lightweight weather app.</p>

<p>Beautiful lightweight weather app based on Python and Gtk</p>

<div align="center">
<h2>Support</h2>
I hope you ❤️ the weather app, if you think it is worth supporting you can do so using below methods

<a href="https://www.buymeacoffee.com/ami9838" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" >
</a>
</div>
<div align="center">
<a href="https://opencollective.com/weather"><img src="https://opencollective.com/spotube/donate/button.png?color=blue" alt="Donate to our Open Collective" height="45"></a>
</div>

---

<img src="https://img.shields.io/github/v/release/amit9838/weather?style=flat&label=Latest+Release&color=%234a92ff">
</div>
<div align="center">
Expand Down
1 change: 1 addition & 0 deletions data/icons/hicolor/scalable/weather_icons/wind.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions data/icons/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ install_data(
join_paths(scalable_dir, 'partly-cloudy-day-fog.svg'),
join_paths(scalable_dir, 'partly-cloudy-night-fog.svg'),
join_paths(scalable_dir, 'rain.svg'),
join_paths(scalable_dir, 'wind.svg'),
join_paths(scalable_dir, 'raindrop.svg'),
join_paths(scalable_dir, 'raindrops.svg'),
join_paths(scalable_dir, 'overcast-rain.svg'),
Expand Down
2 changes: 0 additions & 2 deletions src/Models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# Models for All weather data data
import time


class CurrentWeather:
total_instances = 0
Expand Down
Empty file removed src/__init__.py
Empty file.
2 changes: 1 addition & 1 deletion src/backendAirPollution.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def current_air_pollution(latitude: float, longitude: float, **kwargs):
except requests.exceptions.RequestException as e:
print(f"Error: {e}")

def _get_current_air_pollution(self,lat,lon):
def _get_current_air_pollution(self, lat, lon):
current_args = [
"european_aqi",
"us_aqi",
Expand Down
99 changes: 49 additions & 50 deletions src/backendWeather.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
from typing import List
import requests
import datetime

from gi.repository import Gio



base_url = "https://api.open-meteo.com/v1/forecast"

class Weather():

class Weather:
"""
See Documentation at: https://open-meteo.com/en/docs
"""

def __init__(self) -> None:
global settings,measurement_type,temperature_unit,wind_speed_unit
global settings, measurement_type, temperature_unit, wind_speed_unit
settings = Gio.Settings(schema_id="io.github.amit9838.weather")
measurement_type = settings.get_string('measure-type')
measurement_type = settings.get_string("measure-type")
if measurement_type == "imperial":
temperature_unit = "fahrenheit"
wind_speed_unit = "mph"

# Current Weather =============================================
@staticmethod
def current_weather(latitude: float, longitude: float, **kwargs):

url = base_url + f"?latitude={latitude}&longitude={longitude}"

# Check for kwargs keyword parameters
if 'current' in kwargs:
current_fields = ",".join(kwargs.get('current'))
url = url+f"&current={current_fields}"
if "current" in kwargs:
current_fields = ",".join(kwargs.get("current"))
url = url + f"&current={current_fields}"

if measurement_type == "imperial":
url += f"&temperature_unit={temperature_unit}&wind_speed_unit={wind_speed_unit}"

try:
url = url+f"&timeformat=unixtime"
url = url + f"&timeformat=unixtime"
response = requests.get(url)
response.raise_for_status() # Raise an exception if the request was unsuccessful
data = response.json()
return data
except requests.exceptions.RequestException as e:
print(f"Error: {e}")

def _get_current_weather(self,lat,lon):
def _get_current_weather(self, lat, lon):
current_args = [
"temperature_2m",
"relativehumidity_2m",
Expand All @@ -53,85 +53,84 @@ def _get_current_weather(self,lat,lon):
"weathercode",
"surface_pressure",
"windspeed_10m",
"winddirection_10m"
"winddirection_10m",
]
return self.current_weather(lat,lon,current = current_args)

return self.current_weather(lat, lon, current=current_args)

# Hourly Forecast ==============================================
@staticmethod
def forecast_hourly(latitude: float, longitude: float, **kwargs):

url = base_url + f"?latitude={latitude}&longitude={longitude}"

# Check for kwargs keyword parameters
if 'hourly' in kwargs:
hourly_fields = ",".join(kwargs.get('hourly'))
url = url+f"&hourly={hourly_fields}"
if "hourly" in kwargs:
hourly_fields = ",".join(kwargs.get("hourly"))
url = url + f"&hourly={hourly_fields}"

if measurement_type == "imperial":
url += f"&temperature_unit={temperature_unit}&wind_speed_unit={wind_speed_unit}"

try:
url = url+f"&timeformat=unixtime"
url = url + f"&timeformat=unixtime"
response = requests.get(url)
response.raise_for_status() # Raise an exception if the request was unsuccessful
data = response.json()
return data
except requests.exceptions.RequestException as e:
print(f"Error: {e}")


def _get_hourly_forecast(self,lat,lon):
def _get_hourly_forecast(self, lat, lon):
hourly_args = [
'temperature_2m',
'relativehumidity_2m',
'dewpoint_2m',
'apparent_temperature',
'weathercode',
'precipitation',
'surface_pressure',
'visibility',
'windspeed_10m',
'wind_direction_10m',
'uv_index',
'is_day'
"temperature_2m",
"relativehumidity_2m",
"dewpoint_2m",
"apparent_temperature",
"weathercode",
"precipitation",
"precipitation_probability",
"surface_pressure",
"visibility",
"windspeed_10m",
"wind_direction_10m",
"uv_index",
"is_day",
]

today = datetime.datetime.today().date()
tomorrow = today+datetime.timedelta(days=1)
return self.forecast_hourly(lat, lon,hourly=hourly_args,start_date=today,end_date=tomorrow)

tomorrow = today + datetime.timedelta(days=1)
return self.forecast_hourly(
lat, lon, hourly=hourly_args, start_date=today, end_date=tomorrow
)

# Forecast daily ====================================================
@staticmethod
def forecast_daily(latitude: float, longitude: float, **kwargs):
url = base_url + f"?latitude={latitude}&longitude={longitude}"
if 'daily' in kwargs:
hourly_fields = ",".join(kwargs.get('daily'))
url = url+f"&daily={hourly_fields}"
if "daily" in kwargs:
hourly_fields = ",".join(kwargs.get("daily"))
url = url + f"&daily={hourly_fields}"

if 'timezone' in kwargs:
url = url+f"&timezone={kwargs.get('timezone')}"
if 'start_date' in kwargs:
url = url+f"&start_date={kwargs.get('start_date')}"
if "timezone" in kwargs:
url = url + f"&timezone={kwargs.get('timezone')}"
if "start_date" in kwargs:
url = url + f"&start_date={kwargs.get('start_date')}"

if 'end_date' in kwargs:
url = url+f"&end_date={kwargs.get('end_date')}"
if "end_date" in kwargs:
url = url + f"&end_date={kwargs.get('end_date')}"

if measurement_type == "imperial":
url += f"&temperature_unit={temperature_unit}&wind_speed_unit={wind_speed_unit}"

try:
url = url+f"&timeformat=unixtime"
url = url + f"&timeformat=unixtime"
response = requests.get(url)
response.raise_for_status() # Raise an exception if the request was unsuccessful
data = response.json()
return data
except requests.exceptions.RequestException as e:
print(f"Error: {e}")

def _get_daily_forecast(self,lat,lon):
def _get_daily_forecast(self, lat, lon):
daily_args = [
"weathercode",
"temperature_2m_max",
Expand All @@ -143,4 +142,4 @@ def _get_daily_forecast(self,lat,lon):
"windspeed_10m_max",
]

return self.forecast_daily(lat,lon,daily=daily_args,timezone="GMT")
return self.forecast_daily(lat, lon, daily=daily_args, timezone="GMT")
4 changes: 4 additions & 0 deletions src/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@
"95n": icon_loc + "thunderstorms-rain.svg",
"96n": icon_loc + "thunderstorms-night-overcast-snow.svg",
"99n": icon_loc + "snowflake.svg",

"arrow": icon_loc + "arrow.svg",
"raindrop": icon_loc + "raindrop.svg",
"raindrops": icon_loc + "raindrops.svg",
"wind": icon_loc + "wind.svg",
}

bg_css = {
Expand Down
2 changes: 1 addition & 1 deletion src/css.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
}
.custom_card_forecast_item{
padding: .15rem 1.5rem;
padding: 0.15rem 1.5rem;
border-radius: .7rem;
}
Expand Down
38 changes: 34 additions & 4 deletions src/frontendForecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def page_stacks(self, page_name):
orientation=Gtk.Orientation.VERTICAL, margin_top=0, margin_bottom=0)
scrolled_window.set_child(forecast_container)


# Get Tomorrow's data from hourly forecast
tomorrow_date_time_list = [d_t for d_t in hourly_data.time.get("data") if int(
datetime.fromtimestamp(d_t).strftime(r"%d")) == (datetime.today() + timedelta(days=1)).date().day]
Expand Down Expand Up @@ -135,12 +136,41 @@ def page_stacks(self, page_name):
icon_main.set_halign(Gtk.Align.END)
icon_main.set_hexpand(True)
icon_main.set_pixel_size(50)
icon_main.set_margin_end(60)
icon_main.set_margin_end(30)
forecast_item_grid.attach(icon_main, 1, 0, 1, 1)

forecast_cond_grid = Gtk.Grid(valign=Gtk.Align.CENTER,margin_end = 20)
forecast_item_grid.attach(forecast_cond_grid, 2, 0, 1, 1)

# prec probability
if page_name == 'tomorrow':
prec_probability = hourly_data.precipitation_probability.get("data")[i]
wind_probability = hourly_data.windspeed_10m.get("data")[i]


drop_icon = Gtk.Image().new_from_file(icons["raindrop"])
drop_icon.set_pixel_size(25)
drop_icon.set_halign(Gtk.Align.START)
forecast_cond_grid.attach(drop_icon, 0, 0, 1, 1)

prec_probability_label = Gtk.Label(label=f" {prec_probability}%", margin_top=5)
prec_probability_label.set_halign(Gtk.Align.START)
forecast_cond_grid.attach(prec_probability_label, 1, 0, 1, 1)

# Wind speed probability
wind_icon = Gtk.Image().new_from_file(icons["wind"])
wind_icon.set_pixel_size(25)
wind_icon.set_halign(Gtk.Align.START)
forecast_cond_grid.attach(wind_icon, 0, 1, 1, 1)
speed_unit= hourly_data.windspeed_10m.get("unit")
wind_probability_label = Gtk.Label(label=f" {wind_probability} {speed_unit}", margin_top=5)
forecast_cond_grid.attach(wind_probability_label, 1, 1, 1, 1)


# Temp label grid
temp_label_grid = Gtk.Grid(valign=Gtk.Align.CENTER)
forecast_item_grid.attach(temp_label_grid, 2, 0, 1, 1)
forecast_item_grid.attach(temp_label_grid, 3, 0, 1, 1)


# Max temp label ======
temp_max_text = hourly_data.temperature_2m.get("data")[i]
Expand All @@ -149,7 +179,7 @@ def page_stacks(self, page_name):

temp_max = Gtk.Label(label=f"{temp_max_text:.0f}° ", margin_start=10,)
temp_max.set_css_classes(['text-3', 'bold-2'])
temp_label_grid.attach(temp_max, 0, 0, 1, 1)
temp_label_grid.attach(temp_max, 1, 0, 1, 1)

# Min temp label ======
temp_min_text = hourly_data.temperature_2m.get("data")[i]
Expand All @@ -158,4 +188,4 @@ def page_stacks(self, page_name):

temp_min = Gtk.Label(label=f" {temp_min_text:.0f}°", margin_top=5)
temp_min.set_css_classes(['light-4'])
temp_label_grid.attach(temp_min, 0, 1, 1, 1)
temp_label_grid.attach(temp_min, 1, 1, 1, 1)
2 changes: 0 additions & 2 deletions src/frontendHourlyDetails.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@ def create_stack_page(self, page_name):
"Enjoy a rain-free day today!",
"Umbrella status: resting. No precipitation in sight !",
"No rain in sight today!"


]
no_prec_label = Gtk.Label(label=no_prec_labels[random.randint(0,len(no_prec_labels)-1)])
no_prec_label.set_css_classes(["text-3a", "bold-3", "light-2"])
Expand Down
2 changes: 1 addition & 1 deletion src/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# main.py
#
# Copyright 2023 Amit
# Copyright 2024 Amit
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
1 change: 0 additions & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ configure_file(


weather_sources = [
'__init__.py',
'main.py',
'weather.py',
'weatherData.py',
Expand Down
12 changes: 0 additions & 12 deletions src/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,3 @@
def get_measurement_type():
settings = Gio.Settings.new("io.github.amit9838.weather")
return settings.get_string("measure-type")

# Units and measurements
measurements = {
"metric":{"temp_unit":"°C",
"speed_unit":'km/h',"speed_mul":3.6, # convert speed from m/s to km/h
"dist_unit":'km',"dist_mul":0.001
},
"imperial":{"temp_unit":"°F",
"speed_unit":'mph',"speed_mul":1, #speed miles/hr
"dist_unit":'miles',"dist_mul":0.0006213712,
}
}
Loading

0 comments on commit 0b106f1

Please sign in to comment.