Adafruit_Learning_System_Gu.../Star_Fragment_Lamp/code.py
2023-03-07 07:47:44 -05:00

323 lines
11 KiB
Python

# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT
import os
import ssl
import time
import microcontroller
import board
import wifi
import socketpool
import adafruit_requests
import neopixel
import simpleio
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
from adafruit_io.adafruit_io import IO_HTTP
# latitude
lat = 42.36
# longitude
long = -71.06
# API request to open-meteo
weather_url = "https://api.open-meteo.com/v1/forecast?"
# pass latitude and longitude
# will return sunrise and sunset times
weather_url += "latitude=%d&longitude=%d&timezone=auto&daily=sunrise,sunset" % (lat, long)
# connect to SSID
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
pool = socketpool.SocketPool(wifi.radio)
# adafruit IO info
aio_username = os.getenv('aio_username')
aio_key = os.getenv('aio_key')
location = "America/New York"
# io HTTP for getting the time from the internet
io = IO_HTTP(aio_username, aio_key, requests)
def reset_on_error(delay, error):
print("Error:\n", str(error))
print("Resetting microcontroller in %d seconds" % delay)
time.sleep(delay)
microcontroller.reset()
# function for making http requests with try/except
def get_request(tries, ping):
for i in range(tries):
try:
n = ping
except Exception as error:
print(error)
time.sleep(10)
if i < tries - 1:
continue
raise
break
return n
# get the time on start-up
# pylint: disable=broad-except
try:
now = get_request(5, io.receive_time())
except Exception as e:
reset_on_error(10, e)
print(now)
today = now.tm_mday
# function to make a request to open-meteo
def sun_clock():
# make the API request
response = get_request(5, requests.get(weather_url))
# packs the response into a JSON
response_as_json = response.json()
# gets sunrise
_rise = response_as_json['daily']['sunrise'][0]
# gets sunset
_set = response_as_json['daily']['sunset'][0]
return _rise, _set
# initial API call
try:
sunrise, sunset = sun_clock()
except Exception as e:
reset_on_error(10, e)
print(sunrise)
print(sunset)
# the sunrise/sunset time is returned as a JSON aka a string
# this function chops up the string to get the hours and minutes as integers
def divide_time(z):
string_time = z.split("-")
clock_time = string_time[2].split("T")
int_time = clock_time[1].split(":")
event_time = time.struct_time(
(int(string_time[0]), int(string_time[1]), int(clock_time[0]), int(int_time[0]),
int(int_time[1]), 0, -1, -1, False)
)
# print(event_time)
return event_time
rise_time = divide_time(sunrise)
set_time = divide_time(sunset)
# function that tracks how many hours/minutes until sunrise or sunset
def sun_countdown(sun_event):
n = get_request(5, io.receive_time())
remaining = time.mktime(sun_event) - time.mktime(n)
<<<<<<< Updated upstream
=======
r = remaining
>>>>>>> Stashed changes
# print(remaining)
# calculate the seconds remaining
secs_remaining = remaining % 60 # pylint: disable=unused-variable
remaining //= 60
# calculate the minutes remaining
minutes_until = remaining % 60
remaining //= 60
# calculate the hours remaining
hours_until = remaining % 24
remaining //= 24
<<<<<<< Updated upstream
return remaining, hours_until, minutes_until, n
total_until_rise, hours_until_sunrise, mins_until_sunrise, now = sun_countdown(rise_time)
total_until_set, hours_until_sunset, mins_until_sunset, now = sun_countdown(set_time)
=======
return r, hours_until, minutes_until, n
try:
total_until_rise, hours_until_sunrise, mins_until_sunrise, now = sun_countdown(rise_time)
except Exception as e:
reset_on_error(10, e)
try:
total_until_set, hours_until_sunset, mins_until_sunset, now = sun_countdown(set_time)
except Exception as e:
reset_on_error(10, e)
>>>>>>> Stashed changes
# red and yellow color percentage for neopixels
percent_red = 0
percent_yellow = 0
# neopixel setup
NUMPIXELS = 30 # number of neopixels
BRIGHTNESS = 0.05 # A number between 0.0 and 1.0, where 0.0 is off, and 1.0 is max.
PIN = board.A3 # This is the default pin on the NeoPixel Driver BFF.
pixels = neopixel.NeoPixel(PIN, NUMPIXELS, brightness=BRIGHTNESS, auto_write=False)
print(total_until_set)
# check to see if the star fragment should be lit up on start-up
if total_until_set < 0:
<<<<<<< Updated upstream
=======
print("star glow true")
>>>>>>> Stashed changes
star_glow = True
percent_red = 255
percent_yellow = 125
# turn neopixels on using RGB values
pixels.fill((percent_red, percent_yellow, 0))
pixels.show()
else:
print("star glow false")
star_glow = False
percent_red = 0
percent_yellow = 0
# turn neopixels on using RGB values
pixels.fill((percent_red, percent_yellow, 0))
pixels.show()
# ticks time tracker
clock = ticks_ms()
# tracker for initial start-up state
first_run = True
# 15 minutes in milliseconds
time_check = 900000
# state to tell if it's after midnight yet before sunrise
looking_for_sunrise = False
while True:
try:
# if it's daytime
if not star_glow:
# every 15 minutes...
if first_run or ticks_diff(ticks_ms(), clock) > time_check:
print("pinging Open-Meteo")
sunrise, sunset = sun_clock()
(total_until_set, hours_until_sunset,
mins_until_sunset, now) = sun_countdown(set_time)
<<<<<<< Updated upstream
=======
print(now)
>>>>>>> Stashed changes
print("%d hour(s) until sunset" % hours_until_sunset)
print("%d minutes(s) until sunset" % mins_until_sunset)
print(sunset)
print()
# less than an hour until sunset...
<<<<<<< Updated upstream
if hours_until_sunset == 0 or hours_until_sunset == 23:
# check every minute
time_check = 60000
=======
if hours_until_sunset in (0, 23):
# check every minute
time_check = 300000
>>>>>>> Stashed changes
# map color to ramp up in brightness over the course of the final hour
percent_red = simpleio.map_range(mins_until_sunset, 59, 0, 0, 255)
percent_yellow = simpleio.map_range(mins_until_sunset, 59, 0, 0, 125)
# if the sun has set..
<<<<<<< Updated upstream
if mins_until_sunset < 1:
=======
if total_until_set < 0:
>>>>>>> Stashed changes
percent_red = 255
percent_yellow = 125
time_check = 900000
star_glow = True
print("star is glowing")
# otherwise just keep checking every 15 minutes
else:
time_check = 900000
percent_red = 0
percent_yellow = 0
if first_run:
first_run = False
else:
# reset clock
clock = ticks_add(clock, time_check)
# if it's nighttime...
else:
if first_run or ticks_diff(ticks_ms(), clock) > time_check:
if today != now.tm_mday or (first_run and now.tm_hour < rise_time.tm_hour):
today = now.tm_mday
looking_for_sunrise = True
# begin tracking the incoming sunrise
if looking_for_sunrise:
print("pinging Open-Meteo")
sunrise, sunset = sun_clock()
(total_until_rise, hours_until_sunrise,
mins_until_sunrise, now) = sun_countdown(rise_time)
<<<<<<< Updated upstream
print("%d hour(s) until sunrise" % hours_until_sunrise)
print("%d minutes(s) until sunrise" % mins_until_sunrise)
print(sunrise)
print(now)
print()
# less than an hour until sunset...
if hours_until_sunrise == 0 or hours_until_sunrise == 23:
# check every minute
time_check = 60000
=======
print(now)
print("%d hour(s) until sunrise" % hours_until_sunrise)
print("%d minutes(s) until sunrise" % mins_until_sunrise)
print(sunrise)
print()
# less than an hour until sunset...
if hours_until_sunrise in (0, 23):
# check every minute
time_check = 300000
>>>>>>> Stashed changes
# map color to decrease brightness over the course of the final hour
percent_red = simpleio.map_range(mins_until_sunrise, 59, 0, 255, 0)
percent_yellow = simpleio.map_range(mins_until_sunrise, 59, 0, 125, 0)
# if the sun has risen..
<<<<<<< Updated upstream
if mins_until_sunrise < 1:
=======
if total_until_rise < 0:
>>>>>>> Stashed changes
percent_red = 0
percent_yellow = 0
time_check = 900000
star_glow = False
looking_for_sunrise = False
print("star is off")
# otherwise just keep checking every 15 minutes
# and keep neopixels on
else:
time_check = 900000
percent_red = 255
percent_yellow = 125
# otherwise just keep checking every 15 minutes
# and keep neopixels on
else:
now = get_request(5, io.receive_time())
print("not looking for sunrise")
print(now)
print()
time_check = 900000
percent_red = 255
percent_yellow = 125
if first_run:
first_run = False
else:
# reset clock
clock = ticks_add(clock, time_check)
# turn neopixels on using RGB values
pixels.fill((percent_red, percent_yellow, 0))
pixels.show()
<<<<<<< Updated upstream
# pylint: disable=broad-except
except Exception as e:
print("Error:\n", str(e))
print("Resetting microcontroller in 10 seconds")
time.sleep(10)
microcontroller.reset()
=======
except Exception as e:
reset_on_error(10, e)
>>>>>>> Stashed changes