diff --git a/extron_audio_matrix/extron_audio_matrix_telnet_control.py b/extron_audio_matrix/extron_audio_matrix_telnet_control.py new file mode 100644 index 0000000..56187e4 --- /dev/null +++ b/extron_audio_matrix/extron_audio_matrix_telnet_control.py @@ -0,0 +1,57 @@ +import asyncio +import time + +import aiomqtt +import telnetlib3 +from extron_audio_matrix_telnet_interpreter import * + + +async def extron_audio_telnet_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 extron_audio_telnet_control(client, writer): + await client.subscribe("p1/audio_matrix/#") + async with client.messages() as msgs: + async for mesg in msgs: + print(mesg.topic.value) + if mesg.topic.matches('p1/audio_matrix/+/command/#'): + # format: //[input/output]_[%02number]/command/ + _cmd = mesg.topic.value.split("/")[-1] + _payload = mesg.payload.decode() + _fullio = mesg.topic.value.split("/")[-3] # TODO is there a better way to do this? + _io, _id = _fullio.split("_", maxsplit=2) + ind = int(_id) + + cmd = ActionType.Gain if _cmd == "GAIN" else (ActionType.Mute if _cmd == "MUTE" else None) + io = IOType.Input if _io == "input" else (IOType.Output if _io == "output" else None) + + extronCmd = field_to_eam_telnet_code(EAMValue(cmd, io, ind, _payload)) + print(f" Received update: [{mesg.topic.value}] with value [{_payload}]") + print(f"Sending following command to Extron: [{extronCmd.strip()}]..") + writer.write(extronCmd) + await asyncio.sleep(0.2) + pass + +# TODO add initial pull +async def shell(reader, writer): + async with aiomqtt.Client('localhost', 1883) as client: + #task_status_query = asyncio.create_task(extron_audio_telnet_query_status(client, writer, reader)) + task_control = asyncio.create_task(extron_audio_telnet_control(client, writer)) + await asyncio.gather(task_control) + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + coro = telnetlib3.open_connection('localhost', 1234, shell=shell) + #coro = telnetlib3.open_connection('192.168.192.14', 23, shell=shell) + reader, writer = loop.run_until_complete(coro) + loop.run_until_complete(writer.protocol.waiter_closed) diff --git a/extron_audio_matrix/extron_audio_matrix_telnet_interpreter.py b/extron_audio_matrix/extron_audio_matrix_telnet_interpreter.py new file mode 100644 index 0000000..0a009b3 --- /dev/null +++ b/extron_audio_matrix/extron_audio_matrix_telnet_interpreter.py @@ -0,0 +1,71 @@ +# DMP 128 COMMAND SET +# +# inputs 0 - 11 +# outputs 0 - ? + +from enum import * +from dataclasses import dataclass + + +class ActionType(str, Enum): + Gain = 'G' + Mute = 'M' + + +class IOType(int, Enum): + Input: int = 40000 + Output: int = 60000 + + +# IMPORTANT: for proper functionality, matrix *MUST* be set to verbose mode = 3 + + +@dataclass +class EAMValue: + act: ActionType + io: IOType + id: int + val: str + + def __init__(self, act, io, id, val): + self.act, self.io, self.id, self.val = act, io, id, val + + +def field_to_eam_telnet_code(field: EAMValue) -> str: + _io = str(field.io + field.id) + _val = str(int(float(field.val) * 10) + 2048) if field.act == ActionType.Gain else \ + (1 if field.val == "ON" else 0) + return f"\e{field.act}{_io}*{_val}AU\r\n" + + +def eam_telnet_code_to_field(code: str) -> EAMValue: + if code.startswith("E"): + return None # TODO error handling + # code.strip().removeprefix("Ds") + code = code[2:].strip() + action = ActionType(code[0]) # always the case allegedly + _temp = code[1:].split("*", 2) + _line = int(_temp[0]) + value = int(_temp[1]) + line_id = _line % 100 + io_type = IOType(_line - line_id) + value = str((value - 2048) / 10) if action == ActionType.Gain else ('ON' if value == 1 else 'OFF') + # print(action.name + "\n" + io_type.name + "\n" + str(line_id) + "\n" + str(value) + \ + # (" dB" if action == ActionType.Gain else "")) + return EAMValue(action, io_type, line_id, value) + + +# TODO limits on values + + +# 00 naglavni 01 rocni1 02 rocni02 03 kravatniidk 04 / 05 / 06 hdmiL 97 hdmiR 08 vga1L 09 vga1R + +# TODO have person input dict with labels, also maybe "available" inputs + +""" +Mic/line input gain controls (A) -18.0 dB to +80 dB, (1868 to 2848 ) in 0.1 dB increments. +Input pre-mixer gains (B) -100.0 dB to +12.0 dB, (1048 to 2168) in 0.1 dB increments. +Virtual returns, pre-mixer gains (C) -100.0 dB to +12.0 dB, (1048 to 2168) in 0.1 dB increments. +Output trim control (post-mixer trim) (D) -12.0 dB to +12.0 dB, (1928 to 2168) in 0.1 dB increments. +Output volume controls (E) -100.0 dB to +0.0 dB, (1048 to 2048 ) in 0.1 dB increments +""" diff --git a/relay_board/relay_board_controler.py b/relay_board/relay_board_controler.py deleted file mode 100644 index ce76e39..0000000 --- a/relay_board/relay_board_controler.py +++ /dev/null @@ -1,2 +0,0 @@ -import gpiozero as GPIO -