Initial Commit
This commit is contained in:
238
src/main.py
Normal file
238
src/main.py
Normal 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)
|
||||
|
||||
235
src/pytevolve.py
Normal file
235
src/pytevolve.py
Normal file
@@ -0,0 +1,235 @@
|
||||
import requests
|
||||
import json
|
||||
import threading
|
||||
import websocket
|
||||
import time
|
||||
|
||||
data = "username=1202283%40uad.ac.uk&password=24e76d8e4&grant_type=password"
|
||||
url = "https://api-tevolve.termoweb.net/client/token"
|
||||
|
||||
headers = {'content-type': 'application/x-www-form-urlencoded',
|
||||
'authorization': 'Basic NWM0OWRjZTk3NzUxMDM1MTUwNmM0MmRiOnRldm9sdmU='}
|
||||
dev_id = "082e858131ff012c51"
|
||||
|
||||
|
||||
class Tevolve:
|
||||
setmode = ""
|
||||
setTemperature = ""
|
||||
|
||||
token = None
|
||||
sid = ""
|
||||
websocket_url = ""
|
||||
mode = ""
|
||||
set_point = ""
|
||||
websocket_message = ""
|
||||
|
||||
hallway_mode = ""
|
||||
hallway_current_temp = ""
|
||||
hallway_set_temp = ""
|
||||
hallway_active = ""
|
||||
|
||||
livingroom_mode = ""
|
||||
livingroom_current_temp = ""
|
||||
livingroom_set_temp = ""
|
||||
livingroom_active = ""
|
||||
|
||||
@staticmethod
|
||||
def token_manager():
|
||||
|
||||
while Tevolve.token is None:
|
||||
|
||||
x = requests.post(url, headers=headers, data=data)
|
||||
|
||||
print(x)
|
||||
|
||||
if x.status_code == 200:
|
||||
Tevolve.token = x.json()["access_token"]
|
||||
else:
|
||||
time.sleep(30)
|
||||
|
||||
@staticmethod
|
||||
def get_sid():
|
||||
time.sleep(5)
|
||||
|
||||
url = "https://api-tevolve.termoweb.net/socket.io/?token=" + Tevolve.token + "&dev_id=082e858131ff012c51&EIO" \
|
||||
"=3&transport=polling"
|
||||
|
||||
payload = {}
|
||||
|
||||
response = requests.request("GET", url, data=payload)
|
||||
|
||||
if response.status_code == 200:
|
||||
|
||||
temp = response.text[5:]
|
||||
temp = json.loads(temp)
|
||||
|
||||
Tevolve.sid = temp['sid']
|
||||
else:
|
||||
Tevolve.token = None
|
||||
Tevolve.token_manager()
|
||||
|
||||
@staticmethod
|
||||
def post_websocket():
|
||||
|
||||
Tevolve.token_manager()
|
||||
Tevolve.get_sid()
|
||||
|
||||
|
||||
url = "https://api-tevolve.termoweb.net/socket.io/?token=" + Tevolve.token + "&dev_id=082e858131ff012c51&EIO" \
|
||||
"=3&transport=polling&t=Ntb6xXn" \
|
||||
"&sid=" + Tevolve.sid
|
||||
|
||||
payload = "401:40/api/v2/socket_io?token=" + Tevolve.token + "&dev_id=082e858131ff012c51"
|
||||
|
||||
headers = {
|
||||
'Cookie': "io=" + Tevolve.sid,
|
||||
'Content-Type': 'text/plain',
|
||||
'Connection': 'keep-alive'
|
||||
|
||||
}
|
||||
|
||||
requests.request("POST", url, headers=headers, data=payload)
|
||||
|
||||
@staticmethod
|
||||
def create_websocket():
|
||||
time.sleep(5)
|
||||
|
||||
websocket_url = "wss://api-tevolve.termoweb.net/socket.io/?token=" + Tevolve.token + "&dev_id=082e858131ff012c51&EIO=3&transport=websocket&sid=" + Tevolve.sid + ""
|
||||
|
||||
def on_message(ws, message):
|
||||
Tevolve.websocket_message = message
|
||||
|
||||
def on_open(ws):
|
||||
|
||||
def run():
|
||||
print("websocket (run)")
|
||||
counter = 0
|
||||
ws.send("2probe")
|
||||
time.sleep(2)
|
||||
ws.send(str("5"))
|
||||
while 1:
|
||||
ws.send("2")
|
||||
counter = counter + 1
|
||||
if counter >= 360:
|
||||
break
|
||||
time.sleep(10)
|
||||
|
||||
r = threading.Thread(target=run, daemon=True)
|
||||
r.start()
|
||||
|
||||
def on_close(ws, close_status_code, close_msg):
|
||||
print("WEB SOCKET ClOSED")
|
||||
Tevolve.post_websocket()
|
||||
Tevolve.create_websocket()
|
||||
|
||||
|
||||
def on_error(ws, err):
|
||||
print("WEB SOCKET ERROR")
|
||||
Tevolve.post_websocket()
|
||||
Tevolve.create_websocket()
|
||||
|
||||
ws = websocket.WebSocketApp(websocket_url)
|
||||
websocket.enableTrace(False)
|
||||
ws.on_message = on_message
|
||||
ws.on_open = on_open
|
||||
ws.on_close = on_close
|
||||
ws.on_error = on_error
|
||||
|
||||
ws.run_forever(ping_interval=10, ping_payload='42/api/v2/socket_io,["message","ping"]')
|
||||
|
||||
@staticmethod
|
||||
def set_mode(heater_id):
|
||||
|
||||
heater_id = heater_id
|
||||
mode = Tevolve.setmode
|
||||
headers = {
|
||||
'host': 'api-tevolve.termoweb.net',
|
||||
'origin': 'https://tevolve.termoweb.net',
|
||||
'content-type': 'application/json',
|
||||
'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,
|
||||
'referer': 'https://tevolve.termoweb.net/'
|
||||
|
||||
}
|
||||
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/htr/" + heater_id + "/status"
|
||||
|
||||
if mode == "heat":
|
||||
mode = "manual"
|
||||
|
||||
payload = json.dumps({
|
||||
"mode": mode
|
||||
})
|
||||
|
||||
response = requests.post(url, headers=headers, data=payload)
|
||||
if response.status_code == 201 or response.status_code == 200:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_mode(heater_id):
|
||||
headers = {
|
||||
'host': 'api-tevolve.termoweb.net',
|
||||
'origin': 'https://tevolve.termoweb.net',
|
||||
'content-type': 'application/json',
|
||||
'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,
|
||||
'referer': 'https://tevolve.termoweb.net/',
|
||||
|
||||
}
|
||||
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/htr/" + heater_id + "/status"
|
||||
|
||||
response = requests.get(url, headers=headers)
|
||||
if response.status_code == 201 or response.status_code == 200:
|
||||
mode = response.json()["mode"]
|
||||
if mode == "manual":
|
||||
return "heat"
|
||||
|
||||
@staticmethod
|
||||
def get_status(heater_id):
|
||||
|
||||
headers = {
|
||||
'host': 'api-tevolve.termoweb.net',
|
||||
'origin': 'https://tevolve.termoweb.net',
|
||||
'content-type': 'application/json',
|
||||
'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,
|
||||
'referer': 'https://tevolve.termoweb.net/',
|
||||
|
||||
}
|
||||
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/htr/" + heater_id + "/status"
|
||||
|
||||
response = requests.get(url, headers=headers)
|
||||
if response.status_code == 201 or response.status_code == 200:
|
||||
return response.json()
|
||||
|
||||
@staticmethod
|
||||
def set_temperature(heater_id, set_temperature):
|
||||
|
||||
headers = {
|
||||
'host': 'api-tevolve.termoweb.net',
|
||||
'origin': 'https://tevolve.termoweb.net',
|
||||
'content-type': 'application/json',
|
||||
'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,
|
||||
'referer': 'https://tevolve.termoweb.net/'
|
||||
|
||||
}
|
||||
|
||||
url = "https://api-tevolve.termoweb.net/api/v2/devs/082e858131ff012c51/htr/" + heater_id + "/status"
|
||||
|
||||
payload = json.dumps({
|
||||
"stemp": str(float(set_temperature)),
|
||||
"units": "C",
|
||||
"mode": "manual"
|
||||
})
|
||||
|
||||
response = requests.post(url, headers=headers, data=payload)
|
||||
if response.status_code == 201 or response.status_code == 200:
|
||||
pass
|
||||
Reference in New Issue
Block a user