![Проект на Python за управление на ESP8266 Контрол на релета и сензори чрез бутони и WEB интерфейс](http://ardudevelop.eu/wp-content/uploads/2024/09/Проект-на-Python-за-управление-на-ESP8266-Контрол-на-релета-и-сензори-чрез-бутони-и-WEB-интерфейс.png)
ТОЗИ КОД Е НАПИСАН СПЕЦИАЛНО ЗА УПРАВЛЕНИЕ НА УСТОРЙСТВОТО ОТ СТАТИЯТА НИ: Проект с ESP8266 D1 Mini: Контрол на четири релета чрез бутони и WEB интерфейс и изчитане на сензори
Този проект демонстрира как можем да управляваме ESP8266 D1 Mini, оборудван с четири релета, чрез графичен интерфейс, създаден с Python и библиотеки за GUI, както и чрез бутони и уеб интерфейс. В допълнение към контрола на релетата, проектът чете данни от DHT11 сензор за температура и влажност и аналоговя вход.
Кодът за управлението на ESP8266 е написан на C++, а графичният интерфейс за управление и мониторинг на устройството е реализиран с помощта на Python, като основната комуникация се извършва чрез HTTP заявки.
Подготовка на средата за работа с Python
Преди да разгледаме кода, нека създадем и настроим виртуална среда на Python, в която ще работим по проекта. Използването на виртуална среда помага за управлението на библиотеките и версиите им, без да засяга глобалната инсталация на Python на системата.
1. Създаване на виртуална среда
Въвеждането на виртуална среда е ключова стъпка при работа с Python, тъй като тя изолира проектните зависимости. За този проект ще създадем виртуална среда, която наричаме my_env
. Изпълнете следната команда:
python3 -m venv my_env
Това създава папка my_env
, в която се намират всички необходими изпълними файлове и библиотеки за Python.
2. Активиране на виртуалната среда
След като сме създали виртуалната среда, трябва да я активираме. Активирането зависи от операционната система:
Linux/MacOS:
source my_env/bin/activate
Windows:
my_env\Scripts\activate
![Python my_env среда](http://ardudevelop.eu/wp-content/uploads/2024/09/Python-my_env-среда-1024x188.png)
След активиране ще видите, че името на средата (в случая my_env
) се появява в началото на командния ред.
3. Деактивиране на виртуалната среда
Когато приключите с работата по проекта, можете да деактивирате виртуалната среда с командата:
deactivate
4. Инсталиране на библиотеки
След като средата е активирана, можем да инсталираме необходимите библиотеки. Ако искаме да видим инсталираните библиотеки в текущата среда, изпълняваме:
python3 -m pip freeze
За да експортираме списъка с библиотеките във файл, използваме:
python3 -m pip freeze >> req.txt
Това ще създаде файл req.txt
, който можем да използваме за възстановяване на същата конфигурация на библиотеките в бъдеще с командата:
python3 -m pip install -r req.txt
Тази команда ще инсталира всички библиотеки които се намират в req.txt файла. Тези библиотеки се записват с предишната команда, след като сте изпробвали кода.
Библиотеките за този пример може са инсталирате с горе-посочения метод след като ги свалите файла от тук: req.txt
Нашата програма за управление на ЕСП8266 с Python GUI
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QFrame)
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QFont
import requests
# Импортираме библиотеката за комуникация с ESP8266
class DeviceReader:
def __init__(self, device_ip):
self.device_ip = device_ip
def _get_data(self, endpoint):
url = f'http://{self.device_ip}/{endpoint}'
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
return None
def read_analog(self):
data = self._get_data('readAnalog')
try:
return int(data.strip())
except (ValueError, TypeError):
return None
def read_buttons(self):
data = self._get_data('readButtons')
if data:
buttons = {}
for line in data.splitlines():
if line.startswith("Button"):
parts = line.split(":")
if len(parts) == 2:
button_num = int(parts[0].split()[1])
counter = int(parts[1].strip())
buttons[f"Button {button_num}"] = counter
return buttons
return None
def read_relays(self):
data = self._get_data('readRelays')
if data:
relays = {}
for line in data.splitlines():
if line.startswith("Relay"):
parts = line.split(":")
if len(parts) == 2:
relay_num = int(parts[0].split()[1])
status = parts[1].strip()
relays[f"Relay {relay_num}"] = status
return relays
return None
def read_dht(self):
data = self._get_data('readDHT')
if data:
dht_data = {}
for line in data.splitlines():
if "Temperature" in line:
temp_str = line.split(":")[1].strip().split()[0]
dht_data["Temperature"] = float(temp_str)
elif "Humidity" in line:
hum_str = line.split(":")[1].strip().split()[0]
dht_data["Humidity"] = float(hum_str)
return dht_data
return None
def toggle_relay(self, relay_num):
"""Изпраща заявка за превключване на състоянието на реле"""
endpoint = f'toggleRelay{relay_num}'
return self._get_data(endpoint)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
# Настройки за ESP8266
self.device_reader = DeviceReader("192.168.1.132") # Заместете с IP на вашия ESP8266
# UI Инициализация
self.setWindowTitle("ESP8266 Control Interface")
self.setGeometry(100, 100, 600, 400)
layout = QVBoxLayout()
# Показване на температура и влажност от DHT
self.dht_frame = QFrame(self)
self.dht_frame.setFrameShape(QFrame.Box)
layout.addWidget(self.dht_frame)
self.dht_layout = QVBoxLayout(self.dht_frame)
self.temp_label = QLabel("Temperature: -- °C", self)
self.hum_label = QLabel("Humidity: -- %", self)
self.temp_label.setFont(QFont("Arial", 16))
self.hum_label.setFont(QFont("Arial", 16))
self.dht_layout.addWidget(self.temp_label)
self.dht_layout.addWidget(self.hum_label)
# Показване на състоянието на релеите
self.relay_frame = QFrame(self)
self.relay_frame.setFrameShape(QFrame.Box)
layout.addWidget(self.relay_frame)
self.relay_layout = QVBoxLayout(self.relay_frame)
self.relay_status_labels = []
self.relay_buttons = []
for i in range(1, 5):
relay_label = QLabel(f"Relay {i}: --", self)
relay_button = QPushButton(f"Toggle Relay {i}", self)
relay_button.clicked.connect(lambda checked, i=i: self.toggle_relay(i))
self.relay_status_labels.append(relay_label)
self.relay_buttons.append(relay_button)
self.relay_layout.addWidget(relay_label)
self.relay_layout.addWidget(relay_button)
# Показване на аналогова стойност
self.analog_label = QLabel("Analog Value: --", self)
self.analog_label.setFont(QFont("Arial", 16))
layout.addWidget(self.analog_label)
# Настройка на таймер за обновяване на данните
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_data)
self.timer.start(2000) # Обновяване на всяка 2 секунди
self.setLayout(layout)
def update_data(self):
# Обновяване на данни от сензорите
dht_data = self.device_reader.read_dht()
if dht_data:
self.temp_label.setText(f"Temperature: {dht_data['Temperature']} °C")
self.hum_label.setText(f"Humidity: {dht_data['Humidity']} %")
# Обновяване на състоянието на релеите
relays = self.device_reader.read_relays()
if relays:
for i in range(1, 5):
status = relays.get(f"Relay {i}", "Unknown")
self.relay_status_labels[i - 1].setText(f"Relay {i}: {status}")
# Обновяване на аналогова стойност
analog_value = self.device_reader.read_analog()
if analog_value is not None:
self.analog_label.setText(f"Analog Value: {analog_value}")
def toggle_relay(self, relay_num):
"""Превключване на състоянието на реле"""
result = self.device_reader.toggle_relay(relay_num)
if result:
print(f"Relay {relay_num} toggled successfully")
self.update_data()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Обяснение на Python GUI кода
Програмата, която създадохме за управлението на ESP8266, използва библиотеката PySide6 за графичния интерфейс (GUI) и библиотеката requests
за изпращане на HTTP заявки към ESP8266.
Нека разгледаме основния код на Python:
import sys
from PySide6.QtWidgets import (QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QFrame)
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QFont
import requests
Тук първо импортираме основните модули на PySide6, които ще използваме за изграждане на потребителския интерфейс. Импортираме също библиотеката requests
, която позволява лесно изпращане на HTTP заявки към ESP8266.
Клас за комуникация с ESP8266
class DeviceReader:
def __init__(self, device_ip):
self.device_ip = device_ip
def _get_data(self, endpoint):
url = f'http://{self.device_ip}/{endpoint}'
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"Error fetching data from {url}: {e}")
return None
Този клас представлява основната връзка с ESP8266, като използва IP адреса на устройството и различни крайни точки (endpoints), за да получава данни. Например, чрез _get_data()
функцията, изпращаме GET заявка към ESP8266, за да получим данни от специфична крайна точка.
Функции за четене на сензорни данни
def read_analog(self):
data = self._get_data('readAnalog')
try:
return int(data.strip())
except (ValueError, TypeError):
return None
def read_buttons(self):
data = self._get_data('readButtons')
if data:
buttons = {}
for line in data.splitlines():
if line.startswith("Button"):
parts = line.split(":")
if len(parts) == 2:
button_num = int(parts[0].split()[1])
counter = int(parts[1].strip())
buttons[f"Button {button_num}"] = counter
return buttons
return None
Тези функции използват _get_data()
метода, за да извлекат данни за аналоговия вход и състоянието на бутоните от ESP8266. Данните се парсират и връщат в подходящ формат.
Графичен потребителски интерфейс (GUI)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.device_reader = DeviceReader("192.168.100.132")
# UI Инициализация
self.setWindowTitle("ESP8266 Control Interface")
self.setGeometry(100, 100, 600, 400)
layout = QVBoxLayout()
# Показване на температура и влажност от DHT
self.dht_frame = QFrame(self)
self.dht_frame.setFrameShape(QFrame.Box)
layout.addWidget(self.dht_frame)
self.dht_layout = QVBoxLayout(self.dht_frame)
self.temp_label = QLabel("Temperature: -- °C", self)
self.hum_label = QLabel("Humidity: -- %", self)
self.temp_label.setFont(QFont("Arial", 16))
self.hum_label.setFont(QFont("Arial", 16))
self.dht_layout.addWidget(self.temp_label)
self.dht_layout.addWidget(self.hum_label)
# Показване на състоянието на релеите
self.relay_frame = QFrame(self)
self.relay_frame.setFrameShape(QFrame.Box)
layout.addWidget(self.relay_frame)
self.relay_layout = QVBoxLayout(self.relay_frame)
self.relay_status_labels = []
self.relay_buttons = []
for i in range(1, 5):
relay_label = QLabel(f"Relay {i}: --", self)
relay_button = QPushButton(f"Toggle Relay {i}", self)
relay_button.clicked.connect(lambda checked, i=i: self.toggle_relay(i))
self.relay_status_labels.append(relay_label)
self.relay_buttons.append(relay_button)
self.relay_layout.addWidget(relay_label)
self.relay_layout.addWidget(relay_button)
В този клас създаваме основния прозорец на приложението, където добавяме различни елементи за визуализиране на данните и контрол на релетата. Температурата и влажността от DHT11 се показват чрез два QLabel
елемента. За всяко реле създаваме бутон за превключване на състоянието му, както и етикет, показващ текущото състояние.
Превключване на релетата и обновяване на данните
def toggle_relay(self, relay_num):
result = self.device_reader.toggle_relay(relay_num)
if result:
print(f"Relay {relay_num} toggled successfully")
self.update_data()
def update_data(self):
dht_data = self.device_reader.read_dht()
if dht_data:
self.temp_label.setText(f"Temperature: {dht_data['Temperature']} °C")
self.hum_label.setText(f"Humidity: {dht_data['Humidity']} %")
relays = self.device_reader.read_relays()
if relays:
for i in range(1, 5):
status = relays.get(f"Relay {i}", "Unknown")
self.relay_status_labels[i - 1].setText(f"Relay {i}: {status}")
analog_value = self.device_reader.read_analog()
if analog_value is not None:
self.analog_label.setText(f"Analog Value: {analog_value}")
Методът toggle_relay()
изпраща команда за превключване на реле и обновява състоянието на всички релета, както и на сензорите. update_data()
методът се извиква периодично чрез таймер, за да се обновяват показваните стойности в GUI.
Стартиране на програмата
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
Този ред гарантира, че програмата ще стартира само ако файлът се изпълнява директно, а не когато е импортиран като модул в друг скрипт.app = QApplication(sys.argv)
Създава се инстанция наQApplication
, която управлява цикъла на събитията и обработва действията на потребителя. Аргументътsys.argv
дава възможност за предаване на параметри от командния ред.window = MainWindow()
Тук се създава основният прозорец на приложението, който съдържа графичния интерфейс.window.show()
Този метод показва прозореца на екрана, правейки интерфейса достъпен за потребителя.sys.exit(app.exec())
Започва цикъла на събитията на приложението. След като прозорецът бъде затворен, приложението приключва, иsys.exit()
гарантира коректно излизане от програмата.
Видео презентация на кода:
![Проект на Python за управление на ESP8266 Контрол на релета и сензори чрез бутони и WEB интерфейс RaspberryPI LCD](http://ardudevelop.eu/wp-content/uploads/2024/09/Проект-на-Python-за-управление-на-ESP8266-Контрол-на-релета-и-сензори-чрез-бутони-и-WEB-интерфейс-RaspberryPI-LCD-1024x579.png)
Заключение
Този Python проект с графичен интерфейс предоставя удобно средство за контрол на ESP8266 и неговите релета, като същевременно чете данни от различни сензори. Интерфейсът е интуитивен и се обновява автоматично на всеки няколко секунди, за да показва актуални данни от устройството.