当前位置:   article > 正文

基于ESP32+ASRPRO的智能家居助手设计与实现_asrpro与esp32

asrpro与esp32

项目介绍

实物图

请添加图片描述

项目名称

  • 基于ESP32+ASRPRO的智能家居助手设计与实现

项目背景

随着科技的不断进步,物联网(IoT)技术正在迅速改变我们的生活和工作方式。为了利用这一趋势,我开发了"基于ESP32+ASRPRO的智能家居助手设计与实现",旨在通过连接设备和数据,实现更智能化、更方便的生活。

项目目标

"基于ESP32+ASRPRO的智能家居助手设计与实现"的主要目标是:

  • 实现设备远程监测与管理
  • 全天候数据监测
  • 增强用户设备控制体验

项目架构

设备层:
使用ESP32作为主控制器,ASRPRO作为语音识别设备,DHT11作为温湿度数据检测设备
网络层:

  • 设备与服务器通过MQTTWiFi连接
  • 设备与设备之间通过WiFi蓝牙(可选)连接

数据层:

  • 数据主要通过主控制器进行处理并上传阿里云服务器

应用层:
[描述最终用户如何与系统交互,如手机应用、网页界面等]

  • 使用1.8寸TFT屏幕显示数据以及交互信息
  • 使用阿里云物联网平台开发的程序可在手机、网页、电脑端进行设备控制及数据查看
  • 可通过阿里云服务器对数据进行监控、修改
  • 本地通过语音控制其他设备以及获取其他设备信息

主要功能

  • 数据监测: 通过板载DHT11传感器实时采集温湿度数据,并在显示屏显示。

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

  • 语音控制: 通过ASRPRO模块用户可以在本地通过语音控制设备。

  • 警报和通知: 在检测到异常情况时,板载蜂鸣器会自动发送警报通知用户。

  • 功能拓展:分别预留ESP32、ASRPRO的IO*2并用2.0mm间距3Pin接口引出用于功能拓展

技术实现

通信协议:

采用的通信协议:

  • MQTT :设备与服务器间的数据传输
  • HTTP/HTTPS :实时网络时间获取
  • UDP:各设备之前的数据传输

硬件:

模块
  • 主控制器:ESP32
  • 语音识别模块:ASRPRO
  • 温湿度传感器:DHT11
  • 报警器:12095蜂鸣器
  • 数据显示器:1.8寸TFT屏幕
  • 状态指示器:LED灯若干
外壳设计

底壳
在这里插入图片描述

PCB设计

PCB设计使用嘉立创EDA完成

原理图在这里插入图片描述
PCB

在这里插入图片描述

3D模型预览

在这里插入图片描述

软件:

  • 开发语言和框架:基于Arduino IDE(ESP32)以及天问 BLOCK(ASRPRO)使用C/C++进行开发
  • 控制程序基于阿里云物联网平台进行开发
控制程序-控制界面

在这里插入图片描述

控制程序-数据监测界面

在这里插入图片描述

ESP32代码
  • 长代码警告!(后续会进行封装)
#include <WiFi.h>
#include <WiFiUdp.h>
#include <DHT.h>  //引入DHT库使用DHT11
#include <AliyunIoTSDK.h>// 引入阿里云 IoT SDK
//引入显示屏库
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include "TFT_Image.h"       // 包含图片数组头文件

#include <NTPClient.h> //获取网络时间
// 中国的NTP服务器地址,可以选择多个
const char* ntpServer = "cn.pool.ntp.org";
const long  gmtOffset_sec = 8 * 3600;  // 中国标准时间(UTC+8)
const int   daylightOffset_sec = 0;    // 无夏令时偏移
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ntpServer, gmtOffset_sec, 60000);  // 更新时间间隔为60000ms
int currentHour =0;
int currentMinute = 0;
int currentSecond = 0; 
char timeArr[] = "TIME:23-38-30";    
#define TIME_COLOUR ST7735_YELLOW 

#define TFT_CS    14 // 请替换为您的CS引脚号
#define TFT_DC    27 // 请替换为您的DC引脚号
#define TFT_RST   5 // 请替换为您的RST引脚号
//#define TFT_SCK   18 // 请替换为您的SCK引脚号 
//#define TFT_MOSI  23 // 请替换为您的MOSI引脚号
//已经默认配置
//#define COMPUTER_PIN 0 //连接继电器的引脚
#define DHTPIN 25  
#define DHTTYPE DHT11   // 定义传感器类型
DHT dht(DHTPIN, DHTTYPE);

char HumiStr[6] = "78";
char TempStr[6] = "34.8";

// 图片尺寸
#define IMAGE_WIDTH  60
#define IMAGE_HEIGHT 60
extern const unsigned char gImage_humi[];
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);//创建显示屏对象并初始化

hw_timer_t * timer = NULL; // 创建一个定时器对象

static WiFiClient espClient;

// 设置 wifi 信息
#define WIFI_SSID "Redmi_DC21"
#define WIFI_PASSWD "88888888"
//UDP变量定义
WiFiUDP udp;
WiFiUDP discoveryUdp;
const int udpPort = 5088;
const int discoveryPort = 5089;  // 用于动态发现的UDP端口
#define MAX_CONNECT_COUNT 10 //预期的最大连接设备数
//char incomingPacket[255];//UDP接收数据数组
struct DeviceInfo{//存储其他设备name及ip 
  String name;
  IPAddress ip;
};
DeviceInfo devices[MAX_CONNECT_COUNT];
int deviceCount = 0; //已经连接设备数

#define SEND_DELAY_TIME 200 //单位ms

// 设置产品和设备的信息,从阿里云设备信息里查看
#define PRODUCT_KEY "xxxxxxxxxxx"
#define DEVICE_NAME "xxxxxxxxx"
#define DEVICE_SECRET "xxxxxxxxxxxxxxxxxxxxx"
#define REGION_ID "cn-shanghai"
//定义使用的颜色
#define BACKGROUND_COLOUR ST7735_BLACK //背景颜色
#define RECT1_COLOUR ST7735_RED 
#define TEXT1_COLOUR ST7735_GREEN
#define LINE1_COLOUR ST7735_RED
#define TEXT2_COLOUR ST7735_BLUE
#define RECT2_COLOUR ST7735_RED
#define TEXT3_COLOUR ST7735_GREEN
#define TEXT4_COLOUR ST7735_BLUE
#define DATA_COLOUR ST7735_WHITE
#define DATANAME_COLOUR ST7735_WHITE

#define SHOWDELAY_TIME 500 //字幕滚动速度
#define MAX_TEXT_COUNT 30 //输入文本最大字符数
#define MAX_SHOW_COUNT 12 //最大同时显示字符数
#define MAX_SHOW_STRING 6 //最大同时刷新字符串数量

#define SHOW_MODE_SEND 1 //向外发送的消息
#define SHOW_MODE_RECIVED 2//从外部收到的消息
#define SHOW_MODE_MYSELF 3 //内部消息

int textShowX[MAX_SHOW_STRING] = {0};
int textShowY[MAX_SHOW_STRING] = {0};
int showCount[MAX_SHOW_STRING] = {0};//实际显示数量
int maxCount[MAX_SHOW_STRING] = {0};//需要显示数量
char textShowString[MAX_SHOW_STRING][MAX_SHOW_COUNT + 1] = {"null"} ;//实际显示的字符串
char textMaxString[MAX_SHOW_STRING][MAX_TEXT_COUNT] = {"null"};//需要显示的字符串
int showFlag[MAX_SHOW_STRING] = {0};//显示刷新标志位

float humidity = 0;//温湿度
float temperature = 0;

bool ComputerControl = 1;//电脑控制

bool FanControl = 0;//风扇控制
int FanPwm = 50;//风扇调速
int FanRunTimeHour = 3;//风扇定时-时
int FanRunTimeMin = 30;//定时-分

bool Led1Control = 0;//灯光控制
int LedLuminance = 50;//亮度控制

int LightValue = 100;//光照检测
int SmokeDetection = 100;//烟雾检测

bool AmbientLightControl = 0;//氛围灯控制
int AmbientLightRed = 100;//氛围灯颜色控制
int AmbientLightGreen = 100;
int AmbientLightBlue = 100;
int AmbientLightLuminance = 50;//氛围灯亮度
int AmbientLightCount = 30;

// 定时器相关变量
unsigned long previousMillis = 0;
const unsigned long interval = 100; // 每100毫秒

unsigned long previousMillisUpdate = 0;
const unsigned long updateInterval = 1000; // 每1秒

unsigned long previousMillisData = 0;
const unsigned long dataInterval = 10000; // 每10秒

void displayImage(int16_t x, int16_t y, const unsigned char *image, uint16_t width, uint16_t height) {
  // 遍历图片数组,逐像素显示图片
  for (uint16_t row = 0; row < height; row++) {
    for (uint16_t col = 0; col < width; col++) {
      uint32_t pixelColor = pgm_read_byte(image + (row * width + col));
      tft.drawPixel(x + col, y + row, pixelColor);
    }
  }
}

void messageShowUI(const int x,const int y,char text1[],char text2[],char text3[],char text4[]){

  const int RectX = x;//基准坐标 (矩形左上角)
  const int RectY = y;//基准坐标
  const int RectWight = 160;//宽160
  const int RectHight = 14;//高14

  const int Rect1x = RectX;//矩形框1x坐标
  const int Rect1y = RectY;//矩形框1y坐标
  const int Rect1w = RectWight - RectX;//矩形框1宽度
  const int Rect1h = RectHight;//矩形框1高度
//tft.drawRect(Rect1x,Rect1y,Rect1w,Rect1h,RECT1_COLOUR);//绘制矩形框1 外部包围

  const int Text1x = Rect1x +3;//Text1x坐标
  const int Text1y = Rect1y +3;//Text1y坐标
  const int Text1C = 4;//Text1字符数量
  char Text1String[Text1C + 1];//Text1字符数组
  strncpy(Text1String, text1,Text1C);//从text1拷贝Text1C个字符到Text1String
  Text1String[Text1C] = '\0'; // 添加字符串结束符
  const int Text1Size = 1;

  const int Line1x = Text1x + Text1C * 6 + 3;//字符大小为6*8
  const int Line1y = RectY;
  const int Line1h = RectHight;

  const int Text2x = Line1x + 3;//Text2x坐标
  const int Text2y = Text1y;//Text2y坐标
  const int Text2C = 6 ;//Text2字符数量
  const int Text2Size = 1;
  char Text2String[Text2C + 1];//Text2字符数组
  strncpy(Text2String, text2,Text2C);//从text2拷贝Text2C个字符到Text2String
  Text2String[Text2C] = '\0'; // 添加字符串结束符


  const int Rect2x = Text2x + Text2C * 6 + 1;//矩形框2x坐标
  const int Rect2y = RectY;//矩形框2y坐标
  const int Rect2w = 14;//矩形框2宽度
  const int Rect2h = 14;//矩形框2高度

  const int Text3x = Rect2x + 5;//Text3x坐标
  const int Text3y = Text1y;//Text3y坐标
  const int Text3C = 1;//Text3字符数量
  const int Text3Size = 1;
  char Text3String[Text3C + 1];//Text3字符数组
  strncpy(Text3String, text3,Text3C);//从text3拷贝Text3C个字符到Text3String
  Text3String[Text3C] = '\0'; // 添加字符串结束符

  const int Text4x = Rect2x + Rect2w + 3;//Text4x坐标
  const int Text4y = Text1y ;//Text4y坐标
  const int Text4Size = 1;
  const int Text4C = (159 - Text4x)/6 ;//剩余空间可显示字符数量(以0,0作为起点最多显示12个字符)字符大小6*8
  char Text4String[Text4C + 1];//Text4字符数组
  int Text4Length = 0;//传入需要显示的字符数量
  while (text4[Text4Length] != '\0') {//动态分配的数组不能使用sizeof来计算数组大小
    Text4Length++;
  }
  static bool flag = true;  
  if(flag){
    tft.initR(INITR_BLACKTAB); // 使用适当的初始化参数
    tft.setRotation(1); // 设置显示方向,1表示顺时针旋转90度
    tft.fillScreen(BACKGROUND_COLOUR);//设置背景颜色
    flag = false; //初始化完成改变标志位防止重复初始化
  }     
  tft.drawRect(Rect1x,Rect1y,Rect1w,Rect1h,RECT1_COLOUR);//绘制矩形框1:整体框架
  
  tft.setTextColor(TEXT1_COLOUR);//设置文字颜色
  tft.setTextSize(Text1Size);//设置字体大小
  tft.setCursor(Text1x,Text1y);//设置起始位置
  tft.print(Text1String);//显示Text1 From

  tft.drawFastVLine(Line1x,Line1y,Line1h,LINE1_COLOUR);//绘制Text1后竖线
  
  tft.setTextColor(TEXT2_COLOUR);//设置文字颜色
  tft.setTextSize(Text2Size);//设置字体大小
  tft.setCursor(Text2x,Text2y);//设置起始位置
  tft.fillRect(Text2x, Text2y, 6 * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
  tft.print(Text2String);//显示Text2 ASRPRO

  //tft.drawFastVLine(Line2x,Line2y,Line2h,LINE2_COLOUR);//绘制Text2后竖线

  tft.fillRect(Rect2x,Rect2y,Rect2w,Rect2h,RECT2_COLOUR);//绘制矩形框2:Text3包围框
  
  tft.setTextColor(TEXT3_COLOUR);//设置文字颜色
  tft.setTextSize(Text3Size);//设置字体大小
  tft.setCursor(Text3x,Text3y);//设置起始位置
  tft.print(Text3String);//显示Text3 R

  tft.setTextWrap(false);//关闭超出范围自动换行 实现滚动字幕显示
  if(Text4Length > Text4C){//需要显示的数据数量大于剩余空间可显示字符数量
    //传递参数
    for(int i = 0; i < MAX_SHOW_STRING ; i++){
      if(showFlag[i] == 0){
        showFlag[i] = 1;//标记已使用
        showCount[i] = Text4C;//可显示的字符数
        maxCount[i] = Text4Length;//需要显示的字符数
        textShowX[i] = Text4x;
        textShowY[i] = Text4y;
        strcpy(textMaxString[i],text4);//传递需要显示的字符串
        timerAlarmEnable(timer); // 启用定时器
        
        //直接静态显示
        tft.fillRect(Text4x, Text4y, Text4C * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
        strncpy(Text4String, text4,Text4C);//从text4拷贝Text4C个字符到Text4String
        Text4String[Text4C] = '\0'; // 添加字符串结束符
        tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
        tft.setTextSize(Text4Size);//设置字体大小
        tft.setCursor(Text4x,Text4y);//设置起始位置
        tft.print(Text4String);//显示Text4 Recived data!
        return ;//找到可显示位置即退出循环
      }
    }
  }
  else{//直接静态显示
    tft.fillRect(Text4x, Text4y, Text4C * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
    strncpy(Text4String, text4,Text4C);//从text4拷贝Text4C个字符到Text4String
    Text4String[Text4C] = '\0'; // 添加字符串结束符
    tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
    tft.setTextSize(Text4Size);//设置字体大小
    tft.setCursor(Text4x,Text4y);//设置起始位置
    tft.print(Text4String);//显示Text4 Recived data!
  }  
}
void showDataUI(int dataX,int dataY,int Icon,char dataArr[],char dataName[]){//起始点坐标x,y 显示图标 数据字符串 数据名称
  int IconX = dataX;
  int IconY = dataY;
  int IconW = 12;
  int IconH = 25;
  int IconN = Icon;//0代表温度
  if(IconN == 0) tft.fillRect(IconX,IconY,IconW,IconH,ST7735_GREEN);
  else tft.fillRect(IconX,IconY,IconW,IconH,ST7735_BLUE);//ICON绘制

  tft.fillRect(IconX + IconW + 5, IconY, 10 * 5, 16, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
  tft.setCursor(IconX + IconW + 5,IconY);//设置起始位置
  tft.setTextColor(DATA_COLOUR);//设置文字颜色
  tft.setTextSize(2);//设置字体大小
  tft.print(dataArr);//显示Text4 Recived data!
  if(dataX == 0) tft.print("C");
  else tft.print("%");

  //tft.fillRect(IconX + IconW + 1, IconY + 18, 10 * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
  tft.setCursor(IconX + IconW + 1,IconY + 18);//设置起始位置
  tft.setTextColor(DATANAME_COLOUR);//设置文字颜色
  tft.setTextSize(1);//设置字体大小
  tft.print(dataName);//显示Humidity
  
}
void showLongMessage(int Mode,String Message){
  static int LongMessageCount = 3;
  static int showCount = 0;
  int X = 0;
  int Y = 0;
  int MessageX = X;
  int MessageY = 100 - 1 - 13 * LongMessageCount + showCount % 3 * 13;
  int MessageW = 160 - X;
  int MessageH = 14;
  
  tft.drawRect(MessageX, MessageY, MessageW, MessageH, ST7735_RED);//绘制矩形框
  
  tft.fillRect(MessageX,MessageY, 14, 14, ST7735_RED);//绘制包围矩形框
  tft.setCursor(MessageX + 3,MessageY + 3);//设置起始位置
  tft.setTextColor(ST7735_GREEN);//设置文字颜色
  tft.setTextSize(1);//设置字体大小
  if(Mode == SHOW_MODE_RECIVED) tft.print("R");//显示R
  else if(Mode == SHOW_MODE_SEND) tft.print("S");//显示S
  else if(Mode == SHOW_MODE_MYSELF) tft.print("M");//显示M
  
  tft.fillRect(MessageX + 3 + 15,MessageY + 3, (160 - 3 - X - 14) / 6 * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
  tft.setCursor(MessageX + 3 + 15,MessageY + 3);//设置起始位置
  tft.setTextColor(ST7735_BLUE);//设置文字颜色
  tft.setTextSize(1);//设置字体大小
  tft.print(Message);//显示Message
  showCount += 1;
  
}


void ComputerControlCallBack(JsonVariant p){
  //电脑控制回调函数
    int ComputerControl = p["ComputerControl"];
    //digitalWrite(COMPUTER_PIN,LOW);
    delay(500);
    //digitalWrite(COMPUTER_PIN,HIGH);
}
void LedControlCallBack(JsonVariant p){
  //灯光控制回调函数
  int LedControl = p["LedControl"];
  Serial.println("LedControl:" + String(LedControl));
}
void DateSend(void){
// 发送一个数据到云平台,CurrentTemperature 是在设备产品中定义的物联网模型的 id
    AliyunIoTSDK::send("Temperature", temperature);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("Humility", humidity);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("ComputerControl", ComputerControl);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("FanControl", FanControl);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("FanPwm", FanPwm);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("FanRunTimeHour", FanRunTimeHour);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("FanRunTimeMin", FanRunTimeMin);
    delay(SEND_DELAY_TIME);  
    AliyunIoTSDK::send("LedControl", Led1Control);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("LedLuminance", LedLuminance);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("LightValue", LightValue);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("SmokeDetection", SmokeDetection);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("AmbientLightControl", AmbientLightControl);
    delay(SEND_DELAY_TIME);   
    AliyunIoTSDK::send("AmbientLightRed", AmbientLightRed);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("AmbientLightGreen", AmbientLightGreen);
    delay(SEND_DELAY_TIME);
    AliyunIoTSDK::send("AmbientLightBlue", AmbientLightBlue);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("AmbientLightCount", AmbientLightCount);
    delay(SEND_DELAY_TIME);    
    AliyunIoTSDK::send("AmbientLightLuminance", AmbientLightLuminance);
    delay(SEND_DELAY_TIME);    
}
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 serial2DataDispose(){//处理串口2接收的数据 
  if(Serial2.available() > 0) { // 如果串口2中有数据可用 数据格式From:Name-State 
    String receivedFromString2  = Serial2.readStringUntil(':');//读取一行字符串,直到换行符 ':'
    String receivedNameString2  = Serial2.readStringUntil('-'); // 读取一行字符串,直到符  '-'
    String receivedStateString2 = Serial2.readStringUntil('\n'); // 读取一行字符串,直到换行符 '\n'  
    
    char receivedFromArray2[receivedFromString2.length() + 1];
    receivedFromString2.toCharArray(receivedFromArray2, receivedFromString2.length() + 1);
    
    char receivedNameArray2[receivedNameString2.length() + 1];    
    receivedNameString2.toCharArray(receivedNameArray2, receivedNameString2.length() + 1);
    
    char receivedStateArray2[receivedStateString2.length() + 1];    
    receivedStateString2.toCharArray(receivedStateArray2, receivedStateString2.length() + 1);
    
    String receivedMessageString2 = String(receivedNameString2 + '-' + receivedStateString2);
    char receivedMessageArray2[receivedMessageString2.length() + 1];    
    receivedMessageString2.toCharArray(receivedMessageArray2, receivedMessageString2.length() + 1);
        
    if(receivedNameString2 == ""){//name为空 无格式字符串
      messageShowUI(0,113 - 13 * 1,"From","NULL","R",receivedFromArray2);
      showLongMessage(SHOW_MODE_RECIVED,String(receivedFromString2 + receivedNameString2));
    }     
    else {//定义格式字符串      
      messageShowUI(0,113 - 13 * 1,"From",receivedFromArray2,"R",receivedMessageArray2);
      showLongMessage(SHOW_MODE_RECIVED,String(receivedFromString2 + ':' + receivedMessageString2));         
      if(receivedNameArray2[0] == 'T' && receivedNameArray2[1] == 'i' && receivedNameArray2[2] == 'm'){//Time-Get
        if(receivedStateArray2[0] == 'G' && receivedStateArray2[1] == 'e' && receivedStateArray2[2] == 't'){          
          sprintf(timeArr, "Time:%02d-%02d-%02d", currentHour, currentMinute, currentSecond);// 使用sprintf格式化时间
          Serial2.printf(timeArr);//使用printf ASRPRO才能接收到数据
          messageShowUI(0,113,"Goal","ASRPRO","S",timeArr);//目标 名称 发送 数据 
          showLongMessage(SHOW_MODE_SEND,timeArr);   
        }
      }
      else if(receivedNameArray2[0] == 'L' && receivedNameArray2[1] == 'e' && receivedNameArray2[2] == 'd'){//Led-On
        if(receivedStateArray2[0] == 'O' && receivedStateArray2[1] == 'n' ){
          for(int i = 0; i < deviceCount;i++){
            if(strncmp(devices[i].name.c_str(),"Led",3) == 0){
              udp.beginPacket(devices[i].ip, udpPort);
              udp.printf("Led:On");
              udp.endPacket();
              messageShowUI(0,113,"Goal","Led","S","Led-On");//目标 名称 发送 数据 
              showLongMessage(SHOW_MODE_SEND,"Led-On"); 
              Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
              break;                
            }
            else if(i == deviceCount - 1){//当i == deviceCount - 1 时仍未找到即不存在该设备
              showLongMessage(SHOW_MODE_SEND,"No found device!"); 
            }
          }        
          messageShowUI(0,113,"Goal","Led","S","Led-On");//目标 名称 发送 数据 
          showLongMessage(SHOW_MODE_SEND,"Led-On");   
        }
        else if(receivedStateArray2[0] == 'O' && receivedStateArray2[1] == 'f' && receivedStateArray2[2] == 'f'){//Led-Off
          for(int i = 0; i < deviceCount;i++){
            if(strncmp(devices[i].name.c_str(),"Led",3) == 0){
              udp.beginPacket(devices[i].ip, udpPort);
              udp.printf("Led:Off");
              udp.endPacket();
              messageShowUI(0,113,"Goal","Led","S","Led-Off");//目标 名称 发送 数据 
              showLongMessage(SHOW_MODE_SEND,"Led-Off"); 
              Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
              break;                
            }
            else if(i == deviceCount - 1){//当i == deviceCount - 1 时仍未找到即不存在该设备
              showLongMessage(SHOW_MODE_SEND,"No found device!"); 
            }
          }  
          messageShowUI(0,113,"Goal","Led","S","Led-Off");//目标 名称 发送 数据 
          showLongMessage(SHOW_MODE_SEND,"Led-Off");          
        }         
      }
      else if(receivedNameArray2[0] == 'R' && receivedNameArray2[1] == 'e' && receivedNameArray2[2] == 'l'){//Relay-On
        if(receivedStateArray2[0] == 'O' && receivedStateArray2[1] == 'n' ){       
          for(int i = 0; i < deviceCount;i++){
            if(strncmp(devices[i].name.c_str(),"Relay",5) == 0){
              udp.beginPacket(devices[i].ip, udpPort);
              udp.printf("Relay:On");
              udp.endPacket();
              messageShowUI(0,113,"Goal","Relay","S","Relay-On");//目标 名称 发送 数据 
              showLongMessage(SHOW_MODE_SEND,"Relay-On"); 
              Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
              break;                
            }
            else if(i == deviceCount - 1){//当i == deviceCount - 1 时仍未找到即不存在该设备
              showLongMessage(SHOW_MODE_SEND,"No found device!"); 
            }
          }        
        }
        else if(receivedStateArray2[0] == 'O' && receivedStateArray2[1] == 'f' && receivedStateArray2[2] == 'f'){//Relay-Off         
          for(int i = 0; i < deviceCount;i++){
            if(strncmp(devices[i].name.c_str(),"Relay",5) == 0){
              udp.beginPacket(devices[i].ip, udpPort);
              udp.printf("Relay:Off");
              udp.endPacket();
              messageShowUI(0,113,"Goal","Relay","S","Relay-Off");//目标 名称 发送 数据 
              showLongMessage(SHOW_MODE_SEND,"Relay-Off"); 
              Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
              break;                
            }
            else if(i == deviceCount - 1){//当i == deviceCount - 1 时仍未找到即不存在该设备
              showLongMessage(SHOW_MODE_SEND,"No found device!"); 
            }
          }      
        }  
        else if(receivedStateArray2[0] == 'O' && receivedStateArray2[1] == 'p' && receivedStateArray2[2] == 'e'){//Relay-Open         
          for(int i = 0; i < deviceCount;i++){
            if(strncmp(devices[i].name.c_str(),"Relay",5) == 0){
              udp.beginPacket(devices[i].ip, udpPort);
              udp.printf("Relay:Open");
              udp.endPacket();
              messageShowUI(0,113,"Goal","Relay","S","Relay-Open");//目标 名称 发送 数据 
              showLongMessage(SHOW_MODE_SEND,"Relay-Open"); 
              Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
              break;                
            }
            else if(i == deviceCount - 1){//当i == deviceCount - 1 时仍未找到即不存在该设备
              showLongMessage(SHOW_MODE_SEND,"No found device!"); 
            }
          }      
        } 
        else if(receivedStateArray2[0] == 'C' && receivedStateArray2[1] == 'l' && receivedStateArray2[2] == 'o'){//Relay-Close         
          for(int i = 0; i < deviceCount;i++){
            if(strncmp(devices[i].name.c_str(),"Relay",5) == 0){
              udp.beginPacket(devices[i].ip, udpPort);
              udp.printf("Relay:Close");
              udp.endPacket();
              messageShowUI(0,113,"Goal","Relay","S","Relay-Close");//目标 名称 发送 数据 
              showLongMessage(SHOW_MODE_SEND,"Relay-Close"); 
              Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
              break;                
            }
            else if(i == deviceCount - 1){//当i == deviceCount - 1 时仍未找到即不存在该设备
              showLongMessage(SHOW_MODE_SEND,"No found device!"); 
            }
          }      
        }                         
      }      
    }
  }
}
void dht11DataGet(void){
  static bool initFlag = false;
  if(!initFlag)//未初始化  
  {
    delay(2000);  // 延迟2秒以便传感器稳定
    initFlag = true;
  }
  humidity = dht.readHumidity();        // 读取湿度
  temperature = dht.readTemperature();  // 读取温度(默认摄氏度)
  if (isnan(humidity) || isnan(temperature)) {
    showLongMessage(SHOW_MODE_MYSELF,"Failed to read from DHT sensor!");
    return;
  }
  sprintf(HumiStr,"%.0f",humidity);//"%.1f"一位小数的float类型
  sprintf(TempStr,"%.1f",temperature);
}
void showTimeUI(void){
  char timeString[] = "23:59:59";
  int timeX = 6;
  int timeY = 32;
  int timeSize = 3;
  static int showHour = 0;
  static int showMinute = 0;
  static int showSecond = 0;
  tft.setTextColor(TIME_COLOUR);//设置文字颜色
  tft.setTextSize(timeSize);//设置字体大小
  if(showHour != currentHour){
    showHour = currentHour;
    char showHourArr[] = "59";
    sprintf(showHourArr,"%02d",showHour); //格式化%02d      
    tft.fillRect(timeX,timeY,6*timeSize*2,8*timeSize,ST7735_BLACK);//刷新
    tft.setCursor(timeX,timeY);//设置显示位置   
    tft.print(showHourArr);//showHourArr 
  }
  tft.setCursor(timeX + 6 * timeSize * 2,timeY);//设置显示位置
  tft.print(":");//: 
  if(showMinute != currentMinute){
    showMinute = currentMinute;
    char showMinuteArr[] = "59";
    sprintf(showMinuteArr,"%02d",showMinute); //格式化%02d     
    tft.fillRect(timeX + 6 * timeSize * 3,timeY,6 * timeSize * 2,8 * timeSize,ST7735_BLACK);//刷新
    tft.setCursor(timeX + 6 * timeSize * 3,timeY);//设置显示位置   
    tft.print(showMinuteArr);//showMinuteArr 
  }
  tft.setCursor(timeX + 6 * timeSize * 5,timeY);//设置显示位置  
  tft.print(":");//: 
  if(showSecond != currentSecond){
    showSecond = currentSecond;
    char showSecondArr[] = "59";
    sprintf(showSecondArr,"%02d",showSecond);
    tft.fillRect(timeX + 6 * timeSize * 6,timeY,6 * timeSize * 2,8 * timeSize,ST7735_BLACK);//刷新
    tft.setCursor(timeX + 6 * timeSize * 6,timeY);//设置显示位置   
    tft.print(showSecondArr);//showSecondArr 
  }
  else{
    char showSecondArr[] = "59";
    sprintf(showSecondArr,"%02d",showSecond); 
    tft.setCursor(timeX + 6 * timeSize * 6,timeY);//设置显示位置   
    tft.print(showSecondArr);//showSecondArr       
  }
}
void processDiscoverPacket(){//处理5089端口的发现请求
  int packetSize = discoveryUdp.parsePacket();
  if(packetSize){
    char incomingPacket[255];
    int len = discoveryUdp.read(incomingPacket,255);//读取数据
    if(len > 0){
      incomingPacket[len] = 0;
    }
    //处理发送请求
    if (strcmp(incomingPacket, "DISCOVER") == 0) {
      discoveryUdp.beginPacket(discoveryUdp.remoteIP(), discoveryUdp.remotePort());
      discoveryUdp.printf("ESP32_IP:%s,PORT:%d", WiFi.localIP().toString().c_str(), udpPort);
      discoveryUdp.endPacket();
    }    
  }
}

void processIncomingPacket(){//处理5088端口接收的数据
  int packetSize = udp.parsePacket();
  if (packetSize) {
    char incomingPacket[255];
    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);
    showLongMessage(SHOW_MODE_MYSELF,incomingPacket);

    // 处理设备消息
    String message = String(incomingPacket);
    String deviceName = message.substring(0, message.indexOf(':'));//数据格式deviceName:stateName 例如Relay:On
    String stateName = message.substring(message.indexOf(':') + 1 );
    IPAddress senderIP = udp.remoteIP();
    // 处理具体的设备信息
    if(strcmp(stateName.c_str(),"Link") == 0){
      udp.beginPacket(senderIP, udpPort);
      udp.printf("OK");
      udp.endPacket(); 
      showLongMessage(SHOW_MODE_MYSELF,"Send OK!");      
    }    
    bool deviceExists = false;
    for (int i = 0; i < deviceCount; i++) {
      if (devices[i].name == deviceName) {
        deviceExists = true;
        devices[i].ip = senderIP;  // 更新设备IP
        break;
      }
    }    
    if (!deviceExists && deviceCount < MAX_CONNECT_COUNT) {
      devices[deviceCount].name = deviceName;
      devices[deviceCount].ip = senderIP;
      deviceCount++;
    }
    Serial.println("Device List:");
    for (int i = 0; i < deviceCount; i++) {
      Serial.printf("Device %d: Name = %s, IP = %s\n", i + 1, devices[i].name.c_str(), devices[i].ip.toString().c_str());
    }


  }
}
void IRAM_ATTR onTimer() {
  // 在定时器中断服务程序中更新屏幕显示
  //static int timeCount = 0;
  //开启滚动显示
  static int i[MAX_SHOW_STRING] = {0};
  for(int j = 0; j < MAX_SHOW_STRING; j++){
    if(showFlag[j] == 1){//需要显示
      if(i[j] <= maxCount[j] - showCount[j]){//滚动字幕显示 
        tft.fillRect(textShowX[j], textShowY[j], showCount[j] * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域 
        strncpy(textShowString[j], textMaxString[j] + i[j],showCount[j]);//从textMaxString[j]的第i[j]个字符开始,拷贝showCount[j]个字符到textShowString[j]  
        textShowString[j][showCount[j]] = '\0'; // 添加字符串结束符
        tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
        tft.setTextSize(1);//设置字体大小
        tft.setCursor(textShowX[j],textShowY[j]);//设置显示位置
        tft.print(textShowString[j]);//显示Text4 Recived data!
        i[j] += 1;
      }
      else{//滚动字幕显示结束 显示前showCount[j]个字符
        tft.fillRect(textShowX[j], textShowY[j], showCount[j] * 6, 8, BACKGROUND_COLOUR);//绘制矩形刷新部分区域
        strncpy(textShowString[j], textMaxString[j],showCount[j]);//将textMaxString[j]的前showCount[j]个字符,拷贝到textShowString[j] 
        textShowString[j][showCount[j]] = '\0'; // 添加字符串结束符
        tft.setTextColor(TEXT4_COLOUR);//设置文字颜色
        tft.setTextSize(1);//设置字体大小
        tft.setCursor(textShowX[j],textShowY[j]);//设置显示位置
        tft.print(textShowString[j]);//显示Text4 Recived data!
        i[j] = 0;
        showFlag[j] = 0;
        //timerEnd(timer); // 关闭定时器      
      }
    }
  }
}
void setup() { 
  Serial.begin(115200);//初始化串口0用于调试
  Serial2.begin(115200);//初始化串口2用于交换数据
  dht.begin();        // 初始化DHT传感器
  // 初始化 wifi
  wifiInit(WIFI_SSID, WIFI_PASSWD);
  // 启动两个UDP服务器
  udp.begin(udpPort);// udpPort
  discoveryUdp.begin(discoveryPort);// discoveryPort
  // 初始化 iot,需传入 wifi 的 client,和设备产品信息
  AliyunIoTSDK::begin(espClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, REGION_ID);
  // 初始化NTP客户端
  timeClient.begin();
  // 配置硬件定时器
  timer = timerBegin(0, 80, true); // 使用定时器0,分频器80,计数上升沿触发中断
  timerAttachInterrupt(timer, &onTimer, true); // 将中断服务程序与定时器关联
  timerAlarmWrite(timer, SHOWDELAY_TIME * 1000, true); // 设置定时器触发时间为SHOWDELAY_TIME*1000(单位:微秒)默认为500us*1000 = 0.5s
  //timerAlarmEnable(timer); // 启用定时器

  dht11DataGet();
  messageShowUI(0,113 - 13 * 1,"From","ASRPRO","R","Recived data:Hello World!");
  messageShowUI(0,113,"Goal","Fan","S","Send data:Hello World!");  
  showDataUI(0,0,0,TempStr, "Temperature");
  showDataUI(80,0,1,HumiStr,"Humidity");
  //showLongMessage(SHOW_MODE_MYSELF,"Hello World!");
}

void loop() {
  unsigned long currentMillis = millis();//获取已运行时间
  static char oldHumiStr[6] = "78";
  static char oldTempStr[6] = "34.8";  
  // 每100毫秒处理一次数据
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    serial2DataDispose();
    processIncomingPacket();//处理5088端口接收的数据
  } 
  // 每1秒更新一次时间
  if (currentMillis - previousMillisUpdate >= updateInterval) {
    previousMillisUpdate = currentMillis;
    timeClient.update();
    unsigned long epochTime = timeClient.getEpochTime();
    struct tm *ptm = gmtime((time_t *)&epochTime);
    currentHour = ptm->tm_hour;
    currentMinute = ptm->tm_min;
    currentSecond = ptm->tm_sec;
    showTimeUI();
    processDiscoverPacket();//处理5089端口的发现请求
  }
  // 每10秒更新一次温度和湿度数据
  if (currentMillis - previousMillisData >= dataInterval) {
    previousMillisData = currentMillis;
    dht11DataGet();
    if (strcmp(oldTempStr, TempStr) != 0) {
      showDataUI(0, 0, 0, TempStr, "Temperature");
      strcpy(oldTempStr, TempStr);
      AliyunIoTSDK::send("Temperature", temperature);//上传数据到服务器    
    }
    if (strcmp(oldHumiStr, HumiStr) != 0) {
      showDataUI(80, 0, 1, HumiStr, "Humidity");
      strcpy(oldHumiStr, HumiStr);
      AliyunIoTSDK::send("Humility", humidity);//上传数据到服务器    
    }
    AliyunIoTSDK::loop(); // 你提到的保持服务器的连接,每10秒执行一次
  }    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700
  • 701
  • 702
  • 703
  • 704
  • 705
  • 706
  • 707
  • 708
  • 709
  • 710
  • 711
  • 712
  • 713
  • 714
  • 715
  • 716
  • 717
  • 718
  • 719
  • 720
  • 721
  • 722
  • 723
  • 724
  • 725
  • 726
  • 727
  • 728
  • 729
  • 730
  • 731
  • 732
  • 733
  • 734
  • 735
  • 736
  • 737
  • 738
  • 739
  • 740
  • 741
  • 742

显示部分代码可参考Arduino平台基于GFX库的滚动字幕消息显示UI设计(定时器实现刷新)
阿里云平台SDK相关代码参考使用ESP-01S与阿里云物联网平台服务器的连接与配置(温湿度检测)

ASRPRO代码
#include "asr.h"
extern "C"{ void * __dso_handle = 0 ;}
#include "setup.h"
#include "HardwareSerial.h"
#include "myLib/asr_event.h"

uint32_t snid;
void ASR_CODE();

//{speak:小蝶-清新女声,vol:4,speed:10,platform:haohaodada}
//{playid:10001,voice:欢迎使用智能家居助手,用小璐同学唤醒我。}
//{playid:10002,voice:我退下了,用小璐同学唤醒我}

/*默认循环函数
*/
void ASR_CODE(){
  String Serial1_Data = "TIME:23-45-30";
  String Data_Type = "0";
  String Clock = "0";
  String Min = "0";
  switch (snid) {
   case 2:
    Serial1.println("ASRPRO:Led-On");
    delay(10);
    break;
   case 3:
    Serial1.println("ASRPRO:Led-Off");
    delay(10);
    break;
   case 4:
    Serial1.println("ASRPRO:Led-Up");
    delay(10);
    break;
   case 5:
    Serial1.println("ASRPRO:Led-Down");
    delay(10);
    break;
   case 8:
    Serial1.println("ASRPRO:Computer-On");
    delay(10);
    break;
   case 9:
    Serial1.println("ASRPRO:Computer-Off");
    delay(10);
    break;
   case 10:
    Serial1.println("ASRPRO:Fan-On");
    delay(10);
    break;
   case 11:
    Serial1.println("ASRPRO:Fan-Off");
    delay(10);
    break;
   case 12:
    Serial1.println("ASRPRO:Fan-Up");
    delay(10);
    break;
   case 13:
    Serial1.println("ASRPRO:Fan-Down");
    delay(10);
    break;
   case 14:
    Serial1.println("ASRPRO:Led-Up");
    delay(10);
    break;
   case 15:
    Serial1.println("ASRPRO:Led-Down");
    delay(10);
    break;
   case 16:
    Serial1.println("ASRPRO:Led-Max");
    delay(10);
    break;
   case 17:
    Serial1.println("ASRPRO:Led-Min");
    delay(10);
    break;
   case 18:
    Serial1.println("ASRPRO:Switch-On");
    delay(10);
    //{playid:10500,voice:开关已打开}
    play_audio(10500);
    break;
   case 19:
    Serial1.println("ASRPRO:Switch-Off");
    delay(10);
    //{playid:10501,voice:开关已关闭}
    play_audio(10501);
    break;
   case 20:
    Serial1.println("ASRPRO:Fan-Max");
    delay(10);
    break;
   case 21:
    Serial1.println("ASRPRO:Fan-Min");
    delay(10);
    break;
   case 22:
    Serial1.println("ASRPRO:Time-Get");
    delay(500);
    if(Serial1.available() > 0){
      Serial1_Data = Serial1.readString();
      Data_Type = String(Serial1_Data).substring(1,4);
      if(String(Data_Type).indexOf("TIME",1)){
        Clock = String(Serial1_Data).substring(5,7);
        Min = String(Serial1_Data).substring(8,10);
        //{playid:10502,voice:现在时间}
        play_audio(10502);
        play_num((int64_t)((String(Clock).toInt()) * 100), 1);
        //{playid:10503,voice:点}
        play_audio(10503);
        play_num((int64_t)((String(Min).toInt()) * 100), 1);
        //{playid:10504,voice:分}
        play_audio(10504);
      }
    }
    break;
   case 23:
    Serial1.println("ASRPRO:Sweater-Get");
    delay(500);
    break;
   case 24:
    Serial1.println("ASRPRO:Relay-On");
    delay(100);
    break;
   case 25:
    Serial1.println("ASRPRO:Relay-Off");
    delay(100);
    break;
  }

}

void hardware_init(){
  setPinFun(2,FORTH_FUNCTION);
  setPinFun(3,FORTH_FUNCTION);
  Serial1.begin(115200);
  vTaskDelete(NULL);
}

void setup()
{
  //{ID:0,keyword:"唤醒词",ASR:"小璐同学",ASRTO:"我在"}
  //{ID:1,keyword:"命令词",ASR:"退下",ASRTO:"好的"}
  //{ID:2,keyword:"命令词",ASR:"开灯",ASRTO:"好的,马上打开灯光"}
  //{ID:3,keyword:"命令词",ASR:"关灯",ASRTO:"好的,马上关闭灯光"}
  //{ID:4,keyword:"命令词",ASR:"灯亮一点",ASRTO:"好的,正在为您增加亮度"}
  //{ID:14,keyword:"命令词",ASR:"亮一点",ASRTO:"好的,正在为您增加亮度"}
  //{ID:5,keyword:"命令词",ASR:"灯暗一点",ASRTO:"好的,正在为您降低亮度"}
  //{ID:15,keyword:"命令词",ASR:"暗一点",ASRTO:"好的,正在为您降低亮度"}
  //{ID:6,keyword:"命令词",ASR:"当前温度",ASRTO:"当前温度二十七摄氏度"}
  //{ID:7,keyword:"命令词",ASR:"当前湿度",ASRTO:"当前湿度百分之七十"}
  //{ID:8,keyword:"命令词",ASR:"打开电脑",ASRTO:"好的,正在为您打开电脑"}
  //{ID:9,keyword:"命令词",ASR:"关闭电脑",ASRTO:"好的,正在为您关闭电脑"}
  //{ID:10,keyword:"命令词",ASR:"打开风扇",ASRTO:"好的,正在为您打开风扇"}
  //{ID:11,keyword:"命令词",ASR:"关闭风扇",ASRTO:"好的,正在为您关闭风扇"}
  //{ID:12,keyword:"命令词",ASR:"风扇快一点",ASRTO:"好的,正在增大风速"}
  //{ID:13,keyword:"命令词",ASR:"风扇慢一点",ASRTO:"好的,正在减小风速"}
  //{ID:16,keyword:"命令词",ASR:"亮度调到最大",ASRTO:"好的,正在调整为最大亮度"}
  //{ID:17,keyword:"命令词",ASR:"亮度调到最小",ASRTO:"好的,正在调整为最小亮度"}
  //{ID:18,keyword:"命令词",ASR:"打开开关",ASRTO:"好的,正在为您打开开关"}
  //{ID:19,keyword:"命令词",ASR:"关闭开关",ASRTO:"好的,正在为您关闭开关"}
  //{ID:20,keyword:"命令词",ASR:"风速调到最大",ASRTO:"好的,正在调整为最大风速"}
  //{ID:21,keyword:"命令词",ASR:"风速调到最小",ASRTO:"好的,正在调整为最小风速"}
  //{ID:22,keyword:"命令词",ASR:"几点了",ASRTO:"正在查询"}
  //{ID:23,keyword:"命令词",ASR:"今天天气怎么样",ASRTO:"正在查询"}
  //{ID:24,keyword:"命令词",ASR:"打开继电器",ASRTO:"好的,正在为您打开继电器"}
  //{ID:25,keyword:"命令词",ASR:"关闭继电器",ASRTO:"好的,正在为您关闭继电器"}

  //{playid:10084,voice:零}
  //{playid:10085,voice:一}
  //{playid:10086,voice:二}
  //{playid:10087,voice:三}
  //{playid:10088,voice:四}
  //{playid:10089,voice:五}
  //{playid:10090,voice:六}
  //{playid:10091,voice:七}
  //{playid:10092,voice:八}
  //{playid:10093,voice:九}
  //{playid:10094,voice:十}
  //{playid:10095,voice:百}
  //{playid:10096,voice:千}
  //{playid:10097,voice:万}
  //{playid:10098,voice:亿}
  //{playid:10099,voice:负}
  //{playid:10100,voice:点}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188

应用场景

智能家居:
配合其他设备实现家庭设备的智能化管理,如照明、温控等。

项目进展

已完成部分功能以及测试,包括但不限于:

  • 本地语音控制
  • 控制程序开发
  • 手机、电脑网页端控制
  • 阿里云物联网平台后台控制
  • 设备间通信及控制
  • 温湿度数据获取、显示以及上传
  • 网络实时时间获取及显示
  • 语音报时

后续进行完善及补充,后续将在立创开源社区进行软硬件开源,后续以开源社区更新为准,此博客不实时更新
点击前往立创开源社区查看:智能家居助手

演示视频

语音控制继电器以及LED灯演示

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/724945
推荐阅读
相关标签
  

闽ICP备14008679号