diff --git a/components/layout.py b/components/layout.py new file mode 100644 index 0000000..0858db3 --- /dev/null +++ b/components/layout.py @@ -0,0 +1,26 @@ +html = """ + + + Thermostate + + + + + + + + + +
+ %s +
+ + +""" \ No newline at end of file diff --git a/components/main.py b/components/main.py new file mode 100644 index 0000000..1787abb --- /dev/null +++ b/components/main.py @@ -0,0 +1,68 @@ +import constants +import globals + +_content = """ +

Thermostat

+
+ %s +
+%s +""" + +_header_buttons = """ + + +""" + +_by_week_content = """ +
+

Settings for all day

+
+ %s +
+
+ + + +
+
+""" + +def _format_edit_line(time, temp, i): + return """ +
+ + +
+ """ % (time, i, temp, i) + +def get_main(day_mode): + return _content % (get_header_buttons(day_mode), get_settings_with_id(day_mode)) + +def get_header_buttons(day_mode): + return _header_buttons % ( + "btn-primary" if day_mode == constants.BY_WEEK else "btn-secondary", + "btn-primary" if day_mode == constants.BY_DAY else "btn-secondary" + ) + +def _get_settings_container(oob): + return ("""
""" if not oob + else """
""") + "%s
" + +def get_settings_with_id(day_mode, oob = False): + return _get_settings_container(oob) % get_settings(day_mode) + +def get_settings(day_mode): + return get_byweek_settings() if day_mode == constants.BY_WEEK else "WIP" + +def get_byweek_settings(): + return _by_week_content % get_byweek_settings_content() + +def get_byweek_settings_content(): + content = "" + i = 0 + for setting in globals.by_week_settings: + content += _format_edit_line(setting.time.format(), setting.temp, i) + i += 1 + + return content \ No newline at end of file diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..40cc549 --- /dev/null +++ b/constants.py @@ -0,0 +1,2 @@ +BY_DAY = 1 +BY_WEEK = 2 \ No newline at end of file diff --git a/globals.py b/globals.py new file mode 100644 index 0000000..2a79edd --- /dev/null +++ b/globals.py @@ -0,0 +1,16 @@ +import constants +from type import Setting, Time + +global day_mode +global by_day_settings +global by_week_settings + + +def init(): + global day_mode + global by_day_settings + global by_week_settings + + by_day_settings = [] + by_week_settings = [Setting(Time(10,10), 20.5)] + day_mode = constants.BY_WEEK \ No newline at end of file diff --git a/helper.py b/helper.py new file mode 100644 index 0000000..4478254 --- /dev/null +++ b/helper.py @@ -0,0 +1,8 @@ +import uos + +def file_or_dir_exists(filename): + try: + uos.stat(filename) + return True + except OSError: + return False \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..bad3478 --- /dev/null +++ b/main.py @@ -0,0 +1,167 @@ +import os +import network +import socket +import time +from machine import Pin + +import constants +import globals +import helper +import components.layout as layout +import components.main as main +from secrets import secrets +from type import Setting, Time + +# while True: +# time.sleep_ms(200) + +globals.init() + +global day_mode_filename +day_mode_filename = "day_mode.txt" + +led = Pin('LED', Pin.OUT) +def blink_onboard_led(num_blinks): + for i in range(num_blinks): + led.value(1) + time.sleep_ms(200) + led.value(0) + time.sleep_ms(200) + +blink_onboard_led(1) + +if not helper.file_or_dir_exists(day_mode_filename): + print('File does not exist.') + with open(day_mode_filename, "w") as f: + f.write("byweek") + f.close() +else: + with open(day_mode_filename) as f: + content = f.readline() + + if content == "byweek": + print("byweek") + globals.day_mode = constants.BY_WEEK + else: + print("byday") + globals.day_mode = constants.BY_DAY + +ssid = secrets['ssid'] +password = secrets['pw'] + +wlan = network.WLAN(network.STA_IF) +wlan.active(True) +wlan.connect(ssid, password) + +max_wait = 10 +while max_wait > 0: + if wlan.status() < 0 or wlan.status() >= 3: + break + max_wait -= 1 + print('waiting for connection...') + time.sleep(1) + + +if wlan.status() != 3: + blink_onboard_led(3) + raise RuntimeError('network connection failed') +else: + print('connected') + status = wlan.ifconfig() + print( 'ip = ' + status[0] ) + +blink_onboard_led(2) + +addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] + +s = socket.socket() +s.bind(addr) +s.listen(1) + +print('listening on', addr) + +def result_ok(cl, response = None): + cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') + cl.send(response if response is not None else "Ok") + cl.close() + +def result_notfound(cl, response = None): + cl.send('HTTP/1.0 404 NotFound\r\nContent-type: text/html\r\n\r\n') + cl.send(response if response is not None else "Not Found") + cl.close() + +def check_header_button_endpoints(cl, request): + if request.find('/set_by_week') == 6: + set_day_mode(constants.BY_WEEK) + result_ok(cl, main.get_header_buttons(day_mode = globals.day_mode) + main.get_settings_with_id(day_mode = globals.day_mode, oob = True)) + return True + elif request.find('/set_by_day') == 6: + set_day_mode(constants.BY_DAY) + result_ok(cl, main.get_header_buttons(day_mode = globals.day_mode) + main.get_settings_with_id(day_mode = globals.day_mode, oob = True)) + return True + + return False + +def check_by_week_endpoints(cl, request): + if request.find('/add_by_week') == 6: + globals.by_week_settings.append(Setting(Time(10,0), 22)) + result_ok(cl, main.get_byweek_settings_content()) + return True + +def set_day_mode(mode): + global day_mode_filename + if mode == constants.BY_WEEK: + globals.day_mode = constants.BY_WEEK + elif mode == constants.BY_DAY: + globals.day_mode = constants.BY_DAY + else: + return + + with open(day_mode_filename, "w") as f: + value = "byday" if mode == constants.BY_DAY else "byweek" + print("Setting day mode to " + value) + f.write(value) + f.close() + +# Listen for connections +while True: + cl, addr = s.accept() + try: + print('client connected from', addr) + request = cl.recv(1024) + print(request) + + request = str(request) + + if request.find('/ ') == 6: + response = layout.html % main.get_main(day_mode = globals.day_mode) + + result_ok(cl, response) + elif request.find('/light/on') == 6: + print("led on") + led.value(1) + + response = layout.html % main.get_main(day_mode = globals.day_mode) + result_ok(cl, response) + elif request.find('/light/off') == 6: + print("led off") + led.value(0) + + response = layout.html % main.get_main(day_mode = globals.day_mode) + result_ok(cl, response) + elif request.find('/exit') == 6: + print("exiting") + blink_onboard_led(5) + s.close() + break + elif check_header_button_endpoints(cl, request): + pass + elif check_by_week_endpoints(cl, request): + pass + else: + result_notfound(cl) + + + except OSError as e: + cl.close() + print('connection closed') \ No newline at end of file diff --git a/type.py b/type.py new file mode 100644 index 0000000..e73527d --- /dev/null +++ b/type.py @@ -0,0 +1,14 @@ +class Time: + + def __init__(self, hour, minute): + self.hour = hour + self.minute = minute + + def format(self): + return "%02d:%02d" % (self.hour, self.minute) + +class Setting: + + def __init__(self, time, temp): + self.time = time + self.temp = temp