-
Notifications
You must be signed in to change notification settings - Fork 787
/
Copy pathcode.py
278 lines (252 loc) · 9.4 KB
/
code.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# 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
# neopixel setup
NUMPIXELS = 30 # number of neopixels
BRIGHTNESS = 0.5 # 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)
# turn on NeoPixels on boot to check wiring
pixels.fill((255, 125, 0))
pixels.show()
# 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, lambda : 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)
r = remaining
# 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
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)
# red and yellow color percentage for neopixels
percent_red = 0
percent_yellow = 0
print(total_until_set)
# check to see if the star fragment should be lit up on start-up
if total_until_set < 0:
print("star glow true")
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)
print(now)
print("%d hour(s) until sunset" % hours_until_sunset)
print("%d minutes(s) until sunset" % mins_until_sunset)
print(sunset)
print(percent_red)
print()
# less than an hour until sunset...
if hours_until_sunset in (0, 23):
# check every minute
time_check = 300000
# 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..
if total_until_set < 0:
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)
print(now)
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 in (0, 23):
# check every minute
time_check = 300000
# 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..
if total_until_rise < 0:
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()
except Exception as e:
reset_on_error(10, e)