Отдельные уставки на каждый контур. Управляем и насосом тоже
This commit is contained in:
+18
-16
@@ -6,31 +6,33 @@
|
|||||||
"contours": [
|
"contours": [
|
||||||
{
|
{
|
||||||
"sensor": "/devices/workroom_weather/controls/t",
|
"sensor": "/devices/workroom_weather/controls/t",
|
||||||
"control": "/devices/wb-gpio/controls/EXT1_R3A1"
|
"control": "/devices/wb-gpio/controls/EXT1_R3A6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"sensor": "/devices/bathroom_weather/controls/t",
|
"sensor": "/devices/bathroom_weather/controls/t",
|
||||||
"control": "/devices/wb-gpio/controls/EXT1_R3A2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sensor": "/devices/entrance_weather/controls/t",
|
|
||||||
"control": "/devices/wb-gpio/controls/EXT1_R3A3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sensor": "/devices/corridor_weather/controls/t",
|
|
||||||
"control": "/devices/wb-gpio/controls/EXT1_R3A4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"sensor": "/devices/techroom_weather/controls/t",
|
|
||||||
"control": "/devices/wb-gpio/controls/EXT1_R3A5"
|
"control": "/devices/wb-gpio/controls/EXT1_R3A5"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"sensor": "/devices/entrance_weather/controls/t",
|
||||||
|
"control": "/devices/wb-gpio/controls/EXT1_R3A1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sensor": "/devices/corridor_weather/controls/t",
|
||||||
|
"control": "/devices/wb-gpio/controls/EXT1_R3A2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sensor": "/devices/techroom_weather/controls/t",
|
||||||
|
"control": "/devices/wb-gpio/controls/EXT1_R3A4"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"sensor": "/devices/kitchen_weather/controls/t",
|
"sensor": "/devices/kitchen_weather/controls/t",
|
||||||
"control": "/devices/wb-gpio/controls/EXT1_R3A6"
|
"control": "/devices/wb-gpio/controls/EXT1_R3A3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"target_temperature": 21.0,
|
"target_temperature": 21.0,
|
||||||
"hysteresis": 0.5,
|
"hysteresis": 0.5,
|
||||||
"boiler_exhaust_t": "/devices/wb-w1/controls/28-000000860adf",
|
"boiler_exhaust_t": "/devices/wb-w1/controls/28-000000860adf",
|
||||||
"boiler_control": "/devices/wb-gpio/controls/EXT1_R3A8"
|
"pump_control": "/devices/wb-gpio/controls/EXT1_R3A8",
|
||||||
}
|
"boiler_control": "/devices/wb-gpio/controls/EXT1_R3A7"
|
||||||
|
}
|
||||||
|
|
||||||
+7
-1
@@ -8,10 +8,12 @@ class Contour:
|
|||||||
value_time = 0
|
value_time = 0
|
||||||
state = None
|
state = None
|
||||||
state_change_time = 0
|
state_change_time = 0
|
||||||
|
target_value = None
|
||||||
|
|
||||||
def __init__(self, config, logger):
|
def __init__(self, config, logger):
|
||||||
self.sensor_topic = config['sensor']
|
self.sensor_topic = config['sensor']
|
||||||
self.out_topic = config['control']
|
self.out_topic = config['control']
|
||||||
|
self.target_topic = config['target']
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
|
|
||||||
def update(self, value):
|
def update(self, value):
|
||||||
@@ -29,4 +31,8 @@ class Contour:
|
|||||||
if (self.state is None) or (time.time() - self.state_change_time > self.CHANGE_FREQ):
|
if (self.state is None) or (time.time() - self.state_change_time > self.CHANGE_FREQ):
|
||||||
self.state = state_value
|
self.state = state_value
|
||||||
self.logger.info("Contour " + self.sensor_topic + " changed state to " + str(self.state))
|
self.logger.info("Contour " + self.sensor_topic + " changed state to " + str(self.state))
|
||||||
|
|
||||||
|
def update_target(self, target_value):
|
||||||
|
self.target_value = target_value
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+17
-4
@@ -43,7 +43,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
def load_config():
|
def load_config():
|
||||||
"""Load configuration from file"""
|
"""Load configuration from file"""
|
||||||
global config, contours, target_temp, boiler_control, hysteresis
|
global config, contours, target_temp, boiler_control, hysteresis, pump_control
|
||||||
try:
|
try:
|
||||||
with open(CONFIG_FILE, 'r') as f:
|
with open(CONFIG_FILE, 'r') as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
@@ -52,6 +52,7 @@ def load_config():
|
|||||||
target_temp = float(config.get('target_temperature'))
|
target_temp = float(config.get('target_temperature'))
|
||||||
hysteresis = float(config.get('hysteresis'))
|
hysteresis = float(config.get('hysteresis'))
|
||||||
boiler_control = config.get('boiler_control')
|
boiler_control = config.get('boiler_control')
|
||||||
|
pump_control = config.get('pump_control')
|
||||||
if (boiler_control is None):
|
if (boiler_control is None):
|
||||||
logger.error("Boiler control not configured")
|
logger.error("Boiler control not configured")
|
||||||
exit(1)
|
exit(1)
|
||||||
@@ -74,6 +75,7 @@ def on_connect(client, userdata, flags, rc):
|
|||||||
# Subscribe to all temperature sensor topics
|
# Subscribe to all temperature sensor topics
|
||||||
for k in contours:
|
for k in contours:
|
||||||
client.subscribe(k.sensor_topic)
|
client.subscribe(k.sensor_topic)
|
||||||
|
client.subscribe(k.target_topic)
|
||||||
logger.info(f"Subscribed to: {k.sensor_topic}")
|
logger.info(f"Subscribed to: {k.sensor_topic}")
|
||||||
# and boiler exhaust topic
|
# and boiler exhaust topic
|
||||||
client.subscribe(config.get('boiler_exhaust_t'))
|
client.subscribe(config.get('boiler_exhaust_t'))
|
||||||
@@ -89,6 +91,10 @@ def on_message(client, userdata, msg):
|
|||||||
temperature = float(msg.payload.decode('utf-8'))
|
temperature = float(msg.payload.decode('utf-8'))
|
||||||
k.update(temperature)
|
k.update(temperature)
|
||||||
logger.debug(f"Updated {k.sensor_topic}: {temperature}°C")
|
logger.debug(f"Updated {k.sensor_topic}: {temperature}°C")
|
||||||
|
if (k.target_topic == msg.topic):
|
||||||
|
temperature = float(msg.payload.decode('utf-8'))
|
||||||
|
k.update_target(temperature)
|
||||||
|
logger.debug(f"Updated target {k.target_topic}: {temperature}°C")
|
||||||
if msg.topic == config.get('boiler_exhaust_t'):
|
if msg.topic == config.get('boiler_exhaust_t'):
|
||||||
boiler_exhaust_t = float(msg.payload.decode('utf-8'))
|
boiler_exhaust_t = float(msg.payload.decode('utf-8'))
|
||||||
logger.debug(f"Updated boiler exhaust: {boiler_exhaust_t}°C")
|
logger.debug(f"Updated boiler exhaust: {boiler_exhaust_t}°C")
|
||||||
@@ -106,12 +112,14 @@ def check_temperatures():
|
|||||||
# check boiler exhaust, turn off if too big
|
# check boiler exhaust, turn off if too big
|
||||||
if (boiler_exhaust_t > BOILER_EXHAUST_LIMIT):
|
if (boiler_exhaust_t > BOILER_EXHAUST_LIMIT):
|
||||||
logger.error("Boiler exhaust overheat")
|
logger.error("Boiler exhaust overheat")
|
||||||
# will open all contours (to force coolant circulation)
|
# will open all contours (to force coolant circulation),
|
||||||
|
# turn on the pump
|
||||||
# and turn off the boiler of course
|
# and turn off the boiler of course
|
||||||
for c in contours:
|
for c in contours:
|
||||||
# valves are normally-opened, so 0 means "open"
|
# valves are normally-opened, so 0 means "open"
|
||||||
mqtt_client.publish(c.out_topic, "0", retain=True)
|
mqtt_client.publish(c.out_topic, "0", retain=True)
|
||||||
mqtt_client.publish(boiler_control, "0", retain=True)
|
mqtt_client.publish(boiler_control, "0", retain=True)
|
||||||
|
mqtt_client.publish(pump_control, "1", retain=True)
|
||||||
return
|
return
|
||||||
#
|
#
|
||||||
sum_t = 0
|
sum_t = 0
|
||||||
@@ -137,10 +145,13 @@ def check_temperatures():
|
|||||||
# sensor is offline
|
# sensor is offline
|
||||||
if contour_t is None:
|
if contour_t is None:
|
||||||
contour_t = sum_t / count_t
|
contour_t = sum_t / count_t
|
||||||
if contour_t < target_temp - hysteresis:
|
target_t = target_temp
|
||||||
|
if not c.target_value is None:
|
||||||
|
target_t = c.target_value
|
||||||
|
if contour_t < target_t - hysteresis:
|
||||||
# should turn on contour
|
# should turn on contour
|
||||||
c.check_state(True)
|
c.check_state(True)
|
||||||
if contour_t > target_temp + hysteresis:
|
if contour_t > target_t + hysteresis:
|
||||||
# should turn off contour
|
# should turn off contour
|
||||||
c.check_state(False)
|
c.check_state(False)
|
||||||
if c.state:
|
if c.state:
|
||||||
@@ -161,8 +172,10 @@ def check_temperatures():
|
|||||||
|
|
||||||
if any_opened and time.time() - any_opened_start > BOILER_TURN_ON_AFTER:
|
if any_opened and time.time() - any_opened_start > BOILER_TURN_ON_AFTER:
|
||||||
mqtt_client.publish(boiler_control, "1", retain=True)
|
mqtt_client.publish(boiler_control, "1", retain=True)
|
||||||
|
mqtt_client.publish(pump_control, "1", retain=True)
|
||||||
else:
|
else:
|
||||||
mqtt_client.publish(boiler_control, "0", retain=True)
|
mqtt_client.publish(boiler_control, "0", retain=True)
|
||||||
|
mqtt_client.publish(pump_control, "0", retain=True)
|
||||||
|
|
||||||
def main_cycle():
|
def main_cycle():
|
||||||
"""Main 5-second cycle"""
|
"""Main 5-second cycle"""
|
||||||
|
|||||||
Reference in New Issue
Block a user