diff --git a/README.md b/README.md
index bf1bb5b0be8171b495c6ef0720d3a437e0ba1924..6f53ccd5a1deccf94777119c273e6c3e306112af 100644
--- a/README.md
+++ b/README.md
@@ -58,3 +58,6 @@ It's designed to be:
   and the modules can be easily created or modified.
 - Easily extensible, with a simple API for creating new modules. The clock is also designed to be 
   easily configurable, with a simple configuration file that can be edited to change the appearance of the clock.
+
+## Attribution
+Weather Icons by [Icons8](https://icons8.com/)
diff --git a/config.py b/config.py
index c171108e35085b262ee42588587b72ea7f4a81ff..7167164158bb20997ffa8e3fb4feef05f1bdbabc 100644
--- a/config.py
+++ b/config.py
@@ -15,7 +15,12 @@ default_hw_config = {
     "flask_port": 5000,
     "show_fps": False,
     "fps_max": 60,
-    "main_update_frequency": 500
+    "main_update_frequency": 500,
+    "owm_api_key": "YOUR_API_KEY",
+    "weather_lat": 0.0,
+    "weather_long": 0.0,
+    "weather_update_frequency": 600,
+    "weather_units": "metric"
 }
 
 hw_config = default_hw_config.copy()
@@ -49,7 +54,8 @@ PROP_AVAILABLE_WIDGETS = [
     "IPShowWidget",
     "TestWidget",
     "AnalogClockWidget",
-    "DigitalClockWidget"
+    "DigitalClockWidget",
+    "WeatherWidget",
 ]
 
 PROP_AVAILABLE_PATTERNS = [
diff --git a/icons/weather/01d@2x.png b/icons/weather/01d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed42ad9e01a8ac5c6a724cce862c79efe64c5113
Binary files /dev/null and b/icons/weather/01d@2x.png differ
diff --git a/icons/weather/01n@2x.png b/icons/weather/01n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..85efa16b13f4a9555e895d290ff14721a9ff1dff
Binary files /dev/null and b/icons/weather/01n@2x.png differ
diff --git a/icons/weather/02d@2x.png b/icons/weather/02d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..fabd9c3b31a1032119075253795e9b7ed4116bcd
Binary files /dev/null and b/icons/weather/02d@2x.png differ
diff --git a/icons/weather/02n@2x.png b/icons/weather/02n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..288a40ea0fa34005bd83cce484c6639ac53f6baa
Binary files /dev/null and b/icons/weather/02n@2x.png differ
diff --git a/icons/weather/03d@2x.png b/icons/weather/03d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef2e9f7f955fe1b8da7f30e9ae15b2f707387c48
Binary files /dev/null and b/icons/weather/03d@2x.png differ
diff --git a/icons/weather/03n@2x.png b/icons/weather/03n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef2e9f7f955fe1b8da7f30e9ae15b2f707387c48
Binary files /dev/null and b/icons/weather/03n@2x.png differ
diff --git a/icons/weather/04d@2x.png b/icons/weather/04d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c64ea86b6a93c7fd61543c696956b0657454fe9
Binary files /dev/null and b/icons/weather/04d@2x.png differ
diff --git a/icons/weather/04n@2x.png b/icons/weather/04n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c64ea86b6a93c7fd61543c696956b0657454fe9
Binary files /dev/null and b/icons/weather/04n@2x.png differ
diff --git a/icons/weather/09d@2x.png b/icons/weather/09d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..0f14cb61a53463cf6ca803561716b21a41cd3c36
Binary files /dev/null and b/icons/weather/09d@2x.png differ
diff --git a/icons/weather/09n@2x.png b/icons/weather/09n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..0f14cb61a53463cf6ca803561716b21a41cd3c36
Binary files /dev/null and b/icons/weather/09n@2x.png differ
diff --git a/icons/weather/10d@2x.png b/icons/weather/10d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..62304fded6be1c5cea4a6a353cf336a98bec4c3f
Binary files /dev/null and b/icons/weather/10d@2x.png differ
diff --git a/icons/weather/10n@2x.png b/icons/weather/10n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..b5e5d101266c3a54b4893e8e38e3c0014f3fdfa2
Binary files /dev/null and b/icons/weather/10n@2x.png differ
diff --git a/icons/weather/11d@2x.png b/icons/weather/11d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a885cfa9e79bc113e3d2dc7c7ad7d425e97e1fc
Binary files /dev/null and b/icons/weather/11d@2x.png differ
diff --git a/icons/weather/11n@2x.png b/icons/weather/11n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a885cfa9e79bc113e3d2dc7c7ad7d425e97e1fc
Binary files /dev/null and b/icons/weather/11n@2x.png differ
diff --git a/icons/weather/13d@2x.png b/icons/weather/13d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..7867322e900068a96547ec05d5e1a7b841d4ab64
Binary files /dev/null and b/icons/weather/13d@2x.png differ
diff --git a/icons/weather/13n@2x.png b/icons/weather/13n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..7867322e900068a96547ec05d5e1a7b841d4ab64
Binary files /dev/null and b/icons/weather/13n@2x.png differ
diff --git a/icons/weather/50d@2x.png b/icons/weather/50d@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..f04122b30fdcde958c90ca339bb990fb5508ffef
Binary files /dev/null and b/icons/weather/50d@2x.png differ
diff --git a/icons/weather/50n@2x.png b/icons/weather/50n@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..f04122b30fdcde958c90ca339bb990fb5508ffef
Binary files /dev/null and b/icons/weather/50n@2x.png differ
diff --git a/icons/weather/icons8-cloud-96.png b/icons/weather/icons8-cloud-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..41a851fb7ec77f501eb3a23e72e7a9181f592a99
Binary files /dev/null and b/icons/weather/icons8-cloud-96.png differ
diff --git a/icons/weather/icons8-cloud-lightning-96.png b/icons/weather/icons8-cloud-lightning-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..11ea0efdd1c014ec8aa29d1454b3dbc4fe4c4f2a
Binary files /dev/null and b/icons/weather/icons8-cloud-lightning-96.png differ
diff --git a/icons/weather/icons8-clouds-96.png b/icons/weather/icons8-clouds-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f5d4d4f83f350f50164835cf7eeb2ed07b0dbde
Binary files /dev/null and b/icons/weather/icons8-clouds-96.png differ
diff --git a/icons/weather/icons8-heavy-rain-96.png b/icons/weather/icons8-heavy-rain-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f8ad3e629d228e6be393ab15230490b6a1b5a13
Binary files /dev/null and b/icons/weather/icons8-heavy-rain-96.png differ
diff --git a/icons/weather/icons8-light-rain-96.png b/icons/weather/icons8-light-rain-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..80b3971a63afab9bc569f19c7b68ac9c9b697215
Binary files /dev/null and b/icons/weather/icons8-light-rain-96.png differ
diff --git a/icons/weather/icons8-light-snow-96.png b/icons/weather/icons8-light-snow-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..14a792fbf2515f1d9c965921480bd6090778f2c0
Binary files /dev/null and b/icons/weather/icons8-light-snow-96.png differ
diff --git a/icons/weather/icons8-night-96.png b/icons/weather/icons8-night-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..91793582810fe14fbdef162e84094953e6b9e1f6
Binary files /dev/null and b/icons/weather/icons8-night-96.png differ
diff --git a/icons/weather/icons8-night-wind-96.png b/icons/weather/icons8-night-wind-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..7e80a387879545bdb4b1a320727ea27780467562
Binary files /dev/null and b/icons/weather/icons8-night-wind-96.png differ
diff --git a/icons/weather/icons8-partly-cloudy-day-96.png b/icons/weather/icons8-partly-cloudy-day-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..7207cab9fba18be0a8b6b8573f5b3f75062fbce0
Binary files /dev/null and b/icons/weather/icons8-partly-cloudy-day-96.png differ
diff --git a/icons/weather/icons8-rain-96.png b/icons/weather/icons8-rain-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..1c2bd69874e13d2e8eb29d388f14cf5c1e128dc0
Binary files /dev/null and b/icons/weather/icons8-rain-96.png differ
diff --git a/icons/weather/icons8-rain-cloud-96.png b/icons/weather/icons8-rain-cloud-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..74e3556e6f45cbbd7b3832b50aecaec0397d6b36
Binary files /dev/null and b/icons/weather/icons8-rain-cloud-96.png differ
diff --git a/icons/weather/icons8-snow-96.png b/icons/weather/icons8-snow-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e94bbaec4740238ebec3208ba6239697e11ad3b
Binary files /dev/null and b/icons/weather/icons8-snow-96.png differ
diff --git a/icons/weather/icons8-storm-96.png b/icons/weather/icons8-storm-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..5ac2f7b64c2522c20371f37f2be91107b8cb6cac
Binary files /dev/null and b/icons/weather/icons8-storm-96.png differ
diff --git a/icons/weather/icons8-storm-with-heavy-rain-96.png b/icons/weather/icons8-storm-with-heavy-rain-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..7fe09cfa179312fe6d3ac88f6e1815bd38403d61
Binary files /dev/null and b/icons/weather/icons8-storm-with-heavy-rain-96.png differ
diff --git a/icons/weather/icons8-thermometer-96.png b/icons/weather/icons8-thermometer-96.png
new file mode 100644
index 0000000000000000000000000000000000000000..fb19b5bcc1f98682363f5ca52927749c4aed575f
Binary files /dev/null and b/icons/weather/icons8-thermometer-96.png differ
diff --git a/main.py b/main.py
index dd13857ec595d4272dd5f69947049be3a1e5cac0..0e605cbfc7155b0f0221f8e183cf0693e4b68ad1 100644
--- a/main.py
+++ b/main.py
@@ -436,6 +436,8 @@ if __name__ == "__main__":
             try:
                 message = mainthread_queue.get_nowait()
                 parts = message.split(":")
+                print("Main Message Received")
+                print(message)
                 if message == "EXIT":
                     display_queue.put("EXIT")
                     led_queue.put("EXIT")
diff --git a/module_defaults.json b/module_defaults.json
index c25c3ba950faa9a18c7f7da670d72aa6bb6a82f1..14c9c1c1f6467122c45af82133d43c2386ef6ee7 100644
--- a/module_defaults.json
+++ b/module_defaults.json
@@ -274,6 +274,63 @@
             "type": "string"
         }
     },
+    "WeatherWidget": {
+        "scalable_font_size": {
+            "name": "Font size",
+            "description": "The font size of the clock.",
+            "default": 15,
+            "type": "integer"
+        },
+        "font_color": {
+            "name": "Font colour",
+            "description": "The colour of the font.",
+            "default": "#ffffff",
+            "type": "color"
+        },
+        "font_name": {
+            "name": "Font name",
+            "description": "The name of the font to use.",
+            "default": null,
+            "type": "font"
+        },
+        "font_bold": {
+            "name": "Font bold",
+            "description": "Whether the font should be bold.",
+            "default": false,
+            "type": "boolean"
+        },
+        "font_italic": {
+            "name": "Font italic",
+            "description": "Whether the font should be italic.",
+            "default": false,
+            "type": "boolean"
+        },
+        "draw_background": {
+            "name": "Draw background",
+            "description": "Draw the background of the widget.",
+            "default": true,
+            "type": "boolean"
+        },
+        "background_type": {
+            "name": "Background type",
+            "description": "The type of background to use (`color` or `image`).",
+            "default": "color",
+            "type": "enum",
+            "allowed_values": ["color", "image"]
+        },
+        "background_color": {
+            "name": "Background colour",
+            "description": "The colour of the background.",
+            "default": "#000000",
+            "type": "color"
+        },
+        "background_image": {
+            "name": "Background image",
+            "description": "The image to use as the background.",
+            "default": "",
+            "type": "filepath"
+        }
+    },
     "SolidColorPattern": {
         "tick_rate": {
             "name": "Tick rate",
diff --git a/requirements.txt b/requirements.txt
index e041ca2758dcfacaacf0a77ed2965fc3b34f6463..bec2c92274a5f16fd42afd7501b8b28e54d66310 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
 pygame~=2.6.0
-flask~=3.0.3
\ No newline at end of file
+flask~=3.0.3
+requests~=2.32.3
\ No newline at end of file
diff --git a/screenwidgets.py b/screenwidgets.py
index 12884e02e916bfbdf56cc6c4905d17e16931f3c9..a74da57c3cc416336770223304391fb4edd75b00 100644
--- a/screenwidgets.py
+++ b/screenwidgets.py
@@ -1,10 +1,12 @@
 import math
+import time
 from datetime import datetime
 
-from config import PROP_WINDOW_SCALE, PROP_SCREEN_WIDTH, PROP_SCREEN_HEIGHT
+from config import PROP_WINDOW_SCALE, PROP_SCREEN_WIDTH, PROP_SCREEN_HEIGHT, hw_config
 from utils.num import get_screen_centre
 from utils.net import get_ip
 from utils.fonts import get_font_path_or_default
+from utils.weather import Weather
 
 
 class IWidgetMeta(type):
@@ -241,3 +243,78 @@ class IPShowWidget(IWidget):
         screen.blit(text_surface, text_rect)
         screen.blit(text_surface_2, text_rect_2)
 
+class WeatherWidget(IWidget):
+    def __init__(self, config: dict):
+        super().__init__(config)
+        self.pygame = config['pygame']
+
+        # Get the font path
+        self.font_path = get_font_path_or_default(self.pygame, config.get("font_name", None),
+                                                  config.get("font_bold", False), config.get("font_italic", False))
+
+        # Load the font
+        self.font = self.pygame.font.Font(self.font_path, config.get("font_size", 15 * PROP_WINDOW_SCALE))
+        self.font.bold = config.get("font_bold", False)
+        self.font.italic = config.get("font_italic", False)
+
+        # Set the colours
+        self.color = config.get("font_color", "white")
+        self.background_color = config.get("background_color", "black")
+
+        # Set background options
+        self.draw_background = config.get("draw_background", False)
+        self.background_type = config.get("background_type", "color")
+        if self.background_type == "image" and config.get("background_image", "") != "":
+            self.bg_image = self.pygame.image.load(config.get("background_image", ""))
+            self.bg_image = self.pygame.transform.scale(self.bg_image, (
+            PROP_SCREEN_WIDTH * PROP_WINDOW_SCALE, PROP_SCREEN_HEIGHT * PROP_WINDOW_SCALE))
+
+        # Set the weather object
+        self.weather = Weather(hw_config["owm_api_key"], hw_config["weather_lat"], hw_config["weather_long"], hw_config["weather_units"])
+        self.last_updated = 0
+        self.place_name = "No Data"
+        self.weather_description = ""
+        self.weather_icon = ""
+        self.temperature = 0
+
+        self.update_frequency = hw_config["weather_update_frequency"]
+
+    def draw(self, screen):
+        if time.time() - self.last_updated > self.update_frequency:
+            self.last_updated = time.time()
+            print("Updating weather")
+            # Update the weather
+            weather = self.weather.get_weather()
+            if weather is not None:
+                self.place_name = weather["name"]
+                self.weather_description = weather["description"]
+                self.weather_icon = weather["icon"]
+                self.temperature = weather["temp"]
+            else:
+                self.place_name = "No Data"
+                self.weather_description = ""
+                self.weather_icon = ""
+                self.temperature = 0
+
+
+        # Fill the background
+        if self.draw_background:
+            if self.background_type == "color":
+                screen.fill(self.background_color)
+            elif self.background_type == "image":
+                screen.blit(self.bg_image, (0, 0))
+
+        # Render the text
+        if self.weather_icon != "":
+            wicon = self.pygame.image.load(self.weather_icon)
+            wicon = self.pygame.transform.scale(wicon, (65 * PROP_WINDOW_SCALE, 65 * PROP_WINDOW_SCALE))
+
+            screen.blit(wicon, (get_screen_centre()[0] - 50 * PROP_WINDOW_SCALE, get_screen_centre()[1] - 50 * PROP_WINDOW_SCALE))
+
+        text_surface = self.font.render(f"{self.place_name}", True, self.color)
+        text_surface_2 = self.font.render(f"{self.weather_description}", True, self.color)
+        text_surface_3 = self.font.render(f"{self.temperature}", True, self.color)
+
+        screen.blit(text_surface, (get_screen_centre()[0] - 50 * PROP_WINDOW_SCALE, get_screen_centre()[1] + 50 * PROP_WINDOW_SCALE))
+        screen.blit(text_surface_2, (get_screen_centre()[0] - 50 * PROP_WINDOW_SCALE, get_screen_centre()[1] + 70 * PROP_WINDOW_SCALE))
+        screen.blit(text_surface_3, (get_screen_centre()[0] - 50 * PROP_WINDOW_SCALE, get_screen_centre()[1] + 90 * PROP_WINDOW_SCALE))
\ No newline at end of file
diff --git a/utils/weather.py b/utils/weather.py
new file mode 100644
index 0000000000000000000000000000000000000000..876b1c79d1c108ed40f90bb4ac032855ac911638
--- /dev/null
+++ b/utils/weather.py
@@ -0,0 +1,40 @@
+import os.path
+
+import requests
+
+# weather['name']
+# weather['weather'][0]['description']
+# weather['weather'][0]['icon']
+# weather['main']['temp']
+# weather['main']['feels_like']
+
+class Weather:
+    def __init__(self, api_key, latitude, longitude, weather_units):
+        self.api_key = api_key
+        self.lat = latitude
+        self.long = longitude
+        self.weather_units = weather_units
+    def get_weather(self):
+        r = requests.get(f"https://api.openweathermap.org/data/2.5/weather?lat={self.lat}&lon={self.long}&appid={self.api_key}&units={self.weather_units}")
+
+        if r.status_code != 200:
+            return None
+        jsn = r.json()
+
+        if "weather" not in jsn or len(jsn.get("weather", [])) == 0:
+            return None
+
+        # Get icon path
+        icon = jsn['weather'][0]['icon']
+        icon_path = f"icons/weather/{icon}@2x.png"
+
+        if not os.path.exists(icon_path):
+            icon_path = ""
+
+        return {
+            "name": jsn['name'],
+            "description": jsn['weather'][0]['description'],
+            "icon": icon_path,
+            "temp": jsn['main']['temp'],
+            "feels_like": jsn['main']['feels_like']
+        }