feat: better typing
fix: emulator split admin message
This commit is contained in:
parent
457790362a
commit
9094ba0cb3
|
@ -26,6 +26,7 @@ services:
|
||||||
- REDIS_PORT=$REDIS_PORT
|
- REDIS_PORT=$REDIS_PORT
|
||||||
- RTMP_HOST=$RTMP_HOST
|
- RTMP_HOST=$RTMP_HOST
|
||||||
- RTMP_PORT=$RTMP_PORT
|
- RTMP_PORT=$RTMP_PORT
|
||||||
|
- EMULATOR_RAND_RATE=0.2
|
||||||
depends_on:
|
depends_on:
|
||||||
- rtmp
|
- rtmp
|
||||||
- redis
|
- redis
|
||||||
|
|
|
@ -39,7 +39,11 @@ screen: mgba.image.Image = mgba.image.Image(EMULATOR_WIDTH, EMULATOR_HEIGHT)
|
||||||
core.set_video_buffer(screen)
|
core.set_video_buffer(screen)
|
||||||
core.reset()
|
core.reset()
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(name)s %(levelname)-8s %(message)s", datefmt="(%F %T)")
|
||||||
|
|
||||||
|
# disable all loggers from different files
|
||||||
|
logging.getLogger("asyncio").setLevel(logging.ERROR)
|
||||||
|
logging.getLogger("asyncio.coroutines").setLevel(logging.ERROR)
|
||||||
mgba.log.silence()
|
mgba.log.silence()
|
||||||
|
|
||||||
r: redis.Redis = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
|
r: redis.Redis = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
|
||||||
|
@ -82,7 +86,7 @@ stream = Popen(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def next_action(core: mgba.core.Core):
|
def next_action(core: mgba.core.Core) -> None:
|
||||||
"""Select the next key from the redis database.
|
"""Select the next key from the redis database.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -98,7 +102,7 @@ def next_action(core: mgba.core.Core):
|
||||||
core.clear_keys(*KEYS_MGBA)
|
core.clear_keys(*KEYS_MGBA)
|
||||||
|
|
||||||
|
|
||||||
def state_manager(loop: asyncio.AbstractEventLoop):
|
def state_manager(loop: asyncio.AbstractEventLoop) -> None:
|
||||||
"""Subscribe and respond to messages received from redis.
|
"""Subscribe and respond to messages received from redis.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -110,16 +114,16 @@ def state_manager(loop: asyncio.AbstractEventLoop):
|
||||||
while True:
|
while True:
|
||||||
for message in ps.listen():
|
for message in ps.listen():
|
||||||
if message["type"] == "message":
|
if message["type"] == "message":
|
||||||
match message["data"].decode("utf-8").split(":"):
|
match message["data"].decode("utf-8").split(":", 1):
|
||||||
case ["save"]:
|
case ["save"]:
|
||||||
asyncio.ensure_future(utils.save(core), loop=loop)
|
asyncio.ensure_future(utils.save(core), loop=loop)
|
||||||
case ["load", filename]:
|
case ["load", filename]:
|
||||||
asyncio.ensure_future(utils.load(core, filename), loop=loop)
|
asyncio.ensure_future(utils.load(core, filename), loop=loop)
|
||||||
case _:
|
case _:
|
||||||
print(f"Command not understood: {message}")
|
logging.debug(f"Command not understood: {message}")
|
||||||
|
|
||||||
|
|
||||||
async def emulator():
|
async def emulator() -> None:
|
||||||
"""Start the main loop responsible for handling inputs and sending images to ffmpeg."""
|
"""Start the main loop responsible for handling inputs and sending images to ffmpeg."""
|
||||||
while True:
|
while True:
|
||||||
last_frame_t = time.time()
|
last_frame_t = time.time()
|
||||||
|
@ -141,8 +145,9 @@ async def emulator():
|
||||||
await asyncio.sleep(sleep_t)
|
await asyncio.sleep(sleep_t)
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main() -> None:
|
||||||
"""Start the emulator."""
|
"""Start the emulator."""
|
||||||
|
logging.debug("Emulator started !")
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
# setup states in redis
|
# setup states in redis
|
||||||
|
|
|
@ -30,7 +30,7 @@ logging.getLogger("websockets.server").setLevel(logging.ERROR)
|
||||||
logging.getLogger("websockets.protocol").setLevel(logging.ERROR)
|
logging.getLogger("websockets.protocol").setLevel(logging.ERROR)
|
||||||
|
|
||||||
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
|
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, db=0)
|
||||||
r.mset(KEYS_RESET)
|
r.mset(KEYS_RESET) # type: ignore
|
||||||
|
|
||||||
USERS: Users = Users()
|
USERS: Users = Users()
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ async def parse_message(user: User, message: websockets.typing.Data) -> None:
|
||||||
logging.error(f"unsupported action: {message!r} from {user}")
|
logging.error(f"unsupported action: {message!r} from {user}")
|
||||||
|
|
||||||
|
|
||||||
async def handler(websocket: websockets.server.WebSocketServerProtocol, path: str):
|
async def handler(websocket: websockets.server.WebSocketServerProtocol, path: str) -> None:
|
||||||
"""Handle the messages sent by a user.
|
"""Handle the messages sent by a user.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -75,7 +75,7 @@ async def handler(websocket: websockets.server.WebSocketServerProtocol, path: st
|
||||||
USERS.unregister(user)
|
USERS.unregister(user)
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main() -> None:
|
||||||
"""Start the websocket server."""
|
"""Start the websocket server."""
|
||||||
logging.debug("Server started !")
|
logging.debug("Server started !")
|
||||||
async with websockets.serve(handler, WEBSOCKET_SERVE, WEBSOCKET_PORT): # nosec
|
async with websockets.serve(handler, WEBSOCKET_SERVE, WEBSOCKET_PORT): # nosec
|
||||||
|
|
10
src/utils.py
10
src/utils.py
|
@ -24,7 +24,7 @@ class User:
|
||||||
self.websocket = websocket
|
self.websocket = websocket
|
||||||
self.last_message = time.time()
|
self.last_message = time.time()
|
||||||
|
|
||||||
async def send(self, data: str):
|
async def send(self, data: str) -> None:
|
||||||
"""Send data through the user's websocket.
|
"""Send data through the user's websocket.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -45,7 +45,7 @@ class User:
|
||||||
class Users(set):
|
class Users(set):
|
||||||
"""Store `User`s connected to the server."""
|
"""Store `User`s connected to the server."""
|
||||||
|
|
||||||
def register(self, user: User):
|
def register(self, user: User) -> None:
|
||||||
"""Register a user in the set.
|
"""Register a user in the set.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -54,7 +54,7 @@ class Users(set):
|
||||||
self.add(user)
|
self.add(user)
|
||||||
logging.debug(f"user registered: {user}")
|
logging.debug(f"user registered: {user}")
|
||||||
|
|
||||||
def unregister(self, user: User):
|
def unregister(self, user: User) -> None:
|
||||||
"""Unregister a user in the set.
|
"""Unregister a user in the set.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -64,7 +64,7 @@ class Users(set):
|
||||||
logging.debug(f"user unregistered: {user}")
|
logging.debug(f"user unregistered: {user}")
|
||||||
|
|
||||||
|
|
||||||
async def save(core: mgba.core.Core):
|
async def save(core: mgba.core.Core) -> None:
|
||||||
state = core.save_raw_state()
|
state = core.save_raw_state()
|
||||||
current_time = time.strftime("%Y-%m-%dT%H:%M:%S")
|
current_time = time.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
with open(f"states/{current_time}.state", "wb") as state_file:
|
with open(f"states/{current_time}.state", "wb") as state_file:
|
||||||
|
@ -73,7 +73,7 @@ async def save(core: mgba.core.Core):
|
||||||
logging.debug(f"state saved : {current_time}.state")
|
logging.debug(f"state saved : {current_time}.state")
|
||||||
|
|
||||||
|
|
||||||
async def load(core: mgba.core.Core, filename: str):
|
async def load(core: mgba.core.Core, filename: str) -> None:
|
||||||
state = ffi.new("unsigned char[397312]") # pulled 397312 straight from my ass, TODO: check mGBA sources ?
|
state = ffi.new("unsigned char[397312]") # pulled 397312 straight from my ass, TODO: check mGBA sources ?
|
||||||
with open(f"states/{filename}.state", "rb") as state_file:
|
with open(f"states/{filename}.state", "rb") as state_file:
|
||||||
for i in range(len(state)):
|
for i in range(len(state)):
|
||||||
|
|
Loading…
Reference in a new issue