Old Barco projectors (initial implementation)

This commit is contained in:
Frangež, Miha 2024-10-29 21:07:41 +01:00
parent f41dfc4f86
commit a9820001b4
4 changed files with 314 additions and 0 deletions

View file

@ -0,0 +1,96 @@
import re
import asyncio
import telnetlib3
from dataclasses import dataclass
from enum import StrEnum
PORT = 43680
RE_STATUS = re.compile(r"OP (.+?)(?:$| = (.+)$)")
@dataclass(frozen=True)
class ACK:
command: str
@dataclass(frozen=True)
class ValueUpdate:
key: str
value: str
class Status(StrEnum):
standby = "0"
warmup = "1"
imaging = "2"
cooling = "3"
warning = "4"
class LampMode(StrEnum):
economy = "0"
standard = "1"
dimming = "2"
class ValueType(StrEnum):
status = "status"
picture_mute = "picture.mute"
lamp_mode = "lamp.mode"
class BarcoRLMW_TCP:
def __init__(self, projector_ip):
self.projector_ip = projector_ip
self.session = None
async def init(self):
self.reader, self.writer = await telnetlib3.open_connection(self.projector_ip, 3023)
async def exec(self, cmd):
await self.writer.write("op " + cmd + "\r")
async def set(self, key, val):
await self.writer.write("op " + key + " = " + val + "\r")
async def query(self, key):
await self.writer.write("op " + key + " ?\r")
async def set_power(self, power):
await self.exec(f"power.{onoff(power)}")
async def set_shutter(self, shutter):
await self.set("picture.mute", int(shutter))
async def iter_messages(self):
"""Async iterator that processes feedback from the projector.
Yields ACK (acknowledgement) and ValueUpdate (value has changed) messages."""
while True:
line = await self.reader.readuntil('\r').decode().strip()
msg = self.parse_response(line)
if msg:
yield msg
def parse_response(self, line):
matches = RE_STATUS.findall(line)
if len(matches) == 0:
return None
match = matches[0]
if len(match) == 2:
return ACK(match[1])
if len(match) == 3:
return ValueUpdate(match[1], match[2])
def onoff(state: bool) -> str:
if state:
return "on"
else:
return "off"
if __name__ == "__main__":
async def main():
barco = BarcoRLMW_TCP("192.168.192.12")
status = await barco.get_status()
print(status)
await barco.click_remote("kymenu")
asyncio.run(main())

72
barco_rlmw_tcp/main.py Normal file
View file

@ -0,0 +1,72 @@
import asyncio
import aiomqtt
from collections import defaultdict
from barco_rlmw_tcp import BarcoRLMW_TCP, ValueUpdate, Status, ACK, ValueType
# TODO MAKE THIS CONFIGURALBE
PROJECTOR_IP = "192.168.192.12"
MQTT_PREFIX = "p22/projektorji/glavni"
MQTT_HOST = "-------"
POLLING_PERIOD_SEC = 10
class BarcoRLMW_TCP_MQTT:
def __init__(self, projector_ip, mqtt_prefix):
self.projector_ip = projector_ip
self.mqtt_prefix = mqtt_prefix
self.barco = BarcoRLMW_TCP(projector_ip)
self.last_status = defaultdict(lambda: '')
async def run(self):
async with aiomqtt.Client(MQTT_HOST, 1883) as client:
self.client = client
task_polling = asyncio.create_task(self.task_polling())
task_control = asyncio.create_task(self.task_control())
await asyncio.gather(task_control, task_polling)
async def task_control(self):
topicMatch = f"{self.mqtt_prefix}/ukaz/+"
await self.client.subscribe(topicMatch)
async for mesg in self.client.messages:
cmd = mesg.topic.value.split("/")[-1]
val = mesg.payload.decode()
if cmd == "power":
await self.barco.set_power(onoff(val))
elif cmd == "shutter":
await self.barco.set_shutter(onoff(val))
async def task_polling(self):
while True:
await self.barco.query("status")
await asyncio.sleep(POLLING_PERIOD_SEC)
async def write_status(self, status, value):
await self.client.publish(f"{self.mqtt_prefix}/status/{status}", payload=value)
async def task_process_messages(self):
async for msg in self.barco.iter_messages():
# We only care about value updates
if isinstance(msg, ValueUpdate):
# Power status
if msg.key == ValueType.status:
if msg.value in (Status.imaging, Status.warmup):
self.write_status("power", 1)
elif msg.value in (Status.standby, Status.cooling):
self.write_status("power", 0)
# Video mute
if msg.key == ValueType.picture_mute:
self.write_status("shutter", msg.value)
def onoff(input):
if input == "1":
return True
elif input == "0":
return False
if __name__ == '__main__':
barco = BarcoRLMW_TCP_MQTT(PROJECTOR_IP, MQTT_PREFIX)
asyncio.run(barco.run())