import asyncio
from collections.abc import Callable, Iterable, Sequence
from typing import Optional
from urllib import parse
import aioftp
import websockets
from websockets.asyncio.client import ClientConnection
from logger import spr
import norsonic_fetcher
MSG_OUT_NEW = "NewMeasurement"
MSG_OUT_START = "StartMeasurement"
KEY_STATE = 'State'
KEY_FILENAME = 'GraphHeader'
VAL_STATE_NEW = ''
VAL_STATE_RECORDING = ""
VAL_STATE_WAITING = ""
VAL_STATE_DONE = ""
def parse_msg(msg: str) -> dict[str, str]:
ret = {}
for l in msg.splitlines():
# print(f'par "{l}"')
if len(l) == 0:
continue
if l == 'clear':
break
if ':' not in l:
print(f'W: Unexpected line in message: {l}')
continue
k, v = l.split(':', 1)
if k in ret:
if ret[k] == v:
continue
if len(v) == 0:
continue
print(f'W: Duplicate key detected ({k}: {v})')
raise RuntimeError()
ret[k] = v
return ret
class NSWSConnection:
# def __init__(self, ws: Web)
...
async def recv_msg(sock: ClientConnection) -> dict[str, str]:
recv = await sock.recv()
if not isinstance(recv, str):
raise RuntimeError('Invalid message received')
msg = parse_msg(recv)
return msg
async def wait_for_state(sock: ClientConnection, state: str, expected_states: Iterable[str] = []) -> dict[str, str]:
while True:
msg = await recv_msg(sock)
# spr(msg)
if KEY_STATE in msg:
if msg[KEY_STATE] == state:
return msg
elif msg[KEY_STATE] not in expected_states:
spr(f'W: Unexpected state received: {msg[KEY_STATE]}')
async def record(sock: ClientConnection, start_callback: Optional[Callable[[], None]] = None):
await sock.send(MSG_OUT_NEW)
spr('Initializing measurement')
await wait_for_state(sock, VAL_STATE_NEW, (VAL_STATE_DONE, ))
await sock.send(MSG_OUT_START)
spr('Starting measurement')
await wait_for_state(sock, VAL_STATE_WAITING, (VAL_STATE_NEW, ))
spr('Waiting for start')
await wait_for_state(sock, VAL_STATE_RECORDING)
if start_callback is not None:
start_callback()
spr('Waiting for finish')
msg = await wait_for_state(sock, VAL_STATE_DONE)
return msg[KEY_FILENAME]
async def open_connection(address: str) -> ClientConnection:
return await websockets.connect(f'ws://{address}/live', ping_interval=None)
# async def main():
# sock = await websockets.connect('ws://10.145.1.1/live')
# spr('Connected to server')
# name = await record(sock)
# spr(f'finished {name}')
# c = aioftp.Client(parse_list_line_custom=norsonic_fetcher.ftp_parse_line)
# res = await c.connect('10.145.1.1')
# res = await c.login('AAAA', '1234')
# global x
# # x = norsonic_fetcher.parse_report(await norsonic_fetcher.ftp_fetch(c, norsonic_fetcher.recording_path(name)))
# x = norsonic_fetcher.parse_report(await norsonic_fetcher.ftp_fetch(c, norsonic_fetcher.FNAME))
# print(x)