import logging import flask import threading import paho.mqtt as mqtt import paho.mqtt.client import paho.mqtt.publish from pathlib import Path import os import yaml import re import json from pkg_resources import resource_string, resource_filename, cleanup_resources import atexit # remove temporary files created by resource_filename atexit.register(cleanup_resources, force=True) secrets_path = Path(os.environ.get("LIGHTS_WEB_SECRETS", 'secrets.yaml')) config_path = Path(os.environ.get("LIGHTS_WEB_CONFIG", 'config.yaml')) config = yaml.safe_load(config_path.read_text()) config.update(yaml.safe_load(secrets_path.read_text())) c = threading.Condition() application = flask.Flask(__name__) application.msg="ab" application.lights = { lid: False for lid in config['lights'] } application.logger.removeHandler(flask.logging.default_handler) logging.basicConfig(level=logging.DEBUG) def on_message(client,userdata,message): c.acquire() for lid, cfg in config['lights'].items(): if cfg['mqtt_path'] == message.topic: if message.payload == b'true': application.lights[lid] = True elif message.payload == b'false': application.lights[lid] = False c.release() def on_connect(client, userdata, rc, l): logging.info(f"connected") for lid, cfg in config['lights'].items(): logging.info(f"subscribing: {cfg}") client.subscribe(cfg['mqtt_path']) mc = mqtt.client.Client() mc.username_pw_set(config['mqtt_rw_username'], config['mqtt_rw_password']) mc.on_connect = on_connect mc.on_message = on_message mc.connect_async(config["mqtt_server"]) mc.enable_logger() mc.loop_start() @application.route("/") def main(): return flask.send_file(resource_filename(__name__, 'static/index.html')) @application.route("/status") def status(): print("Main Thread: " + str(threading.current_thread())) c.acquire() st = {"lights" : application.lights} c.release() return json.dumps(st) @application.route("/config") def get_config(): return flask.jsonify({ "mqtt_server": config["mqtt_server"], "mqtt_port": config["mqtt_port"], "mqtt_username": config["mqtt_ro_username"], "mqtt_password": config["mqtt_ro_password"], "lights": config['lights'] }) def publish(path, payload): mc.publish(path, payload, qos=1) @application.route('/light//on/set', methods=['POST']) def set_light(lid): try: path = config["lights"][lid]["mqtt_path"] except KeyError: return flask.jsonify({"ok": False}) publish(path + '/set', "true") return flask.jsonify({"ok": True}) @application.route('/light//on/toggle', methods=['POST']) def toggle_light(lid): try: cfg = config["lights"][lid] toggle = cfg.get('toggle', False) path = cfg["mqtt_path"] except KeyError: print(config["lights"]) logging.exception("toggle exception") return flask.jsonify({"ok": False}) if toggle: publish(path + '/toggle', "true") elif application.lights[lid]: publish(path + '/set', "false") else: publish(path + '/set', "true") return flask.jsonify({"ok": True}) def run_development(): application.run(host='127.0.0.1',port=8000,debug=True) if __name__ == "__main__": run_development()