В данном уроке мы создадим веб-сервер используя socket и API socket microPython.
socket — это программный интерфейс для обеспечения информационного обмена между процессами. С помощью socket можно отправлять текст страницы, так же socket прочитает ответ, а затем будет уничтожен.
Для подключения библиотеке мы будем использовать следующие строчки:
try:
import usocket as socket
except:
import socket
Так же мы подключим библиотеку для работы с выводами нашего микроконтроллера:
from machine import Pin
Далее нам нужна будет библиотека для подключения нашего микроконтроллера к сети:
import network
После всех подключений, мы отключим отладочные сообщения ОС (хотя на этапе проверки можно и оставить):
import esp
esp.osdebug(None)
и запустим подпрограмму которая очистит нашу память от лишнего мусора:
import gc
gc.collect()
Дальше мы установим данные нашей сети и подключимся к ней (данный алгоритм мы уже использовали когда подключали микроконтроллер ESP8266 к сети WiFi).
Таким образом у нас получается следующий код, который необходимо поместить в boot.py:
try:
import usocket as socket
except:
import socket
import network
from machine import Timer
import time
import esp
esp.osdebug(None)
import gc
gc.collect()
ssid = 'lyusi28'
password = '11223344'
ap = network.WLAN(network.STA_IF)
ap.active(True)
ap.connect(ssid, password)
while ap.isconnected() == False:
print('.')
time.sleep(.5)
print('Connection successful')
print(ap.ifconfig())
network.WLAN() — создает точку доступа, где в качестве аргумента мы используем следующие параметры:
Функция active () — активирует сетевой интерфейс, работает с двумя параметрами: True и False.
Функция config () — задает параметры пароль и логин для подключения к WiFi сети.
import socket
from machine import Pin
led = Pin(2, Pin.OUT)
def web_page():
if led.value() == 1:
gpio_state="ON"
else:
gpio_state="OFF"
html = """
<style>
html{font-family: Helvetica; display:inline-block; margin:0px auto; text-align: center;}
h1{color: #0F3376; padding:2vh;}
p{font-size:1.5rem;}
.button{display:inline-block; background-color: #e7bd3b; border: none;
border-radius:4px; color: white; padding:16px 40px; text-decoration: none;
font-size:30px; margin:2px; cursor: pointer;}
.button1{background-color: #4286f4;}
</style>
</head>
<body>
<h1>ESP Web Server</h1>
<p>GPIO state:<strong>""" + gpio_state + """</strong></p>
<p><a href="/?led=on"><button class="button">ON</button></a></p>
<p><a href="/?led=off"><button class="button button1">OFF</button></a></p>
</body>
</html>"""
return html
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('',80))
s.listen(5)
while True:
conn, addr = s.accept()
print('Got a connection from %s'%str(addr))
request = conn.recv(1024)
request =str(request)
print('Content = %s'% request)
led_on = request.find('/?led=on')
led_off = request.find('/?led=off')
if led_on ==6:
print('LED ON')
led.value(1)
if led_off ==6:
print('LED OFF')
led.value(0)
response =web_page()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)
conn.close()
Данная программа начинается с создания функции с именем web_page(). Эта функция возвращает переменную с именем html которая содержит HTML-текст для создания веб-страницы:
На веб-странице отображается текущее состояние подключенной ножки.
Для правильной работы выхода мы, перед генерацией HTML-текста проверям состояние светодиода и сохраняем его состояние.
if led.value() == 1:
gpio_state="ON"
else:
gpio_state="OFF"
После этого добавляем переменную gpio_state в текст HTML с помощью знака «+» для объединения строк.
Далее мы создаем новый объект socket с именем s с заданным семейством адресов и типом socket:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
где:
AF_INET — означает, что мы используем Internet протокол IPv4,
SOCK_STREAM — данная константа указывает, что мы будем использовать протокол ТСР, ориентированный на соединение.
Затем привязываем socket к адресу (сетевой интерфейс и номер порта):
s.bind(('', 80))
В данном случаи мы передаем пустую строку «» в качестве IP-адреса и номер порта 80.
У нас пустой IP адрес, так как в данном случае пустая строка относится к IP-адресу локального хоста (тоесть IP-адрес ESP32 или ESP8266).
Дальше мы начинаем принимать соединения, указав при этом максимальное количество подключений в очереди:
s.listen(5)
В цикле while мы слушаем запросы и отправляем ответы.
conn, addr = s.accept()
В данном случаи:
conn — это новый объект сокета, который можно использовать для отправки и получения данных в соединении,
address — это адрес, привязанный к сокету на другом конце соединения.
Обмен данными между клиентом и сервером осуществляется с помощью response() и recv ().
Следующая строка получает запрос, полученный во вновь созданном socket и сохраняет его в переменной.
request = conn.recv(1024)
recv () получает данные из клиентского socket (не забываем, что мы создали новый объект socket на conn переменную). Аргумент recv () определяет максимальное количество данных, которые могут быть получены за один раз.
Следующая строка просто выводит содержимое запроса:
print('Content = %s' % str(request))
Следующая строчка создает переменную с именем ответа который содержит текст HTML:
response = web_page()
После отправляем ответ клиенту:
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')# указываем, что клиент или сервер хотели бы закрыть соединение
conn.sendall(response)
И закрываем созданный socket.
conn.close()