from machine import Pin, time_pulse_us
import urequests
import utime
import network
import ujson
import _thread
import socket
# Пины для компонентов
TRIG_PIN = 26
ECHO_PIN = 12
RELAY_PIN = 27
RED_LED = 4 # Красный светодиод (100 см) и индикатор Wi-Fi
ORANGE_LED = 17 # Оранжевый светодиод (75 см)
YELLOW_LED = 2 # Желтый светодиод (50 см)
GREEN_LED = 16 # Зеленый светодиод (10 см)
MAX_DISTANCE_CM = 38 # Максимальная высота бака в см
SSID = "Home130"
PASSWORD = "rooter2017"
TELEGRAM_BOT_TOKEN = "7991237697:AAHRjliS3nf2JoDmUQ0Zyd4G778HzOntqvI"
CHAT_ID = "1285166140"
# Инициализация Wi-Fi
wlan = network.WLAN(network.STA_IF)
wifi_connected = False # Флаг состояния Wi-Fi
# Инициализация компонентов
trig = Pin(TRIG_PIN, Pin.OUT)
echo = Pin(ECHO_PIN, Pin.IN)
relay = Pin(RELAY_PIN, Pin.OUT, value=1)
red_led = Pin(RED_LED, Pin.OUT)
orange_led = Pin(ORANGE_LED, Pin.OUT)
yellow_led = Pin(YELLOW_LED, Pin.OUT)
green_led = Pin(GREEN_LED, Pin.OUT)
last_water_level = -1
auto_mode = True # По умолчанию автоматический режим включен
# Подключение к Wi-Fi
def connect_wifi():
global wifi_connected
wlan.active(True)
wlan.connect(SSID, PASSWORD)
while not wlan.isconnected():
print("Подключение к Wi-Fi...")
utime.sleep(20)
wifi_connected = True
print("Wi-Fi подключен")
print("IP:", wlan.ifconfig()[0])
# Поток для поддержания подключения к Wi-Fi
def wifi_connection_thread():
global wifi_connected
while True:
if not wlan.isconnected():
wifi_connected = False
print("Потеряно соединение с Wi-Fi. Повторное подключение...")
connect_wifi()
utime.sleep(60)
# Измерение уровня воды
def get_water_level():
trig.off()
utime.sleep_us(2)
trig.on()
utime.sleep_us(10)
trig.off()
duration = time_pulse_us(echo, 1, 30000) # Измеряем время сигнала
distance = (duration * 0.0343) / 2
# Рассчитываем процент заполнения
water_level_percent = int((MAX_DISTANCE_CM - distance) * 119 / MAX_DISTANCE_CM)
return max(0, min(water_level_percent, 119))
# Управление насосом
def control_relay(water_level_percent):
if auto_mode: # Управление насосом только в автоматическом режиме
relay.value(1 if water_level_percent >= 3 else 0)
# Отправка уведомления в Telegram (только при наличии Wi-Fi)
def send_telegram_message(water_level_percent):
if not wlan.isconnected():
print("Wi-Fi не подключен. Сообщение в Telegram не отправлено.")
return
message = f"Уровень воды в баке: {water_level_percent}%"
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
try:
response = urequests.post(url, json={"chat_id": CHAT_ID, "text": message})
response.close()
except Exception as e:
print("Ошибка отправки сообщения в Telegram:", e)
# Обработка клиентских запросов
def handle_client(cl):
request = cl.recv(1024).decode()
print("Запрос:", request)
if "GET /dashboard" in request:
# Отправка HTML-страницы
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Water Tank Dashboard</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
text-align: center;
padding: 20px;
}
.tank {
width: 100px;
height: 200px;
background-color: #e0e0e0;
border: 2px solid #333;
position: relative;
margin: 0 auto;
overflow: hidden;
}
.water {
width: 100%;
background-color: #00bcd4;
position: absolute;
bottom: 0;
transition: height 0.5s;
}
.button {
margin: 10px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Water Tank Dashboard</h1>
<div class="tank">
<div class="water" id="water-level" style="height: 0%;"></div>
</div>
<p>Уровень воды: <span id="water-percent">0%</span></p>
<script>
function updateDashboard() {
fetch("/data")
.then(response => response.json())
.then(data => {
document.getElementById("water-level").style.height = data.water_level + "%";
document.getElementById("water-percent").textContent = data.water_level + "%";
})
.catch(error => console.error("Ошибка:", error));
}
setInterval(updateDashboard, 1000);
</script>
</body>
</html>
"""
cl.send("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" + html)
elif "GET /data" in request:
# Отправка данных в формате JSON
data = ujson.dumps({"water_level": last_water_level})
cl.send("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + data)
elif "POST /control" in request:
# Обработка команд от дашборда
content_length = int(request.split("Content-Length: ")[1].split("\r\n")[0])
post_data = cl.recv(content_length).decode()
command = ujson.loads(post_data)
if "auto_mode" in command:
global auto_mode
auto_mode = command["auto_mode"]
print("Автоматический режим:", "включен" if auto_mode else "выключен")
if "pump_state" in command:
relay.value(1 if command["pump_state"] else 0)
print("Насос:", "включен" if command["pump_state"] else "выключен")
if "reboot" in command and command["reboot"]:
print("Перезагрузка ESP32...")
machine.reset()
cl.send("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + ujson.dumps({"status": "ok"}))
cl.close()
# HTTP-сервер
def http_server(ip):
addr = socket.getaddrinfo(ip, 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print("Сервер запущен по адресу", addr)
while True:
cl, addr = s.accept()
print("Новое подключение от:", addr)
_thread.start_new_thread(handle_client, (cl,))
# Управление светодиодами в отдельном потоке
def leds_control_thread():
while True:
water_level = get_water_level()
update_leds(water_level)
utime.sleep(1) # Обновление каждую секунду
# Обновление состояния светодиодов
def update_leds(water_level_percent):
green_led.value(0)
yellow_led.value(0)
orange_led.value(0)
red_led.value(0)
if water_level_percent >= 15 and water_level_percent <= 25:
red_led.value(1)
elif water_level_percent >= 5 and water_level_percent <= 14:
red_led.value(1)
utime.sleep(0.5)
red_led.value(0)
utime.sleep(0.5)
elif water_level_percent >= 36 and water_level_percent <= 50:
orange_led.value(1)
elif water_level_percent >= 26 and water_level_percent <= 35:
orange_led.value(1)
utime.sleep(0.5)
orange_led.value(0)
utime.sleep(0.5)
elif water_level_percent >= 61 and water_level_percent <= 75:
yellow_led.value(1)
elif water_level_percent >= 51 and water_level_percent <= 60:
yellow_led.value(1)
utime.sleep(0.5)
yellow_led.value(0)
utime.sleep(0.5)
elif water_level_percent >= 86:
green_led.value(1)
elif water_level_percent >= 76 and water_level_percent <= 85:
green_led.value(1)
utime.sleep(0.5)
green_led.value(0)
utime.sleep(0.5)
# Основная логика
def main():
global last_water_level
# Запуск потока для Wi-Fi
_thread.start_new_thread(wifi_connection_thread, ())
print("Запуск потока для Wi-Fi")
# Запуск потока для управления светодиодами
_thread.start_new_thread(leds_control_thread, ())
# Стартуем HTTP-сервер в отдельном потоке
ip = wlan.ifconfig()[0]
_thread.start_new_thread(http_server, (ip,))
while True:
water_level = get_water_level()
if water_level != last_water_level:
last_water_level = water_level
print(f"Уровень воды: {water_level}%")
send_telegram_message(water_level)
control_relay(water_level)
utime.sleep(7)
# Запуск основной функции
main()