Files
WallE/tickworker.py

100 lines
2.7 KiB
Python

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