diff --git a/README.md b/README.md index 1a244cd..cfdeb92 100644 --- a/README.md +++ b/README.md @@ -152,3 +152,8 @@ Let's assume you haven't built the ESP8266 sensor. You can still test your servi ### Libs - https://github.com/jczic/MicroWebSrv + + +## rshell + +rshell is a shell for accessing a mi \ No newline at end of file diff --git a/basic_dht/main.py b/basic_dht/main.py new file mode 100644 index 0000000..f13a7f4 --- /dev/null +++ b/basic_dht/main.py @@ -0,0 +1,23 @@ +import time + +from dht import DHT11 +from machine import Pin + + +sensor1 = DHT11(Pin(2)) +# sensor2 = DHT11(Pin(2)) + + +while True: + data = { + "sensor_1": { + "temp": sensor1.temperature(), + "humidity": sensor1.humidity(), + }, + # "sensor_2": { + # "temp": sensor2.temperature(), + # "humidity": sensor2.humidity(), + # }, + } + print(data) + time.sleep(3) diff --git a/iot_power/SPEC.md b/iot_power/SPEC.md new file mode 100644 index 0000000..71d2370 --- /dev/null +++ b/iot_power/SPEC.md @@ -0,0 +1,17 @@ +# Open Water Change Specification + +## Startup + +On startup the Open Water Change(OWC) should check for a config.json file under the root directory. If found it should parse the contents and attempts to connect to wireless access points in the order that they are listed. + +``` +{ +"xor_key": 42, +access_points: [ + { + "ssid": "whatever", + "secret": "" + } +] +} +``` \ No newline at end of file diff --git a/iot_power/boot.py b/iot_power/boot.py new file mode 100644 index 0000000..b4307c1 --- /dev/null +++ b/iot_power/boot.py @@ -0,0 +1,67 @@ +# import json +# import network +# import time + + +# # def xor_encrypt_decrypt(input_string, key): +# # output = "".join(chr(ord(char) ^ key) for char in input_string) +# # return output + + +# # def wifi_connect(ssid, password, timeout=10): +# # """ +# # Connects to the specified Wi-Fi access point. + +# # :param ssid: The SSID of the Wi-Fi network. +# # :param password: The password for the Wi-Fi network. +# # :param timeout: Time in seconds to wait for connection. +# # :return: True if connected, False otherwise. +# # """ +# # wlan = network.WLAN(network.STA_IF) +# # wlan.active(True) + +# # if not wlan.isconnected(): +# # print(f"Connecting to network: {ssid}...") +# # wlan.connect(ssid, password) + +# # start_time = time.time() +# # while not wlan.isconnected(): +# # if time.time() - start_time > timeout: +# # print("Connection timeout!") +# # wlan.active(False) +# # del wlan +# # return False +# # time.sleep(1) + +# # print("Network connected!") +# # print("IP Address:", wlan.ifconfig()[0]) +# # return True + + +# def wifi_setup(): +# # try: +# # with open("config.json", "r") as f: +# # config = json.load(f) + +# # for ap in config.get("access_points", []): +# # result = wifi_connect( +# # ap["ssid"], xor_encrypt_decrypt(ap["secret"], config["xor_key"]) +# # ) +# # if result: +# # return + +# # except (OSError, ValueError) as e: +# # print("OSError config.json unreadable or no") + +# print("Falling back on selfhosted AP") +# ap = network.WLAN(network.AP_IF) +# ap.config(essid="RP2040-AP-2", password="testing123") +# ap.ifconfig(("192.168.4.1", "255.255.255.0", "192.168.4.1", "192.168.4.1")) +# ap.active(True) +# print("SSID RP2040-AP") +# return + + +# print("Attempting to connect to wifi") +# time.sleep(10) +# wifi_setup() diff --git a/iot_power/main.py b/iot_power/main.py new file mode 100644 index 0000000..fe2695f --- /dev/null +++ b/iot_power/main.py @@ -0,0 +1,71 @@ +import network +import socket +import machine +import time + +# Setup RP2040 as an access point +ap = network.WLAN(network.AP_IF) +ap.config(essid="RP2040-AP-3", password="testing123") +ap.ifconfig(("192.168.4.1", "255.255.255.0", "192.168.4.1", "192.168.4.1")) +ap.active(True) + +# Initialize onboard LED +led = machine.Pin("LED", machine.Pin.OUT, value=1) +motor_ctl_a = machine.Pin(16, machine.Pin.OUT, value=0) +motor_ctl_b = machine.Pin(17, machine.Pin.OUT, value=0) + +# Create a socket and listen on port 80 +addr = socket.getaddrinfo("0.0.0.0", 80)[0][-1] +# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s = socket.socket() +s.bind(addr) +# only allowed to listen to 5 connections in AP mode +s.listen(5) + +print("listening on", ap.ifconfig()[0]) + +# HTML to send to browsers +html = """ + + + +

Toggle Motor

+ + + + +""" + + +def serve(): + conn, addr = s.accept() + print("client connected from", addr) + request = conn.recv(1024) + request_str = str(request) + print("request:", request_str) + + if "POST /toggle" in request_str: + led.toggle() + motor_ctl_a.toggle() # Toggle LED state + conn.send("HTTP/1.1 200 OK\n\nLED Toggled") + else: + conn.send("HTTP/1.1 200 OK\n") + conn.send("Content-Type: text/html\n") + conn.send("Connection: close\n\n") + conn.sendall(html) # Send HTML page + conn.close() + + +# Main loop: accept connections and respond +for i in range(10): + print(f"Preparing to serve...{i}") + time.sleep(1) + +while True: + serve() diff --git a/open_water_change/SPEC.md b/open_water_change/SPEC.md new file mode 100644 index 0000000..71d2370 --- /dev/null +++ b/open_water_change/SPEC.md @@ -0,0 +1,17 @@ +# Open Water Change Specification + +## Startup + +On startup the Open Water Change(OWC) should check for a config.json file under the root directory. If found it should parse the contents and attempts to connect to wireless access points in the order that they are listed. + +``` +{ +"xor_key": 42, +access_points: [ + { + "ssid": "whatever", + "secret": "" + } +] +} +``` \ No newline at end of file diff --git a/open_water_change/boot.py b/open_water_change/boot.py new file mode 100644 index 0000000..163ceda --- /dev/null +++ b/open_water_change/boot.py @@ -0,0 +1,67 @@ +import json +import network +import time + + +def xor_encrypt_decrypt(input_string, key): + output = "".join(chr(ord(char) ^ key) for char in input_string) + return output + + +def wifi_connect(ssid, password, timeout=10): + """ + Connects to the specified Wi-Fi access point. + + :param ssid: The SSID of the Wi-Fi network. + :param password: The password for the Wi-Fi network. + :param timeout: Time in seconds to wait for connection. + :return: True if connected, False otherwise. + """ + wlan = network.WLAN(network.STA_IF) + wlan.active(True) + + if not wlan.isconnected(): + print(f"Connecting to network: {ssid}...") + wlan.connect(ssid, password) + + start_time = time.time() + while not wlan.isconnected(): + if time.time() - start_time > timeout: + print("Connection timeout!") + wlan.active(False) + del wlan + return False + time.sleep(1) + + print("Network connected!") + print("IP Address:", wlan.ifconfig()[0]) + return True + + +def wifi_setup(): + # try: + # with open("config.json", "r") as f: + # config = json.load(f) + + # for ap in config.get("access_points", []): + # result = wifi_connect( + # ap["ssid"], xor_encrypt_decrypt(ap["secret"], config["xor_key"]) + # ) + # if result: + # return + + # except (OSError, ValueError) as e: + # print("OSError config.json unreadable or no") + + print("Falling back on selfhosted AP") + ap = network.WLAN(network.AP_IF) + ap.config(essid="RP2040-AP", password="openwater") + ap.ifconfig(("192.168.4.1", "255.255.255.0", "192.168.4.1", "192.168.4.1")) + ap.active(True) + print("SSID RP2040-AP") + return + + +print("Attempting to connect to wifi") +# time.sleep(10) +wifi_setup() diff --git a/open_water_change/main.py b/open_water_change/main.py new file mode 100644 index 0000000..ca5b551 --- /dev/null +++ b/open_water_change/main.py @@ -0,0 +1,67 @@ +import network +import socket +import machine + + +# Setup RP2040 as an access point +# ap = network.WLAN(network.AP_IF) +# ap.config(essid="RP2040-AP", password="testing123") +# ap.ifconfig(("192.168.4.1", "255.255.255.0", "192.168.4.1", "192.168.4.1")) +# ap.active(True) + +# Initialize onboard LED +led = machine.Pin("LED", machine.Pin.OUT, value=1) +motor_ctl_a = machine.Pin(16, machine.Pin.OUT, value=0) +motor_ctl_b = machine.Pin(17, machine.Pin.OUT, value=0) + +# Create a socket and listen on port 80 +addr = socket.getaddrinfo("0.0.0.0", 80)[0][-1] +# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s = socket.socket() +s.bind(addr) +# only allowed to listen to 5 connections in AP mode +s.listen(5) + +# print("listening on", ap.ifconfig()[0]) + +# HTML to send to browsers +html = """ + + + +

Toggle Motor

+ + + + +""" + + +def serve(): + conn, addr = s.accept() + print("client connected from", addr) + request = conn.recv(1024) + request_str = str(request) + print("request:", request_str) + + if "POST /toggle" in request_str: + led.toggle() + motor_ctl_a.toggle() # Toggle LED state + conn.send("HTTP/1.1 200 OK\n\nLED Toggled") + else: + conn.send("HTTP/1.1 200 OK\n") + conn.send("Content-Type: text/html\n") + conn.send("Connection: close\n\n") + conn.sendall(html) # Send HTML page + conn.close() + + +# Main loop: accept connections and respond +while True: + serve() diff --git a/webserver/turtle_bot_alt.md b/webserver/turtle_bot_alt.md new file mode 100644 index 0000000..ee810b9 --- /dev/null +++ b/webserver/turtle_bot_alt.md @@ -0,0 +1,8 @@ +A Turtlebot Alternative + +Dear Reader, + +Why would you pay $1,336.99 for a Turtlebot4 when you could build one for less than ? Today I’ll break down how I built a ROS2 Turtlebot4 clone, and saved hundreds of dollars in the process. + +What makes a Turtlebot? +Well, a [Turtlebot](https://clearpathrobotics.com/turtlebot-4/) is actually learning platform robot built and sold by Clearpath Robotics dw diff --git a/webserver/webserver.py b/webserver/webserver.py index 5206ca7..8aacdfd 100644 --- a/webserver/webserver.py +++ b/webserver/webserver.py @@ -6,12 +6,13 @@ except ImportError: import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('', 80)) +s.bind(("", 80)) s.listen(5) def render_html(context: dict = {}): - html = """ + html = ( + """

ESP32 Sensor Output

- - - - """ + + + + """ + ) return html @@ -34,16 +44,16 @@ def http_respond(html: str): gc.collect() conn, addr = s.accept() conn.settimeout(3.0) - print('Got a connection from: {addr}'.format(addr=addr)) + print("Got a connection from: {addr}".format(addr=addr)) request = conn.recv(1024) conn.settimeout(None) request = str(request) - print('Content = {}'.format(request)) - conn.send('HTTP/1.1 200 OK\n') - conn.send('Content-Type: text/html\n') - conn.send('Connection: close\n\n') + print("Content = {}".format(request)) + conn.send("HTTP/1.1 200 OK\n") + conn.send("Content-Type: text/html\n") + conn.send("Connection: close\n\n") conn.sendall(html) conn.close() except OSError as err: conn.close() - print('Connection closed') + print("Connection closed")
MEASUREMENTVALUE
Temp. Celsius""" + str(context.get('cel')) + """
Temp. Fahrenheit""" + str(context.get('fahr')) + """F
Light""" + str(context.get('light')) + """%
Humidity""" + str(context.get('hum')) + """%
Temp. Celsius""" + + str(context.get("cel")) + + """
Temp. Fahrenheit""" + + str(context.get("fahr")) + + """F
Light""" + + str(context.get("light")) + + """%
Humidity""" + + str(context.get("hum")) + + """%