lights-web/lights_web/__init__.py

124 lines
3.3 KiB
Python

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/<lid>/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/<lid>/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()