Files
hasaddon/simple-scheduler/rootfs/simplescheduler/main.py
T
admins 088878a693 New Addon
Simple Schedule
2023-07-12 22:23:45 +07:00

816 lines
29 KiB
Python

from flask import Flask, render_template, request, redirect, make_response
import paho.mqtt.client as mqtt
import flask.cli
import logging
import glob
import os
import json
import uuid
from datetime import datetime, timedelta
import pytz
import requests
import re
import psutil
import simpleschedulerconf
lwt_topic = "homeassistant/switch/simplescheduler/availability"
sun_data = ""
schedulers_list = []
options = []
weekday = []
has_changed: bool = False
mqttclient = None
ha_timezone = "utc"
scheduler_pid = 0
request_timeout = 5 # seconds
app = Flask(__name__)
@app.route("/")
@app.route("/main")
def webserver_home():
return render_template('index.html',
data=load_json_schedulers(),
o=get_options(),
css=get_css(),
switchlist=get_switch_html_select_options(),
friendlynames=get_switch_friendly_names(),
sort=get_sort_list(),
weekday=weekday,
statusbarinfo=get_statusbar_info()
)
@app.route("/new")
def webserver_new():
return render_template('new.html')
@app.route('/delete', methods=['GET'])
def webserver_delete():
args = request.args
sid = args.get('id')
file = simpleschedulerconf.json_folder + sid + '.json'
if os.path.exists(file):
os.remove(file)
if options['MQTT']['enabled']:
mqttclient.publish('homeassistant/switch/simplescheduler/' + sid + '/config', "", qos=0, retain=1)
return redirect("main")
@app.route('/edit', methods=['GET'])
def webserver_edit():
is_new = False
args = request.args
sid = args.get('id')
stype: str = args.get('type')
file = simpleschedulerconf.json_folder + sid + '.json'
if sid != "0":
with open(file, "r") as read_file:
param = json.load(read_file)
else:
param = json.loads(get_json_template(stype))
param['id'] = uuid.uuid4().hex
is_new = True
return render_template('edit.html',
p=param,
o=get_options(),
weekday=weekday,
switchlist=get_switch_html_select_options(),
is_new=is_new
)
@app.route('/config', methods=['GET'])
def webserver_config():
return render_template('config.html',
o=get_options()
)
@app.route('/saveconfig', methods=['GET'])
def webserver_saveconfig():
jsondata = {}
translations = {}
components = {}
mqttconf = {}
content = request.args
for item in content:
if content[item] == '0' or content[item] == '1':
value = int(content[item])
else:
value = content[item]
if "." in item:
p = item.split(".")
cat = p[0].lower()
subcat = p[1]
if cat == "translations": translations[subcat] = value
if cat == "components": components[subcat] = value
if cat == "mqtt": mqttconf[subcat] = value
else:
jsondata[item] = value
jsondata["translations"] = translations
jsondata["components"] = components
jsondata["MQTT"] = mqttconf
option_file_path = os.path.join(simpleschedulerconf.json_folder, "options.dat")
with open(option_file_path, 'w') as option_file:
json_config = json.dump(jsondata, option_file)
init()
return redirect("main")
@app.route('/clone', methods=['GET'])
def webserver_clone():
args = request.args
sid = args.get('id')
file = simpleschedulerconf.json_folder + sid + '.json'
if os.path.exists(file) and sid != "0":
with open(file, "r") as read_file:
param = json.load(read_file)
newsid = uuid.uuid4().hex
newfile = simpleschedulerconf.json_folder + newsid + '.json'
param['id'] = newsid
param['name'] = param['name'] + " (2) "
with open(newfile, 'w') as jsonFile:
json.dump(param, jsonFile)
return redirect("main")
@app.route("/update", methods=['POST'])
def webserver_update():
sid = request.form.get('id')
enabled = request.form.get("enabled")
dontretry = request.form.get("dontretry")
name = request.form.get("name")
entity_id = request.form.getlist('entity_id[]')
type = request.form.get('type')
if type != 'weekly':
on_tod = request.form.get('on_tod')
off_tod = request.form.get('off_tod')
on_dow = ""
off_dow = ""
for o in request.form.getlist('on_dow[]'):
on_dow += o
for o in request.form.getlist('off_dow[]'):
off_dow += o
data = json.loads(get_json_template(type))
data['id'] = sid
data['name'] = name if name else sid
data['enabled'] = enabled if enabled else 0
data['dontretry'] = dontretry if dontretry else 0
data['entity_id'] = entity_id
if type == 'weekly':
data['weekly']['on_1'] = request.form.get('on_1')
data['weekly']['on_2'] = request.form.get('on_2')
data['weekly']['on_3'] = request.form.get('on_3')
data['weekly']['on_4'] = request.form.get('on_4')
data['weekly']['on_5'] = request.form.get('on_5')
data['weekly']['on_6'] = request.form.get('on_6')
data['weekly']['on_7'] = request.form.get('on_7')
data['weekly']['off_1'] = request.form.get('off_1')
data['weekly']['off_2'] = request.form.get('off_2')
data['weekly']['off_3'] = request.form.get('off_3')
data['weekly']['off_4'] = request.form.get('off_4')
data['weekly']['off_5'] = request.form.get('off_5')
data['weekly']['off_6'] = request.form.get('off_6')
data['weekly']['off_7'] = request.form.get('off_7')
elif type == 'recurring':
data['recurring']['on_start'] = request.form.get('on_start')
data['recurring']['on_end'] = request.form.get('on_end')
data['recurring']['on_interval'] = request.form.get('on_interval')
data['recurring']['off_start'] = request.form.get('off_start')
data['recurring']['off_end'] = request.form.get('off_end')
data['recurring']['off_interval'] = request.form.get('off_interval')
data['on_tod'] = on_tod
data['off_tod'] = off_tod
data['on_dow'] = on_dow
data['off_dow'] = off_dow
else:
data['on_tod'] = on_tod
data['off_tod'] = off_tod
data['on_dow'] = on_dow
data['off_dow'] = off_dow
file = simpleschedulerconf.json_folder + sid + '.json'
with open(file, 'w') as jsonFile:
json.dump(data, jsonFile)
if options['MQTT']['enabled']:
mqtt_send_config(mqttclient)
# mqtt_publish_state(mqttclient, id, enabled, True)
return redirect("main")
@app.route("/sort", methods=['GET'])
def webserver_sort():
data = request.args
save_sort_list(data)
return make_response("", 200)
@app.route("/log", methods=['GET'])
def webserver_log():
response = ""
logfilepath = os.path.join(simpleschedulerconf.json_folder, "simplescheduler.log")
with open(logfilepath, "r", encoding='utf-8') as logfile:
response += logfile.read()
return make_response(response, 200)
@app.route("/dirty")
def webserver_dirty():
global has_changed
if has_changed:
r = '1'
has_changed = False
else:
r = '0'
return make_response(r, 200)
@app.context_processor
def utility_processor():
def format_event(value: str, showvalue: bool):
if not value: return ''
result: str = ""
extra: str = ""
events = value.upper().replace(',', ' ').replace(';', ' ').split(' ')
for e in events:
p = e.split('>') # separate time from extra commands
t: str = p[0]
extra = ""
if len(p) > 1 and showvalue: # verify extra commands
prefix = p[1][0]
v: str = p[1][1:]
if prefix == 'F':
extra = '<span class="event-type-f"><i class="mdi mdi-fan" aria-hidden="true"></i>' + v + '%</span>'
if prefix == 'P':
extra = '<span class="event-type-p"><i class="mdi mdi-arrow-up-down" aria-hidden="true"></i>' + v + '%</span>'
if prefix == 'B':
if v[0] == 'A':
v = v[1:]
extra = '<span class="event-type-b"><i class="mdi mdi-lightbulb" aria-hidden="true"></i>' + v + '</span>'
else:
extra = '<span class="event-type-b"><i class="mdi mdi-lightbulb" aria-hidden="true"></i>' + v + '%</span>'
if prefix == 'T':
if v[0] == 'O':
v = v[1:]
extra = '<span class="event-type-to"><i class="mdi mdi-thermometer" aria-hidden="true"></i>' + v + '&deg;</span>'
else:
extra = '<span class="event-type-t"><i class="mdi mdi-power" aria-hidden="true"></i>' + v + '&deg;</span>'
result += '<span>' + t + extra + '</span >'
return result
return dict(format_event=format_event)
@app.context_processor
def utility_processor():
def get_friendly_html_dow(value: str, is_on: bool):
result: str = "<div>"
if len(value) > 0:
onOffClass = "dowHiglightG" if is_on else "dowHiglightR"
for wd in range(1, 8):
d = weekday[wd]
dclass = ""
if str(wd) in value:
dclass = onOffClass
result += '<div class="dowIcon ' + dclass + ' " >' + d + '</div>'
result += '</div>'
return result
return dict(get_friendly_html_dow=get_friendly_html_dow)
def on_connect(client, userdata, flags, rc):
if rc == 0:
printlog("STATUS: MQTT connected! ")
client.publish(lwt_topic, payload="online", qos=0, retain=True)
client.subscribe("homeassistant/switch/simplescheduler/#")
else:
printlog("ERROR: MQTT Error " + str(rc))
def on_message(client, userdata, msg):
global has_changed
payload = 0
pieces = msg.topic.split("/")
if len(pieces) > 4:
if pieces[4] == "set":
sid = pieces[3]
printlog('MQTT: RCV ' + msg.topic + " --> " + msg.payload.decode())
if msg.payload.decode() == 'ON':
payload = 1
update_json_file(sid, 'enabled', payload)
if options['MQTT']['enabled']:
mqtt_publish_state(client, sid, payload, True)
has_changed = "1"
def get_statusbar_info():
r = {
"sunrise": "N/A",
"sunset": "N/A",
"timezone": "N/A",
"scheduler": "Not running",
"mqtt": "Disabled"
}
tz = get_ha_timezone()
sunrise, sunset = get_sun(tz)
r['timezone'] = tz if tz else "N/A"
r['sunrise'] = sunrise.strftime("%H:%M") if sunrise else "N/A"
r['sunset'] = sunset.strftime("%H:%M") if sunset else "N/A"
pid = get_scheduler_pid()
if pid > 0:
r['scheduler'] = "Running (PID %s)" % pid
if options['MQTT']['enabled']:
r['mqtt'] = "Connected" if mqttclient.is_connected() else "Disconnected"
return r
def get_switch_list(domains):
full_switch_list = []
url = simpleschedulerconf.HASSIO_URL + "/states"
headers = {'content-type': 'application/json', 'Authorization': 'Bearer ' + simpleschedulerconf.SUPERVISOR_TOKEN}
try:
r = requests.get(url=url, headers=headers, timeout=request_timeout)
for block in r.json():
item = {
"id": block["entity_id"],
"state": block["state"],
"friendly_name": "",
"domain": "",
}
pieces = block["entity_id"].split(".")
item["domain"] = pieces[0]
attributes = block["attributes"]
if "friendly_name" in attributes:
item["friendly_name"] = attributes["friendly_name"]
if item["domain"] in domains:
full_switch_list.append(item)
full_switch_list.sort(key=lambda x: x["id"], reverse=False)
except:
printlog("ERROR: Unable to obtain entities info from Home Assistant")
return full_switch_list
def get_switch_friendly_names():
friendly_names = {}
url = simpleschedulerconf.HASSIO_URL + "/states"
headers = {'content-type': 'application/json', 'Authorization': 'Bearer ' + simpleschedulerconf.SUPERVISOR_TOKEN}
try:
r = requests.get(url=url, headers=headers, timeout=request_timeout)
for block in r.json():
key = block["entity_id"]
value = key
if "friendly_name" in block["attributes"]:
value = block["attributes"]["friendly_name"]
friendly_names[key] = value
except:
printlog("ERROR: Unable to obtain entities names from Home Assistant")
return friendly_names
def update_json_file(object_id, field_name, field_value):
file = simpleschedulerconf.json_folder + object_id + '.json'
try:
if os.path.exists(file):
with open(file, "r") as jsonFile:
data = json.load(jsonFile)
data[field_name] = field_value
with open(file, "w") as jsonFile:
json.dump(data, jsonFile)
except:
printlog("ERROR: Unable to update JSON file")
return True
def load_json_schedulers():
ss = []
os.chdir(simpleschedulerconf.json_folder)
for file in glob.glob("*.json"):
with open(file, "r") as read_file:
try:
ss.append(json.load(read_file))
except:
printlog("ERROR: scheduler file %s is corrupted" % file )
return ss
def mqtt_publish_state(client, object_id, pub_value, echo=False):
payload = 'OFF'
if pub_value:
payload = 'ON'
topic = 'homeassistant/switch/simplescheduler/' + object_id + '/state'
client.publish(topic, payload, qos=0, retain=1)
if echo:
printlog('MQTT: PUB ' + topic + ' --> ' + payload)
def mqtt_send_config(client):
schedulers = load_json_schedulers()
payload_template = '{"unique_id": "simplescheduler_###",' \
'"name": "SimpleScheduler: @@@" ,' \
'"icon":"mdi:calendar-clock" ,' \
'"cmd_t": "homeassistant/switch/simplescheduler/###/set",' \
'"stat_t": "homeassistant/switch/simplescheduler/###/state",' \
'"avty_t": "homeassistant/switch/simplescheduler/availability",' \
'"pl_avail":"online",' \
'"pl_not_avail":"offline"}'
config_topic_template = 'homeassistant/switch/simplescheduler/###/config'
for S in schedulers:
if S and 'name' in S:
topic = config_topic_template.replace('###', S['id'])
payload = payload_template.replace('###', S['id'])
payload = payload.replace('@@@', S['name'])
# slug = slugify(S['name'], separator="_")
# payload = payload.replace('&&&', slug)
client.publish(topic, payload, qos=0, retain=1)
# time.sleep(.1)
mqtt_publish_state(client, S['id'], S['enabled'], False)
# time.sleep(.1)
def get_options():
# path = "/data/options.json"
path = os.path.join(simpleschedulerconf.json_folder, "options.dat")
if not os.path.exists(path):
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "options.dat")
with open(path, "r", encoding='utf-8') as read_file:
opt = json.load(read_file)
return opt
def get_css():
global options
path_light = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates", "light.css")
path_dark = os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates", "dark.css")
css = ""
# try:
with open(path_light, "r", encoding='utf-8') as css_file:
css += css_file.read()
if options['dark_theme']:
with open(path_dark, "r", encoding='utf-8') as css_file:
css += css_file.read()
# except:
# printlog("ERROR: Something went wrong while loading CSS")
return css
def get_enabled_domains():
enabled_domains = []
opt = get_options()
for d in opt['components']:
if opt['components'][d]:
enabled_domains.append(d)
return enabled_domains
def get_switch_html_select_options():
htmlstring: str = ''
switch_list = get_switch_list(get_enabled_domains())
comp = ""
for s in switch_list:
c = s['id'].split('.')
if comp != c[0]:
if comp != "":
htmlstring += '</optgroup>'
comp = c[0]
htmlstring += '<optgroup label="' + comp + '">'
name = s['id'] if s['friendly_name'] == "" else s['friendly_name'] + '(' + s['id'] + ')'
htmlstring += '<option value="' + s['id'] + '">' + name + '</option>'
htmlstring += '</optgroup>'
htmlstring = htmlstring.replace(chr(39), "&#39;")
return htmlstring
def get_json_template(t: str):
t = t.lower()
json_template: str = ''
if t == 'w' or t == 'weekly':
json_template = '{"id":"","name":"","enabled":"1","entity_id":[""],"weekly":{"on_1":"","on_2":"","on_3":"",' \
'"on_4":"","on_5":"","on_6":"","on_7":"","off_1":"","off_2":"","off_3":"","off_4":"",' \
'"off_5":"","off_6":"","off_7":""}} '
if t == 'd' or t == 'daily' or t is None:
json_template = '{"id":"","name":"","enabled":"1","entity_id":[""],"on_tod":"","on_dow":"","off_tod":"",' \
'"off_dow":""} '
if t == 'r' or t == 'recurring':
json_template = '{"id":"","name":"","enabled":"1","entity_id":[""],"recurring":{"on_start":"","on_end":"",' \
'"on_interval":"","off_start":"","off_end":"","off_interval":""},"on_tod":"","on_dow":"",' \
'"off_tod":"","off_dow":""} '
return json_template
def get_sort_list():
sorting = {}
sort_file_path = simpleschedulerconf.json_folder + "sort.dat"
if os.path.exists(sort_file_path):
with open(sort_file_path, "r") as sort_file:
order = json.load(sort_file)
i = 0
for sid in order['id_order']:
sorting[sid] = i
i = i + 1
return sorting
def save_sort_list(data):
idlist = []
for el in data:
idlist.append(data[el])
jsonlist = json.loads('{"id_order":[]}')
jsonlist['id_order'] = idlist
with open(simpleschedulerconf.json_folder + "sort.dat", "w") as sort_file:
json.dump(jsonlist, sort_file)
return True
def get_events_in_html():
events_html = {"events_on": "events_on", "events_off": "events_off", "days_on": "days_on", "days_off": "days_off"}
return events_html
def get_entity_status(e, check):
response = ""
url = simpleschedulerconf.HASSIO_URL + "/states/" + e
headers = {'content-type': 'application/json', 'Authorization': 'Bearer ' + simpleschedulerconf.SUPERVISOR_TOKEN}
try:
r = requests.get(url=url, headers=headers, timeout=request_timeout)
result = r.json()
response = str(result['state']).lower()
if check:
altered_response = response
domain = e.lower().split(".")
if domain[0] == 'cover':
altered_response = 'on' if response == "open" else 'off'
if domain[0] == 'climate' and response != 'off':
altered_response = 'on'
response = altered_response
except:
printlog("ERROR: Unable to obtain entity status from Home Assistant")
return response
def call_ha_api(command_url: str, post_data: str):
opt = get_options()
headers = {'content-type': 'application/json', 'Authorization': 'Bearer ' + simpleschedulerconf.SUPERVISOR_TOKEN}
try:
r = requests.post(url=command_url, data=post_data, headers=headers, timeout=request_timeout)
command = command_url.replace(simpleschedulerconf.HASSIO_URL + "/services/", "")
if opt['debug']: printlog("DEBUG: %s %s" % (command, post_data))
if r.status_code != 200:
printlog("ERROR: Error calling HA API " + str(r.status_code))
except:
printlog("ERROR: Unable to call Home Assistant service")
return True
def call_ha(eid_list, action, passedvalue, friendly_name):
if not isinstance(eid_list, list):
eid_list = {eid_list}
for eid in eid_list:
command = "Turning " + action.upper()
extra = ""
v = ""
value = passedvalue.upper()
domain = eid.split(".")
command_url = simpleschedulerconf.HASSIO_URL + "/services/" + domain[0] + "/turn_" + action
postdata = '{"entity_id":"%s"}' % eid
if action == 'on':
if domain[0] == "light" and value != "":
if value[0] == "A":
v = int(value[1:])
extra = "to %d" % v
elif value.isdigit():
v = int(int(value) * 2.55)
extra = "to " + value + '%'
postdata = '{"entity_id":"%s","brightness":"%d"}' % (eid, v)
if domain[0] == "fan" and value != "":
v = value
extra = "to " + v + '%'
postdata = '{"entity_id":"%s","percentage":"%s"}' % (eid, v)
if domain[0] == "cover":
if value != "":
command_url = simpleschedulerconf.HASSIO_URL + "/services/cover/set_cover_position"
postdata = '{"entity_id":"%s","position":"%s"}' % (eid, value)
command = "Setting"
extra = "position to " + value + '%'
else:
if action == "on":
command_url = simpleschedulerconf.HASSIO_URL + "/services/cover/open_cover"
command = "Opening"
if domain[0] == "climate" and value != "":
if value[0] == "O":
v = value[1:]
command_url = simpleschedulerconf.HASSIO_URL + "/services/climate/set_temperature"
postdata = '{"entity_id":"%s","temperature":"%s"}' % (eid, v)
command = "Setting"
extra = "temperature to " + v + '°'
else:
if domain[0] == "cover":
command_url = simpleschedulerconf.HASSIO_URL + "/services/cover/close_cover"
command = "Closing"
printlog("SCHED: %s [%s] %s" % (command, friendly_name.get(eid, eid), extra))
call_ha_api(command_url, postdata)
if domain[0] == "climate" and value != "":
if value[0] != "O":
command_url = simpleschedulerconf.HASSIO_URL + "/services/climate/set_temperature"
postdata = '{"entity_id":"%s","temperature":"%s"}' % (eid, value)
call_ha_api(command_url, postdata)
command = "Setting"
extra = "temperature to " + value + '°'
printlog("SCHED: %s [%s] %s" % (command, friendly_name.get(eid, eid), extra))
return True
def is_a_retry_domain(entity):
response = True
if "scene." in entity : response = False
if "script." in entity: response = False
if "automation." in entity: response = False
if "media_player." in entity: response = False
if "camera." in entity: response = False
return response
def get_events_array(s):
s = s.upper().replace(',', ' ').replace(';', ' ').strip()
s = re.sub(' +', ' ', s)
events = s.split(' ')
return events
def evaluate_event_time(s, sunrise, sunset):
event = ""
sunrise_day = ""
sunset_day = ""
if sunrise:
sunrise_day = sunrise.strftime("%d")
if sunset:
sunset_day = sunset.strftime("%d")
today = datetime.now().strftime("%d")
if len(s) > 3:
p = s.upper().split('>')
event = p[0]
operator = "~"
if event[:3] == "SUN":
if event.find('+') != -1: operator = "+"
if event.find('-') != -1: operator = "-"
eventime = event.split(operator)
event = ""
if eventime[0] == "SUNRISE" and sunrise_day == today:
event = sunrise.strftime("%H:%M")
if eventime[0] == "SUNSET" and sunset_day == today:
event = sunset.strftime("%H:%M")
if event != "" and len(eventime) > 1:
hm = event.split(":")
if operator == '+':
event = (datetime(2022, 1, 1, int(hm[0]), int(hm[1])) + timedelta(
minutes=int(eventime[1]))).strftime("%H:%M")
else:
event = (datetime(2022, 1, 1, int(hm[0]), int(hm[1])) - timedelta(
minutes=int(eventime[1]))).strftime("%H:%M")
if event:
hm = event.split(":")
if 0 <= int(hm[0]) < 24 and 0 <= int(hm[1]) < 60:
event = datetime(2022, 1, 1, int(hm[0]), int(hm[1])).strftime("%H:%M") # fix missing leading zeroes
return event
def get_sun(tz, sunrise="", sunset=""):
if tz:
mytimezone = pytz.timezone(tz)
url = simpleschedulerconf.HASSIO_URL + "/states/sun.sun"
headers = {'content-type': 'application/json',
'Authorization': 'Bearer ' + simpleschedulerconf.SUPERVISOR_TOKEN}
try:
r = requests.get(url=url, headers=headers, timeout=request_timeout)
result = r.json()
response = result['attributes']
sunrise = datetime.fromisoformat(response['next_rising']).astimezone(mytimezone)
sunset = datetime.fromisoformat(response['next_setting']).astimezone(mytimezone)
except:
printlog("ERROR: Unable to obtain sun info from Home Assistant")
return sunrise, sunset
def get_ha_timezone():
response = ""
url = simpleschedulerconf.HASSIO_URL + "/config"
headers = {'content-type': 'application/json', 'Authorization': 'Bearer ' + simpleschedulerconf.SUPERVISOR_TOKEN}
try:
r = requests.get(url=url, headers=headers, timeout=request_timeout)
result = r.json()
response = result['time_zone']
except:
printlog("ERROR: Unable to obtain timezone from Home Assistant")
else:
try:
if not response:
response = os.environ["TZ"]
except:
printlog("ERROR: Unable to obtain timezone from OS")
return response
def get_scheduler_pid():
pid = 0
try:
for process in psutil.process_iter():
if "/simplescheduler/scheduler.py" in process.cmdline():
pid = process.pid
except:
printlog("ERROR: Unable to obtain scheduler PID")
return pid
def printlog(message):
t = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
fullrow = "[%s] %s" % (t, message)
print(fullrow)
if not os.path.exists(simpleschedulerconf.json_folder):
os.makedirs(simpleschedulerconf.json_folder)
logfilepath = os.path.join(simpleschedulerconf.json_folder, "simplescheduler.log")
with open(logfilepath, "a", encoding='utf-8') as logfile:
logfile.write(fullrow + "\n")
def init():
global options
global weekday
global schedulers_list
global ha_timezone
options = get_options()
weekday = \
[
options['translations']['text_sunday'][:2],
options['translations']['text_monday'][:2],
options['translations']['text_tuesday'][:2],
options['translations']['text_wednesday'][:2],
options['translations']['text_thursday'][:2],
options['translations']['text_friday'][:2],
options['translations']['text_saturday'][:2],
options['translations']['text_sunday'][:2]
]
if options['debug']:
printlog(" QUESTION: What do you get if you multiply six by nine?")
printlog(" ANSWER: 42")
schedulers_list = load_json_schedulers()
ha_timezone = get_ha_timezone()
if __name__ == '__main__':
printlog('STATUS: Starting main program')
init()
if options['MQTT']['enabled']:
printlog('STATUS: Starting MQTT')
mqttclient = mqtt.Client(client_id="SimpleScheduler", clean_session=False)
mqttclient.on_connect = on_connect
mqttclient.on_message = on_message
mqttclient.will_set(lwt_topic, payload="offline", qos=0, retain=True)
mqttclient.username_pw_set(options['MQTT']['username'], options['MQTT']['password'])
try:
mqttclient.connect(options['MQTT']['server'], int(options['MQTT']['port']), 60)
except:
printlog("ERROR: MQTT Connection failed")
else:
mqttclient.loop_start()
mqtt_send_config(mqttclient)
# Disable Flask Messages
log = logging.getLogger('werkzeug')
log.disabled = True
flask.cli.show_server_banner = lambda *args: None
# app.logger.disabled = True
printlog('STATUS: Starting WebServer')
app.run(host='0.0.0.0', port=8099, debug=False)