/*
ESP32 I2S Ejemplo de uso del micrófono
Muestrea sonido con el micrófono y lo despliega en el graficador serial
Requiere un Micrófono INMP441
*/
#include <Wire.h>
#include "WiFi.h"
#include <string.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "HTTPClient.h"
//MQTT 连接服务器参数定义
const char* MQTT_SERVER = "121.43.237.80";
const int MQTT_PORT = 1883;
const char* MQTT_USRNAME = "esp32";
const char* MQTT_PASSWD = "123456";
const char *topic = "esp32/sub";
const char* CLIENT_ID = "esp32"; //当前设备的clientid标志
WiFiClient espClient;
PubSubClient client(espClient);
//定义MQTT要订阅的TOPIC
const char *Subtopic = "alarm/function";
//定义MQTT 发布的TOPIC
const String PubTopic = "alarm/property";
//提醒消息列表定义
#define Reminder_MAXLEN 6
uint16_t reminder_time[Reminder_MAXLEN] ={0,};//以正整数方式存储提醒时间(eg. 16:37 存储为1637)
String reminder_event[Reminder_MAXLEN];//String格式存储提醒事件
uint8_t reminder_index = 0;//提醒消息列表索引
uint8_t reminder_len = 0;//提醒消息长度
//定义wifi客户端对象和SSID/PASSWORD等参数
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
//定义 http连接客户端
HTTPClient http_client;//语音识别使用
//网络时钟设置
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;
String ipaddress;
//MQTT重连函数
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(CLIENT_ID,MQTT_USRNAME,MQTT_PASSWD)) {
Serial.println("connected");
// 连接成功时订阅主题
client.subscribe(Subtopic);
Reminder_Upload();
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
//MQTT回调函数
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic); // 打印主题信息
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]); // 打印主题内容
}
Serial.println();
//对接收数据进行处理
//如果接收到的是预期的topic,则进行下一步处理
if(strstr(topic,Subtopic) != NULL){
//json序列化payload
DynamicJsonDocument doc(200);
deserializeJson(doc, payload);
//如果存在add键
if(doc.containsKey("add")){
Reminder_Add(doc["add"]["time"].as<String>(),doc["add"]["event"].as<String>());
}
else if(doc.containsKey("del")){
Reminder_Del(doc["del"]["index"]);
}
else if(doc.containsKey("edit")){
Reminder_Edit(doc["edit"]["index"],doc["edit"]["time"].as<String>(),doc["edit"]["event"].as<String>());
}
else if(doc.containsKey("query")){
Reminder_Upload();
}
else if(doc.containsKey("note")){
}
else
;
}
}
//初始化函数
void setup() {
// 配置串口监视器
Serial.begin(115200);
Serial.println(" ");
delay(1000);
//初始化wifi
uint8_t count=0;
WiFi.disconnect(true);
WiFi.begin(WIFI_SSID,WIFI_PASSWORD);//填写自己的wifi账号密码
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
count++;
if(count>=75){
Serial.printf("\r\n-- wifi connect fail! --");
break;
}
vTaskDelay(200);
}
Serial.printf("\r\n-- wifi connect success! --\r\n");
Serial.print("IP address: "); // 同时还将输出IP地址。这一功能是通过调用
Serial.println(WiFi.localIP()); // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
ipaddress = WiFi.localIP().toString();
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
//连接MQTT服务器
client.setServer(MQTT_SERVER, MQTT_PORT); //设定MQTT服务器与使用的端口,1883是默认的MQTT端口
client.setCallback(callback); //设定回调方式,当ESP8266收到订阅消息时会调用此方法
}
//提醒事项添加函数,
void Reminder_Add(String time,String event){
//检查当前列表是否已满,满了则不再添加
if(reminder_index < Reminder_MAXLEN)
{
//检查事件字符串格式
uint16_t u16_time = time.toInt()*100+ (time.substring(3,5)).toInt();
reminder_time[reminder_index] = u16_time;
reminder_event[reminder_index] = event;
reminder_index++;
}
//返回数据已满,无法添加提示
else{
}
Reminder_Upload();
}
//提醒事项删除函数
void Reminder_Del(uint8_t del_index){
//如果del_index 合法,则删除列表中对应项并更新列表
if((del_index>=0)&&(del_index<reminder_index))
{
for(int i=del_index;i<reminder_index-1;i++)
{
reminder_time[i] = reminder_time[i+1];
reminder_event[i] = reminder_event[i+1];
}
reminder_index--;
}
//返回删除索引无效
else{
}
Reminder_Upload();
}
//提醒事项修改函数
void Reminder_Edit(uint8_t eidt_index,String time,String event){
//如果edit_index 合法,则修改列表中对应项
if((eidt_index>=0)&&(eidt_index<reminder_index))
{
//检查事件字符串格式
uint16_t u16_time = time.toInt()*100+ (time.substring(3,5)).toInt();
reminder_time[eidt_index] = u16_time;
reminder_event[eidt_index] = event;
}
//返回修改索引无效
else{
}
Reminder_Upload();
}
//上传当前提醒事项列表
void Reminder_Upload()
{
//分配JSON结构体空间
DynamicJsonDocument alarm(200);
// StaticJsonDocument 在栈区分配内存 它也可以被 DynamicJsonDocument(内存在堆区分配) 代替
// DynamicJsonDocument doc(200);
//序列化alarm结构体
int i =0;
JsonArray list = alarm.createNestedArray("alarmlist");
String time_str = "00:00";
for(i= 0;i<reminder_index;i++){
sprintf((char *)&time_str[0],"%02d:%02d",reminder_time[i]/100,reminder_time[i]%100);
JsonObject Item = list.createNestedObject();
Item["time"] = time_str;
Item["event"] = reminder_event[i];
}
Serial.println(reminder_index);
//串口打印结果
String json_str;
//alarm.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
//输出结构体到字符串
serializeJson(alarm, json_str);
Serial.println(json_str);
//MQTT发布消息
client.publish("alarm/property",(const char *)&json_str[0]);
}
//提醒事项查询
void Reminder_Query(uint8_t del_index){
}
//语音播报任务函数
void Speaker_Task(){
}
void timer_show() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
Serial.print("Failed to obtain time");
Serial.print(ipaddress);
return;
}
uint32_t time_net = timeinfo.tm_hour*10000+timeinfo.tm_min*100+timeinfo.tm_sec;
for(int i= 0;i<reminder_index;i++){
uint32_t time_alarm = ((uint32_t)reminder_time[i])*100;
if((time_net - time_alarm>0)&&(time_net - time_alarm<10)){
Serial.print("notes:");
Serial.println(i);
}
}
}
void loop() {
static uint32_t cnt =0;
if (!client.connected())
{
reconnect();
}
client.loop();
if(cnt%10==0)
timer_show();
cnt++;
delay(100);
}Loading
esp32-s3-devkitc-1
esp32-s3-devkitc-1