git.haldean.org bitpic / 2b9e1a1
multithreaded animation updates Haldean Brown 2 years ago
1 changed file(s) with 39 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
1414 import requests
1515 import screen
1616 from screen import Screen
17 import threading
1718 import time
19 import traceback
1820
1921
2022 class SerialError(Exception):
3436 def __init__(self):
3537 self._sid = None
3638 print("starting bitpic with screen ID {}".format(self.sid))
39 self.new_screen = None
3740 self.current_screen = None
3841 self.current_anim = None
3942 self.last_anim_check = None
153156 print("failed to load screen: {}".format(e))
154157 return None
155158
156 def loop(self):
157 time_check = (self.last_anim_check is None or
158 datetime.now() - self.last_anim_check > timedelta(seconds=30))
159 if time_check or self.current_anim is None:
160 new_screen = self.load()
161 if new_screen is not None:
162 self.current_anim = None
163 if new_screen != self.current_screen:
164 self.fade_between(self.current_screen, new_screen)
165 self.current_screen = new_screen
166 else:
167 # we write even if the screen hasn't changed so we can
168 # detect disconnected displays for reconnection
169 self.write_screen(self.current_screen)
170 time.sleep(5)
171 return
172 if self.current_anim is not None:
159 def load_loop(self):
160 self.new_screen = self.load()
161 if self.new_screen is not None:
162 self.current_anim is None
163
164 def anim_loop(self):
165 current_anim = self.current_anim
166 current_screen = self.current_screen
167 new_screen = self.new_screen
168
169 if current_anim is not None:
173170 # if we get here, we either didn't check for new data and are in an
174171 # animation, or we did check for new data and found out we're in an
175172 # animation.
176 anim_screen = self.current_anim.get_screen()
173 anim_screen = current_anim.get_screen()
177174 self.write_screen(anim_screen)
178 time.sleep(self.current_anim.desired_frame_time)
175 time.sleep(current_anim.desired_frame_time)
176 elif new_screen is not None:
177 if new_screen != current_screen:
178 self.fade_between(current_screen, new_screen)
179 self.current_screen = new_screen
180 else:
181 # we write even if the screen hasn't changed so we can
182 # detect disconnected displays for reconnection
183 self.write_screen(current_screen)
184 time.sleep(0.1)
185 else:
186 time.sleep(0.1)
179187
180188 def main(self):
189 def run_load_loop():
190 while True:
191 try:
192 self.load_loop()
193 except Exception:
194 traceback.print_exc()
195 time.sleep(5)
196
197 load_thread = threading.Thread(target=run_load_loop, daemon=True)
198 load_thread.start()
181199 try:
182200 while True:
183201 try:
184 self.loop()
202 self.anim_loop()
185203 except SerialError:
186204 self.create_driver()
187205 except KeyboardInterrupt:
188206 self.led.all_off()
189207 self.led.push_to_driver()
190208
209
191210 if __name__ == "__main__":
192211 bp = Bitpic()
193212 bp.main()