vibrating_alarm_m5stickc.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. """
  2. tested on uiflow for stickc v1.8.1
  3. """
  4. # pylint: disable=import-error
  5. import json
  6. import m5ui
  7. import machine
  8. import micropython
  9. import utils
  10. from m5stack import axp, btnA, btnB, lcd
  11. _FONT = lcd.FONT_DejaVu40
  12. _DEFAULT_FONT_COLOR = lcd.WHITE
  13. _ALARM_TIME_PATH = "alarm.json"
  14. _SCREEN_WIDTH, _SCREEN_HEIGHT = lcd.winsize()
  15. class App:
  16. # pylint: disable=too-few-public-methods
  17. def __init__(self):
  18. self._rtc = None
  19. self._clock_text_box = None
  20. self._menu_position = 0
  21. self._alarm_hour = None
  22. self._alarm_minute = None
  23. self._alarm_hour_text_box = None
  24. self._alarm_minute_text_box = None
  25. def _load_alarm_time(self):
  26. with open(_ALARM_TIME_PATH, "r") as alarm_time_file:
  27. alarm_time = json.load(alarm_time_file)
  28. self._alarm_hour = alarm_time["hour"]
  29. self._alarm_minute = alarm_time["minute"]
  30. def _save_alarm_time(self):
  31. with open(_ALARM_TIME_PATH, "w") as alarm_time_file:
  32. json.dump(
  33. {"hour": self._alarm_hour, "minute": self._alarm_minute},
  34. alarm_time_file,
  35. )
  36. def _update_menu(self, event_arg: None):
  37. # pylint: disable=unused-argument; callback
  38. self._alarm_hour_text_box.setColor(
  39. lcd.GREEN
  40. if self._menu_position == 1
  41. else (lcd.RED if self._menu_position == 2 else _DEFAULT_FONT_COLOR)
  42. )
  43. self._alarm_minute_text_box.setColor(
  44. lcd.GREEN
  45. if self._menu_position == 3
  46. else (lcd.RED if self._menu_position == 4 else _DEFAULT_FONT_COLOR)
  47. )
  48. def _button_a_pressed(self):
  49. self._menu_position = (self._menu_position + 1) % 5
  50. # https://docs.micropython.org/en/latest/library/micropython.html#micropython.schedule
  51. micropython.schedule(self._update_menu, None)
  52. def _update_alarm_time(self, event_arg: None):
  53. # pylint: disable=unused-argument; callback
  54. self._alarm_hour_text_box.setText("{:02d}".format(self._alarm_hour))
  55. self._alarm_minute_text_box.setText("{:02d}".format(self._alarm_minute))
  56. self._save_alarm_time()
  57. def _button_b_pressed(self):
  58. if self._menu_position == 1:
  59. self._alarm_hour += 1
  60. elif self._menu_position == 2:
  61. self._alarm_hour -= 1
  62. elif self._menu_position == 3:
  63. self._alarm_minute += 1
  64. elif self._menu_position == 4:
  65. self._alarm_minute -= 1
  66. self._alarm_hour %= 24
  67. self._alarm_minute %= 60
  68. micropython.schedule(self._update_alarm_time, None)
  69. def _format_time(self) -> str:
  70. return "{:02d}:{:02d}".format(*self._rtc.datetime()[4:6])
  71. def _setup_clock(self):
  72. # > [contradictory to] official micropython documentation, to set RTC,
  73. # > use particular tuple (year , month, day, week=0, hour, minute, second, timestamp=0)
  74. # https://community.m5stack.com/topic/3108/m5stack-core2-micropython-rtc-example
  75. self._rtc = machine.RTC()
  76. # https://github.com/m5stack/UIFlow-Code/wiki/M5UI#textbox
  77. self._clock_text_box = m5ui.M5TextBox(
  78. _SCREEN_WIDTH - 1,
  79. 0,
  80. self._format_time(),
  81. _FONT,
  82. _DEFAULT_FONT_COLOR,
  83. rotate=90,
  84. )
  85. machine.Timer(0).init(
  86. period=10000, # ms
  87. mode=machine.Timer.PERIODIC,
  88. callback=lambda t: self._clock_text_box.setText(self._format_time()),
  89. )
  90. def run(self):
  91. m5ui.setScreenColor(0x000000) # clear screen
  92. print("battery:", axp.getBatVoltage(), "V")
  93. self._setup_clock()
  94. if not utils.exists(_ALARM_TIME_PATH):
  95. self._alarm_hour = self._alarm_minute = 0
  96. self._save_alarm_time()
  97. else:
  98. self._load_alarm_time()
  99. self._alarm_hour_text_box = m5ui.M5TextBox(
  100. _SCREEN_WIDTH // 2,
  101. 0,
  102. "{:02d}".format(self._alarm_hour),
  103. _FONT,
  104. _DEFAULT_FONT_COLOR,
  105. rotate=90,
  106. )
  107. m5ui.M5TextBox(
  108. _SCREEN_WIDTH // 2, 53, ":", _FONT, _DEFAULT_FONT_COLOR, rotate=90
  109. )
  110. self._alarm_minute_text_box = m5ui.M5TextBox(
  111. _SCREEN_WIDTH // 2,
  112. 66,
  113. "{:02d}".format(self._alarm_minute),
  114. _FONT,
  115. _DEFAULT_FONT_COLOR,
  116. rotate=90,
  117. )
  118. btnA.wasPressed(self._button_a_pressed)
  119. btnB.wasPressed(self._button_b_pressed)
  120. App().run()
  121. # TODO https://docs.micropython.org/en/latest/library/machine.WDT.html#machine-wdt
  122. # TODO https://docs.micropython.org/en/latest/esp8266/tutorial/powerctrl.html#deep-sleep-mode