Narete stvari da delajo
This commit is contained in:
parent
64a10b0512
commit
29b2beca5a
45 changed files with 809 additions and 1600 deletions
|
@ -1,114 +1,122 @@
|
|||
import asyncio
|
||||
import socket
|
||||
from collections import defaultdict
|
||||
import aiomqtt
|
||||
import telnetlib3
|
||||
import toml
|
||||
import sys
|
||||
import sys
|
||||
import os
|
||||
|
||||
#GLOBALS
|
||||
#GLOBALS
|
||||
|
||||
room: str
|
||||
barcoPosition: str
|
||||
barcoIP: str
|
||||
telnetPort: int
|
||||
mqttPort: int
|
||||
mqttIP: str
|
||||
barcoReached: bool
|
||||
|
||||
lastState = defaultdict(lambda: None)
|
||||
|
||||
cmdMap = {
|
||||
'power': 'POWR',
|
||||
'shutter': 'PMUT',
|
||||
'freeze': 'FRZE'
|
||||
'freeze': 'FRZE',
|
||||
#'test_pattern': 'TPRN',
|
||||
}
|
||||
reverseCmdMap = {v: k for k, v in cmdMap.items()}
|
||||
|
||||
# There needs to be a minimum time between writes. Since we have two "threads", we use a lock and a sleep in barco_send() to enforce it
|
||||
lock = asyncio.Lock()
|
||||
|
||||
def parse_barco_response(raw: str):
|
||||
global room, barcoPosition, barcoReached
|
||||
raw = raw[1:-1] # strip square brackets
|
||||
#print(raw)
|
||||
|
||||
if raw.startswith("ERR"):
|
||||
print("Projector" + room + " " + barcoPosition + " returned" + raw)
|
||||
print("ERROR:", raw)
|
||||
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'
|
||||
status = int(status)
|
||||
|
||||
barcoReached = True
|
||||
return cmd, status
|
||||
|
||||
|
||||
async def barco_telnet_command(client, writer, select: str):
|
||||
global room
|
||||
onSub = f"{room}/projectors/{select}/#"
|
||||
#print('TEST', onSub)
|
||||
onMatch = f"{room}/projectors/{select}/command/+" #TODO should be set?
|
||||
await client.subscribe(onSub)
|
||||
#async with client.messages as msgs:
|
||||
async for mesg in client.messages:
|
||||
# print(mesg.topic.value)
|
||||
# print(mesg.payload.decode())
|
||||
# print('on', select)
|
||||
async def barco_send(writer, value):
|
||||
async with lock:
|
||||
writer.write(value + '\r\n')
|
||||
print("Writing", value)
|
||||
await asyncio.sleep(0.2) # sleep between writes necessary, otherwise it gets confused.
|
||||
|
||||
async def barco_telnet_command(client, writer, select: str):
|
||||
"""Receive commands from MQTT and send them to the projector"""
|
||||
await client.subscribe(f"{room}/projectors/{select}/#")
|
||||
|
||||
async for mesg in client.messages:
|
||||
|
||||
if mesg.topic.matches(f"{room}/projectors/{select}/set/+"):
|
||||
cmd = mesg.topic.value.rsplit("/", maxsplit=1)[-1]
|
||||
val = mesg.payload.decode()
|
||||
|
||||
if val not in ("0", "1") or cmd not in cmdMap:
|
||||
print("INVALID COMMAND OR VALUE:", cmd, val)
|
||||
continue
|
||||
|
||||
barcoCmd = cmdMap[cmd]
|
||||
# Send command to projector
|
||||
await barco_send(writer, f"[{barcoCmd}{val}]")
|
||||
# Immediately ask for a status
|
||||
await barco_send(writer, f"[{barcoCmd}?]")
|
||||
|
||||
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() == '1' else '0' # refactor to direct 0 and 1
|
||||
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):
|
||||
global room
|
||||
"""Read status reports (we trigger them in the polling task as well as whenver sending a command)"""
|
||||
while True:
|
||||
output = await reader.readuntil(b']')
|
||||
raw_response: str = output.decode().strip() # strip not necessary? needed for local netcat testing though
|
||||
raw_response: str = output.decode()
|
||||
print("Received: " + raw_response + " from Barco (" + select + ')')
|
||||
parsed = parse_barco_response(raw_response)
|
||||
if parsed is None:
|
||||
continue #TODO alert for errors
|
||||
print(f"Updating topic [{parsed[0]}] with value [{parsed[1]}]")
|
||||
await client.publish(f"{room}/projectors/{select}/status/{parsed[0]}", payload=parsed[1])
|
||||
|
||||
try:
|
||||
key, val = parse_barco_response(raw_response)
|
||||
except:
|
||||
print("NOT PARSED:", raw_response)
|
||||
continue
|
||||
|
||||
await client.publish(f"{room}/projectors/{select}/status/{key}", payload=val)
|
||||
|
||||
|
||||
async def barco_telnet_query_status(writer, select: str):
|
||||
"""Periodically ask the projector for its status"""
|
||||
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(0.2) # 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
|
||||
# Most queries only work when turned on, so if we're not sure, only query power
|
||||
if lastState[cmdMap["power"]] == "01":
|
||||
queries = cmdMap.values()
|
||||
else:
|
||||
queries = [cmdMap["power"]]
|
||||
|
||||
for val in queries:
|
||||
await barco_send(writer, f"[{val}?]")
|
||||
|
||||
# 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)
|
||||
await asyncio.sleep(2) # TODO find appropriate period
|
||||
|
||||
|
||||
async def main():
|
||||
global room, barcoReached
|
||||
global barcoPosition, barcoIP, telnetPort, mqttIP, mqttPort
|
||||
global room, barcoReached, barcoPosition
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit("No position provided")
|
||||
else:
|
||||
barcoPosition = sys.argv[1]
|
||||
|
||||
conf = toml.load('./malinaConfig.toml')
|
||||
config_file = os.getenv('MM_CONFIG_PATH', './malinaConfig.toml')
|
||||
conf = toml.load(config_file)
|
||||
room = conf['global']['room']
|
||||
mqttHost = conf['global']['mqttHost']
|
||||
mqttPort = conf['global']['mqttPort']
|
||||
|
||||
g62Barcos = {k: v for k,v in conf["barco_G62"].items()}
|
||||
currentBarco = g62Barcos[barcoPosition]
|
||||
barcoIP = currentBarco['ip']
|
||||
telnetPort = int(currentBarco["port"])
|
||||
|
||||
room = conf["global"]["room"]
|
||||
mqttPort = int(conf["global"]["mqttPort"])
|
||||
mqttIP = conf["global"]["mqttIp"]
|
||||
barcoReached = False
|
||||
try:
|
||||
barcoReader, barcoWriter = await telnetlib3.open_connection(barcoIP, telnetPort)
|
||||
|
@ -116,8 +124,8 @@ async def main():
|
|||
except Exception as e:
|
||||
print("Connection failed: " + barcoIP + ": " + str(e))
|
||||
barcoReached = False
|
||||
finally:
|
||||
async with aiomqtt.Client(mqttIP, mqttPort) as client:
|
||||
else:
|
||||
async with aiomqtt.Client(mqttHost, mqttPort) as client:
|
||||
task_status_query_barco = asyncio.create_task(barco_telnet_query_status(barcoWriter, barcoPosition))
|
||||
task_status_reader_barco = asyncio.create_task(barco_telnet_read_status(client, barcoReader, barcoPosition))
|
||||
task_control_barco = asyncio.create_task(barco_telnet_command(client, barcoWriter, barcoPosition))
|
||||
|
@ -125,18 +133,6 @@ async def main():
|
|||
await asyncio.gather(task_status_query_barco, task_status_reader_barco, task_control_barco)
|
||||
await client.publish(f"{room}/projectors/{barcoPosition}/error", payload=("UNREACHABLE" if not barcoReached else "OK"))
|
||||
|
||||
### fuj to, ne tk delat
|
||||
|
||||
# if __name__ == '__main__':
|
||||
|
||||
# loop = asyncio.get_event_loop()
|
||||
# coro = telnetlib3.open_connection(mainBarcoIP, 3023, shell=shell)
|
||||
# coro = telnetlib3.open_connection(mainBarcoIP, 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)
|
||||
|
||||
#mqttIP = sys.argv[1]
|
||||
#barcoIP = sys.argv[2]
|
||||
|
||||
asyncio.run(main())
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue