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)