Compare commits

...

2 Commits

Author SHA1 Message Date
a46405f4fd Refactor 2025-04-12 14:49:06 +01:00
1cb68fa011 Refactor 2025-04-04 23:43:03 +01:00
5 changed files with 371 additions and 236 deletions

15
src/climate.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "{name}",
"device_class": "climate",
"state_topic": "homeassistant/climate/{uid}/state",
"modes": ["heat", "off"],
"mode_command_topic": "{name}/heater/setmode",
"mode_state_topic": "{name}/heater/currentmode",
"min_temp": 7,
"max_temp": 30,
"temp_step": 0.5,
"current_temperature_topic": "{name}/heater/currenttemp",
"temperature_command_topic": "{name}/heater/settemp",
"temperature_state_topic": "{name}/heater/currentsettemp",
"action_topic": "{name}/heater/idleaction"
}

View File

@@ -1,238 +1,24 @@
import time
from pytevolve import Tevolve
import paho.mqtt.client as mqtt
import threading
import json
broker_address = "192.168.0.100"
from mqtt_manager import MqttManager
def on_disconnect(client, userdata, rc):
client.connect(broker_address)
def on_connect(client, userdata, flags, rc):
try:
# client.username_pw_set("admin", "bK2F2ZPjyyngmsN6R32s")
# client.username_pw_set(username="admin", password ="bK2F2ZPjyyngmsN6R32s")
client.connect(broker_address)
except:
time.sleep(10)
client.connect(client)
def on_message(client, userdata, message):
new_topic = str(message.topic)
if new_topic == "hallway/heater/settemp":
tevolve.set_temperature("3", str(message.payload.decode("utf-8")))
# Assume set temp success (Prevent debounce)
client.publish("hallway/heater/currentsettemp", payload=str(message.payload.decode("utf-8")), qos=0, retain=False)
if new_topic == "hallway/heater/setmode":
if str(message.payload.decode("utf-8")) == "heat":
mode = "manual"
# client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload="heat", qos=0, retain=False)
else:
mode = "off"
client.publish("hallway/heater/currentmode", payload="off", qos=0, retain=False)
client.publish("hallway/heater/idleaction", payload="off", qos=0, retain=False)
if mode == "manual":
if float(Tevolve.hallway_current_temp) > float(Tevolve.hallway_set_temp):
client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
else:
client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
Tevolve.setmode = mode
tevolve.set_mode("3")
if new_topic == "livingroom/heater/settemp":
tevolve.set_temperature("2", str(message.payload.decode("utf-8")))
# Assume set temp success (Prevent debounce)
client.publish("livingroom/heater/currentsettemp", payload=str(message.payload.decode("utf-8")), qos=0,
retain=False)
if new_topic == "livingroom/heater/setmode":
# print(str(message.payload.decode("utf-8")))
if str(message.payload.decode("utf-8")) == "heat":
mode = "manual"
client.publish("livingroom/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload="heat", qos=0, retain=False)
else:
mode = "off"
client.publish("livingroom/heater/currentmode", payload="off", qos=0, retain=False)
client.publish("livingroom/heater/idleaction", payload="off", qos=0, retain=False)
if mode == "manual":
if float(Tevolve.livingroom_current_temp) > float(Tevolve.livingroom_set_temp):
client.publish("livingroom/heater/idleaction", payload="idle", qos=0, retain=False)
else:
client.publish("livingroom/heater/idleaction", payload="heating", qos=0, retain=False)
Tevolve.setmode = mode
tevolve.set_mode("2")
if __name__ == '__main__':
if __name__ == "__main__":
tevolve = Tevolve()
devices = tevolve.get_devices()
tevolve.post_websocket()
time.sleep(1)
mqtt_manager = MqttManager()
t = threading.Thread(target=tevolve.create_websocket, daemon=True, args=())
t.start()
client = mqtt.Client("ryan-heating")
# client.username_pw_set("admin", "bK2F2ZPjyyngmsN6R32s")
client.connect(broker_address)
client.on_message = on_message
client.on_disconnect = on_disconnect
client.loop_start()
client.subscribe("hallway/heater/settemp")
client.subscribe("hallway/heater/setmode")
client.subscribe("livingroom/heater/settemp")
client.subscribe("livingroom/heater/setmode")
mqtt_manager.client.connect(heaters=devices["nodes"])
livingroom_status = tevolve.get_status("2")
hallway_status = tevolve.get_status("3")
tevolve.get_token()
tevolve.get_dev()
Tevolve.hallway_active = hallway_status["active"]
Tevolve.hallway_mode = hallway_status["mode"]
Tevolve.hallway_set_temp = hallway_status["stemp"]
Tevolve.hallway_current_temp = hallway_status["mtemp"]
# Tevolve.livingroom_active = livingroom_status["active"]
# Tevolve.livingroom_mode = livingroom_status["mode"]
# Tevolve.livingroom_set_temp = livingroom_status["stemp"]
# Tevolve.livingroom_current_temp = livingroom_status["mtemp"]
if Tevolve.livingroom_mode == "manual":
Tevolve.livingroom_mode = "heat"
if Tevolve.hallway_mode == "manual":
Tevolve.hallway_mode = "heat"
client.publish("hallway/heater/currenttemp", payload=Tevolve.hallway_current_temp, qos=0, retain=False)
client.publish("livingroom/heater/currenttemp", payload=Tevolve.livingroom_current_temp, qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload=Tevolve.hallway_mode, qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload=Tevolve.livingroom_mode, qos=0, retain=False)
client.publish("hallway/heater/currentsettemp", payload=Tevolve.hallway_set_temp, qos=0, retain=False)
client.publish("livingroom/heater/currentsettemp", payload=Tevolve.livingroom_set_temp, qos=0, retain=False)
# Setup initial hallway heater values
if Tevolve.hallway_mode == "off":
client.publish("hallway/heater/setmode", payload="off", qos=0, retain=False)
# client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
if Tevolve.hallway_mode == "manual":
if float(Tevolve.hallway_current_temp) >= float(Tevolve.hallway_set_temp):
client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
if float(Tevolve.hallway_set_temp) > float(Tevolve.hallway_current_temp):
client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
# Setup initial living room heater values
if Tevolve.livingroom_mode == "off":
client.publish("livingroom/heater/setmode", payload="off", qos=0, retain=False)
if Tevolve.livingroom_mode == "manual":
if float(Tevolve.livingroom_current_temp) >= float(Tevolve.livingroom_set_temp):
client.publish("livingroom/heater/idleaction", payload="idle", qos=0, retain=False)
if float(Tevolve.livingroom_set_temp) > float(Tevolve.livingroom_current_temp):
client.publish("livignroom/heater/idleaction", payload="heating", qos=0, retain=False)
while True:
if Tevolve.websocket_message != "":
if "/api/v2" in Tevolve.websocket_message:
print(Tevolve.websocket_message[30:-1])
m = json.loads(Tevolve.websocket_message[30:-1])
# print(m)
if m["path"] == "/htr/3/status":
Tevolve.hallway_active = m["body"]["active"]
Tevolve.hallway_mode = m["body"]["mode"]
Tevolve.hallway_set_temp = m["body"]["stemp"]
Tevolve.hallway_current_temp = m["body"]["mtemp"]
mqtt_manager.publish_discovery()
if Tevolve.hallway_mode == "off":
client.publish("hallway/heater/setmode", payload="off", qos=0, retain=False)
# client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
if Tevolve.hallway_mode == "manual":
if float(Tevolve.hallway_set_temp) > float(Tevolve.hallway_current_temp):
client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload="heat", qos=0, retain=False)
if float(Tevolve.hallway_set_temp) <= float(Tevolve.hallway_current_temp):
client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload="heat", qos=0, retain=False)
client.publish("hallway/heater/currentsettemp", payload=m["body"]["stemp"], qos=0, retain=False)
# Publish hallway current temperature
client.publish("hallway/heater/currenttemp", payload=m["body"]["mtemp"], qos=0, retain=False)
if m["path"] == "/htr/2/status":
Tevolve.livingroom_active = m["body"]["active"]
Tevolve.livingroom_mode = m["body"]["mode"]
Tevolve.livingroom_set_temp = m["body"]["stemp"]
Tevolve.livingroom_current_temp = m["body"]["mtemp"]
if Tevolve.livingroom_mode == "off":
client.publish("livingroom/heater/setmode", payload="off", qos=0, retain=False)
if Tevolve.livingroom_mode == "manual":
if float(Tevolve.livingroom_set_temp) > float(Tevolve.livingroom_current_temp):
client.publish("livingroom/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload="heat", qos=0, retain=False)
if float(Tevolve.livingroom_set_temp) <= float(Tevolve.livingroom_current_temp):
client.publish("livingroom/heater/idleaction", payload="idle", qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload="heat", qos=0, retain=False)
client.publish("livingroom/heater/currentsettemp", payload=m["body"]["stemp"], qos=0, retain=False)
# Publish hallway current temperature
client.publish("livingroom/heater/currenttemp", payload=m["body"]["mtemp"], qos=0, retain=False)
Tevolve.websocket_message = ""
time.sleep(1)
tevolve.get_sid()
# test.post_websocket()
# test.create_websocket()

238
src/main_old.py Normal file
View File

@@ -0,0 +1,238 @@
import time
from pytevolve import Tevolve
import paho.mqtt.client as mqtt
import threading
import json
broker_address = "192.168.0.100"
def on_disconnect(client, userdata, rc):
client.connect(broker_address)
def on_connect(client, userdata, flags, rc):
try:
# client.username_pw_set("admin", "bK2F2ZPjyyngmsN6R32s")
# client.username_pw_set(username="admin", password ="bK2F2ZPjyyngmsN6R32s")
client.connect(broker_address)
except:
time.sleep(10)
client.connect(client)
def on_message(client, userdata, message):
new_topic = str(message.topic)
if new_topic == "hallway/heater/settemp":
tevolve.set_temperature("3", str(message.payload.decode("utf-8")))
# Assume set temp success (Prevent debounce)
client.publish("hallway/heater/currentsettemp", payload=str(message.payload.decode("utf-8")), qos=0, retain=False)
if new_topic == "hallway/heater/setmode":
if str(message.payload.decode("utf-8")) == "heat":
mode = "manual"
# client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload="heat", qos=0, retain=False)
else:
mode = "off"
client.publish("hallway/heater/currentmode", payload="off", qos=0, retain=False)
client.publish("hallway/heater/idleaction", payload="off", qos=0, retain=False)
if mode == "manual":
if float(Tevolve.hallway_current_temp) > float(Tevolve.hallway_set_temp):
client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
else:
client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
Tevolve.setmode = mode
tevolve.set_mode("3")
if new_topic == "livingroom/heater/settemp":
tevolve.set_temperature("2", str(message.payload.decode("utf-8")))
# Assume set temp success (Prevent debounce)
client.publish("livingroom/heater/currentsettemp", payload=str(message.payload.decode("utf-8")), qos=0,
retain=False)
if new_topic == "livingroom/heater/setmode":
# print(str(message.payload.decode("utf-8")))
if str(message.payload.decode("utf-8")) == "heat":
mode = "manual"
client.publish("livingroom/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload="heat", qos=0, retain=False)
else:
mode = "off"
client.publish("livingroom/heater/currentmode", payload="off", qos=0, retain=False)
client.publish("livingroom/heater/idleaction", payload="off", qos=0, retain=False)
if mode == "manual":
if float(Tevolve.livingroom_current_temp) > float(Tevolve.livingroom_set_temp):
client.publish("livingroom/heater/idleaction", payload="idle", qos=0, retain=False)
else:
client.publish("livingroom/heater/idleaction", payload="heating", qos=0, retain=False)
Tevolve.setmode = mode
tevolve.set_mode("2")
if __name__ == '__main__':
tevolve = Tevolve()
tevolve.post_websocket()
time.sleep(1)
t = threading.Thread(target=tevolve.create_websocket, daemon=True, args=())
t.start()
client = mqtt.Client("ryan-heating")
# client.username_pw_set("admin", "bK2F2ZPjyyngmsN6R32s")
client.connect(broker_address)
client.on_message = on_message
client.on_disconnect = on_disconnect
client.loop_start()
client.subscribe("hallway/heater/settemp")
client.subscribe("hallway/heater/setmode")
client.subscribe("livingroom/heater/settemp")
client.subscribe("livingroom/heater/setmode")
livingroom_status = tevolve.get_status("2")
hallway_status = tevolve.get_status("3")
Tevolve.hallway_active = hallway_status["active"]
Tevolve.hallway_mode = hallway_status["mode"]
Tevolve.hallway_set_temp = hallway_status["stemp"]
Tevolve.hallway_current_temp = hallway_status["mtemp"]
# Tevolve.livingroom_active = livingroom_status["active"]
# Tevolve.livingroom_mode = livingroom_status["mode"]
# Tevolve.livingroom_set_temp = livingroom_status["stemp"]
# Tevolve.livingroom_current_temp = livingroom_status["mtemp"]
if Tevolve.livingroom_mode == "manual":
Tevolve.livingroom_mode = "heat"
if Tevolve.hallway_mode == "manual":
Tevolve.hallway_mode = "heat"
client.publish("hallway/heater/currenttemp", payload=Tevolve.hallway_current_temp, qos=0, retain=False)
client.publish("livingroom/heater/currenttemp", payload=Tevolve.livingroom_current_temp, qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload=Tevolve.hallway_mode, qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload=Tevolve.livingroom_mode, qos=0, retain=False)
client.publish("hallway/heater/currentsettemp", payload=Tevolve.hallway_set_temp, qos=0, retain=False)
client.publish("livingroom/heater/currentsettemp", payload=Tevolve.livingroom_set_temp, qos=0, retain=False)
# Setup initial hallway heater values
if Tevolve.hallway_mode == "off":
client.publish("hallway/heater/setmode", payload="off", qos=0, retain=False)
# client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
if Tevolve.hallway_mode == "manual":
if float(Tevolve.hallway_current_temp) >= float(Tevolve.hallway_set_temp):
client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
if float(Tevolve.hallway_set_temp) > float(Tevolve.hallway_current_temp):
client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
# Setup initial living room heater values
if Tevolve.livingroom_mode == "off":
client.publish("livingroom/heater/setmode", payload="off", qos=0, retain=False)
if Tevolve.livingroom_mode == "manual":
if float(Tevolve.livingroom_current_temp) >= float(Tevolve.livingroom_set_temp):
client.publish("livingroom/heater/idleaction", payload="idle", qos=0, retain=False)
if float(Tevolve.livingroom_set_temp) > float(Tevolve.livingroom_current_temp):
client.publish("livignroom/heater/idleaction", payload="heating", qos=0, retain=False)
while True:
if Tevolve.websocket_message != "":
if "/api/v2" in Tevolve.websocket_message:
print(Tevolve.websocket_message[30:-1])
m = json.loads(Tevolve.websocket_message[30:-1])
# print(m)
if m["path"] == "/htr/3/status":
Tevolve.hallway_active = m["body"]["active"]
Tevolve.hallway_mode = m["body"]["mode"]
Tevolve.hallway_set_temp = m["body"]["stemp"]
Tevolve.hallway_current_temp = m["body"]["mtemp"]
if Tevolve.hallway_mode == "off":
client.publish("hallway/heater/setmode", payload="off", qos=0, retain=False)
# client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
if Tevolve.hallway_mode == "manual":
if float(Tevolve.hallway_set_temp) > float(Tevolve.hallway_current_temp):
client.publish("hallway/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload="heat", qos=0, retain=False)
if float(Tevolve.hallway_set_temp) <= float(Tevolve.hallway_current_temp):
client.publish("hallway/heater/idleaction", payload="idle", qos=0, retain=False)
client.publish("hallway/heater/currentmode", payload="heat", qos=0, retain=False)
client.publish("hallway/heater/currentsettemp", payload=m["body"]["stemp"], qos=0, retain=False)
# Publish hallway current temperature
client.publish("hallway/heater/currenttemp", payload=m["body"]["mtemp"], qos=0, retain=False)
if m["path"] == "/htr/2/status":
Tevolve.livingroom_active = m["body"]["active"]
Tevolve.livingroom_mode = m["body"]["mode"]
Tevolve.livingroom_set_temp = m["body"]["stemp"]
Tevolve.livingroom_current_temp = m["body"]["mtemp"]
if Tevolve.livingroom_mode == "off":
client.publish("livingroom/heater/setmode", payload="off", qos=0, retain=False)
if Tevolve.livingroom_mode == "manual":
if float(Tevolve.livingroom_set_temp) > float(Tevolve.livingroom_current_temp):
client.publish("livingroom/heater/idleaction", payload="heating", qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload="heat", qos=0, retain=False)
if float(Tevolve.livingroom_set_temp) <= float(Tevolve.livingroom_current_temp):
client.publish("livingroom/heater/idleaction", payload="idle", qos=0, retain=False)
client.publish("livingroom/heater/currentmode", payload="heat", qos=0, retain=False)
client.publish("livingroom/heater/currentsettemp", payload=m["body"]["stemp"], qos=0, retain=False)
# Publish hallway current temperature
client.publish("livingroom/heater/currenttemp", payload=m["body"]["mtemp"], qos=0, retain=False)
Tevolve.websocket_message = ""
time.sleep(1)

86
src/mqtt_manager.py Normal file
View File

@@ -0,0 +1,86 @@
import json
from pathlib import Path
import paho.mqtt.client as mqtt
class MqttManager:
def __init__(self):
self.host = "192.168.0.100"
self.username = "connorroy"
self.password = "arkreactor7"
self.object_ids = None
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.client.username_pw_set(username=self.username, password=self.password)
# self.client.connect(self.host, 1883, 60)
self.client.loop_forever()
def mqtt_connect(self):
pass
def on_connect(self, client, userdata, flags, reason_code, properties, heaters=None):
self.object_ids = heaters
print(f"Connected with result code {reason_code}")
discovery_topic = "homeassistant/climate/"
json_payload = self._load_json()
for index, i in enumerate(self.object_ids):
json_topic = "hmd/climate/" + i["uid"]
self.client.publish(topic=discovery_topic + i["uid"] + "/config", qos=0, retain=False,
payload=json.dumps(json_payload[index]))
for device_index, device in enumerate(self.object_ids):
print(json_payload[device_index]["current_temperature_topic"])
self.client.publish(topic=json_payload[device_index]["current_temperature_topic"], qos=0, retain=False,
payload=json.dumps(json_payload[index]))
# # Subscribing in on_connect() means that if we lose the connection and
# # reconnect then subscriptions will be renewed.
# client.subscribe("$SYS/#")
def on_message(self, client, userdata, msg):
print(msg.topic + " " + str(msg.payload))
def publish_discovery(self):
discovery_topic = "homeassistant/climate/"
for i in self.object_ids:
self.client.publish(topic=discovery_topic + i["uid"] + "/config", qos=0, retain=False)
def _load_json(self):
path = Path(__file__).parent
json_list = []
with open(str(path) + "/climate.json") as j:
data = json.load(j)
for dev in self.object_ids:
new_data = data.copy()
for i in new_data:
if "{name}" in str(new_data.get(i)):
new_data[i] = new_data[i].replace("{name}", dev["name"])
elif "{uid}" in str(new_data.get(i)):
new_data[i] = new_data[i].replace("{uid}", dev["uid"])
json_list.append(new_data)
return json_list
# test = MqttManager()
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.

View File

@@ -23,6 +23,7 @@ class Tevolve:
self.token_primary = ""
self.token_refresh = ""
self.sid = ""
self.devices = []
setmode = ""
setTemperature = ""
@@ -112,13 +113,16 @@ class Tevolve:
def get_devices(self):
endpoint = "/devs/082e858131ff012c51/mgr/nodes"
endpoint = "/devs/"+self.dev_id+"/mgr/nodes"
header = {"Authorization": "Bearer " + self.token_primary}
header = {'content-type': 'application/json',
"Authorization": "Bearer " + self.token_primary}
devices_request = requests.get(str(self.api_url + endpoint), headers=headers).json()
devices_request = requests.get(str(self.api_url + endpoint), headers=header).json()
print(devices_request)
self.devices = devices_request
return self.devices
@@ -222,8 +226,8 @@ class Tevolve:
if response.status_code == 201 or response.status_code == 200:
pass
@staticmethod
def get_mode(heater_id):
def get_mode(self):
headers = {
'host': 'api-tevolve.termoweb.net',
'origin': 'https://tevolve.termoweb.net',
@@ -231,11 +235,11 @@ class Tevolve:
'accept': 'application/json, text/plain, */*',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) '
'Version/15.4 Safari/605.1.15',
'authorization': 'Bearer ' + Tevolve.token,
'authorization': 'Bearer ' + self.token_primary,
'referer': 'https://tevolve.termoweb.net/',
}
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/htr/" + heater_id + "/status"
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/htr/" + self.heater_id + "/status"
response = requests.get(url, headers=headers)
if response.status_code == 201 or response.status_code == 200:
@@ -244,7 +248,7 @@ class Tevolve:
return "heat"
def get_status(self):
def get_status(self, heater_id):
headers = {
'host': 'api-tevolve.termoweb.net',
@@ -257,7 +261,7 @@ class Tevolve:
'referer': 'https://tevolve.termoweb.net/',
}
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/status"
url = "https://api-tevolve.termoweb.net/api/v2/devs/"+self.dev_id+"/htr/"+str(heater_id)+"/status"
response = requests.get(url, headers=headers)
if response.status_code == 201 or response.status_code == 200:
@@ -297,8 +301,14 @@ if __name__ == '__main__':
test.get_devices()
for device in test.devices["nodes"]:
if device["name"] == "Hallway":
test.get_status(device["addr"])
test.get_sid()
test.get_status()
test.post_websocket()
test.create_websocket()