stepper-clock/Screens.py
2020-03-27 19:06:36 +01:00

358 lines
14 KiB
Python

import StepperClock
import uasyncio as asyncio
import Buzzer
import Settings
import Hardware as HW
import math
import network
import time
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 = StepperClock.StepperClock()
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.stepperminu.rotateTo(0)
HW.stepperhour.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.stepperhour.reset() # Set the new Zero
HW.stepperminu.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 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 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 = ShowNumberScreen(number=[int(i) for i in self.IP.replace(".","")],onDigitShown=self.beepAndWaitIP)
await showNumberScreen
HW.housingLEDs.fill((0,0,0))
class ShowNumberScreen():
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.stepperminu.rotateTo(0)
HW.stepperhour.rotateTo(0)
self.digit_shown = 0
await self.onDigitShown(self.digit_shown)
while self.digit_shown < len(self.number):
HW.stepperminu.rotateTo(-((self.number[self.digit_shown]%10)/12))
while self.running and (not HW.stepperminu.isAtTarget() or not HW.stepperhour.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 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.stepperminu.rotateTo(-(self.number/12))
HW.stepperhour.rotateTo(0)
while not HW.stepperhour.isAtTarget() or not HW.stepperminu.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.stepperminu.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.stepperminu.rotateTo(-(self.pickedTime[1])/12)
HW.stepperhour.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.stepperhour.isAtTarget() or not HW.stepperminu.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.stepperminu.rotateTo(direction=(1 if button == 0 else -1))
elif self.mode == 1:
HW.stepperhour.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.stepperminu.stop()
else:
HW.stepperhour.stop()
if self.onSelectedTimeChange:
# TODO This is probably not save as its super unstable around the hour-increments
minutes = (60-HW.stepperminu.getOrientation()*60)
hours = (12-HW.stepperminu.getOrientation()*12)
self.pickedTime = (hours,minutes)
self.onSelectedTimeChange(self.pickedTime)
class GetTimeScreen():
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[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.stepperhour.isAtTarget() or not HW.stepperminu.isAtTarget():
await asyncio.sleep_ms(200)
if self.onStart:
self.onStart(self.calcTupleTime())
while self.running:
HW.stepperminu.rotateTo(-(self.pickedTime/60))
HW.stepperhour.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:
self.direction = 0