import sched import time from threading import Thread from multiprocessing import Queue from queue import Empty, Full import json import logging from redis import Redis from control.walle import WallE from control.audio import AudioSystem logging.basicConfig(level=logging.DEBUG) INTERVAL_TICK = 0.025 # 40/s sound_action_queue = Queue() class RedisConnection(Thread): def __init__(self): super(RedisConnection, self).__init__() self.keep_running = True self.dbcon = Redis() self.pubsub = self.dbcon.pubsub() self.pubsub.subscribe(['move', 'look', 'sound']) def run(self) -> None: while self.keep_running: item = self.pubsub.get_message() if not item: time.sleep(0.01) continue channel = item['channel'].decode() data = item['data'] if not isinstance(data, bytes): print(f"Channel {channel} got message that is not bytes {data}") continue try: self.handle_message(channel, data) except ValueError: pass # todo self.pubsub.close() def stop(self): self.keep_running = False def handle_message(self, channel: str, data: bytes): data_dict = json.loads(data.decode()) if channel == 'move': walle.set_movement(data_dict['angle'], data_dict['force']) elif channel == 'look': walle.set_eye_velocity(data_dict['angle'], data_dict['force']) elif channel == 'sound': try: sound_action_queue.put_nowait(data_dict) except Full: print(f'Queue was full, skipping sound') else: print(f'Unknown channel {channel}') def store_audio(self, sounds): self.dbcon.set('sound_data', json.dumps(sounds)) scheduler = sched.scheduler() audio = AudioSystem(scheduler, 'sounds.json') walle = WallE() walle.setup() def walle_tick(): scheduler.enter(INTERVAL_TICK, 3, walle_tick) walle.tick() while True: try: item = sound_action_queue.get_nowait() except Empty: break if item['action'] == 'play': audio.queue_sound(item['name']) scheduler.enter(INTERVAL_TICK, 3, walle_tick) audio.queue_sound('walle.boot') if __name__ == '__main__': redisdb = Redis() redis_connection = RedisConnection() redis_connection.store_audio([{'name': sound['name'], 'title': sound.get('title', sound['name'])} for sound in audio.sound_data['sounds']]) redis_connection.start() try: scheduler.run() except KeyboardInterrupt: redis_connection.stop() raise