Continue Flask migration.
This commit is contained in:
parent
09cb8cec5a
commit
cba1fdabc2
310
thermostat.py
310
thermostat.py
@ -80,6 +80,55 @@ def status_as_text():
|
|||||||
+'forced_mode: '+str(forced_mode)+'\n'\
|
+'forced_mode: '+str(forced_mode)+'\n'\
|
||||||
+'\n'.join(['Target temperature for '+room+': '+str(rooms_settings[room][target_name])+'\n'+'Current temperature for '+room+': '+str(get_metric(rooms_settings[room]["metric"], current_time, relay_control_interval)) for room in enabled_rooms()])
|
+'\n'.join(['Target temperature for '+room+': '+str(rooms_settings[room][target_name])+'\n'+'Current temperature for '+room+': '+str(get_metric(rooms_settings[room]["metric"], current_time, relay_control_interval)) for room in enabled_rooms()])
|
||||||
|
|
||||||
|
def relay_state(relay):
|
||||||
|
try:
|
||||||
|
returned_output = subprocess.check_output(["./relay.py", relay, "status"])
|
||||||
|
return returned_output.strip().decode("utf-8")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
logging.error("relay "+relay+" status: Failed to command relays board.")
|
||||||
|
sys.stdout.flush()
|
||||||
|
return "Failed"
|
||||||
|
|
||||||
|
def set_relay(relay, state):
|
||||||
|
try:
|
||||||
|
returned_output = subprocess.check_output(["./relay.py", relay, state])
|
||||||
|
logging.info("set relay "+relay+" to "+state+", new global status: "+returned_output.decode("utf-8").split('\n')[1])
|
||||||
|
sys.stdout.flush()
|
||||||
|
return "OK"
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
logging.error("set relay "+relay+" to "+state+": Failed to command relays board.")
|
||||||
|
sys.stdout.flush()
|
||||||
|
return "KO"
|
||||||
|
|
||||||
|
def get_metric(metric, current_time, interval):
|
||||||
|
url = "http://localhost:3000/"+metric
|
||||||
|
try:
|
||||||
|
r = requests.get(url)
|
||||||
|
data = json.loads(r.text)
|
||||||
|
timestamp = getDateTimeFromISO8601String(data['timestamp']).replace(tzinfo=timezone.utc).timestamp()
|
||||||
|
if current_time - timestamp < interval * 2:
|
||||||
|
return data['value']
|
||||||
|
else:
|
||||||
|
logging.warning("WARNING: No recent load data available.")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
sys.stdout.flush()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_forced_mode(cur):
|
||||||
|
cur.execute("SELECT value, timestamp FROM set_mode WHERE name='mode'")
|
||||||
|
row = cur.fetchone()
|
||||||
|
data = dict(zip(['value', 'timestamp'], row))
|
||||||
|
timestamp = getDateTimeFromISO8601String(data['timestamp']).replace(tzinfo=timezone.utc).timestamp()
|
||||||
|
# We ignore old targets but never ignore absence modes
|
||||||
|
if data['value'] in targets and time.time() - timestamp > forced_mode_duration:
|
||||||
|
logging.debug("Ignoring old set mode.")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return data['value']
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@ -147,6 +196,111 @@ first_loop = True
|
|||||||
# print(row)
|
# print(row)
|
||||||
#sys.stdout.flush()
|
#sys.stdout.flush()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# if stop.is_set():
|
||||||
|
# httpd.shutdown()
|
||||||
|
# httpd.server_close()
|
||||||
|
# dbconn.close()
|
||||||
|
# break
|
||||||
|
|
||||||
|
if new_forced_mode is not None:
|
||||||
|
cursor.execute("INSERT OR REPLACE INTO set_mode (value) VALUES ('"+new_forced_mode+"')")
|
||||||
|
dbconn.commit()
|
||||||
|
logging.info("Switch to "+new_forced_mode)
|
||||||
|
target_name = new_forced_mode
|
||||||
|
new_forced_mode = None
|
||||||
|
# Force immediate action:
|
||||||
|
last_control_time = None
|
||||||
|
current_time = time.time()
|
||||||
|
current_date = datetime.datetime.now()
|
||||||
|
today_awake_time = current_date.replace(hour=int(awake_hour.split(':')[0]), minute=int(awake_hour.split(':')[1]), second=0, microsecond=0)
|
||||||
|
today_sleep_time = current_date.replace(hour=int(sleep_hour.split(':')[0]), minute=int(sleep_hour.split(':')[1]), second=0, microsecond=0)
|
||||||
|
forced_mode = get_forced_mode(cursor)
|
||||||
|
if forced_mode is not None and forced_mode in targets:
|
||||||
|
if target_name != forced_mode:
|
||||||
|
target_name = forced_mode
|
||||||
|
logging.info("Switch to "+forced_mode)
|
||||||
|
else:
|
||||||
|
if forced_mode == "long_absence":
|
||||||
|
if target_name != "target_frost_protection" or first_loop:
|
||||||
|
target_name = "target_frost_protection"
|
||||||
|
logging.info("Switch to "+target_name)
|
||||||
|
elif forced_mode == "short_absence" or first_loop:
|
||||||
|
if target_name != "target_sleep_temperature":
|
||||||
|
target_name = "target_sleep_temperature"
|
||||||
|
logging.info("Switch to "+target_name)
|
||||||
|
elif current_date > today_awake_time and current_date < today_sleep_time:
|
||||||
|
if target_name != "target_unconfirmed_awake_temperature" and target_name != "target_awake_temperature":
|
||||||
|
target_name = "target_unconfirmed_awake_temperature"
|
||||||
|
logging.info("Switch to unconfirmed awake mode.")
|
||||||
|
elif current_date < today_awake_time or current_date > today_sleep_time:
|
||||||
|
if target_name != "target_unconfirmed_sleep_temperature" and target_name != "target_sleep_temperature":
|
||||||
|
target_name = "target_unconfirmed_sleep_temperature"
|
||||||
|
logging.info("Switch to unconfirmed sleep mode.")
|
||||||
|
|
||||||
|
first_loop = False
|
||||||
|
|
||||||
|
# Load shedder
|
||||||
|
current_load = get_metric("Modane_elec_main_power", current_time, load_shedder_interval)
|
||||||
|
if current_load is None:
|
||||||
|
time.sleep(load_shedder_interval)
|
||||||
|
continue
|
||||||
|
elif max_load - current_load < load_margin:
|
||||||
|
logging.warning("Load too high: "+str(current_load)+"VA")
|
||||||
|
total_shedded = 0
|
||||||
|
for room in shedding_order:
|
||||||
|
current_state = relay_state(rooms_settings[room]["relays"])
|
||||||
|
if current_state != "Failed":
|
||||||
|
logging.debug("Got relay_state: '"+current_state+"'")
|
||||||
|
if current_state == "1":
|
||||||
|
result = set_relay(rooms_settings[room]["relays"], "off")
|
||||||
|
if result == "OK":
|
||||||
|
total_shedded += relays_load[rooms_settings[room]["relays"]]
|
||||||
|
if max_load - current_load - total_shedded < load_margin:
|
||||||
|
logging.info("Load should be back to normal.")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Thermostat
|
||||||
|
if last_control_time is None or current_time - last_control_time > relay_control_interval:
|
||||||
|
last_control_time = current_time
|
||||||
|
for room in rooms_settings:
|
||||||
|
if not rooms_settings[room]["enabled"]:
|
||||||
|
continue
|
||||||
|
target = rooms_settings[room][target_name]
|
||||||
|
logging.debug("Target: "+str(target))
|
||||||
|
temperature = get_metric(rooms_settings[room]["metric"], current_time, relay_control_interval)
|
||||||
|
if temperature is None:
|
||||||
|
continue
|
||||||
|
logging.debug(room+": "+str(temperature))
|
||||||
|
current_state = relay_state(rooms_settings[room]["relays"])
|
||||||
|
if current_state != "Failed":
|
||||||
|
logging.debug("Got relay_state: '"+current_state+"'")
|
||||||
|
if temperature < target - hysteresis:
|
||||||
|
if current_state == "0":
|
||||||
|
logging.info(room+": Target temperature is "+str(target))
|
||||||
|
logging.info(room+": Current temperature is "+str(temperature))
|
||||||
|
if current_load + relays_load[rooms_settings[room]["relays"]] + load_margin > max_load:
|
||||||
|
logging.warning(room+": Load too high cannot start heaters.")
|
||||||
|
else:
|
||||||
|
logging.info(room+": Starting heaters.")
|
||||||
|
set_relay(rooms_settings[room]["relays"], "on")
|
||||||
|
sys.stdout.flush()
|
||||||
|
else:
|
||||||
|
logging.debug("Relay already on.")
|
||||||
|
|
||||||
|
elif temperature > target + hysteresis:
|
||||||
|
if current_state == "1":
|
||||||
|
logging.info(room+": Target temperature is "+str(target))
|
||||||
|
logging.info(room+": Current temperature is "+str(temperature))
|
||||||
|
logging.info(room+": Stopping heaters.")
|
||||||
|
sys.stdout.flush()
|
||||||
|
set_relay(rooms_settings[room]["relays"], "off")
|
||||||
|
else:
|
||||||
|
logging.debug("Relay already off.")
|
||||||
|
time.sleep(load_shedder_interval)
|
||||||
|
|
||||||
|
logging.info("====== Ended successfully ======")
|
||||||
|
|
||||||
#import subprocess
|
#import subprocess
|
||||||
#from datetime import timezone
|
#from datetime import timezone
|
||||||
#import requests
|
#import requests
|
||||||
@ -204,55 +358,7 @@ first_loop = True
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
#def relay_state(relay):
|
|
||||||
# try:
|
|
||||||
# returned_output = subprocess.check_output(["./relay.py", relay, "status"])
|
|
||||||
# return returned_output.strip().decode("utf-8")
|
|
||||||
# except Exception as e:
|
|
||||||
# logging.error(e)
|
|
||||||
# logging.error("relay "+relay+" status: Failed to command relays board.")
|
|
||||||
# sys.stdout.flush()
|
|
||||||
# return "Failed"
|
|
||||||
#
|
|
||||||
#def set_relay(relay, state):
|
|
||||||
# try:
|
|
||||||
# returned_output = subprocess.check_output(["./relay.py", relay, state])
|
|
||||||
# logging.info("set relay "+relay+" to "+state+", new global status: "+returned_output.decode("utf-8").split('\n')[1])
|
|
||||||
# sys.stdout.flush()
|
|
||||||
# return "OK"
|
|
||||||
# except Exception as e:
|
|
||||||
# logging.error(e)
|
|
||||||
# logging.error("set relay "+relay+" to "+state+": Failed to command relays board.")
|
|
||||||
# sys.stdout.flush()
|
|
||||||
# return "KO"
|
|
||||||
#
|
|
||||||
#def get_metric(metric, current_time, interval):
|
|
||||||
# url = "http://localhost:3000/"+metric
|
|
||||||
# try:
|
|
||||||
# r = requests.get(url)
|
|
||||||
# data = json.loads(r.text)
|
|
||||||
# timestamp = getDateTimeFromISO8601String(data['timestamp']).replace(tzinfo=timezone.utc).timestamp()
|
|
||||||
# if current_time - timestamp < interval * 2:
|
|
||||||
# return data['value']
|
|
||||||
# else:
|
|
||||||
# logging.warning("WARNING: No recent load data available.")
|
|
||||||
# except Exception as e:
|
|
||||||
# logging.error(e)
|
|
||||||
# sys.stdout.flush()
|
|
||||||
# return None
|
|
||||||
#
|
|
||||||
#def get_forced_mode(cur):
|
|
||||||
# cur.execute("SELECT value, timestamp FROM set_mode WHERE name='mode'")
|
|
||||||
# row = cur.fetchone()
|
|
||||||
# data = dict(zip(['value', 'timestamp'], row))
|
|
||||||
# timestamp = getDateTimeFromISO8601String(data['timestamp']).replace(tzinfo=timezone.utc).timestamp()
|
|
||||||
# # We ignore old targets but never ignore absence modes
|
|
||||||
# if data['value'] in targets and time.time() - timestamp > forced_mode_duration:
|
|
||||||
# logging.debug("Ignoring old set mode.")
|
|
||||||
# return None
|
|
||||||
# else:
|
|
||||||
# return data['value']
|
|
||||||
#
|
|
||||||
#logging.info("====== Starting ======")
|
#logging.info("====== Starting ======")
|
||||||
#stop = Event()
|
#stop = Event()
|
||||||
#last_data = {}
|
#last_data = {}
|
||||||
@ -305,108 +411,4 @@ first_loop = True
|
|||||||
#webserver_thread = WebThread()
|
#webserver_thread = WebThread()
|
||||||
#webserver_thread.start()
|
#webserver_thread.start()
|
||||||
#
|
#
|
||||||
#while True:
|
|
||||||
# if stop.is_set():
|
|
||||||
# httpd.shutdown()
|
|
||||||
# httpd.server_close()
|
|
||||||
# dbconn.close()
|
|
||||||
# break
|
|
||||||
#
|
|
||||||
# if new_forced_mode is not None:
|
|
||||||
# cursor.execute("INSERT OR REPLACE INTO set_mode (value) VALUES ('"+new_forced_mode+"')")
|
|
||||||
# dbconn.commit()
|
|
||||||
# logging.info("Switch to "+new_forced_mode)
|
|
||||||
# target_name = new_forced_mode
|
|
||||||
# new_forced_mode = None
|
|
||||||
# # Force immediate action:
|
|
||||||
# last_control_time = None
|
|
||||||
# current_time = time.time()
|
|
||||||
# current_date = datetime.datetime.now()
|
|
||||||
# today_awake_time = current_date.replace(hour=int(awake_hour.split(':')[0]), minute=int(awake_hour.split(':')[1]), second=0, microsecond=0)
|
|
||||||
# today_sleep_time = current_date.replace(hour=int(sleep_hour.split(':')[0]), minute=int(sleep_hour.split(':')[1]), second=0, microsecond=0)
|
|
||||||
# forced_mode = get_forced_mode(cursor)
|
|
||||||
# if forced_mode is not None and forced_mode in targets:
|
|
||||||
# if target_name != forced_mode:
|
|
||||||
# target_name = forced_mode
|
|
||||||
# logging.info("Switch to "+forced_mode)
|
|
||||||
# else:
|
|
||||||
# if forced_mode == "long_absence":
|
|
||||||
# if target_name != "target_frost_protection" or first_loop:
|
|
||||||
# target_name = "target_frost_protection"
|
|
||||||
# logging.info("Switch to "+target_name)
|
|
||||||
# elif forced_mode == "short_absence" or first_loop:
|
|
||||||
# if target_name != "target_sleep_temperature":
|
|
||||||
# target_name = "target_sleep_temperature"
|
|
||||||
# logging.info("Switch to "+target_name)
|
|
||||||
# elif current_date > today_awake_time and current_date < today_sleep_time:
|
|
||||||
# if target_name != "target_unconfirmed_awake_temperature" and target_name != "target_awake_temperature":
|
|
||||||
# target_name = "target_unconfirmed_awake_temperature"
|
|
||||||
# logging.info("Switch to unconfirmed awake mode.")
|
|
||||||
# elif current_date < today_awake_time or current_date > today_sleep_time:
|
|
||||||
# if target_name != "target_unconfirmed_sleep_temperature" and target_name != "target_sleep_temperature":
|
|
||||||
# target_name = "target_unconfirmed_sleep_temperature"
|
|
||||||
# logging.info("Switch to unconfirmed sleep mode.")
|
|
||||||
#
|
|
||||||
# first_loop = False
|
|
||||||
#
|
|
||||||
# # Load shedder
|
|
||||||
# current_load = get_metric("Modane_elec_main_power", current_time, load_shedder_interval)
|
|
||||||
# if current_load is None:
|
|
||||||
# time.sleep(load_shedder_interval)
|
|
||||||
# continue
|
|
||||||
# elif max_load - current_load < load_margin:
|
|
||||||
# logging.warning("Load too high: "+str(current_load)+"VA")
|
|
||||||
# total_shedded = 0
|
|
||||||
# for room in shedding_order:
|
|
||||||
# current_state = relay_state(rooms_settings[room]["relays"])
|
|
||||||
# if current_state != "Failed":
|
|
||||||
# logging.debug("Got relay_state: '"+current_state+"'")
|
|
||||||
# if current_state == "1":
|
|
||||||
# result = set_relay(rooms_settings[room]["relays"], "off")
|
|
||||||
# if result == "OK":
|
|
||||||
# total_shedded += relays_load[rooms_settings[room]["relays"]]
|
|
||||||
# if max_load - current_load - total_shedded < load_margin:
|
|
||||||
# logging.info("Load should be back to normal.")
|
|
||||||
# break
|
|
||||||
#
|
|
||||||
# # Thermostat
|
|
||||||
# if last_control_time is None or current_time - last_control_time > relay_control_interval:
|
|
||||||
# last_control_time = current_time
|
|
||||||
# for room in rooms_settings:
|
|
||||||
# if not rooms_settings[room]["enabled"]:
|
|
||||||
# continue
|
|
||||||
# target = rooms_settings[room][target_name]
|
|
||||||
# logging.debug("Target: "+str(target))
|
|
||||||
# temperature = get_metric(rooms_settings[room]["metric"], current_time, relay_control_interval)
|
|
||||||
# if temperature is None:
|
|
||||||
# continue
|
|
||||||
# logging.debug(room+": "+str(temperature))
|
|
||||||
# current_state = relay_state(rooms_settings[room]["relays"])
|
|
||||||
# if current_state != "Failed":
|
|
||||||
# logging.debug("Got relay_state: '"+current_state+"'")
|
|
||||||
# if temperature < target - hysteresis:
|
|
||||||
# if current_state == "0":
|
|
||||||
# logging.info(room+": Target temperature is "+str(target))
|
|
||||||
# logging.info(room+": Current temperature is "+str(temperature))
|
|
||||||
# if current_load + relays_load[rooms_settings[room]["relays"]] + load_margin > max_load:
|
|
||||||
# logging.warning(room+": Load too high cannot start heaters.")
|
|
||||||
# else:
|
|
||||||
# logging.info(room+": Starting heaters.")
|
|
||||||
# set_relay(rooms_settings[room]["relays"], "on")
|
|
||||||
# sys.stdout.flush()
|
|
||||||
# else:
|
|
||||||
# logging.debug("Relay already on.")
|
|
||||||
#
|
|
||||||
# elif temperature > target + hysteresis:
|
|
||||||
# if current_state == "1":
|
|
||||||
# logging.info(room+": Target temperature is "+str(target))
|
|
||||||
# logging.info(room+": Current temperature is "+str(temperature))
|
|
||||||
# logging.info(room+": Stopping heaters.")
|
|
||||||
# sys.stdout.flush()
|
|
||||||
# set_relay(rooms_settings[room]["relays"], "off")
|
|
||||||
# else:
|
|
||||||
# logging.debug("Relay already off.")
|
|
||||||
# time.sleep(load_shedder_interval)
|
|
||||||
#
|
|
||||||
#logging.info("====== Ended successfully ======")
|
|
||||||
#
|
|
||||||
|
Loading…
Reference in New Issue
Block a user