diff --git a/barco_telnet/barco_telnet_control.py b/barco_telnet/barco_telnet_control.py new file mode 100644 index 0000000..534e484 --- /dev/null +++ b/barco_telnet/barco_telnet_control.py @@ -0,0 +1,72 @@ +import asyncio +import aiomqtt +import telnetlib3 + +cmdMap = { + 'POWER': 'POWR', + 'SHUTTER': 'PMUT', + 'FREEZE': 'FRZE' +} +reverseCmdMap = {v: k for k, v in cmdMap.items()} + +def parse_barco_response(raw: str): + raw = raw[1:-1] # strip square brackets + #print(raw) + if raw.startswith("ERR"): + return None # TODO parse type error - "disabled control" is special case + cmd, status = raw.split("!", maxsplit=2) + #print(cmd + " " + status) + cmd = reverseCmdMap[cmd] + status = 'ON' if status == '01' else 'OFF' + return cmd, status + + +async def barco_telnet_command(client, writer): + await client.subscribe("p1/projectors/main/#") + async with client.messages() as msgs: + async for mesg in msgs: + if mesg.topic.matches('p1/projectors/main/command/+'): + cmd = mesg.topic.value.split("/")[-1] + val = '1' if mesg.payload.decode() == 'ON' else '0' + barcoCmd = f"[{cmdMap[cmd]}{val}]" + print("Received: [" + mesg.topic.value + "] payload: [" + mesg.payload.decode() + "]") + print("Sending command to Barco: " + barcoCmd) + writer.write(barcoCmd) + + +async def barco_telnet_read_status(client, reader): + while True: + output = await reader.readuntil(b']') + raw_response: str = output.decode().strip() # strip not necessary? needed for local netcat testing though + print("Received: " + raw_response + " from Barco") + parsed = parse_barco_response(raw_response) + if parsed == None: + continue #TODO alert for errors + print(f"Updating topic [{parsed[0]}] with value [{parsed[1]}]") + await client.publish(f"p1/projectors/main/status/{parsed[0]}", payload=parsed[1]) + + +async def barco_telnet_query_status(writer): + while True: + for val in cmdMap.values(): + print(f"Querying Barco with: [{val}?]") + writer.write(f"[{val}?]" + '\r\n') # TODO test if funny CRLF necessary (it probably gets ignored) + await asyncio.sleep(1) # sleep between writes necessary, otherwise it gets confused. + # simultaneous commands from control could break this? TODO fix later + await asyncio.sleep(1000) # TODO find appropriate period + + +async def shell(reader, writer): + async with aiomqtt.Client('localhost', 1883) as client: + task_status_query = asyncio.create_task(barco_telnet_query_status(writer)) + task_status_reader = asyncio.create_task(barco_telnet_read_status(client, reader)) + task_control = asyncio.create_task(barco_telnet_command(client, writer)) + await asyncio.gather(task_status_query, task_status_reader, task_control) + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + #coro = telnetlib3.open_connection('192.168.192.12', 3023, shell=shell) + coro = telnetlib3.open_connection('localhost', 1234, shell=shell) + reader, writer = loop.run_until_complete(coro) + loop.run_until_complete(writer.protocol.waiter_closed)