import utime
from machine import Pin, RTC, I2C
import urequests
import network, json
from ssd1306 import SSD1306_I2C
import time
WIDTH = 128
HEIGHT = 64
# Initialize I2C and OLED display
i2c = I2C(0, scl=Pin(17), sda=Pin(16), freq=400000)
display = SSD1306_I2C(WIDTH, HEIGHT, i2c)
# Load configuration
with open('config.json') as f:
config = json.load(f)
if config['ssid'] == 'Enter_Wifi_SSID':
raise ValueError("config.json has not been updated with your unique keys and data")
# Connect to WiFi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
print("Connecting to WiFi: {}".format(config['ssid']))
wlan.connect(config['ssid'], config['ssid_password'])
while not wlan.isconnected():
time.sleep(1) # Avoid busy-waiting
def sync_time_with_worldtimeapi_org(rtc):
TIME_API = "http://worldtimeapi.org/api/timezone/Asia/Shanghai"
retry_interval = 1 # seconds
while True:
try:
response = urequests.get(TIME_API)
data = response.json()
response.close()
current_time = data.get("datetime")
if not current_time:
raise ValueError("Datetime field is missing in response")
date_part, time_part = current_time.split("T")
year, month, day = date_part.split("-")
year = int(year)
month = int(month)
day = int(day)
time_part = time_part.split(".")[0]
hours, minutes, seconds = time_part.split(":")
hours = int(hours)
minutes = int(minutes)
seconds = int(seconds)
week_day = data.get("day_of_week")
if week_day is None:
week_day = 0
rtc.datetime((year, month, day, week_day, hours, minutes, seconds, 0))
break
except Exception as e:
print(f"Error syncing time: {e}")
time.sleep(retry_interval) # Retry after a short delay
rtc = RTC()
sync_time_with_worldtimeapi_org(rtc)
def fetch_weather(api_key, city, country_code):
WEATHER_API = f"http://api.openweathermap.org/data/2.5/weather?q={city},{country_code}&appid={api_key}&units=metric"
try:
response = urequests.get(WEATHER_API)
data = response.json()
response.close()
if data['cod'] == 200:
pressure = data['main']['pressure']
temp_max = data['main']['temp_max']
humidity = data['main']['humidity']
weather_main = data['weather'][0]['main']
return pressure, temp_max, humidity, weather_main
else:
return None, None, None, "Weather data not available"
except Exception as e:
print("Error fetching weather:", e)
return None, None, None, "Error fetching weather"
def update_display(weather_data):
# Get current time
Y, M, D, W, H, M, S, SS = rtc.datetime()
# Clear the display
display.fill(0)
# Display time
display.text("Time:{:02}:{:02}:{:02}".format(H, M, S), 0, 0)
# Display weather information
pressure, temp_max, humidity, weather_main = weather_data
if pressure is not None:
display.text(f"Pressure: {pressure} hPa", 0, 20)
display.text(f"Temp Max: {temp_max:.1f} C", 0, 30)
display.text(f"Humidity: {humidity}%", 0, 40)
display.text(f"Weather: {weather_main}", 0, 50)
else:
display.text(weather_main, 0, 20)
# Show the updated display
display.show()
# Define GPIO pins for LEDs
hour_msd_pins = [Pin(pin, Pin.OUT) for pin in [0, 1]] # Most significant digit of hours
hour_lsd_pins = [Pin(pin, Pin.OUT) for pin in [2, 3, 4, 5]] # Least significant digit of hours
minute_msd_pins = [Pin(pin, Pin.OUT) for pin in [6, 7, 8]] # Most significant digit of minutes
minute_lsd_pins = [Pin(pin, Pin.OUT) for pin in [9, 10, 11, 12]] # Least significant digit of minutes
def update_leds():
# Get the current time
Y, M, D, W, H, M, S, SS = rtc.datetime()
# Calculate most significant and least significant digits for hours and minutes
msd_hour = H // 10 # Most significant digit of the hour (0, 1, or 2)
lsd_hour = H % 10 # Least significant digit of the hour (0-9)
msd_minute = M // 10 # Most significant digit of minutes (0-5)
lsd_minute = M % 10 # Least significant digit of minutes (0-9)
# Convert to binary strings
msd_hour_binary = '{:02b}'.format(msd_hour) # 2 bits for most significant digit of hours
lsd_hour_binary = '{:04b}'.format(lsd_hour) # 4 bits for least significant digit of hours
msd_minute_binary = '{:03b}'.format(msd_minute) # 3 bits for most significant digit of minutes
lsd_minute_binary = '{:04b}'.format(lsd_minute) # 4 bits for least significant digit of minutes
# Set the LED states based on the binary values for hours (most significant digit)
for i in range(2):
hour_msd_pins[i].value(int(msd_hour_binary[i]))
# Set the LED states based on the binary values for hours (least significant digit)
for i in range(4):
hour_lsd_pins[i].value(int(lsd_hour_binary[i]))
# Set the LED states based on the binary values for minutes (most significant digit)
for i in range(3):
minute_msd_pins[i].value(int(msd_minute_binary[i]))
# Set the LED states based on the binary values for minutes (least significant digit)
for i in range(4):
minute_lsd_pins[i].value(int(lsd_minute_binary[i]))
# Main loop
last_weather_update = 0
weather_data = (None, None, None, "Fetching weather...")
while True:
current_time = time.time()
# Fetch weather data every 5 minutes
if current_time - last_weather_update > 300:
weather_data = fetch_weather(config['weather_api_key'], config['city'], config['country_code'])
last_weather_update = current_time
# Update display and LEDs
update_display(weather_data)
update_leds()
time.sleep(1) # Update every second