当前位置: 首页 > news >正文

网络命令控制ESP32管脚打开

一、主要目的

     用网络连接单片机ESP32,发送命令控制管脚的打开、关闭;

二、技术思路

 1、ESP32单片机开启AP热点接入模式的无线网;

 2、笔记本电脑开启无线网卡,连接ESP32发出的无线网;

 3、ESP32开启TCP服务端监听某个端口;

 4、笔记本电脑开启Java程序,和ESP32建立TCP连接;

 5、控制台输入命令打开和关闭ESP32的端口;

三、ESP32的控制程序(python代码)

 1、引入依赖

import network
import machine
import socket
import _thread

 2、定义工具函数

  1)读取一行的函数

# 读取一行
# socket是TCP套接字
def readline(client):
    line = b''
    
    while True:
        temp = client.recv(1)
        
        if temp == b'\r':
            client.recv(1)
            break
        elif temp == b'':
            raise IOError("close")
        else:
            line = line + temp

    return line

  2)控制引脚的函数

# 打开引脚
def openPin(no):
    pin = machine.Pin(no, machine.Pin.OUT)
    pin.on()

# 关闭引脚
def closePin(no):
    pin = machine.Pin(no, machine.Pin.OUT)
    pin.off()
        
# 查看引脚状态
def showPin(no):
    pin = machine.Pin(no, machine.Pin.OUT)


    # 返回引脚状态
    return pin.value()

  3)判断是否引脚在范围内

# 判断是否在可控的管脚
def inPort(pin):
    
    # 可用的管脚号列表
    pins = [2, 4, 5, 12, 13, 14, 15, 18, 19,
            21, 22, 23, 25, 26, 27, 32, 33, 34, 35]

    # 如果在列表里
    if int(pin) in pins:
        return True
    else:
        return False

  3、线程的任务函数

# 执行方法
def execute_task(client, addr):
    try:
        while True:
            # 读取一行命令
            cmd = readline(client).decode("UTF-8")
                
            print("命令:")
            print(cmd)
        
            # 分割命令    
            cmds = cmd.split(" ")

            # 如果是open命令

            if cmds[0] == "open":
                if len(cmds) != 2 or not inPort(cmds[1]):
                    resp(client, 300, "argument error")
                else:
                    openPin(int(cmds[1]))
                    resp(client, 200, "OK")

            # 如果是show命令
            elif cmds[0] == "show":
                if len(cmds) != 2 or not inPort(cmds[1]):
                    resp(client, 300, "argument error")
                else:
                    resp(client, 200, str(showPin(int(cmds[1]))))
            elif cmds[0] == "close":
                if len(cmds) != 2 or not inPort(cmds[1]):
                    resp(client, 300, "argument error")
                else:
                    closePin(int(cmds[1]))
                    resp(client, 200, "OK")
            elif cmds[0] == "exit":
                resp(client, 200, "OK")
                break
            else:
                # 命令不正确
                resp(client, 300, "cmd incorrect.")

    except BaseException as e:
        print(e.args)
            
    finally:
        if client is not None:
            client.close()
        

# 回复结果
# code是代号,msg是消息文本
def resp(client,   code,   msg):
    client.send((str(code) + " " + msg + "\r\n").encode("UTF-8"))
   

4、开启无线网的AP热点

# 开启AP热点
def open_ap():
    # 1.1、发起WLAN的AP热点
    wlan = network.WLAN(network.AP_IF)

    # 1.2、开启
    wlan.active(True)

    # 1.3、配置SSID、密码、加密模式
    wlan.config(essid="ESP32_C")
    wlan.config(password="12345678")
    wlan.config(authmode=network.AUTH_WPA_WPA2_PSK)
      
 

  5、开启TCP服务端监听

# 3、开始监听处理
def listen_work():
    # 2.1 开启TCP服务端
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.2、绑定地址和端口
    port = 9999
    sock.bind(("0.0.0.0", port))
    print("监听端口:%d" % port)

    # 2.3、开始接听
    #  允许同时50个连接
    sock.listen(50)

    # 2.4、循环处理
    while True:
        # 阻塞获取客户端
        client, addr = sock.accept()
        
        print("客户端地址:%s" % str(addr))

        # 开启线程处理
        # 创建线程
        _thread.start_new_thread(execute_task, (client, addr))

6、开始运行

# 开始调用
open_ap()


listen_work()

四、控制客户端的代码(Java代码)

   在桌面电脑上运行,主动连接ESP32的无线网;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.Scanner;

/**
 * 
 * @version 1.0.0
 * <p>
 * date: 2025/2/7
 **/
public class Client {

    public static void main(String[] args) {


        Socket s = null;

        try {
            // 1、创建控制台扫描器
            Scanner scan = new Scanner(System.in);

            //  2、获得连接;实际需要修改IP地址和端口;
            s = new Socket("192.168.4.1", 9999);

            // 3、输出流
            OutputStream out = s.getOutputStream();

            // 4、获得缓冲输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream(),  "UTF-8"));

            String cmd = "";

            // 5、进入循环
            while(true){
                // 输出提示符
                System.out.print("esp32>");

                // 读取命令
                cmd = scan.nextLine();

                // 不为空
                if(!cmd.equals("")){

                    // 清除左右两边的不可见字符;
                    cmd = cmd.trim();

                    // 发送命令,以回车符和换行符结尾;
                    out.write((cmd + "\r\n").getBytes("UTF-8"));
                    out.flush();

                    // 打印结果
                    System.out.println(reader.readLine());


                    if(cmd.equals("exit")){
                        break;
                    }
                }
            }
        } catch (IOException e){
            e.printStackTrace();
        } finally{
            if (s != null){
                try {
                    s.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

五、控制命令格式

  1、命令格式如下:

命令名  空格  参数 回车符  换行符  

  本案例设计了open、close、show、exit共四个命令;

  2、服务器返回的结果格式:

3位数字  空格  说明字符串 回车符  换行符

  本案例设计200代表执行成功,300代表参数错误;

3、使用案例:

   运行时会弹出"esp32>"的提示符,然后输入命令。

   打开第2号引脚:

esp32>open 2

  关闭2号引脚:

esp32>close 2

  查看2号引脚的状态:

esp32>show 2

  退出连接:

esp32>exit

六、缺点和改进
 (一)缺点:

  1、目前还不够完善,参数分割不准确;

  2、支持的命令太少,功能不丰富;

  3、建立TCP连接后,没有身份认证;

  4、ESP32的无线网功率不足,控制距离太近;

  5、只能支持无线连接的电脑控制;

  (二)改进:

    1、增加功能,例如设置定时,让管脚定时多少分钟或者多少秒就打开或者关闭;

    2、增加密码的验证机制;验证不通过禁止控制;

    3、文本控制不准确,未来可采用二进制协议格式通信;

    4、程序可以改进的更方便执行;

    5、添加移动客户端的控制;例如安卓APP、微信小程序等等;

相关文章:

  • ArkUI-List组件
  • 开发中常用的设计模式 用法及注意事项
  • langserve搭建方法
  • 51c自动驾驶~合集26
  • 如何在 Vue 项目中使用混入(Mixin),它有哪些优缺点?
  • docker 内 pytorch cuda 不可用
  • 基于虚拟知识图谱的语义化决策引擎
  • 算法设计——最坏时间复杂度分析
  • 【算法】十大排序算法(含时间复杂度、核心思想)
  • langfuse追踪Trace
  • 数据结构与算法--数字转字符串方法数
  • 数据结构之栈(C语言)
  • RabbitMQ实现路由模式发送接收消息
  • “零拷贝”(Zero-Copy)技术详解以及使用场景
  • 内网渗透-端口转发
  • 【NLP 40、文本生成任务】
  • 【AI大模型】搭建本地大模型GPT-NeoX:详细步骤及常见问题处理
  • 通往自主智能之路:探索自我成长的AI
  • 图像处理全流程指南(OpenCV 实现)
  • 2025-03-23 学习记录--C/C++-C语言 sprintf()实现将多个值按指定格式拼接成字符串
  • 袁思达已任中国科学院办公厅主任
  • 人民日报访巴西总统卢拉:“巴中关系正处于历史最好时期”
  • 人民网评:守护健康证的“健康”,才有舌尖上的安全
  • 中美经贸高层会谈在日内瓦结束,中国代表团将举行发布会
  • 重温经典|开播20周年,仙剑的那些幕后你知道吗?
  • 国家主席习近平会见斯洛伐克总理菲佐