predavalnice-kontroler/barco_telnet/barco_telnet_control.py

114 lines
No EOL
4.8 KiB
Python

import asyncio
import socket
import aiomqtt
import telnetlib3
import toml
from socket import gethostname
mainBarcoIP = '192.168.192.12'
sideBarcoIP = '192.168.192.13'
# TODO all the checks and stuff
# TODO MAKE THIS CONFIGURALBE
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 which shouldnt normally happen
cmd, status = raw.split("!", maxsplit=2)
#print(cmd + " " + status)
cmd = reverseCmdMap[cmd]
status = '1' if status == '01' else '0'
return cmd, status
async def barco_telnet_command(client, writer, select: str):
onSub = f"p1/projektorji/{select}/#"
print('TEST', onSub)
onMatch = f"p1/projektorji/{select}/ukaz/+"
await client.subscribe(onSub)
async with client.messages() as msgs:
async for mesg in msgs:
# print(mesg.topic.value)
# print(mesg.payload.decode())
# print('on', select)
if mesg.topic.matches(onMatch):
# print("test")
cmd = mesg.topic.value.split("/")[-1]
#val = '1' if mesg.payload.decode() == 'ON' else '0'
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, select: str):
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 (" + select + ')')
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/projektorji/{select}/status/{parsed[0]}", payload=parsed[1])
async def barco_telnet_query_status(writer, select: str):
while True:
for val in cmdMap.values():
print(f"Querying Barco {select} 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(10) # 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)
async def main():
#conf = toml.load('config.toml')
#mainBarcoIP = conf[gethostname()]['projektor_glavni']
#sideBarcoIP = conf[gethostname()]['projektor_stranski']
mainReader, mainWriter = await telnetlib3.open_connection(mainBarcoIP, 3023)
sideReader, sideWriter = await telnetlib3.open_connection(sideBarcoIP, 3023)
async with aiomqtt.Client('localhost', 1883) as client:
task_status_query_main = asyncio.create_task(barco_telnet_query_status(mainWriter, 'glavni'))
task_status_reader_main = asyncio.create_task(barco_telnet_read_status(client, mainReader, 'glavni'))
task_control_main = asyncio.create_task(barco_telnet_command(client, mainWriter, 'glavni'))
task_status_query_side = asyncio.create_task(barco_telnet_query_status(sideWriter, 'stranski'))
task_status_reader_side = asyncio.create_task(barco_telnet_read_status(client, sideReader, 'stranski'))
task_control_side = asyncio.create_task(barco_telnet_command(client, sideWriter, 'stranski'))
await asyncio.gather(task_status_query_main, task_status_reader_main, task_control_main,
task_status_query_side, task_status_reader_side, task_control_side)
### fuj to, ne tk delat
# 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)
asyncio.run(main())