diff --git a/README.md b/README.md deleted file mode 100644 index f90de4d..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# GrowSystem - diff --git a/REDME.md b/REDME.md deleted file mode 100644 index bc52edf..0000000 --- a/REDME.md +++ /dev/null @@ -1,3 +0,0 @@ -# Show output on terminal # -`minicom -b 115200 -o -D /dev/cu.usbmodem3301` - diff --git a/bh1750.old_1/__init__.py b/bh1750.old_1/__init__.py deleted file mode 100644 index ab5e217..0000000 --- a/bh1750.old_1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .bh1750 import BH1750 diff --git a/bh1750.old_1/bh1750.py b/bh1750.old_1/bh1750.py deleted file mode 100644 index 21cebbe..0000000 --- a/bh1750.old_1/bh1750.py +++ /dev/null @@ -1,118 +0,0 @@ -# https://github.com/flrrth/pico-bh1750 - -import math - -from micropython import const -from utime import sleep_ms - - -class BH1750: - """Class for the BH1750 digital Ambient Light Sensor - - The datasheet can be found at https://components101.com/sites/default/files/component_datasheet/BH1750.pdf - """ - - MEASUREMENT_MODE_CONTINUOUSLY = const(1) - MEASUREMENT_MODE_ONE_TIME = const(2) - - RESOLUTION_HIGH = const(0) - RESOLUTION_HIGH_2 = const(1) - RESOLUTION_LOW = const(2) - - MEASUREMENT_TIME_DEFAULT = const(69) - MEASUREMENT_TIME_MIN = const(31) - MEASUREMENT_TIME_MAX = const(254) - - def __init__(self, address, i2c): - self._address = address - self._i2c = i2c - self._measurement_mode = BH1750.MEASUREMENT_MODE_ONE_TIME - self._resolution = BH1750.RESOLUTION_HIGH - self._measurement_time = BH1750.MEASUREMENT_TIME_DEFAULT - - self._write_measurement_time() - self._write_measurement_mode() - - def configure(self, measurement_mode: int, resolution: int, measurement_time: int): - """Configures the BH1750. - - Keyword arguments: - measurement_mode -- measure either continuously or once - resolution -- return measurements in either high, high2 or low resolution - measurement_time -- the duration of a single measurement - """ - if measurement_time not in range(BH1750.MEASUREMENT_TIME_MIN, BH1750.MEASUREMENT_TIME_MAX + 1): - raise ValueError("measurement_time must be between {0} and {1}" - .format(BH1750.MEASUREMENT_TIME_MIN, BH1750.MEASUREMENT_TIME_MAX)) - - self._measurement_mode = measurement_mode - self._resolution = resolution - self._measurement_time = measurement_time - - self._write_measurement_time() - self._write_measurement_mode() - - def _write_measurement_time(self): - buffer = bytearray(1) - - high_bit = 1 << 6 | self._measurement_time >> 5 - low_bit = 3 << 5 | (self._measurement_time << 3) >> 3 - - buffer[0] = high_bit - self._i2c.writeto(self._address, buffer) - - buffer[0] = low_bit - self._i2c.writeto(self._address, buffer) - - def _write_measurement_mode(self): - buffer = bytearray(1) - - buffer[0] = self._measurement_mode << 4 | self._resolution - self._i2c.writeto(self._address, buffer) - sleep_ms(24 if self._measurement_time == BH1750.RESOLUTION_LOW else 180) - - def reset(self): - """Clear the illuminance data register.""" - self._i2c.writeto(self._address, bytearray(b'\x07')) - - def power_on(self): - """Powers on the BH1750.""" - self._i2c.writeto(self._address, bytearray(b'\x01')) - - def power_off(self): - """Powers off the BH1750.""" - self._i2c.writeto(self._address, bytearray(b'\x00')) - - @property - def measurement(self) -> float: - """Returns the latest measurement.""" - if self._measurement_mode == BH1750.MEASUREMENT_MODE_ONE_TIME: - self._write_measurement_mode() - - buffer = bytearray(2) - self._i2c.readfrom_into(self._address, buffer) - lux = (buffer[0] << 8 | buffer[1]) / (1.2 * (BH1750.MEASUREMENT_TIME_DEFAULT / self._measurement_time)) - - if self._resolution == BH1750.RESOLUTION_HIGH_2: - return lux / 2 - else: - return lux - - def measurements(self) -> float: - """This is a generator function that continues to provide the latest measurement. Because the measurement time - is greatly affected by resolution and the configured measurement time, this function attemts to calculate the - appropriate sleep time between measurements. - - Example usage: - - for measurement in bh1750.measurements(): # bh1750 is an instance of this class - print(measurement) - """ - while True: - yield self.measurement - - if self._measurement_mode == BH1750.MEASUREMENT_MODE_CONTINUOUSLY: - base_measurement_time = 16 if self._measurement_time == BH1750.RESOLUTION_LOW else 120 - sleep_ms(math.ceil(base_measurement_time * self._measurement_time / BH1750.MEASUREMENT_TIME_DEFAULT)) - - diff --git a/device_info.py b/device_info.py deleted file mode 100644 index 65ab51a..0000000 --- a/device_info.py +++ /dev/null @@ -1,62 +0,0 @@ -import network - - -class DeviceInfo: - - # Device Infos - name = "Dev Device 1" - - token = "PC]-0Bmp83h7F5#U!D6KJ(A&" - - server_url = 'api.growsystem.muelleronline.org' - - wlan_ssid = 'Oppa-95.lan' - wlan_pw = '95%04-MM' - - sensors = [ - { - 'type': 'moisture', - 'pin_int': 26 - }, - { - 'type': 'ambilight', - 'pin_int': 8, # for compatibility only - 'pin_int_sda': 8, - 'pin_int_scl': 9 - }, - - - # { - # 'type': 'dht22', - # 'pin_int': 15 - # } - ] - - read_secs = 5 - # Device Infos End - - wlan = network.WLAN(network.STA_IF) - - def get_macaddress(self): - return self._format_mac(self.wlan.config('mac').hex()) - - def get_ipaddress(self): - return self.wlan.ifconfig()[0] - - def get_all_device_infos(self): - return { - 'name': self.name, - 'mac_address': self.get_macaddress(), - 'ip_address': self.get_ipaddress(), - 'token': self.token} - - def _format_mac(self, mac): - # Split the MAC address into pairs of two characters each - pairs = [mac[i:i+2] for i in range(0, len(mac), 2)] - # Join the pairs with colons to create the formatted MAC address - formatted_mac = ":".join(pairs) - return formatted_mac - - - - \ No newline at end of file diff --git a/grow_system.py b/grow_system.py deleted file mode 100644 index 3528ea9..0000000 --- a/grow_system.py +++ /dev/null @@ -1,78 +0,0 @@ -import time -from moisture_sensor import MoistureSensor -from dht22 import TemperatureHumiditySensor -from ambilight_sensor import AmbilightSensor -from sensor_data_manager import SensorDataManager -from grow_system_api import GrowSystemApi -from device_info import DeviceInfo - - -class GrowSystem: - - grow_system_api = GrowSystemApi() - - # moisture_sensor = None - # temperature_humidity_sensor = None - - sensors = [] - - most_recent_values = [] - - sensor_data_manager = None - - device_id = None - - device_info = DeviceInfo() - - def __init__(self, settings): - for sensor in self.device_info.sensors: - print("") - print("Initialize sensor:") - print(sensor) - sensor_type = sensor['type'] - if sensor_type == 'moisture': - print("Found sensor of type moisture") - self.sensors.append(MoistureSensor(sensor)) - elif sensor_type == 'dht22': - print("Found sensor of type DHT22") - self.sensors.append(TemperatureHumiditySensor(sensor)) - elif sensor_type == 'ambilight': - print("Found sensor of type GY302/BH1750") - self.sensors.append(AmbilightSensor(sensor)) - else: - print("No sensor type configured for: " + sensor['type']) - - #if not self.moisture_sensor: - # self.moisture_sensor = MoistureSensor(settings['moisture_sensor']) - - #if not self.temperature_humidity_sensor: - # self.temperature_humidity_sensor = TemperatureHumiditySensor(settings['temperature_humidity_sensor']) - - def start(self): - print("Say the server hello...") - result = self.grow_system_api.say_hello() - message = result['message'] - - if message != 'OK': - print("Device not activated. Stopping") - return - - self.device_id = result['data']['device_id'] - self.sensor_data_manager = SensorDataManager(self.device_id) - - print("Start reading sensors ...") - while True: - # Reset data - self.most_recent_values = [] - - for sensor in self.sensors: - print("Read sensor of type " + sensor.type + " at pin " + str(sensor.sensor_pin_int)) - sensor.read() - for measurement in sensor.most_recent_values: - print(f"Got {measurement['value']} {measurement['unit']} ({measurement['type']})") - self.most_recent_values = self.most_recent_values + sensor.most_recent_values - - self.sensor_data_manager.handleData(self.most_recent_values) - - time.sleep(self.device_info.read_secs) - diff --git a/grow_system_api.py b/grow_system_api.py deleted file mode 100644 index 0e3376c..0000000 --- a/grow_system_api.py +++ /dev/null @@ -1,31 +0,0 @@ -from http_client import HTTPClient -from device_info import DeviceInfo -import json - - -class GrowSystemApi: - - http_client = HTTPClient() - - device_info = DeviceInfo() - - base_url = '' - - def __init__(self): - self.base_url = self.device_info.server_url - - def say_hello(self): - response = self.http_client.post(self.base_url + "/api/device", self._get_device_data()) - print(response.text) - jsonResult = json.loads(response.text) - print(jsonResult) - return jsonResult; - - def send_measurements(self, device_id, data): - url = self.base_url + "/api/device/" + str(device_id) + "/sensor-log" - response = self.http_client.post(url, data) - return json.loads(response.text) - - def _get_device_data(self): - return self.device_info.get_all_device_infos() - diff --git a/gs/classes/a_sensors.py b/gs/classes/a_sensors.py new file mode 100644 index 0000000..af4244e --- /dev/null +++ b/gs/classes/a_sensors.py @@ -0,0 +1,13 @@ +class Sensors: + # this is a parent class for the Sensor classes + sensor_pin_int = -1 + + sensor = None + + type = "unset" + + def __init__(self, settings): + self.type = settings['type'] + print("Initialize " + self.type + " sensor. Sensor pin is: " + str(settings['pin_int'])) + + diff --git a/gs/classes/http_request.py b/gs/classes/http_request.py new file mode 100644 index 0000000..c85063c --- /dev/null +++ b/gs/classes/http_request.py @@ -0,0 +1,72 @@ +import json +import ure as re + + +class HttpRequest: + + METHOD = { + "GET": "GET", + "POST": "POST" + } + + method = '' + path = '' + raw_content = '' + headers = {} + + def __init__(self, request): + self.original_request = request + # self.method = method + # self.path = path + # self.headers = headers + # self.raw_content = content + print("http request initialized") + self.parse_request(request) + + def parse_request(self, request): + # Split the request into lines + lines = request.decode().split('\r\n') + + # Extract method, path, and HTTP version from the first line + self.method, self.path, _ = lines[0].split() + + # Parse headers + for line in lines[1:]: + if not line: + break # Empty line indicates end of headers + key, value = line.split(': ', 1) + self.headers[key] = value + + # Content is assumed to be in the last line + self.raw_content = lines[-1] + + def get_content_json(self): + # Parse the POST request content into a dictionary + parsed_content = {} + pairs = self.raw_content.split('&') + for pair in pairs: + key, value = pair.split('=') + parsed_content[key] = value + + # Encode the values in the dictionary + encoded_content = {} + for key, value in parsed_content.items(): + encoded_value = re.sub(r'%([0-9A-Fa-f]{2})', lambda m: chr(int(m.group(1), 16)), value) + encoded_content[key] = encoded_value + + return encoded_content + + def __str__(self): + return { + "method": self.method, + "headers": self.headers, + "content": self.raw_content, + "content_json": self.get_content_json() + } + + + + + + + diff --git a/sensors.py b/gs/classes/sensors.py similarity index 98% rename from sensors.py rename to gs/classes/sensors.py index 23ad803..af4244e 100644 --- a/sensors.py +++ b/gs/classes/sensors.py @@ -10,4 +10,4 @@ class Sensors: self.type = settings['type'] print("Initialize " + self.type + " sensor. Sensor pin is: " + str(settings['pin_int'])) - \ No newline at end of file + diff --git a/ambilight_sensor.py b/gs/classes/sensors/ambilight_sensor.py similarity index 95% rename from ambilight_sensor.py rename to gs/classes/sensors/ambilight_sensor.py index c8f0a3c..df1d966 100644 --- a/ambilight_sensor.py +++ b/gs/classes/sensors/ambilight_sensor.py @@ -1,4 +1,4 @@ -from sensors import Sensors +from gs.classes.a_sensors import Sensors from machine import Pin, I2C from utime import sleep from lib.bh1750 import BH1750 @@ -32,3 +32,4 @@ class AmbilightSensor(Sensors): print('Ambilight Error reading temperature/humidity. Check wires') print() + diff --git a/dht22.py b/gs/classes/sensors/dht22.py similarity index 96% rename from dht22.py rename to gs/classes/sensors/dht22.py index c022666..464b31d 100644 --- a/dht22.py +++ b/gs/classes/sensors/dht22.py @@ -1,4 +1,4 @@ -from sensors import Sensors +from gs.classes.a_sensors import Sensors from dht import DHT22 from machine import ADC, Pin @@ -34,3 +34,4 @@ class TemperatureHumiditySensor(Sensors): except OSError: print('DHT22 Error reading temperature/humidity. Check wires') print() + diff --git a/moisture_sensor.py b/gs/classes/sensors/moisture_sensor.py similarity index 96% rename from moisture_sensor.py rename to gs/classes/sensors/moisture_sensor.py index e11ca76..145cf9a 100644 --- a/moisture_sensor.py +++ b/gs/classes/sensors/moisture_sensor.py @@ -1,5 +1,5 @@ # Moisture Sensor Class -from sensors import Sensors +from gs.classes.a_sensors import Sensors from machine import ADC, Pin @@ -36,4 +36,4 @@ class MoistureSensor(Sensors): normalized_value = self.normalize_sensor_value(raw_value) return round(100 - normalized_value * 100, 1) - \ No newline at end of file + diff --git a/gs/config/app.py b/gs/config/app.py new file mode 100644 index 0000000..f066dbd --- /dev/null +++ b/gs/config/app.py @@ -0,0 +1,2 @@ +api_url = 'api.growsystem.muellerdev.kozow.com' +read_secs = 1 * 60 diff --git a/gs/config/examples/device_config.json b/gs/config/examples/device_config.json new file mode 100644 index 0000000..901d060 --- /dev/null +++ b/gs/config/examples/device_config.json @@ -0,0 +1 @@ +{"sensors": [{"pin_int": 15, "type": "dht22"}, {"pin_int": 26, "type": "moisture"}], "device_id": 9, "name": "Fulltest1", "token": "uStIrOgScrpbUr0Y", "user_id": 1} \ No newline at end of file diff --git a/gs/config/examples/initial_config.py b/gs/config/examples/initial_config.py new file mode 100644 index 0000000..9cd4fe6 --- /dev/null +++ b/gs/config/examples/initial_config.py @@ -0,0 +1 @@ +config = {"ssid": "Oppa-95.lan", "user_id": "1", "password": "95%04-MM", "pin": 9534} \ No newline at end of file diff --git a/gs/device_info.py b/gs/device_info.py new file mode 100644 index 0000000..93f89aa --- /dev/null +++ b/gs/device_info.py @@ -0,0 +1,66 @@ +import network +import json + + +class DeviceInfo: + + wlan = network.WLAN(network.STA_IF) + + app_version = "1.0.0" + + def get_macaddress(self): + return self._format_mac(self.wlan.config('mac').hex()) + + def get_ipaddress(self): + return self.wlan.ifconfig()[0] + + def get_all_device_infos(self): + return { + 'name': self.get_name(), + 'mac_address': self.get_macaddress(), + 'ip_address': self.get_ipaddress(), + 'token': self.get_token()} + + def config(self, filepath=None): + return self._loadJsonConfig(filepath) + + def app_config(self): + import gs.config.app as app_config + return app_config + + def server_url(self): + return self.app_config().api_url + + def get_token(self): + return self.config()['token'] if self.config() and self.config()['token'] else '' + + def get_name(self): + return self.config()['name'] if self.config() and self.config()['name'] else '' + + def get_device_id(self): + return self.config()['device_id'] if self.config() and self.config()['device_id'] else '' + + def _format_mac(self, mac): + # Split the MAC address into pairs of two characters each + pairs = [mac[i:i+2] for i in range(0, len(mac), 2)] + # Join the pairs with colons to create the formatted MAC address + formatted_mac = ":".join(pairs) + return formatted_mac + + def _loadJsonConfig(self, filepath=None): + filepath = filepath if filepath else '/gs/config/device_config.json' + try: + file = open(filepath, "r") + json_content = file.read() + return json.loads(json_content) + except OSError: # open failed + print("File not found: ", filepath) + return None + + #with open(filepath, 'r') as file: + # json_content = file.read() + #return json.loads(json_content) + + + + \ No newline at end of file diff --git a/gs/exceptions/not_subscriptable_error.py b/gs/exceptions/not_subscriptable_error.py new file mode 100644 index 0000000..19fa115 --- /dev/null +++ b/gs/exceptions/not_subscriptable_error.py @@ -0,0 +1,2 @@ +class NotSubscriptableError(Exception): + pass diff --git a/gs/grow_system_api.py b/gs/grow_system_api.py new file mode 100644 index 0000000..2c85799 --- /dev/null +++ b/gs/grow_system_api.py @@ -0,0 +1,64 @@ +from gs.http_client import HTTPClient +from gs.device_info import DeviceInfo +from gs.wlan_client import WlanClient +import json +import gs.config.initial_config as ic + + +class GrowSystemApi: + + http_client = HTTPClient() + + device_info = DeviceInfo() + + base_url = '' + + def __init__(self): + self.base_url = self.device_info.server_url() + self.connect_wifi(ic.config['ssid'], ic.config['password']) + + # config = self.device_info.config() + # print("Config:", config) + # print("Test", config['test']) + + def activate(self, config): + print("ACtivate config:", config) + data = self._get_device_data() + data.update({ + 'user_id': 1, + 'pin': config['pin'] + }) + print("activate ...", data) + response = self.http_client.post(self.base_url + "/api/device/activate", data) + print("REsponse ...", response) + return self._get_json_encoded(response.text) + + def say_hello(self): + response = self.http_client.post(self.base_url + "/api/device", self._get_device_data()) + print(response.text) + jsonResult = json.loads(response.text) + print(jsonResult) + return jsonResult; + + def send_measurements(self, device_id, data): + url = self.base_url + "/api/device/" + str(device_id) + "/sensor-log" + response = self.http_client.post(url, data) + try: + return json.loads(response.text) + except ValueError as e: + print("JSON Value error raised after sending measurements") + except Exception as e: + print("Exception raised while sending measurements", e) + return response + + def _get_device_data(self): + return self.device_info.get_all_device_infos() + + def _get_json_encoded(self, text): + return json.loads(text) + + def connect_wifi(self, ssid, password): + print("Connect WLAN") + self.wlan_client = WlanClient(ssid, password) + self.wlan_client.connect() + diff --git a/gs/growsystem.py b/gs/growsystem.py new file mode 100644 index 0000000..6046be1 --- /dev/null +++ b/gs/growsystem.py @@ -0,0 +1,129 @@ +from gs.setup import Setup +from gs.device_info import DeviceInfo +from gs.sensor_data_manager import SensorDataManager +import os +import ujson +import machine +import time +from gs.classes.sensors.ambilight_sensor import AmbilightSensor +from gs.classes.sensors.dht22 import TemperatureHumiditySensor +from gs.classes.sensors.moisture_sensor import MoistureSensor + + +class GrowSystem: + + version = "1.0" + + initial_config = None + + device_info = DeviceInfo() + + sensors = [] + + def __init__(self): + print("Initialize Growsystem", self.version) + + if not self._is_initial_config_existing(): + print("No config existing. Start setup ...") + self._setup() + return + + from gs.grow_system_api import GrowSystemApi as GSA + self.gsapi = GSA() + + if self._is_config_existing(): + print("Skip Setup. Config existing.") + self._initialize_sensors() + elif self._is_initial_config_existing(): + print("Initial config only existing (no base config). Start activation ...") + self._activate() + + def start(self): + self.sensor_data_manager = SensorDataManager(self.device_info.get_device_id()) + + print("Start reading sensors ...") + + read_secs = self.device_info.app_config().read_secs + + while True: + # Reset data + self.most_recent_values = [] + + for sensor in self.sensors: + print("Read sensor of type " + sensor.type + " at pin " + str(sensor.sensor_pin_int)) + sensor.read() + for measurement in sensor.most_recent_values: + print(f"Got {measurement['value']} {measurement['unit']} ({measurement['type']})") + self.most_recent_values = self.most_recent_values + sensor.most_recent_values + + self.sensor_data_manager.handleData(self.most_recent_values) + + time.sleep(read_secs) + + def _setup(self): + setup = Setup() + setup.setup_pico() + machine.reset + + def _activate(self): + print("Start activation!") + import gs.config.initial_config as ic + self.initial_config = ic.config + device_config = self.gsapi.activate(self.initial_config) + #print("Device Config:", device_config['data']) + + if True: + sensors = device_config['data']['sensors'] + sensor_configs = [] + for sensor in sensors: + sensor_configs.append(sensor['config']) + print(sensor['config']) + device_configs = { + 'name': device_config['data']['name'], + 'device_id': device_config['data']['id'], + 'token': device_config['data']['token'], + 'user_id': device_config['data']['user_id'], + 'sensors': sensor_configs + } + with open("/gs/config/device_config.json", "w") as f: + f.write(ujson.dumps(device_configs)) + if self._is_config_existing(): + machine.reset + + def _is_config_existing(self): + return self._is_file_existing('/gs/config/device_config.json') + + def _is_initial_config_existing(self): + return self._is_file_existing('/gs/config/initial_config.py') + + def _is_file_existing(self, filepath): + try: + f = open(filepath, "r") + f.close() + # continue with the file. + return True + except OSError: # open failed + # handle the file open cas + return False + + def _initialize_sensors(self): + # Init sensors + sensors = self.device_info.config()['sensors'] + for sensor in sensors: + print("--------------------------------------") + print("Initialize sensor:") + print(sensor) + sensor_type = sensor['type'] + if sensor_type == 'moisture': + print("Found sensor of type moisture") + self.sensors.append(MoistureSensor(sensor)) + elif sensor_type == 'dht22': + print("Found sensor of type DHT22") + self.sensors.append(TemperatureHumiditySensor(sensor)) + elif sensor_type == 'ambilight': + print("Found sensor of type GY302/BH1750") + self.sensors.append(AmbilightSensor(sensor)) + else: + print("No sensor type configured for: " + sensor['type']) + + diff --git a/gs/http_client.py b/gs/http_client.py new file mode 100644 index 0000000..b819ff8 --- /dev/null +++ b/gs/http_client.py @@ -0,0 +1,36 @@ +import urequests +import json + +class HTTPClient: + def __init__(self): + pass + + def get(self, url): + url = 'https://' + url + try: + # headers = {'Content-Type': 'application/json'} + response = urequests.get(url) + if response.status_code == 200: + print("Data sent, got response") + return response + else: + print("Failed to get data. Status code:", response.status_code) + except Exception as e: + print("Exception occurred:", e) + + def post(self, url, data): + url = 'https://' + url + try: + headers = {'Content-Type': 'application/json', 'Accept': 'application/json, text/plain, */*'} + json_data = json.dumps(data) + print("Send post request to: " + url) + response = urequests.post(url, data=json_data, headers=headers) + if response.status_code == 200: + print("Request OK (200)") + else: + print("Failed to send data.", response.status_code, response.text) + return response + except Exception as e: + print("Exception raised:", e) + return None + diff --git a/gs/little_apache.py b/gs/little_apache.py new file mode 100644 index 0000000..774a383 --- /dev/null +++ b/gs/little_apache.py @@ -0,0 +1,111 @@ +import socket +from gs.classes.http_request import HttpRequest + + +class LittleApache(): + + available_wifis = [] + keep_webserver_alive = True + + + def __init__(self, net): + self.net = net + addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] + self.s = socket.socket() + self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.s.bind(addr) + self.s.listen() + # print('Listening on', addr) + + def start(self): + print("Webserver started. Connect to: " + self.net.ifconfig()[0]) + print(self.net.ifconfig()) + + while self.keep_webserver_alive: + try: + conn, addr = self.s.accept() + #print('Got a connection from', addr) + + # Receive and parse the request + request = conn.recv(1024) + # print("Request (RAW)", request) + http_request = HttpRequest(request) + self.http_request = http_request + request = str(request) + # print('Request content = %s' % request) + #try: + # request = request.split()[1] + # print('Request:', request) + #except IndexError: + # pass + response = self.response(http_request) + # Send the HTTP response and close the connection + conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') + conn.send(response) + conn.close() + except OSError as e: + conn.close() + print('Connection closed') + return self + + def response(self, request: HttpRequest): + #print("Webpage: ", request) + print("Request method: ", request.method, "Request path: ", request.path) + + header = f""" + + +
+