153 lines
5.4 KiB
Python
153 lines
5.4 KiB
Python
from time import time
|
|
from astral import LocationInfo
|
|
from astral.sun import sun
|
|
from datetime import date
|
|
|
|
from grove.gpio import GPIO
|
|
from grove.display.jhd1802 import JHD1802
|
|
|
|
city = LocationInfo("Seinäjoki", "Finland", "Europe/Helsinki", 62.7900, 22.8400)
|
|
s = sun(city.observer, date=date.today())
|
|
print(f"City: {city.name}, {city.region}")
|
|
print(f"Timezone: {city.timezone}")
|
|
print(f"Latitude: {city.latitude:.6f}; Longitude: {city.longitude:.6f}")
|
|
|
|
def isSunUp() -> bool:
|
|
from datetime import datetime
|
|
now = datetime.now(city.tzinfo)
|
|
return s["sunrise"] <= now <= s["sunset"]
|
|
|
|
# sunset and sunrise
|
|
class AlarmClock:
|
|
ledGpio: GPIO
|
|
buttonGpio: GPIO
|
|
relayGpio: GPIO
|
|
lastKnownButtonState: bool = False
|
|
lcd: JHD1802
|
|
lastButtonPressTime: float = 0.0
|
|
lastButtonStateChangeTime: float = 0.0
|
|
debounceDelay: float = 0.05 # 50ms debounce delay
|
|
longPressThreshold: float = 1.0 # 1 second for long press
|
|
buttonPressStartTime: float = 0.0
|
|
configMode: str = "normal" # modes: normal, set_hour, set_minute
|
|
alarmHour: int = 7
|
|
alarmMinute: int = 0
|
|
def __init__(self, pins: dict = {}):
|
|
self.ledGpio = GPIO(pins.get("led", 5), GPIO.OUT)
|
|
self.buttonGpio = GPIO(pins.get("button", 6), GPIO.IN)
|
|
self.relayGpio = GPIO(pins.get("relay", 16), GPIO.OUT)
|
|
self.lcd = JHD1802()
|
|
self.setLcdText("AlarmClock Init")
|
|
|
|
|
|
def start(self):
|
|
print("AlarmClock started")
|
|
while True:
|
|
self.loop()
|
|
|
|
def setRelayState(self, state: bool):
|
|
self.relayGpio.write(1 if state else 0)
|
|
|
|
def loop(self):
|
|
currentButtonState = not self.buttonGpio.read()
|
|
currentTime = time()
|
|
|
|
if (self.configMode == "normal"):
|
|
currentMinute = int((currentTime / 60) % 60)
|
|
currentHour = int((currentTime / 3600) % 24)
|
|
currrentSecond = int(currentTime % 60)
|
|
|
|
self.setLcdText(f"Time {currentHour:02d}:{currentMinute:02d}:{currrentSecond:02d}\nAlarm {self.alarmHour:02d}:{self.alarmMinute:02d}")
|
|
|
|
# Only process button state change if debounce delay has passed
|
|
if currentButtonState != self.lastKnownButtonState:
|
|
if (currentTime - self.lastButtonStateChangeTime) >= self.debounceDelay:
|
|
self.lastKnownButtonState = currentButtonState
|
|
self.lastButtonStateChangeTime = currentTime
|
|
self.onButtonPress("button", currentButtonState)
|
|
|
|
# Check for long press while button is held
|
|
if currentButtonState and self.buttonPressStartTime > 0:
|
|
pressDuration = currentTime - self.buttonPressStartTime
|
|
if pressDuration >= self.longPressThreshold:
|
|
self.onLongPress()
|
|
self.buttonPressStartTime = 0.0 # Reset to prevent repeated triggers
|
|
|
|
def onButtonPress(self, button: str, state: bool):
|
|
print(f"Button '{button}' pressed state: {state}")
|
|
currentTime = time()
|
|
|
|
if button == "button":
|
|
if state: # Button pressed down
|
|
self.buttonPressStartTime = currentTime
|
|
else: # Button released
|
|
if self.buttonPressStartTime > 0:
|
|
pressDuration = currentTime - self.buttonPressStartTime
|
|
self.buttonPressStartTime = 0.0
|
|
|
|
# Only handle as short press if it wasn't a long press
|
|
if pressDuration < self.longPressThreshold:
|
|
self.onShortPress()
|
|
|
|
def onShortPress(self):
|
|
"""Handle short button press based on current mode"""
|
|
if self.configMode == "normal":
|
|
# Normal mode: toggle relay
|
|
self.setRelayState(not self.relayGpio.read())
|
|
elif self.configMode == "set_hour":
|
|
# Increment hour
|
|
self.alarmHour = (self.alarmHour + 1) % 24
|
|
self.setLcdText(f"Set Hour: {self.alarmHour:02d}")
|
|
elif self.configMode == "set_minute":
|
|
# Increment minute
|
|
self.alarmMinute = (self.alarmMinute + 1) % 60
|
|
self.setLcdText(f"Set Min: {self.alarmMinute:02d}")
|
|
|
|
def onLongPress(self):
|
|
"""Handle long button press - cycle through configuration modes"""
|
|
if self.configMode == "normal":
|
|
self.configMode = "set_hour"
|
|
self.setLcdText(f"Set Hour: {self.alarmHour:02d}")
|
|
print(f"Entering hour setting mode")
|
|
elif self.configMode == "set_hour":
|
|
self.configMode = "set_minute"
|
|
self.setLcdText(f"Set Min: {self.alarmMinute:02d}")
|
|
print(f"Switching to minute setting mode")
|
|
elif self.configMode == "set_minute":
|
|
self.configMode = "normal"
|
|
self.setLcdText(f"Saved: {self.alarmHour:02d}:{self.alarmMinute:02d}")
|
|
print(f"Alarm time saved: {self.alarmHour:02d}:{self.alarmMinute:02d}")
|
|
|
|
lastLcdText: str = ""
|
|
def setLcdText(self, text: str):
|
|
if text == self.lastLcdText:
|
|
return
|
|
self.lastLcdText = text
|
|
self.lcd.clear()
|
|
rows = text.split("\n")
|
|
for i, row in enumerate(rows):
|
|
if i == 0:
|
|
self.lcd.setCursor(0, 0)
|
|
self.lcd.write(f"{(" "+row):<17}")
|
|
elif i == 1:
|
|
self.lcd.setCursor(1, 0)
|
|
self.lcd.write(row)
|
|
print(f"LCD: {text}")
|
|
|
|
|
|
|
|
|
|
|
|
pins = {
|
|
"button": 6,
|
|
"led": 5,
|
|
"buzzer": 12,
|
|
}
|
|
alarm_clock = AlarmClock(pins)
|
|
alarm_clock.start()
|
|
|
|
|
|
|
|
|
|
|