基于ESP-01S的智能电脑控制器

项目介绍

项目名称

基于ESP-01S的智能电脑控制器

项目背景

随着科技的不断进步,物联网(IoT)技术正在迅速改变我们的生活和工作方式。为了利用这一趋势,我开发了基于ESP-01S的智能电脑控制器,旨在通过连接设备和数据,实现更智能、更方便的生活方式。

项目目标

基于ESP-01S的智能电脑控制器的主要目标是:

  1. 远程控制电脑开关
  2. 本地语音控制电脑开关
  3. 定时控制电脑开关

项目架构

设备层:

使用ESP-01S模块继电器模块以及电源
请添加图片描述

网络层:

  • 通过WiFi连接阿里云服务器以及本地的UDP通信

数据层:

  • 本地存储数据并定期上传阿里云服务器

应用层:

  • 基于阿里云平台的应用开发工具,可通过网页端、手机端、小程序端(未实装)的程序来进行远程控制,也可通过阿里云物联网平台对数据进行记录及修改。

主要功能

远程控制:

  • 用户可以通过手机或电脑远程控制设备。

语音控制:

  • 用户可以通过配合其他设备在局域网范围内实现语音控制

技术实现

硬件:

  • 使用ESP-01S作为微控制器,控制继电器通断来实现功能

软件:

  • 使用C语言基于Arduino IDE进行开发
  • 使用MQTT、 HTTP/HTTPS、UDP等通信协议

应用场景

智能家居:
实现家庭设备的智能化管理,通过继电器可以拓展到控制其余用电设备

项目进展

已完成硬件设计以及部分软件开发

  • 已实现通过阿里云物联网平台远程控制
  • 配合其他设备实现本地语音控制

软件设计

  • 本设计需配合基于ESP32的智能家居助手设计与实现 使用
通信流程
  1. ESP-01S通过广播IP(255,255,255,255)向设定的discoveryPort 端口发送"DISCOVER"字符串
  2. ESP32监听discoveryPort 端口 当收到“DISCOVER”字符串信息时 向该来源发送ESP32的IP以及通信端口号
    数据格式:ESP32_IP:192.168.31.88,PORT:5088
  3. ESP-01S 收到IP以及端口号后解析并存储 并监听收到的端口号
  4. ESP-01S 向收到的IP以及端口号发送连接请求 格式为:“Relay:Link” (设备名称:Link )发送后进入延时等待收到"OK"信息
  5. ESP32监听PORT 当收到Link信息时 记录设备名称、发送方IP ,连接设备数 + 1 并回复"OK"
  6. ESP-01S 收到"OK"后 将 esp32Found标志位置为true 进入等待信息接收模式

代码部分

  • 前排提醒:此代码需要配合 基于ESP32的智能家居助手设计与实现 共同使用!!!
// 引入 wifi 模块,并实例化,不同的芯片这里的依赖可能不同
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
static WiFiClient espClient;

// 引入阿里云 IoT SDK
#include <AliyunIoTSDK.h>

// 设置产品和设备的信息,从阿里云设备信息里查看
#define PRODUCT_KEY "xxxxxxxx"
#define DEVICE_NAME "xxxxxxxx"
#define DEVICE_SECRET "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define REGION_ID "cn-shanghai"

// 设置 wifi 信息
#define WIFI_SSID "xxxxxxxx"
#define WIFI_PASSWD "xxxxxxxx"

int udpPort = 5088;
const int discoveryPort = 5089;

WiFiUDP udp;
char incomingPacket[255];
IPAddress esp32Ip;
bool esp32Found = false;
static bool RelayState1 = false;
const int Relay = 0;//定义继电器使用IO

void setup()
{
    Serial.begin(115200);
    
    pinMode(Relay, OUTPUT);  // 将GPIO0引脚设置为输出模式
    
    // 初始化 wifi
    wifiInit(WIFI_SSID, WIFI_PASSWD);
    
    // 初始化 iot,需传入 wifi 的 client,和设备产品信息
    AliyunIoTSDK::begin(espClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, REGION_ID);
    
    // 绑定一个设备属性回调,当远程修改此属性,会触发 powerCallback
    // ComputerControl是在设备产品中定义的物联网模型的 id
    AliyunIoTSDK::bindData("ComputerControl", powerCallback);
    
    // 发送一个数据到云平台,ComputerControl是在设备产品中定义的物联网模型的 id
    AliyunIoTSDK::send("ComputerControl", 1);

    //继电器默认状态为关 即高
    digitalWrite(Relay,HIGH);

    udp.begin(discoveryPort);
}

void loop()
{
  static bool flag1 = false;
  if (!esp32Found) {
    // 发送发现请求
    udp.beginPacket(IPAddress(255, 255, 255, 255), discoveryPort);
    udp.write("DISCOVER");
    udp.endPacket();
    Serial.println("Discovery packet sent");

    // 等待响应
    int packetSize = udp.parsePacket();
    if (packetSize) {
      int len = udp.read(incomingPacket, 255);
      if (len > 0) {
        incomingPacket[len] = 0;
      }
      Serial.printf("Received packet of size %d from %s:%d\n", packetSize, udp.remoteIP().toString().c_str(), udp.remotePort());
      Serial.printf("Packet contents: %s\n", incomingPacket);
      // 查找 IP 地址的起始位置
      char* ipStart = strstr(incomingPacket, "ESP32_IP:");//数据格式:ESP32_IP:192.168.31.88,PORT:88 
      if (ipStart != NULL) {
        // 移动到 IP 地址的起始位置
        ipStart += strlen("ESP32_IP:");
    
        // 查找 IP 地址的结束位置(逗号分隔)
        char* ipEnd = strchr(ipStart, ',');
        if (ipEnd != NULL) {
          // 提取 IP 地址
          char ip[16]; // 保存 IP 地址的字符串数组
          strncpy(ip, ipStart, ipEnd - ipStart); // 拷贝 IP 地址到数组
          ip[ipEnd - ipStart] = '\0'; // 添加字符串结束符
    
          // 将 IP 地址转换为 IPAddress 类型
          esp32Ip.fromString(ip);
          Serial.print("ESP32 IP Address: ");
          Serial.println(esp32Ip);
        }
      }   
      // 查找端口号的起始位置
      char* portStart = strstr(incomingPacket, "PORT:");
      if (portStart != NULL) {
        // 移动到端口号的起始位置
        portStart += strlen("PORT:");
    
        // 提取端口号
        udpPort = atoi(portStart);
        Serial.print("Port: ");
        Serial.println(udpPort);
      }
      if(!flag1){//!!!重复初始化影响消息接收
        udp.begin(udpPort);//监听获取的udpPort端口
        flag1 = true;
      }   
      sendLinkMessage();//向获取的udpPort端口发送连接请求
      //udp.begin(discoveryPort);//!!!重复初始化影响消息接收
      Serial.printf("wait Port:%d\n",udpPort);
      delay(2000);
      int packetSize = udp.parsePacket();    
      char incomingPacket[255];
      int len1 = udp.read(incomingPacket, 255);
      if (len1 > 0) {
        incomingPacket[len1] = 0;
      }
      if (strncmp(incomingPacket, "OK", 2) == 0){
        esp32Found = true;
        Serial.printf("Found ESP32!");         
      }
    }   
    delay(2000);  // 每隔 2 秒发送一次发现请求
  } 
  else {
  //等待接收数据
    static bool udpInitFlag = false;
    if(!udpInitFlag){//没有初始化
      udp.begin(udpPort);//!!!重复初始化影响消息接收
      udpInitFlag = true;
    }  
    Serial.printf("wait Port :%d message\n",udpPort);
    int packetSize = udp.parsePacket();
    if (packetSize){    
      int len = udp.read(incomingPacket, 255);
      if (len > 0) {
        incomingPacket[len] = 0;
      } 
      // 处理设备消息
      Serial.printf("%s\n",incomingPacket);
      if (strncmp(incomingPacket, "Relay:", 6) == 0) {
        String message = String(incomingPacket);
        String deviceName = message.substring(0, message.indexOf(':'));//数据格式Name:On/ Relay:On
        String stateName = message.substring(message.indexOf(':') + 1 );

        Serial.printf("%s",message.c_str());
        if(strcmp(stateName.c_str(),"On") == 0){
          // 启动设备
          RelayState1 = 1;
          digitalWrite(Relay,LOW);
          Serial.println("Relay Open");
        }
        else if(strcmp(stateName.c_str(),"Off") == 0){
          // 关闭设备
          RelayState1 = 0;
          digitalWrite(Relay,HIGH);
          Serial.println("Relay Close");          
        }
        else if(strcmp(stateName.c_str(),"Open") == 0){
          // 开机         
          digitalWrite(Relay,LOW);
          delay(500);
          digitalWrite(Relay,HIGH);
          Serial.println("Computer Open");          
        }
        else if(strcmp(stateName.c_str(),"Close") == 0){
          // 关机
          digitalWrite(Relay,LOW);
          delay(500);
          digitalWrite(Relay,HIGH);
          Serial.println("Computer Close");          
        }                
      }           
    }
  }  
  AliyunIoTSDK::loop();
  delay(1000);  
}
void sendLinkMessage(){
  // 发送数据给 ESP32
  char stateString[] = "Relay:Link";
  udp.beginPacket(esp32Ip, udpPort);
  udp.printf(stateString);//udp.write
  udp.endPacket(); 
  Serial.print("Send Link Message:"); 
  Serial.println(stateString);
}
void sendRelayData(){
  // 发送数据给 ESP32
  char stateString[20];
  if(RelayState1 == false){
    sprintf(stateString,"Relay:Off");
  }
  else{
    sprintf(stateString,"Relay:On");
  }  
  udp.beginPacket(esp32Ip, udpPort);
  udp.printf(stateString);
  udp.endPacket();
  Serial.println("Data packet sent");
}
// 初始化 wifi 连接
void wifiInit(const char *ssid, const char *passphrase)
{
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, passphrase);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(1000);
        Serial.println("WiFi not Connect");
    }
    Serial.println("Connected to AP");
}

// 电源属性修改的回调函数
void powerCallback(JsonVariant p)
{
    RelayState1 = p["ComputerControl"];
    if (RelayState1 == 1)
    {
        // 启动设备
        digitalWrite(Relay,LOW);
        Serial.println("Relay to HIGH");
    }
    else{
        digitalWrite(Relay,HIGH);
        Serial.println("Relay to LOW");
    }
    AliyunIoTSDK::send("ComputerControl", RelayState1);
}

使用教程

  • 提醒:此代码需要配合 基于ESP32的智能家居助手设计与实现 共同使用!!!
  • 开发板选择NodeMCU 1.0
    在这里插入图片描述

在这里插入图片描述

将上面两处代码中的ComputerControl修改为自己设置的属性名称即可
在这里插入图片描述

演示视频

  • 本地语音控制

语音控制继电器演示视频

  • APP控制

阿里云物联网平台应用演示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值