#! /usr/bin/python3 -sPsP
# usbrelayd: Control USB HID connected electrical relay modules via mqtt

# Copyright (C) 2021  Darryl Bond

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


# MQTT daemon for usbrelay
# Publishes a state topic for each connected usbrelay and subscribes to command topics  for each relay
# Topics are stat/SERIAL/RELAY or cmnd/SERIAL/RELAY
# eg stat/QWERT/2 or cmnd/QWERT/2

import paho.mqtt.client as mqtt
import usbrelay_py
import time
import re
import sys
import configparser

def publish_states(client):
    boards = usbrelay_py.board_details()
#    print("Boards: ",boards)
    for board in boards:
#        print("Board: ",board)
        relay = 1
        # determine the state of each relay and publish to the MQTT broker
        while(relay < board[1]+1):
            if ( board[2] & ( 1 << (relay -1) )):
                relay_state = "ON"
            else:
                relay_state = "OFF"
            
            
            topic = "{0}/{1}/{2}"
            topic_str = topic.format("stat",board[0],relay)
            print("State: ", topic_str, relay_state,flush=True)
            client.publish(topic_str, relay_state, qos=0, retain=True)
            topic_str = topic.format("cmnd",board[0],relay)
            print("Subscribed: ", topic_str,flush=True)
            client.subscribe(topic_str)
            relay += 1
        

def on_message(client, userdata, message):
    msg_state = str(message.payload.decode("utf-8"))
    print("received message: " ,message.topic, msg_state,flush=True)
    # any message other than ON is OFF
    if( msg_state == "ON" ):
        relay_cmd = 1
    else:
        relay_cmd = 0
    
    content = re.split("/",message.topic)
    result = usbrelay_py.board_control(content[1],int(content[2]),relay_cmd)
#    print("COntent: ", content , result)
    pub_str = "stat/{0}/{1}"
    client.publish(pub_str.format(content[1],content[2]), msg_state)

# read the server name or IP address from the command lin


config = configparser.ConfigParser()
config.read('/etc/usbrelayd.conf')
mqttBroker = config['MQTT']['BROKER']
clientName = config['MQTT']['CLIENTNAME']

print("MQTT Broker: ", mqttBroker)
print("MQTT Client: ", clientName)


#
# Count connected usbrelay modules, exit if none 
count = usbrelay_py.board_count()

if(count < 1):
    print("No usbrelay modules connected",flush=True)
    # exit with EX_UNAVAILABLE
    exit(69)
else:
    print("Modules Connected: ",count,flush=True)

# connect to the mqtt broker


if "CallbackAPIVersion" in dir(mqtt):
    # paho-mqtt >= 2.0.0
    client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1, clientName)
else:
    # paho-mqtt < 2.0.0
    client = mqtt.Client(clientName)
client.connect(mqttBroker) 
publish_states(client)
client.on_message=on_message 
while(True):
    client.loop_start()
    time.sleep(60)
    count = usbrelay_py.board_count()
    if(count < 1):
        print("No usbrelay modules connected",flush=True)
        # exit with EX_UNAVAILABLE
        exit(69)
    publish_states(client)

