CanMV-K230 Micro Python-Web服务器示例

Micro Python HTTP服务器和Web页面示例

前言:

本示例展示了如何使用MicroPython在一个嵌入式开发板CanMV-K230上创建一个简单的Web服务器,该服务器可以用来通过Web浏览器控制一个LED灯的状态(开/关)。此外,还提供了一个简单的网页,允许用户通过点击按钮来改变LED的状态 实现人机交互,并实时查看当前状态。

通过这示例你可以了解到:

  • 连接WiFi网络;
  • 使用MicroPython创建一个基本的HTTP服务器;
  • 通过Web界面远程控制硬件设备。

源码:

'''
实验名称:HTTP网页控制LED
实验平台:01Studio CanMV-K230
日期:2024-9-15
教程:wiki.01studio.cc
作者:杀破狼
版本:v1.0
'''
import usocket
import network, socket, time, os, sys, utime
from machine import Pin
from media.sensor import * # 导入sensor模块,使用摄像头相关接口
from media.display import * # 导入display模块,使用display相关接口
from media.media import * # 导入media模块,使用media相关接口

# LED初始化
LED = Pin(52, Pin.OUT)  # 初始化为输出模式,默认高电平点亮

time.sleep(2) # 等待WiFi模块初始化

SSID = ''
PASSWORD = ''

# 初始化媒体管理器
MediaManager.init()

# WIFI连接函数
def WIFI_Connect():
    WIFI_LED = Pin(52, Pin.OUT)  # 使用相同的LED引脚作为WIFI指示灯

    wlan = network.WLAN(network.STA_IF)  # STA模式
    wlan.active(True)  # 激活WIFI接口
    if not wlan.isconnected():
        print('正在连接...')
        # 输入WIFI账号密码(仅支持2.4G信号)
        wlan.connect(SSID, PASSWORD)

    if wlan.isconnected():  # 连接成功
        # LED蓝灯点亮
        WIFI_LED.value(1)
        # 串口打印信息
        print('IP:', wlan.ifconfig())
        return wlan.ifconfig()[0]
    else:  # 连接失败
        # LED闪烁3次提示
        for i in range(3):
            WIFI_LED.value(1)
            utime.sleep_ms(300)
            WIFI_LED.value(0)
            utime.sleep_ms(300)
        wlan.active(False)
        return None

# HTTP服务
def handle_client(cl, addr, request_str):
    # 获取请求行
    request_line = request_str.split('\r\n')[0]
    method, path, _ = request_line.split()

    if path == '/':
        # 返回主页
        response = web_page()
    elif path == '/led':
        # 处理LED控制请求
        content_length = int(request_str.split('Content-Length: ')[1].split('\r\n')[0])
        post_data = request_str.split('\r\n\r\n')[1][:content_length]

        if 'state=on' in post_data:
            LED.value(1)  # 点亮
            print('LED ON')
            response = 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nLED ON'
        elif 'state=off' in post_data:
            LED.value(0)  # 熄灭
            print('LED OFF')
            response = 'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nLED OFF'
    elif path == '/status':
        # 返回LED状态
        led_status = "ON" if LED.value() == 1 else "OFF"
        response = f'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n{led_status}'
    else:
        # 资源未找到
        response = 'HTTP/1.1 404 NOT FOUND\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nResource not found.'

    cl.send(response.encode())
    cl.close()
    utime.sleep(0.3)  # 确保所有数据都已发送完毕

def web_page():
    led_value = LED.value()

    # 设置按钮的颜色
    button_color = "#4CAF50" if led_value == 0 else "#D32F2F"  # LED熄灭时按钮绿色,点亮时按钮红色

    html = f"""<!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>CanMV K230 LED Control</title>
        <style>
            body {{
                font-family: Arial, sans-serif;
                display: flex;
                flex-direction: column;
                align-items: center;
                padding: 1rem;
                margin: 0;
                box-sizing: border-box;
            }}
            .container {{
                width: 100%;
                max-width: 600px;
                text-align: center;
            }}
            h1, p {{
                margin: 0.5rem 0;
            }}
            .button {{
                display: inline-block;
                border: none;
                border-radius: 4px;
                color: white;
                padding: 12px 24px;
                text-decoration: none;
                font-size: 16px;
                margin: 0.5rem 0;
                cursor: pointer;
                width: 100%;
                max-width: 300px;
            }}
            @media screen and (max-width: 600px) {{
                .button {{
                    width: 100%;
                }}
            }}
        </style>
        <script>
            function toggleLED() {{
                var xhr = new XMLHttpRequest();
                xhr.open("POST", "/led", true);
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                xhr.send("state=" + (document.querySelector('.button').innerText === 'ON' ? 'off' : 'on'));
                updateStatus(); // 更新状态
            }}

            function updateStatus() {{
                var xhr = new XMLHttpRequest();
                xhr.open("GET", "/status", true);
                xhr.onload = function() {{
                    if (this.status === 200) {{
                        document.querySelector('.button').style.backgroundColor = this.responseText === 'ON' ? '#D32F2F' : '#4CAF50';
                        document.querySelector('.button').innerText = this.responseText === 'ON' ? 'ON' : 'OFF';
                    }}
                }};
                xhr.send();
            }}
        </script>
    </head>
    <body onload="updateStatus()">
        <div class="container">
            <h1>CanMV K230 LED Control</h1>
            <button class="button" style="background-color: {button_color};"
                    onclick="toggleLED()">{"ON" if led_value == 1 else "OFF"}</button>
        </div>
    </body>
    </html>"""
    return f'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n{html}'

try:
    ip_address = WIFI_Connect()
    if ip_address is not None:
        addr = socket.getaddrinfo(ip_address, 80)[0][-1]

        s = socket.socket()
        s.bind(addr)
        s.listen(1)
        print(f'服务器监听 {ip_address}:80')

        while True:
            os.exitpoint()  # 检测IDE中断

            cl, addr = s.accept()
            print('客户端从', addr, '连接')
            request = cl.recv(1024)
            request_str = request.decode()

            if 'HTTP' in request_str:  # 判断是否为HTTP请求
                handle_client(cl, addr, request_str)
except KeyboardInterrupt:
    print("用户停止程序")
except Exception as e:
    print(f"发生异常: {e}")
finally:
    MediaManager.deinit()
    os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)

使用方法: 运行此代码之后在终端查看服务器监听得IP和端口,列如: 192.168.1.101:80


然后在浏览器得地址栏输入对应IP与端口:

运行效果:

1

1 Like