238 lines
7.1 KiB
Python
238 lines
7.1 KiB
Python
import network
|
|
import socket
|
|
import time
|
|
import machine
|
|
import config
|
|
from machine import Pin
|
|
|
|
relay1 = Pin(config.RELAY1_PIN, Pin.OUT)
|
|
relay2 = Pin(config.RELAY2_PIN, Pin.OUT)
|
|
door_sensor1 = Pin(config.DOOR1_SENSOR_PIN, Pin.IN, Pin.PULL_UP)
|
|
door_sensor2 = Pin(config.DOOR2_SENSOR_PIN, Pin.IN, Pin.PULL_UP)
|
|
|
|
relay1.value(config.RELAY_OFF)
|
|
relay2.value(config.RELAY_OFF)
|
|
|
|
last_press_time = {"door1": 0, "door2": 0}
|
|
|
|
wlan = network.WLAN(network.STA_IF)
|
|
wlan.active(True)
|
|
wlan.connect(config.WIFI_SSID, config.WIFI_PASSWORD)
|
|
|
|
max_retries = 30
|
|
while not wlan.isconnected() and max_retries > 0:
|
|
time.sleep(1)
|
|
max_retries -= 1
|
|
|
|
if wlan.isconnected():
|
|
wlan.ifconfig((config.STATIC_IP, config.SUBNET, config.GATEWAY, config.DNS))
|
|
ip_address = config.STATIC_IP
|
|
else:
|
|
ip_address = None
|
|
|
|
|
|
def toggle_door(door_num):
|
|
current_time = int(time.time())
|
|
door_key = f"door{door_num}"
|
|
|
|
if current_time - last_press_time[door_key] < config.PRESS_COOLDOWN:
|
|
return False
|
|
|
|
last_press_time[door_key] = current_time
|
|
|
|
if door_num == 1:
|
|
relay1.value(config.RELAY_ON)
|
|
else:
|
|
relay2.value(config.RELAY_ON)
|
|
|
|
time.sleep(0.5)
|
|
|
|
if door_num == 1:
|
|
relay1.value(config.RELAY_OFF)
|
|
else:
|
|
relay2.value(config.RELAY_OFF)
|
|
|
|
return True
|
|
|
|
|
|
def get_door_status(door_num):
|
|
if door_num == 1:
|
|
sensor = door_sensor1
|
|
else:
|
|
sensor = door_sensor2
|
|
return "open" if sensor.value() == config.DOOR_OPEN else "closed"
|
|
|
|
|
|
def get_html(status1, status2, msg="", client_ip=""):
|
|
return (
|
|
"""<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Garage Door Control</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; text-align: center; padding: 30px; background-color: #f5f5f5; }
|
|
.door-section { background: white; padding: 20px; margin: 20px auto; max-width: 400px; border-radius: 10px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
|
|
.status { font-size: 20px; margin: 15px; padding: 15px; border-radius: 8px; }
|
|
.open { background-color: #90EE90; }
|
|
.closed { background-color: #FFB6C1; }
|
|
button { font-size: 18px; padding: 15px 30px; cursor: pointer; background-color: #4CAF50; color: white; border: none; border-radius: 5px; }
|
|
button:hover { background-color: #45a049; }
|
|
button:disabled { background-color: #cccccc; cursor: not-allowed; }
|
|
.ip { margin-top: 30px; color: #666; }
|
|
.message { color: #ff6600; font-size: 16px; margin: 10px; }
|
|
.log-section {
|
|
background: white;
|
|
padding: 20px;
|
|
margin: 30px auto;
|
|
max-width: 600px;
|
|
border-radius: 10px;
|
|
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
|
height: 250px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.log-section h2 { margin-top: 0; }
|
|
.log-box {
|
|
flex: 1;
|
|
width: 100%;
|
|
font-family: monospace;
|
|
font-size: 12px;
|
|
padding: 10px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 5px;
|
|
resize: none;
|
|
background-color: #1e1e1e;
|
|
color: #00ff00;
|
|
box-sizing: border-box;
|
|
overflow-y: scroll;
|
|
text-align: left;
|
|
}
|
|
.log-entry { margin: 2px 0; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Garage Door Control</h1>
|
|
<div class="door-section">
|
|
<h2>Door 1</h2>
|
|
<div class="status """
|
|
+ status1
|
|
+ """">
|
|
Door is """
|
|
+ status1.upper()
|
|
+ """
|
|
</div>
|
|
<form method="POST">
|
|
<button type="submit" name="action" value="toggle1">Toggle Door 1</button>
|
|
</form>
|
|
</div>
|
|
<div class="door-section">
|
|
<h2>Door 2</h2>
|
|
<div class="status """
|
|
+ status2
|
|
+ """">
|
|
Door is """
|
|
+ status2.upper()
|
|
+ """
|
|
</div>
|
|
<form method="POST">
|
|
<button type="submit" name="action" value="toggle2">Toggle Door 2</button>
|
|
</form>
|
|
</div>
|
|
"""
|
|
+ ('<div class="message">' + msg + "</div>" if msg else "")
|
|
+ """
|
|
<div class="log-section">
|
|
<h2>Activity Log</h2>
|
|
<textarea id="logBox" class="log-box" readonly></textarea>
|
|
</div>
|
|
<div class="ip">IP: """
|
|
+ (ip_address or "Not connected")
|
|
+ """</div>
|
|
<script>
|
|
var clientIP = \""""
|
|
+ client_ip
|
|
+ """\";
|
|
|
|
function loadLog() {
|
|
var log = localStorage.getItem('garageDoorLog') || '';
|
|
document.getElementById('logBox').value = log;
|
|
document.getElementById('logBox').scrollTop = document.getElementById('logBox').scrollHeight;
|
|
}
|
|
|
|
function addLogEntry(door, ip) {
|
|
var now = new Date();
|
|
var timestamp = now.toLocaleString();
|
|
var entry = '[' + timestamp + '] Door ' + door + ' toggled from ' + ip + '\\n';
|
|
|
|
var log = localStorage.getItem('garageDoorLog') || '';
|
|
log = entry + log;
|
|
|
|
var lines = log.split('\\n').filter(function(line) { return line.trim(); });
|
|
if (lines.length > 100) {
|
|
log = lines.slice(0, 100).join('\\n') + '\\n';
|
|
}
|
|
|
|
localStorage.setItem('garageDoorLog', log);
|
|
loadLog();
|
|
}
|
|
|
|
loadLog();
|
|
|
|
document.querySelectorAll('form').forEach(function(form) {
|
|
form.addEventListener('submit', function() {
|
|
var action = form.querySelector('button').value;
|
|
var doorNum = action.replace('toggle', '');
|
|
addLogEntry(doorNum, clientIP);
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>"""
|
|
)
|
|
|
|
|
|
def web_server():
|
|
addr = socket.getaddrinfo("0.0.0.0", 80)[0][-1]
|
|
s = socket.socket()
|
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
s.bind(addr)
|
|
s.listen(1)
|
|
|
|
while True:
|
|
try:
|
|
cl, addr = s.accept()
|
|
client_ip = addr[0]
|
|
request = cl.recv(1024)
|
|
request_str = request.decode("utf-8")
|
|
|
|
message = ""
|
|
if "POST" in request_str:
|
|
if "toggle1" in request_str:
|
|
if toggle_door(1):
|
|
message = ""
|
|
else:
|
|
message = "Please wait before pressing again"
|
|
elif "toggle2" in request_str:
|
|
if toggle_door(2):
|
|
message = ""
|
|
else:
|
|
message = "Please wait before pressing again"
|
|
|
|
status1 = get_door_status(1)
|
|
status2 = get_door_status(2)
|
|
response = get_html(status1, status2, message, client_ip)
|
|
|
|
cl.send("HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n")
|
|
cl.send(response)
|
|
cl.close()
|
|
except Exception as e:
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if ip_address:
|
|
print("Connected, IP:", ip_address)
|
|
web_server()
|
|
else:
|
|
print("Failed to connect to WiFi")
|