diff --git a/door.py b/door.py index 2dcec04..d6ee2dd 100644 --- a/door.py +++ b/door.py @@ -1,5 +1,6 @@ #!/usr/bin/python import os, serial, socket, subprocess, select, datetime, sys +import paho.mqtt.client as mqcl import argparse OPEN_THRESHOLD = 35 @@ -14,16 +15,25 @@ parser.add_argument("--valid_tokens", default="/etc/door_tokens") parser.add_argument("--log_file", default="/tmp/nfc.log") parser.add_argument("--state_timeout", type=float, default=10) parser.add_argument("--repeat_time", type=float, default=5) +parser.add_argument("--mqtt_host", default="10.10.21.2") config = parser.parse_args() +mqttc = mqcl.Client() + +def timestamp(): + return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + # Log data to stdout and the log file def log(*args): - data = "%s %s" % (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), " ".join(str(i) for i in args)) + data = "%s %s" % (timestamp(), " ".join(str(i) for i in args)) lgf.write(data + "\n") lgf.flush() print(data) +def mqtt(topic, msg, persistent = True): + mqttc.publish("door/" + topic, msg, qos=2, retain=persistent) + # Opens the socket that can control the daemon # Commands are TBD def open_control_socket(): @@ -122,14 +132,18 @@ def poll_door_state(): data = serial_port.readline().strip().split() if data[0] == b'pos:': data = int(data[1]) + if state_pos != data: + mqtt("position/value", data, True) state_pos = data changed = False if data < OPEN_THRESHOLD and state != OPEN: state = OPEN changed = True + mqtt("state/value", "open", True) elif data > CLOSED_THRESHOLD and state != CLOSE: state = CLOSE changed = True + mqtt("state/value", "closed", True) return state # Check the door state and send commands through a state machine @@ -209,6 +223,7 @@ def open_door(): log("Opening the door") action = OPEN start_time = None + mqtt("state/target", "open", True) handle_door_state() def close_door(): @@ -217,6 +232,7 @@ def close_door(): log("Closing the door") action = CLOSE start_time = None + mqtt("state/target", "closed", True) handle_door_state() def toggle_door_state(): @@ -245,12 +261,7 @@ def handle_nfc_token(token = None): toggle_door_state() else: log("Invalid token:", token) - -open_logfile() -read_valid_tokens() -open_nfc_fifo() -open_serial_port() -open_control_socket() + mqtt("token/last_invalid", "%s;%s" % (timestamp(), token)) class LineBuffer(object): def __init__(self, f, handler): @@ -269,7 +280,6 @@ class LineBuffer(object): self.handler(self.f, i) return True - def handle_cmd(comm, data): cmd = data.decode('utf8').split() cmd, args = cmd[0], cmd[1:] @@ -300,6 +310,16 @@ def handle_cmd(comm, data): action_names[action], (datetime.datetime.now() - start_time).total_seconds())) +open_logfile() +read_valid_tokens() +open_nfc_fifo() +open_serial_port() +open_control_socket() + +mqttc.on_connect = lambda client, userdata, flags, rc: log("Connected to mqtt host with result %s" % (str(rc), )) +mqttc.connect_async(config.mqtt_host, keepalive = 60) +mqttc.loop_start() + buffers = {} while True: readable = select.select([ nfc_fifo, control_socket ] + comm_channels, [], [], 1)[0]