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

发布时间:2024-11-21 06:31

智能家居通过节能设计,帮助我们实现低碳生活方式 #生活知识# #生活感悟# #科技生活变迁# #智能生活#

项目介绍

实物图

请添加图片描述

项目名称

基于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秒执行一次 } }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742

显示部分代码可参考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:点} }

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188

应用场景

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

项目进展

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

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

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

演示视频

网址:基于ESP32+ASRPRO的智能家居助手设计与实现 https://www.yuejiaxmz.com/news/view/169449

相关内容

基于ESP32的智能家居控制系统设计
基于ESP32的智能家庭健康系统
基于STM32智能家居系统的设计与实现
【DIY】基于STM32智能家居系统的设计与实现
基于STM32的智能家居语音控制系统:集成LD3320、ESP8266设计流程
基于ESP32制作安卓应用蓝牙控制的家庭自动化系统
基于STM32的智能节能风扇的设计与实现
基于Linux的智能家居的设计(1)
基于WiFi的智能家居系统设计
STM32毕业设计——基于STM32+MQTT+WiFi技术的智能家居系统设计与实现(毕业论文+程序源码)——智能家居系统

随便看看