reworked and fixed tse controller to work with new layout, fixed random bugs in barco code -- note: due to testing, some actions are commented out, uncomment those for actual deployment

This commit is contained in:
0xEmm 2024-12-05 22:28:11 +01:00
parent 1984db16bf
commit d42b296bae
3 changed files with 94 additions and 88 deletions

View file

@ -5,7 +5,7 @@ import telnetlib3
import toml import toml
from socket import gethostname from socket import gethostname
mainBarcoIP = '192.168.192.12' mainBarcoIP = 'localhost' #'192.168.192.12'
sideBarcoIP = '192.168.192.13' sideBarcoIP = '192.168.192.13'
# TODO all the checks and stuff # TODO all the checks and stuff
@ -32,25 +32,25 @@ def parse_barco_response(raw: str):
async def barco_telnet_command(client, writer, select: str): async def barco_telnet_command(client, writer, select: str):
onSub = f"p1/projectors/{select}/#" onSub = f"p01/projectors/{select}/#"
#print('TEST', onSub) #print('TEST', onSub)
onMatch = f"p1/projectors/{select}/command/+" onMatch = f"p01/projectors/{select}/command/+"
await client.subscribe(onSub) await client.subscribe(onSub)
async with client.messages() as msgs: #async with client.messages as msgs:
async for mesg in msgs: async for mesg in client.messages:
# print(mesg.topic.value) # print(mesg.topic.value)
# print(mesg.payload.decode()) # print(mesg.payload.decode())
# print('on', select) # print('on', select)
if mesg.topic.matches(onMatch): if mesg.topic.matches(onMatch):
# print("test") # print("test")
cmd = mesg.topic.value.split("/")[-1] cmd = mesg.topic.value.split("/")[-1]
#val = '1' if mesg.payload.decode() == 'ON' else '0' #val = '1' if mesg.payload.decode() == 'ON' else '0'
val = '1' if mesg.payload.decode() == 'ON' else '0' # refactor to direct 0 and 1 val = '1' if mesg.payload.decode() == '1' else '0' # refactor to direct 0 and 1
barcoCmd = f"[{cmdMap[cmd]}{val}]" barcoCmd = f"[{cmdMap[cmd]}{val}]"
print("Received: [" + mesg.topic.value + "] payload: [" + mesg.payload.decode() + "]") print("Received: [" + mesg.topic.value + "] payload: [" + mesg.payload.decode() + "]")
print("Sending command to Barco: " + barcoCmd) print("Sending command to Barco: " + barcoCmd)
writer.write(barcoCmd) writer.write(barcoCmd)
async def barco_telnet_read_status(client, reader, select: str): async def barco_telnet_read_status(client, reader, select: str):
@ -62,7 +62,7 @@ async def barco_telnet_read_status(client, reader, select: str):
if parsed == None: if parsed == None:
continue #TODO alert for errors continue #TODO alert for errors
print(f"Updating topic [{parsed[0]}] with value [{parsed[1]}]") print(f"Updating topic [{parsed[0]}] with value [{parsed[1]}]")
await client.publish(f"p1/projectors/{select}/status/{parsed[0]}", payload=parsed[1]) await client.publish(f"p01/projectors/{select}/status/{parsed[0]}", payload=parsed[1])
async def barco_telnet_query_status(writer, select: str): async def barco_telnet_query_status(writer, select: str):
@ -88,17 +88,17 @@ async def main():
#mainBarcoIP = conf[gethostname()]['projektor_glavni'] #mainBarcoIP = conf[gethostname()]['projektor_glavni']
#sideBarcoIP = conf[gethostname()]['projektor_stranski'] #sideBarcoIP = conf[gethostname()]['projektor_stranski']
mainReader, mainWriter = await telnetlib3.open_connection(mainBarcoIP, 3023) mainReader, mainWriter = await telnetlib3.open_connection(mainBarcoIP, 3023)
sideReader, sideWriter = await telnetlib3.open_connection(sideBarcoIP, 3023) #sideReader, sideWriter = await telnetlib3.open_connection(sideBarcoIP, 3023)
async with aiomqtt.Client('localhost', 1883) as client: async with aiomqtt.Client('localhost', 1883) as client:
task_status_query_main = asyncio.create_task(barco_telnet_query_status(mainWriter, 'glavni')) 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_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_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_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_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')) #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, 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) #task_status_query_side, task_status_reader_side, task_control_side)
### fuj to, ne tk delat ### fuj to, ne tk delat

View file

@ -92,9 +92,9 @@ const platnoStatus = ref(platnoState.UNKNOWN)
<!-- TODO lepš --> <!-- TODO lepš -->
<h4>platna {{ props.position }}</h4> <h4>platna {{ props.position }}</h4>
<button <button
@click="publishMQTTMsg(publishPrefix + 'go', 'UP')"><UpIcon/></button> @click="publishMQTTMsg(publishPrefix + 'goto', 'UP')"><UpIcon/></button>
<button <button
@click="publishMQTTMsg(publishPrefix + 'go', 'DOWN')"><DownIcon/></button> @click="publishMQTTMsg(publishPrefix + 'goto', 'DOWN')"><DownIcon/></button>
<div> <div>
<h5>Manual control</h5> <h5>Manual control</h5>
<button <button

View file

@ -5,15 +5,15 @@ import aiomqtt
from tse_serial_interpreter import * from tse_serial_interpreter import *
from dataclasses import dataclass from dataclasses import dataclass
room = 'p1' #TODO make be do get fronm file of configuration room = 'p01' #TODO make be do get fronm file of configuration
aser: aioserial.AioSerial = aioserial.AioSerial( # aser: aioserial.AioSerial = aioserial.AioSerial(
port='/dev/cu.usbserial-14240', #TODO not hardcode it # port='/dev/cu.usbserial-14240', #TODO not hardcode it
baudrate=1200, # baudrate=1200,
parity=serial.PARITY_NONE, # parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS, # bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE # stopbits=serial.STOPBITS_ONE
) # )
# TODO adjust serial on actual TSE interface # TODO adjust serial on actual TSE interface
#TODO get this from file da ni hardcoded #TODO get this from file da ni hardcoded
@ -44,16 +44,11 @@ shades_mapping = {
# TODO simple reverse lookup za ko kripa pove kaj # TODO simple reverse lookup za ko kripa pove kaj
def parse_topic_from_mqtt(topic: str):
topicArr = topic.split()
async def task_status2mqtt(statusClient: aiomqtt.Client): async def task_status2mqtt(statusClient: aiomqtt.Client):
while True: while True:
data = await aser.read_until_async() #data = await aser.read_until_async()
data = data.decode(errors='ignore').strip() #data = data.decode(errors='ignore').strip()
print("TSE box sent: " + data) #print("TSE box sent: " + data)
#relState = resp_to_relay_state(data) #relState = resp_to_relay_state(data)
#command = reverse_lookup[relState.relay_id] #command = reverse_lookup[relState.relay_id]
#action = relState.state #action = relState.state
@ -70,62 +65,64 @@ async def task_status2mqtt(statusClient: aiomqtt.Client):
await asyncio.sleep(0.01) await asyncio.sleep(0.01)
async def executeAndPublish(topicVal, mqttClient, pubTopic, pubPayload, relStat): async def executeAndPublish(mqttClient, pubTopic, pubPayload, relStat):
setRelayCmd = relay_state_to_cmd(relStat) setRelayCmd = relay_state_to_cmd(relStat)
print("Received: [" + topicVal + "] payload: [" + pubPayload + "]") #print("Received: [" + topicVal + "] payload: [" + pubPayload + "]")
print("Sending to TSE box: " + setRelayCmd) print("Sending to TSE box: " + setRelayCmd)
print(f"Also publishing topic [{pubTopic}] with status [{pubPayload}]") print(f"Also publishing topic [{pubTopic}] with status [{pubPayload}]")
print()
#await aser.write_async(bytes(setRelayCmd + '\r\n', "ascii")) #await aser.write_async(bytes(setRelayCmd + '\r\n', "ascii"))
await mqttClient.publish(pubTopic, payload=pubPayload) await mqttClient.publish(pubTopic, payload=pubPayload)
async def handleTsePower(tval, client, sysSelect, cmd): async def handleTsePower(client, sysSelect, cmd):
rel = RelayState(mapping_toggles[sysSelect], cmd == '1') rel = RelayState(mapping_toggles[sysSelect], cmd == '1')
await executeAndPublish(tval, client, f'{room}/power/{sysSelect}/status', cmd, rel) await executeAndPublish(client, f'{room}/power/{sysSelect}/platno/status', cmd, rel)
async def handleTseSencilo(tval, client, cmd): async def handleTseSencilo(client, cmd):
#relName = tval.split('/')[3] #relName = tval.split('/')[3]
topicPub = f'{room}/firanki/status' topicPub = f'{room}/firanki/status'
if cmd == "MOVE_UP": if cmd == "MOVE_UP":
rel = RelayState(shades_mapping['gor'], True) rel = RelayState(shades_mapping['gor'], True)
await executeAndPublish(tval, client, topicPub, "MOVING_UP", rel) await executeAndPublish(client, topicPub, "MOVING_UP", rel)
elif cmd == "MOVE_DOWN": elif cmd == "MOVE_DOWN":
rel = RelayState(shades_mapping['dol'], True) rel = RelayState(shades_mapping['dol'], True)
await executeAndPublish(tval, client, topicPub, "MOVING_DOWN", rel) await executeAndPublish(client, topicPub, "MOVING_DOWN", rel)
else: else:
await executeAndPublish(tval, client, topicPub, "STATIONARY", RelayState(shades_mapping['gor'], False)) await executeAndPublish(client, topicPub, "STATIONARY", RelayState(shades_mapping['gor'], False))
await executeAndPublish(tval, client, topicPub, "STATIONARY", RelayState(shades_mapping['dol'], False)) await executeAndPublish(client, topicPub, "STATIONARY", RelayState(shades_mapping['dol'], False))
platnoBckgdMoving = False # mucho importante variable prav zares dedoles platnoBckgdMoving = False # mucho importante variable prav zares dedoles
async def platnoTimeout(topicVal, mqttClient, pubTopic, pubPayload, relStat): async def platnoTimeout(mqttClient, pubTopic, pubPayload, relStat: RelayState, intent):
global platnoBckgdMoving global platnoBckgdMoving
await asyncio.sleep(3) #TODO time actual delay await asyncio.sleep(3) #TODO time actual delay
relStat.state = False relStat.state = False
executeAndPublish(topicVal, mqttClient, pubTopic, pubPayload, relStat) await executeAndPublish(mqttClient, pubTopic, intent, relStat)
platnoBckgdMoving = False platnoBckgdMoving = False
async def handleTsePlatno(tval, client, proj, cmdType, cmd): async def handleTsePlatno(client, proj, cmdType, cmd):
global platnoBckgdMoving global platnoBckgdMoving
topicSplit = tval.split('/') #topicSplit = tval.split('/')
# {room} {projectors} {[select]} {platno} {move/goto} # {room} {projectors} {[select]} {platno} {move/goto}
projector = topicSplit[2] #projector = topicSplit[2]
command = topicSplit[4] #command = topicSplit[4]
pubTop = f'{room}/projectors/{projector}/status' pubTop = f'{room}/projectors/{proj}/status'
if platnoBckgdMoving: if platnoBckgdMoving:
if cmd == 'STOP': if cmd == 'STOP':
pubPld = 'UNKNOWN' pubPld = 'UNKNOWN'
rel1 = RelayState(platno_mapping[projector]['gor'], False) rel1 = RelayState(platno_mapping[proj]['gor'], False)
rel2 = RelayState(platno_mapping[projector]['dol'], False) rel2 = RelayState(platno_mapping[proj]['dol'], False)
executeAndPublish(tval,client,pubTop, pubPld, rel1) await executeAndPublish(client,pubTop, pubPld, rel1)
executeAndPublish(tval,client,pubTop, pubPld, rel2) await executeAndPublish(client,pubTop, pubPld, rel2)
platnoBckgdMoving = False
else: else:
return # ignore any other move commands while moving return # ignore any other move commands while moving
#movement cmds #movement cmds
if cmdType == 'move': elif cmdType == 'move':
rel: RelayState rel: RelayState
if cmd == 'UP': if cmd == 'UP':
rel = RelayState(platno_mapping[proj]['gor'], True) rel = RelayState(platno_mapping[proj]['gor'], True)
@ -133,51 +130,60 @@ async def handleTsePlatno(tval, client, proj, cmdType, cmd):
rel = RelayState(platno_mapping[proj]['dol'], True) rel = RelayState(platno_mapping[proj]['dol'], True)
else: else:
return # in case of invalid input skip return # in case of invalid input skip
platnoBckgdState = True platnoBckgdMoving = True
pubPld = 'MOVING' pubPld = 'MOVING'
executeAndPublish(tval, client, pubTop, pubPld, rel) await executeAndPublish(client, pubTop, pubPld, rel)
elif cmdType == 'goto': elif cmdType == 'goto':
# print('received GOTO')
rel: RelayState rel: RelayState
if cmd == 'UP': if cmd == 'UP':
rel = RelayState(platno_mapping[proj]['gor'], True) rel = RelayState(platno_mapping[proj]['gor'], True)
intent = 'UP'
elif cmd == 'DOWN': elif cmd == 'DOWN':
rel = RelayState(platno_mapping[proj]['dol'], True) rel = RelayState(platno_mapping[proj]['dol'], True)
intent = 'DOWN'
else: else:
return # in case of invalid input skip return # in case of invalid input skip
platnoBckgdState = True platnoBckgdMoving = True
pubPld = 'MOVING' pubPld = 'MOVING'
executeAndPublish(tval, client, pubTop, pubPld, rel) await executeAndPublish(client, pubTop, pubPld, rel)
asyncio.create_task(platnoTimeout(tval, client, pubTop, pubPld, rel)) asyncio.create_task(platnoTimeout(client, pubTop, pubPld, rel, intent))
return return
async def task_command2serial(controlClient: aiomqtt.Client): async def task_command2serial(controlClient: aiomqtt.Client):
#print('oge')
await controlClient.subscribe(f"{room}/#") await controlClient.subscribe(f"{room}/#")
async with controlClient.messages as msgs: #print('ogee')
async for mesg in msgs: #async with controlClient.messages as msgs:
mesg: aiomqtt.Message async for mesg in controlClient.messages:
topicVal = mesg.topic.value #print('oge')
msgTopic = mesg.topic.value.split('/')
cmnd = mesg.payload.decode()
if mesg.topic.matches(f'{room}/projectors/+/platno/#'): #mesg: aiomqtt.Message
proj = msgTopic[2] # glavni / stranski topicVal = mesg.topic.value
cmdType = msgTopic[4] # move / goto msgTopic = mesg.topic.value.split('/')
await handleTsePlatno(topicVal, controlClient, proj, cmdType, cmnd) cmnd = mesg.payload.decode()
#print('Received on: ', topicVal, ' with:', cmnd)
#print('bfr')
if mesg.topic.matches(f'{room}/projectors/+/platno/#'):
proj = msgTopic[2] # glavni / stranski
cmdType = msgTopic[4] # move / goto
await handleTsePlatno(controlClient, proj, cmdType, cmnd)
elif mesg.topic.matches(f'{room}/power/#'): elif mesg.topic.matches(f'{room}/power/#'):
systype = msgTopic[2] systype = msgTopic[2]
await handleTsePower(topicVal, controlClient, systype, cmnd) await handleTsePower(controlClient, systype, cmnd)
elif mesg.topic.matches(f'{room}/firanki/command/#'): elif mesg.topic.matches(f'{room}/firanki/command/#'):
await handleTseSencilo(topicVal, controlClient, cmnd) await handleTseSencilo(topicVal, controlClient, cmnd)
else: else:
continue continue
# code after if block doesnt execute in this case # code after if block doesnt execute in this case
#print("after")
await asyncio.sleep(0.01) await asyncio.sleep(0.01)
async def main(): async def main():