diff --git a/app/Routes/heating.py b/app/Routes/heating.py index 34d83a2..f473c24 100644 --- a/app/Routes/heating.py +++ b/app/Routes/heating.py @@ -1,19 +1,6 @@ from lib import migenie, utils - -def format_temp(temp:int): - """_summary_ - - Args: - temp (int): _description_ - - Returns: - _type_: _description_ - """ - temp = str(temp) - whole = temp[:-1] - decimal = temp[-1] - return float(f"{whole}.{decimal}") - +from flask_restful import reqparse +from time import sleep def get_heating_root()->dict: """_summary_ @@ -24,7 +11,6 @@ def get_heating_root()->dict: data = migenie.get_heating_data() return data, 200 - def get_heating_status()->dict: """_summary_ @@ -34,7 +20,7 @@ def get_heating_status()->dict: data = migenie.get_heating_data()['status'] heatingStatus = { "heatingOn": utils.is_item_on(data['currentSetpoint']), - "measuredRoomTemp": format_temp(data['measuredRoomTemp']), + "measuredRoomTemp": utils.format_temp(data['measuredRoomTemp']), "currentSetpoint": utils.convert_to_real_temp(data['currentSetpoint']), "lastTimerSetPoint": utils.convert_to_real_temp(data['lastTimerSetPoint']), "lastTimerDurationMinutes": data['lastTimerDurationMinutes'], @@ -43,4 +29,20 @@ def get_heating_status()->dict: } return heatingStatus, 200 - \ No newline at end of file + +def turn_on_heating()->dict: + parser = reqparse.RequestParser() # initialize + parser.add_argument('time', required=True) + parser.add_argument('temp', required=True) + time = int(parser.parse_args()['time']) + temp = float(parser.parse_args()['temp']) + data = migenie.turn_on_heating(temp, time) + sleep(2) + if get_heating_status()[0]['heatingOn']: + return data, 200 # return data with 200 OK + else: + return data, 400 + +def turn_off_heating()->dict: + data = migenie.turn_off_heating() + return data, 200 \ No newline at end of file diff --git a/app/Routes/water.py b/app/Routes/water.py index 122e218..6623537 100644 --- a/app/Routes/water.py +++ b/app/Routes/water.py @@ -1,5 +1,6 @@ from lib import migenie, utils - +from flask_restful import reqparse +from time import sleep def get_water_root()->dict: """_summary_ @@ -29,4 +30,22 @@ def get_water_status()->dict: } return waterStatus, 200 - \ No newline at end of file + +def boost_water()->dict: + parser = reqparse.RequestParser() # initialize + parser.add_argument('time',required=True) + time = int(parser.parse_args()['time']) + data = migenie.boost_water(time) + sleep(2) + if get_water_status()[0]['waterOn']: + return data, 200 # return data with 200 OK + else: + return data, 400 + +def turn_off_water()->dict: + data = migenie.turn_off_water() + sleep(2) + if get_water_status()[0]['waterOn']: + return data, 400 # return data with 200 OK + else: + return data, 200 \ No newline at end of file diff --git a/app/lib/migenie.py b/app/lib/migenie.py index 9f4510a..fe70c15 100644 --- a/app/lib/migenie.py +++ b/app/lib/migenie.py @@ -2,12 +2,15 @@ import requests from dotenv import load_dotenv import os load_dotenv() +from lib.utils import convert_to_real_temp, is_valid_time username = os.getenv("username") password = os.getenv("password") +root_url = "https://public.wcs.schneider-electric.ws/rpc/public_genie/" + def poll_genie(): - url = "https://public.wcs.schneider-electric.ws/rpc/public_genie/poll" + url = root_url+"poll" payload = "{}" headers = { 'User-Agent-Wiser': 'iPhoneTestTool;iOS6;WiserApp2.0.0', @@ -22,4 +25,54 @@ def get_heating_data(): def get_water_data(): data = poll_genie() - return data['updateData']['zones'][1] \ No newline at end of file + return data['updateData']['zones'][1] + +def boost_water(time:int): + if is_valid_time(time): + url = root_url+"apply_timer" + + payload = '{"zoneId": [1],"setPoint": 255,"durationMinutes": ' + str(time) + '}' + headers = { + 'User-Agent-Wiser': 'iPhoneTestTool;iOS6;WiserApp2.0.0', + 'Content-Type': 'application/javascript' + } + response = requests.request("POST", url, headers=headers, data=payload, auth=(username, password)) + return response.json() + else: + return {"Error":"Time must be multiples of 30"} + +def turn_off_water(): + url = root_url+"cancel_timer" + + payload = '{"zoneId": [1]}' + headers = { + 'User-Agent-Wiser': 'iPhoneTestTool;iOS6;WiserApp2.0.0', + 'Content-Type': 'application/javascript' + } + response = requests.request("POST", url, headers=headers, data=payload, auth=(username, password)) + return response.json() + +def turn_on_heating(temp:int, time): + temp = str(convert_to_real_temp(temp, True)) + if is_valid_time(time): + url = root_url+"adjust_setpoint" + payload = '{"zoneId": [0],"setpoint": ' +temp+',"durationMinutes": '+ str(time) + '}' + headers = { + 'User-Agent-Wiser': 'iPhoneTestTool;iOS6;WiserApp2.0.0', + 'Content-Type': 'application/javascript' + } + response = requests.request("POST", url, headers=headers, data=payload, auth=(username, password)) + return response.json() + else: + return {"Error":"Time must be multiples of 30"} + + +def turn_off_heating(): + url = root_url+"adjust_setpoint" + payload = '{"zoneId": [0],"setpoint": 0}' + headers = { + 'User-Agent-Wiser': 'iPhoneTestTool;iOS6;WiserApp2.0.0', + 'Content-Type': 'application/javascript' + } + response = requests.request("POST", url, headers=headers, data=payload, auth=(username, password)) + return response.json() \ No newline at end of file diff --git a/app/lib/utils.py b/app/lib/utils.py index de6bd09..1955f5d 100644 --- a/app/lib/utils.py +++ b/app/lib/utils.py @@ -1,6 +1,6 @@ import datetime -def convert_to_real_temp(migenie_value:int)->float: +def convert_to_real_temp(migenie_value:int, flip:bool=False)->float: """_summary_ Args: @@ -9,12 +9,23 @@ def convert_to_real_temp(migenie_value:int)->float: Returns: float: _description_ """ - start = [50,5] - if migenie_value == 0: - return 0.0 + if flip: + start = [50,5] + # [88,24] + if migenie_value == 0: + return 0.0 + else: + steps = migenie_value - start[1] + new_steps = steps + start[0] + migenie_val = new_steps + steps + return int(migenie_val) else: - steps = migenie_value - start[0] - return start[1] + .5*steps + start = [50,5] + if migenie_value == 0: + return 0.0 + else: + steps = migenie_value - start[0] + return start[1] + .5*steps def is_item_on(item_name:int)->bool: """_summary_ @@ -50,4 +61,25 @@ def format_time(date_time:int)->str: Returns: str: _description_ """ - return datetime.datetime.fromtimestamp(date_time).strftime('%H:%M:%S') \ No newline at end of file + return datetime.datetime.fromtimestamp(date_time).strftime('%H:%M:%S') + +def format_temp(temp:int): + """_summary_ + + Args: + temp (int): _description_ + + Returns: + _type_: _description_ + """ + temp = str(temp) + whole = temp[:-1] + decimal = temp[-1] + return float(f"{whole}.{decimal}") + +def is_valid_time(time:int): + is_valid = time / 30 + if is_valid.is_integer(): + return True + else: + return False \ No newline at end of file diff --git a/app/main.py b/app/main.py index 5a2ca45..6a8232b 100644 --- a/app/main.py +++ b/app/main.py @@ -12,6 +12,15 @@ def water_root(): @app.route('/water/status') def water_status(): return water.get_water_status() + +@app.route('/water/boost', methods = ['POST']) +def boost_water(): + return water.boost_water() + +@app.route('/water/turn_off', methods = ['POST']) +def turn_off_water(): + return water.turn_off_water() + @app.route('/heating') def heating_root(): @@ -21,5 +30,14 @@ def heating_root(): def heating_status(): return heating.get_heating_status() +@app.route('/heating/turn_on', methods = ['POST']) +def turn_on_heating(): + return heating.turn_on_heating() + +@app.route('/heating/turn_off', methods = ['POST']) +def turn_off_heating(): + return heating.turn_off_heating() + + if __name__ == '__main__': app.run(host='0.0.0.0') # run our Flask app \ No newline at end of file diff --git a/dockerfile b/dockerfile index 12db1e6..4b7a5e1 100644 --- a/dockerfile +++ b/dockerfile @@ -6,7 +6,7 @@ WORKDIR /app ENV PYTHONPATH=${PYTHONPATH}:${PWD} RUN pip3 install poetry RUN poetry config virtualenvs.create false -RUN poetry install --no-dev --no-root +RUN poetry install --only main --no-root CMD [ "python", "main.py"]