Skip to content

Commit 65ffc92

Browse files
authored
Merge branch 'master' into midi_melody_maker
2 parents 8088ab0 + 8f11540 commit 65ffc92

File tree

2 files changed

+60
-58
lines changed

2 files changed

+60
-58
lines changed

M4_Eyes/file.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//34567890123456789012345678901234567890123456789012345678901234567890123456
22

3+
#define ARDUINOJSON_ENABLE_COMMENTS 1
34
#include <ArduinoJson.h> // JSON config file functions
45
#include "globals.h"
56

Matrix_Portal_Moon_Clock/code.py

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,25 @@ class MoonData():
115115
rise : Epoch time of moon rise within this 24-hour period.
116116
set : Epoch time of moon set within this 24-hour period.
117117
"""
118-
def __init__(self, datetime, utc_offset):
118+
def __init__(self, datetime, hours_ahead, utc_offset):
119119
""" Initialize MoonData object elements (see above) from a
120-
time.struct_time and a UTC offset (as a string) and a query
121-
to the MET Norway Sunrise API (also provides lunar data),
122-
documented at:
120+
time.struct_time, hours to skip ahead (typically 0 or 24),
121+
and a UTC offset (as a string) and a query to the MET Norway
122+
Sunrise API (also provides lunar data), documented at:
123123
https://api.met.no/weatherapi/sunrise/2.0/documentation
124124
"""
125+
if hours_ahead:
126+
# Can't change attribute in datetime struct, need to create
127+
# a new one which will roll the date ahead as needed. Convert
128+
# to epoch seconds and back for the offset to work
129+
datetime = time.localtime(time.mktime(time.struct_time(
130+
datetime.tm_year,
131+
datetime.tm_mon,
132+
datetime.tm_mday,
133+
datetime.tm_hour + hours_ahead,
134+
datetime.tm_min,
135+
datetime.tm_sec,
136+
-1, -1, -1)))
125137
# strftime() not available here
126138
url = ('https://api.met.no/weatherapi/sunrise/2.0/.json?lat=' +
127139
str(LATITUDE) + '&lon=' + str(LONGITUDE) +
@@ -140,32 +152,23 @@ def __init__(self, datetime, utc_offset):
140152
self.age = float(moon_data['moonphase']['value']) / 100
141153
self.midnight = time.mktime(parse_time(
142154
moon_data['moonphase']['time']))
143-
self.rise = time.mktime(
144-
parse_time(moon_data['moonrise']['time']))
145-
self.set = time.mktime(
146-
parse_time(moon_data['moonset']['time']))
155+
if 'moonrise' in moon_data:
156+
self.rise = time.mktime(
157+
parse_time(moon_data['moonrise']['time']))
158+
else:
159+
self.rise = None
160+
if 'moonset' in moon_data:
161+
self.set = time.mktime(
162+
parse_time(moon_data['moonset']['time']))
163+
else:
164+
self.set = None
147165
return # Success!
148166
except:
149167
# Moon server error (maybe), try again after 15 seconds.
150168
# (Might be a memory error, that should be handled different)
151169
time.sleep(15)
152170

153171

154-
def next_moon_data(datetime, utc_offset):
155-
""" Given a time.struct_time, compute and return a MoonData object
156-
for the NEXT 24 hour period ahead.
157-
"""
158-
tomorrow = time.struct_time(datetime.tm_year,
159-
datetime.tm_mon,
160-
datetime.tm_mday,
161-
datetime.tm_hour + 24,
162-
datetime.tm_min,
163-
datetime.tm_sec,
164-
-1, -1, -1)
165-
# Convert to epoch seconds and back for the +24 hour offset to work
166-
return MoonData(time.localtime(time.mktime(tomorrow)), utc_offset)
167-
168-
169172
# ONE-TIME INITIALIZATION --------------------------------------------------
170173

171174
MATRIX = Matrix(bit_depth=BITPLANES)
@@ -257,11 +260,14 @@ def next_moon_data(datetime, utc_offset):
257260
DATETIME, UTC_OFFSET = time.localtime(), '+00:00'
258261
LAST_SYNC = time.mktime(DATETIME)
259262

260-
# Poll server for moon data for current 24-hour period
261-
CURRENT_PERIOD = MoonData(DATETIME, UTC_OFFSET)
262-
263-
# Then do same for 24 hours ahead...
264-
NEXT_PERIOD = next_moon_data(DATETIME, UTC_OFFSET)
263+
# Poll server for moon data for current 24-hour period and +24 ahead
264+
PERIOD = []
265+
for DAY in range(2):
266+
PERIOD.append(MoonData(DATETIME, DAY * 24, UTC_OFFSET))
267+
# PERIOD[0] is the current 24-hour time period we're in. PERIOD[1] is the
268+
# following 24 hours. Data is shifted down and new data fetched as days
269+
# expire. Thought we might need a PERIOD[2] for certain circumstances but
270+
# it appears not, that's changed easily enough if needed.
265271

266272

267273
# MAIN LOOP ----------------------------------------------------------------
@@ -283,29 +289,28 @@ def next_moon_data(datetime, utc_offset):
283289
# the server with repeated queries).
284290
LAST_SYNC += 30 * 60 * 60 # 30 minutes -> seconds
285291

286-
# If NEXT_PERIOD has expired, move that to CURRENT_PERIOD and fetch anew
287-
if NOW >= NEXT_PERIOD.midnight:
288-
CURRENT_PERIOD = NEXT_PERIOD
289-
NEXT_PERIOD = next_moon_data(time.localtime(), UTC_OFFSET)
290-
continue # NOW is stale due to server query time; refresh
292+
# If PERIOD has expired, move data down and fetch new +24-hour data
293+
if NOW >= PERIOD[1].midnight:
294+
PERIOD[0] = PERIOD[1]
295+
PERIOD[1] = MoonData(time.localtime(), 24, UTC_OFFSET)
291296

292297
# Determine weighting of tomorrow's phase vs today's, using current time
293-
RATIO = ((NOW - CURRENT_PERIOD.midnight) /
294-
(NEXT_PERIOD.midnight - CURRENT_PERIOD.midnight))
298+
RATIO = ((NOW - PERIOD[0].midnight) /
299+
(PERIOD[1].midnight - PERIOD[0].midnight))
295300
# Determine moon phase 'age'
296301
# 0.0 = new moon
297302
# 0.25 = first quarter
298303
# 0.5 = full moon
299304
# 0.75 = last quarter
300305
# 1.0 = new moon
301-
if CURRENT_PERIOD.age < NEXT_PERIOD.age:
302-
AGE = (CURRENT_PERIOD.age +
303-
(NEXT_PERIOD.age - CURRENT_PERIOD.age) * RATIO) % 1.0
306+
if PERIOD[0].age < PERIOD[1].age:
307+
AGE = (PERIOD[0].age +
308+
(PERIOD[1].age - PERIOD[0].age) * RATIO) % 1.0
304309
else: # Handle age wraparound (1.0 -> 0.0)
305310
# If tomorrow's age is less than today's, it indicates a new moon
306311
# crossover. Add 1 to tomorrow's age when computing age delta.
307-
AGE = (CURRENT_PERIOD.age +
308-
(NEXT_PERIOD.age + 1 - CURRENT_PERIOD.age) * RATIO) % 1.0
312+
AGE = (PERIOD[0].age +
313+
(PERIOD[1].age + 1 - PERIOD[0].age) * RATIO) % 1.0
309314

310315
# AGE can be used for direct lookup to moon bitmap (0 to 99) -- these
311316
# images are pre-rendered for a linear timescale (solar terminator moves
@@ -318,26 +323,22 @@ def next_moon_data(datetime, utc_offset):
318323
else: # Full -> last quarter -> new
319324
PERCENT = (1 + math.cos((AGE - 0.5) * 2 * math.pi)) * 50
320325

321-
if CURRENT_PERIOD.set > CURRENT_PERIOD.rise:
322-
if CURRENT_PERIOD.rise < NOW < CURRENT_PERIOD.set:
323-
RISEN = True
324-
NEXT_EVENT = CURRENT_PERIOD.set
325-
else:
326-
RISEN = False
327-
if NOW < CURRENT_PERIOD.rise:
328-
NEXT_EVENT = CURRENT_PERIOD.rise
329-
else:
330-
NEXT_EVENT = NEXT_PERIOD.rise
331-
else:
332-
if CURRENT_PERIOD.set < NOW < CURRENT_PERIOD.rise:
326+
# Find next rise/set event, complicated by the fact that some 24-hour
327+
# periods might not have one or the other (but usually do) due to the
328+
# Moon rising ~50 mins later each day. This uses a brute force approach,
329+
# working backwards through the time periods to locate rise/set events
330+
# that A) exist in that 24-hour period (are not None), B) are still in
331+
# the future, and C) are closer than the last guess. What's left at the
332+
# end is the next rise or set (and the inverse of the event type tells
333+
# us whether Moon's currently risen or not).
334+
NEXT_EVENT = PERIOD[1].midnight + 100000 # Force first match
335+
for DAY in reversed(PERIOD):
336+
if DAY.rise and NEXT_EVENT >= DAY.rise >= NOW:
337+
NEXT_EVENT = DAY.rise
333338
RISEN = False
334-
NEXT_EVENT = CURRENT_PERIOD.rise
335-
else:
339+
if DAY.set and NEXT_EVENT >= DAY.set >= NOW:
340+
NEXT_EVENT = DAY.set
336341
RISEN = True
337-
if NOW < CURRENT_PERIOD.set:
338-
NEXT_EVENT = CURRENT_PERIOD.set
339-
else:
340-
NEXT_EVENT = NEXT_PERIOD.set
341342

342343
if DISPLAY.rotation in (0, 180): # Horizontal 'landscape' orientation
343344
CENTER_X = 48 # Text along right

0 commit comments

Comments
 (0)