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/tse_box/+/ukaz'):
                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 = "1" if relState.state else "0"
                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())