(Late) initial commit, finalized controler for communication between TSE box serial interface and MQTT

This commit is contained in:
0xEmm 2024-01-09 19:27:31 +01:00
commit 7227decc36
5 changed files with 116 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.idea/
__pycache__/

View file

@ -0,0 +1,2 @@
import gpiozero as GPIO

18
serialTests.py Normal file
View file

@ -0,0 +1,18 @@
import unittest
from tse_serial.tse_serial_interpreter import *
class TestStringMethods(unittest.TestCase):
def test_response_parser(self):
self.assertEquals(resp_to_relay_state("T5A_ON"), RelayState(relay_id=5, state=True))
self.assertEquals(resp_to_relay_state("T3B_OFF"), RelayState(relay_id=11, state=False))
self.assertEquals(resp_to_relay_state("re_2A=OFF"), RelayState(relay_id=2, state=False))
self.assertEquals(resp_to_relay_state("re_1B=OFF"), RelayState(relay_id=9, state=False))
def test_command_parser(self):
self.assertEquals(relay_state_to_cmd(RelayState(3, False)), "r39")
self.assertEquals(relay_state_to_cmd(RelayState(5, True)), "r58")
self.assertEquals(relay_state_to_cmd(RelayState(9, True)), "r16")
self.assertEquals(relay_state_to_cmd(RelayState(11, False)), "r37")

View file

@ -0,0 +1,59 @@
import asyncio
import serial
import aioserial
import aiomqtt
from tse_serial_interpreter import *
aser: aioserial.AioSerial = aioserial.AioSerial(
port='/dev/cu.usbserial-14240',
baudrate=1200,
parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE
)
# TODO adjust serial on actual TSE interface
async def task_status2mqtt(statusClient: aiomqtt.Client):
while True:
data = await aser.read_until_async()
data = data.decode(errors='ignore').strip()
print("TSE box sent: " + data)
relState = resp_to_relay_state(data)
publishTopic = f"p1/tseRelays/{relState.relay_id}/status"
publishPayload = "ON" if relState.state else "OFF"
print("Publishing [" + publishPayload + "] to topic [" + publishTopic + "]")
await statusClient.publish(publishTopic, payload=publishPayload)
async def task_command2serial(controlClient: aiomqtt.Client):
await controlClient.subscribe("p1/tseRelays/#")
async with controlClient.messages() as msgs:
async for mesg in msgs:
mesg: aiomqtt.Message
if mesg.topic.matches('p1/tseRelays/+/command'):
msgTopic = mesg.topic.value
cmnd = mesg.payload.decode()
print("Received: [" + msgTopic + "] payload: [" + cmnd + "]")
relay = int(mesg.topic.value.split("/")[-2])
cmnd = cmnd == "ON"
relState = RelayState(relay, cmnd)
setRelay = relay_state_to_cmd(relState)
print("Sending to TSE box: " + setRelay)
await aser.write_async(bytes(setRelay + '\r\n', "ascii"))
publishTopic = f"p1/tseRelays/{relState.relay_id}/status"
publishPayload = "ON" if relState.state else "OFF"
print("Also publishing topic [" + publishTopic + "] with status [" + publishPayload + "]")
await controlClient.publish(publishTopic, payload=publishPayload)
await asyncio.sleep(0.01)
async def main():
async with aiomqtt.Client('localhost', 1883) as client:
task_status = asyncio.create_task(task_status2mqtt(client))
task_control = asyncio.create_task(task_command2serial(client))
await asyncio.gather(task_status, task_control)
if __name__ == '__main__':
asyncio.run(main())

View file

@ -0,0 +1,35 @@
from dataclasses import dataclass
@dataclass
class RelayState:
relay_id: int
state: bool
def resp_to_relay_state(cmd: str) -> RelayState:
state = True if cmd.find("ON") > -1 else False
#state = False if cmd.find("OFF") > -1 and state == None else None
r_state = RelayState(0, state)
id = 0
if cmd.startswith("T"):
id = int(cmd[1]) + (8 if cmd[2] == "B" else 0)
elif cmd.startswith("re_"):
id = int(cmd[3]) + (8 if cmd[4] == "B" else 0)
r_state = RelayState(id, state)
return r_state
def relay_state_to_cmd(r_state: RelayState) -> str:
#r[NUM][CMD]
cmd = 8 if r_state.state else 9
id = r_state.relay_id
# banka B
if id > 8:
cmd -= 2
id -= 8
return f"r{id}{cmd}"
#return "r" + str(id) + str(cmd)