import Clock import uasyncio as asyncio import Buzzer import Settings import Hardware as HW import math import network import time import ntptime class ClockScreen(): def __await__(self): self.running = True self.init() while self.running: if Settings.alarmOn: minutesNow = (time.localtime()[3]*60+time.localtime()[4])%(24*60) minutesAlarm = (Settings.alarmTime[0]*60+Settings.alarmTime[1])%(24*60) if not self.alarmTrunedOff: self.alarmPlaying = self.alarmPlaying or (minutesNow >= minutesAlarm and ((minutesNow-minutesAlarm)%(24*60) <=5 )) if self.alarmPlaying and not HW.buzzer.isPlaying(): HW.housingLEDs.fill((255,0,0)) for l in HW.leds: l.setOffState(blinkRate=4,pwmDuty=1023) HW.buzzer.playSound(HW.Buzzer.ALARMTONES[Settings.selectedSound]) else: pass elif minutesNow < minutesAlarm: self.alarmTrunedOff = False await asyncio.sleep_ms(200) HW.housingLEDs.fill((0,0,0)) self.cleanup() __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 def finish(self): self.running = False for b in HW.buttons: b.setCallbacks()#Clear Callbacks def __init__(self): self.running = False self.light = False self.clock = Clock.Clock() self.alarmTrunedOff = False self.alarmPlaying = False COLORS = ((255,0,0),(255,0,127),(127,0,255),(0,0,255),(0,127,255),(140,70,255),(0,255,127),(0,255,0),(127,255,0),(255,127,0)) BRIGHTNESS = (5,10,50,100,160,255) def onButtonPressed(self,button): HW.leds[button].on() def onButtonReleased(self,button,pushDownTime): HW.leds[button].off() if self.alarmPlaying: HW.buzzer.stop() self.alarmTrunedOff = True self.alarmPlaying = False HW.housingLEDs.fill((0,0,0)) HW.leds[0].setOffState() HW.leds[1].setOffState() HW.leds[2].setOffState(pwmDuty=200 if Settings.alarmOn else 0) HW.housingLEDs.fill([int(c/255*ClockScreen.BRIGHTNESS[Settings.selectedBrightness]) for c in ClockScreen.COLORS[Settings.selectedColor]] if self.light else (0,0,0)) else: if button == 0: Settings.selectedBrightness=(Settings.selectedBrightness+1)%len(ClockScreen.BRIGHTNESS) elif button == 1: if pushDownTime > 700: self.finish() return self.light = not self.light elif button == 2: if pushDownTime < 700: Settings.selectedColor=(Settings.selectedColor+1)%len(ClockScreen.COLORS) else: Settings.alarmOn = not Settings.alarmOn HW.leds[2].setOffState(pwmDuty=200 if Settings.alarmOn else 0) Settings.save() HW.housingLEDs.fill([int(c/255*ClockScreen.BRIGHTNESS[Settings.selectedBrightness]) for c in ClockScreen.COLORS[Settings.selectedColor]] if self.light else (0,0,0)) def init(self): HW.leds[2].setOffState(pwmDuty=200 if Settings.alarmOn else 0) HW.housingLEDs.fill([int(c/255*ClockScreen.BRIGHTNESS[Settings.selectedBrightness]) for c in ClockScreen.COLORS[Settings.selectedColor]] if self.light else (0,0,0)) for i,b in enumerate(HW.buttons): b.setCallbacks(onPushDown=lambda i=i:self.onButtonPressed(i),onPushUp=lambda pushDownTime,button=i:self.onButtonReleased(button,pushDownTime)) self.clock.start() def cleanup(self): HW.leds[2].setOffState() self.clock.stop() class InitHandsScreen(): def __iter__(self): HW.motorHour.rotateTo(0) HW.motorMinu.rotateTo(0) HW.housingLEDs.upper((50,50,50)) HW.leds[1].setOffState(pwmDuty=500,blinkRate=1.2) timeScreen = Get2PositionsScreen(\ startTime=(0,0),\ onStart=lambda _: HW.buzzer.playSound(HW.Buzzer.BEEP),\ onSelectedTimeChange=None,\ onPicked=lambda _: Settings.save()) await timeScreen HW.motorHour.reset() # Set the new Zero HW.motorMinu.reset() HW.housingLEDs.fill((0,0,0)) HW.leds[1].setOffState() class SetAlarmTimeScreen(): def setAlarmTime(self,selectedTime): Settings.alarmTime = selectedTime Settings.save() def __iter__(self): HW.housingLEDs.fill((255,0,0)) timeScreen = GetTimeScreen(\ startTime=Settings.alarmTime,\ onStart=lambda _: HW.buzzer.playSound(HW.Buzzer.BEEP),\ onSelectedTimeChange=None,\ onPicked=self.setAlarmTime) await timeScreen HW.housingLEDs.fill((0,0,0)) class SetTimeScreen(): def __init__(self): self.timeScreen = None def onShortMiddle(self): try: ntptime.settime() if self.timeScreen != None: ti = HW.rtc.datetime()[4:6] self.timeScreen.pickedTime = ti[0]*60 + ti[1] HW.buzzer.playSound(HW.Buzzer.BEEPBEEP) except Exception as e: HW.buzzer.playSound(HW.Buzzer.BOOP) print("Failed to get NTP Time\n",e) def setTime(self,selectedTime): #TODO if (HW.rtc != None): ti = list(HW.rtc.datetime()[:-1]) ti[4:6] = selectedTime HW.rtc.datetime(ti + [0]) HW.dsRtc.DateTime(ti) def __iter__(self): HW.housingLEDs.fill((255,0,0)) self.timeScreen = GetTimeScreen(\ startTime=HW.rtc.datetime()[4:6],\ onStart=lambda _: HW.buzzer.playSound(HW.Buzzer.BEEP),\ onSelectedTimeChange=None,\ onPicked=self.setTime, onShortMiddle=self.onShortMiddle) await self.timeScreen HW.housingLEDs.fill((0,0,0)) class RingtoneSettingsScreen(): def playAndSetSound(self,number): Settings.selectedSound = number HW.buzzer.playSound(HW.Buzzer.ALARMTONES[number]) def __iter__(self): numberScreen = GetNumberScreen([i for i in range(len(HW.Buzzer.ALARMTONES))],\ startNumber=Settings.selectedSound,\ onStart=self.playAndSetSound,\ onNumberChange=self.playAndSetSound,\ onPicked=lambda _:Settings.save()) await numberScreen HW.buzzer.stop() class HumidityScreen(): def __iter__(self): HW.housingLEDs.fill((0,50,200)) numberScreen = ShowNumberScreen(HW.sensorBme.humidity,numberGetter=lambda : HW.sensorBme.humidity) await numberScreen class TemperatureScreen(): def __iter__(self): HW.housingLEDs.fill((0,50,200)) numberScreen = ShowNumberScreen(HW.sensorBme.temperature,numberGetter=lambda : HW.sensorBme.temperature) await numberScreen class ShowIpScreen(): def __init__(self): self.IP = "0" async def beepAndWaitIP(self,digitShown): HW.housingLEDs.fill(HW.HousingLEDs.WHITE) ipdigit = digitShown+self.IP[:digitShown].count(".") if (ipdigit >= len(self.IP) or self.IP[ipdigit] == "."): HW.buzzer.playSound(HW.Buzzer.BEEPBEEP) await asyncio.sleep_ms(1800) else: HW.buzzer.playSound(HW.Buzzer.BEEP) await asyncio.sleep_ms(1100) HW.housingLEDs.fill((0,0,0)) def __iter__(self): sta_if = network.WLAN(network.STA_IF) if sta_if.status() != network.STAT_GOT_IP: HW.housingLEDs.fill((255,0,0)) HW.buzzer.playSound(HW.Buzzer.BEEP) await asyncio.sleep_ms(1000) else: self.IP = sta_if.ifconfig()[0] showNumberScreen = ShowLongNumberScreen(number=[int(i) for i in self.IP.replace(".","")],onDigitShown=self.beepAndWaitIP) await showNumberScreen HW.housingLEDs.fill((0,0,0)) class ShowLongNumberScreen(): def __init__(self,number,onDigitShown): self.number = number self.digit_shown = 0 self.onDigitShown = onDigitShown self.running = False def onButtonReleased(self,pushDownTime): HW.leds[1].off() if pushDownTime > 700: self.running = False def __await__(self): self.running = True HW.buttons[1].setCallbacks(onPushUp=self.onButtonReleased,onPushDown=lambda :HW.leds[1].on()) HW.motorMinu.rotateTo(0) HW.motorHour.rotateTo(0) self.digit_shown = 0 await self.onDigitShown(self.digit_shown) while self.digit_shown < len(self.number): HW.motorMinu.rotateTo(-((self.number[self.digit_shown]%10)/12)) while self.running and (not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget()): await asyncio.sleep_ms(200) if not self.running: return self.digit_shown=self.digit_shown+1 await self.onDigitShown(self.digit_shown) HW.buttons[1].setCallbacks() __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 class ShowNumberScreen(): def __init__(self,number,numberGetter=None): self.number = number self.running = False self.update = numberGetter def onButtonReleased(self,pushDownTime): HW.leds[1].off() if pushDownTime > 700: self.running = False def __await__(self): self.running = True HW.buttons[1].setCallbacks(onPushUp=self.onButtonReleased,onPushDown=lambda :HW.leds[1].on()) while self.running: if self.update != None: self.number = self.update() while (not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget()): await asyncio.sleep_ms(200) HW.motorMinu.rotateTo(-((self.number%10)/12)) HW.motorrHou.rotateTo(-((self.number//10)/12)) await asyncio.sleep_ms(500) HW.buttons[1].setCallbacks() __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 class GetNumberScreen(): def __init__(self,acceptedInputNumbers,startNumber = None,onStart=None,onNumberChange = None,onPicked = None): self.acceptedInputNumbers = acceptedInputNumbers self.onStart = onStart self.onNumberChange = onNumberChange self.onPicked = onPicked self.running = False if startNumber: self.number = startNumber else: self.number = acceptedInputNumbers[0] def __await__(self): self.running = True for i,b in enumerate(HW.buttons): b.setCallbacks(onPushDown=lambda i=i:self.onButtonPressed(i),onPushUp=lambda pushDownTime,button=i:self.onButtonReleased(button,pushDownTime)) HW.motorMinu.rotateTo(-(self.number/12)) HW.motorHour.rotateTo(0) while not HW.motorHour.isAtTarget() or not HW.motorMinu.isAtTarget(): await asyncio.sleep_ms(200) if self.onStart: self.onStart(self.number) while self.running: await asyncio.sleep_ms(200) if self.onPicked: self.onPicked(self.number) return self.number __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 def onButtonPressed(self,button): HW.leds[button].on() def onButtonReleased(self,button,pushDownTime): HW.leds[button].off() if button == 1: if pushDownTime > 700: self.finish() return else: if pushDownTime < 500: self.number=self.acceptedInputNumbers[(self.acceptedInputNumbers.index(self.number) + (1 if button == 2 else -1)) % len(self.acceptedInputNumbers)] HW.motorMinu.rotateTo(-(self.number/12)) if self.onNumberChange: self.onNumberChange(self.number) def finish(self): self.running = False for b in HW.buttons: b.setCallbacks()#Clear Callbacks class Get2PositionsScreen(): def __init__(self,startTime = (0,0),onStart=None,onSelectedTimeChange = None,onPicked = None): self.onStart = onStart self.onSelectedTimeChange = onSelectedTimeChange self.onPicked = onPicked self.running = False self.pickedTime = startTime self.mode = 0 def __await__(self): self.running = True self.mode=0 # 0: Minutes, 1: Hours HW.motorMinu.rotateTo(-(self.pickedTime[1])/12) HW.motorHour.rotateTo(-(self.pickedTime[0])/12) for number,button in enumerate(HW.buttons): button.setCallbacks(\ onPushDown=lambda i=number:self.onButtonPressed(i),\ onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime)) # Wait for the Hands to move up while not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget(): await asyncio.sleep_ms(200) if self.onStart: self.onStart(self.pickedTime) while self.running: await asyncio.sleep_ms(200) if self.onPicked: self.onPicked(self.pickedTime) __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 def finish(self): self.running = False for b in HW.buttons: b.setCallbacks()#Clear Callbacks for l in HW.leds: l.off() l.setOffState() def onButtonPressed(self,button): HW.leds[button].on() if button != 1: if self.mode == 0: HW.motorMinu.rotateTo(direction=(1 if button == 0 else -1)) elif self.mode == 1: HW.motorHour.rotateTo(direction=(1 if button == 0 else -1)) def onButtonReleased(self,button,time): HW.leds[button].off() if button == 1: self.mode=(1+self.mode )% 2 if time > 700: self.finish() else: if self.mode == 0: HW.motorMinu.stop() else: HW.motorHour.stop() if self.onSelectedTimeChange: # TODO This is probably not save as its super unstable around the hour-increments minutes = (60-HW.motorMinu.getOrientation()*60) hours = (12-HW.motorMinu.getOrientation()*12) self.pickedTime = (hours,minutes) self.onSelectedTimeChange(self.pickedTime) class GetTimeScreen(): def __init__(self,startTime = (0,0),onStart=None,onSelectedTimeChange = None,onPicked = None,onShortMiddle = None): self.onShortMiddle = onShortMiddle self.onStart = onStart self.onSelectedTimeChange = onSelectedTimeChange self.onPicked = onPicked self.running = False self.pickedTime = (startTime[0]*60 + startTime[1])%(24*60) self.AM = (self.pickedTime < 12*60) self.direction = 0 def calcTupleTime(self): return (int(self.pickedTime/60)%24,self.pickedTime%60) def __await__(self): self.running = True HW.leds[1].setOffState(blinkRate=1.2) HW.housingLEDs.upper(HW.HousingLEDs.BLUE if self.AM else HW.HousingLEDs.YELLOW) for number,button in enumerate(HW.buttons): button.setCallbacks(\ onPushDown=lambda i=number:self.onButtonPressed(i),\ onPushUp=lambda pushDownTime,button=number:self.onButtonReleased(button,pushDownTime)) # Wait for the Hands to move up while not HW.motorMinu.isAtTarget() or not HW.motorHour.isAtTarget(): await asyncio.sleep_ms(200) if self.onStart: self.onStart(self.calcTupleTime()) while self.running: HW.motorMinu.rotateTo(-(self.pickedTime/60)) HW.motorHour.rotateTo(-(self.pickedTime/60/12)) # Color the Top LED to indikate AM or PM self.AM = (self.pickedTime < 12*60) HW.housingLEDs.upper(HW.HousingLEDs.BLUE if self.AM else HW.HousingLEDs.YELLOW) await asyncio.sleep_ms(100) self.pickedTime = (self.pickedTime+self.direction)%(24*60) if self.onSelectedTimeChange: self.onSelectedTimeChange(self.calcTupleTime()) if self.onPicked: self.onPicked(self.calcTupleTime()) __iter__ = __await__ # https://github.com/micropython/micropython/issues/2678 def finish(self): self.running = False for b in HW.buttons: b.setCallbacks()#Clear Callbacks for l in HW.leds: l.off() l.setOffState() def onButtonPressed(self,button): HW.leds[button].on() if button != 1: self.direction = (-1 if button == 0 else 1) def onButtonReleased(self,button,time): HW.leds[button].off() if button == 1: if time > 700: self.finish() else: if self.onShortMiddle != None: self.onShortMiddle() else: self.direction = 0