#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#else
#include "ESP8266WiFi.h" // 本程序使用 ESP8266WiFi库
#endif
#include <DHT.h> //引入DHT11库
#include <ESP8266WebServer.h> // ESP8266WebServer库
#include <WiFiClient.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <EEPROM.h>
#include <FastLED.h>
#include <Ticker.h>
#include <PubSubClient.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h>
#include <ArduinoOTA.h>
#include "config.h"
int otaFlag=0; //0:普通工作模式,1:刷机模式
bool otaInProgress = false;
String devwxid="";
String deviceId="";
String deviceType="0";
String wifiSetting = "0"; //0代表未完成,1代表完成
const char *pubTOPIC = "pub_topic_mqtt";
int recCount=0;
unsigned char recBuffer[5]; //定义串口接收数组
WiFiClient espClient;
PubSubClient mqttClient(espClient);
CRGB leds[NUM_LEDS]; //建立光带leds
//CHSV timerHSVColor(39,255,50); //HSV方法定义计时器显示颜色timerHSVColor(色调,饱和度,亮度)
int curColor;
uint32_t curDelay;
Ticker ledActionTimer;
WiFiUDP ntpUDP; //创建UDP实例
NTPClient timeClient(ntpUDP, "pool.ntp.org");
//Last time when the LEDs were updated
bool needTo_sendDHT=false;
DHT dhtSensor(DHT_DATA_PIN,DHTTYPE);
float sensor_hum;
float sensor_tem;
Ticker delayTimer;
//定义闪存WIFI信息结构体
struct config_type{
char stassid[32];
char stapsw[64];
char devid[16];
char curMode[16];
};
config_type devConfig;
int clockCount;
Ticker clockTicker; //每隔1分钟采集一次网络时间
int dhtCount;
Ticker dhtTicker;
Ticker ringTimer; //定义铃声
int ringCount = 0; //定义播放次数计数器
int input1Time=0; //定义第一面的计时秒数
int input2Time=0; //定义第二面的计时秒数
int lightUpInterval=0; //定义循环时间
int lightsOff=NUM_LEDS-1; //要熄灭的led灯
int timerCount=0;
Ticker timerTicker;
uint32_t timesTotal=0;
bool timerFlag=false; //计时标志
Ticker totalTimerTicker; //秒数计时
ESP8266WebServer esp8266_server(80); // 建立ESP8266WebServer对象,对象名称为esp8266_server
void setup(){
//设置串口波特率,以便打印信息
Serial.begin(9600);
while(Serial.read()>= 0) {} //清除串口缓存
//Serial1.begin(115200);
// INIT LED
FastLED.addLeds<LED_TYPE, LED_DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS); // 光带初始化WS2812B (Neopixel)
FastLED.setMaxPowerInVoltsAndMilliamps(5, 100); //电源管理:设置最大电压(5v)和最大电流(500mA),让不会消耗Arduino太大电流。
FastLED.setBrightness(max_bright); // 设置光带亮度
FastLED.clear();
FastLED.show();
delay(100);
loadConfig(); //获取ESP8266闪存数据
if (strcmp(devConfig.curMode, "") == 0) {
//Serial1.println("当前为离线模式WIFI未设置");
VoicePlay(0x05,0,0); //发送语音告知
delay(2000);
//curRGBColor.r=0;
//curRGBColor.g=0;
//curRGBColor.b=255;
//leds[0]=CRGB::Red; //熄灭最后一盏灯
//leds[11]=CRGB::Green; //熄灭最后一盏灯
//leds[2]=CRGB::Blue; //熄灭最后一盏灯
//FastLED.show();
for (int i=0;i<3;i++) {
fill_solid(leds, NUM_LEDS,CRGB::Red);
FastLED.show();
delay(500);
fill_solid(leds, NUM_LEDS,CRGB::Black);
FastLED.show();
delay(500);
}
}
if (strcmp(devConfig.curMode, "1") == 0) {
connectWiFi();
if (WiFi.status() == WL_CONNECTED) {
Serial1.println(F("WIFI IS SUCCESSED..."));
VoicePlay(0x06,0,0); //发送在线语音告知
ledOff();
for (int i=0;i<3;i++) {
fill_solid(leds, NUM_LEDS,CRGB::Green);
FastLED.show();
delay(500);
fill_solid(leds, NUM_LEDS,CRGB::Black);
FastLED.show();
delay(500);
}
// INIT OTA
ArduinoOTA.setHostname(ESP_NAME);
ArduinoOTA.onStart([]() {
otaInProgress = true;
Serial.println(F("Start updating..."));
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.println(progress / (total / 100));
});
ArduinoOTA.onEnd([]() {
Serial.println(F("\nend"));
otaInProgress = false;
});
ArduinoOTA.onError([](ota_error_t error) {
String msg;
if (error == OTA_AUTH_ERROR)
msg = F("auth failed");
else if (error == OTA_BEGIN_ERROR)
msg = F("begin failed");
else if (error == OTA_CONNECT_ERROR)
msg = F("connect failed");
else if (error == OTA_RECEIVE_ERROR)
msg = F("receive failed");
else if (error == OTA_END_ERROR)
msg = F("end failed");
Serial.printf_P(PSTR("Error: %s"), msg.c_str());
});
ArduinoOTA.begin();
//初始化ONENET通信,客户端设置MQTT服务器 & 回调函数
mqttClient.setServer(MQTT_SERVER, MQTT_PORT);
mqttClient.setCallback(mqttCallback);
//mqttClient.setBufferSize(MQTT_BUFF_SIZE);
mqttConnect();
delay(300);
// CLOCK
timeClient.begin();
timeClient.setTimeOffset(28800);
getNtpTime();
clockTicker.attach(1,tickerClockCount);
delay(50);
}
}
if (strcmp(devConfig.curMode, "2") == 0) {
initWiFi(); //进入配网函数
}
FastLED.clear();
FastLED.show();
delay(100);
//DHT
dhtSensor.begin();
getDHTdata();
dhtTicker.attach(1, tickerDhtCount);
}
void loop()
{
unsigned long curMillis = millis(); //获取当前系统时间
// put your main code here, to run repeatedly:
getSerialData();
if (recCount==5) { //串口数据包长度正确
recCount=0;
if ((recBuffer[0]==0xAA) && (recBuffer[1]==0x55) && (recBuffer[3]==0x55) && (recBuffer[4]==0xAA)) {
unsigned char cmdUart=recBuffer[2];
switch (cmdUart) {
case 0xB8: //8分熟牛排
led1Default(); //led计时初始化
input1Time=60; //第一面定义60秒计时
input2Time=90; //第二面定义90秒计时
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xB5: //5分熟牛排
led1Default();
input1Time=40; //第一面定义40秒计时
input2Time=60; //第二面定义60秒计时
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xBF: //全熟牛排
led1Default();
input1Time=60; //第一面定义60秒计时
input2Time=120; //第二面定义120秒计时
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD8: //清蒸大闸蟹
led1Default(); //led计时初始化
input1Time=1320; //冷水大火蒸22分钟计时
input2Time=300; //关火后焖5分钟计时
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xF0: //调亮一点
max_bright=max_bright+1;
FastLED.setBrightness(max_bright);
break;
case 0xF1: //调暗一点
max_bright=max_bright-1;
if (max_bright <= 0){
max_bright=0;
}
FastLED.setBrightness(max_bright);
break;
case 0xFE: //启动WIFI配置模式
restoreFactory(true);
break;
case 0xFF: //恢复初始设置
delay(3000);
restoreFactory(false);
break;
case 0xDD: //切换到时钟模式
//timerTicker.detach();
Serial.println(F("switch NETWORK TIME... \n"));
//delay(2000);
//VoicePlay(0x01,0,0);
break;
case 0xEE: //取消计时|停止计时
ledOff();
ringTimer.detach();
input1Time=0;
input2Time=0;
if (timerFlag == true) { //时间计时中
totalTimerTicker.detach();
int mHours, mMinutes, mSeconds;
convertSecondsToTime(timesTotal, mHours, mMinutes, mSeconds);
VoicePlay(0x0E,mHours,0);
delay(10);
VoicePlay(0x0F,mMinutes,0);
delay(20);
VoicePlay(0x10,mSeconds,0);
timesTotal=0;
}
else {
VoicePlay(0x01,0,0);
}
timerFlag=false;
break;
case 0xD0: //三十秒计时
led1Default();
input1Time=30;
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
//Serial.println("30s start()........");
break;
case 0xD1: //四十秒计时
led1Default();
input1Time=40;
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD2: //五十秒计时
led1Default();
input1Time=50;
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD3: //一分钟钟计时
led1Default();
input1Time=60;
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD4: //一分半计时
led1Default();
input1Time=90;
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD5: //两分钟计时
led1Default();
input1Time=120; //定义120秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD6: //两分半计时
led1Default();
input1Time=150; //定义150秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xD7: //三分计时
led1Default();
input1Time=180; //定义180秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xC4: //四分计时
led1Default();
input1Time=240; //定义320秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xC5: //五分计时
led1Default();
input1Time=300; //定义300秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
break;
case 0xC6: //六分计时
led1Default();
input1Time=360; //定义360秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xC7: //七分计时
led1Default();
input1Time=420; //定义420秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xC8: //八分计时
led1Default();
input1Time=480; //定义480秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xC9: //九分计时
led1Default();
input1Time=540; //定义540秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA1: //十分钟计时
led1Default();
input1Time=600; //定义600秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA2: //十五分钟计时
led1Default();
input1Time=900; //定义900秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA3: //二十分钟计时
led1Default();
input1Time=1200; //定义1200秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA6: //二十五分钟计时
led1Default();
input1Time=1500; //定义1500秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA4: //三十分钟计时
led1Default();
input1Time=1800; //定义1800秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA7: //三十五分钟计时
led1Default();
input1Time=2100; //定义2100秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA8: //四十分钟计时
led1Default();
input1Time=2400; //定义2400秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xB6: //四十五分钟计时
led1Default();
input1Time=2700; //定义2700秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xB7: //五十分钟计时
led1Default();
input1Time=3000; //定义3000秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xA5: //一小时计时
led1Default();
input1Time=3600; //定义3600秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xC3: //一个半小时计时
led1Default();
input1Time=5400; //定义5400秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xC2: //两小时计时
led1Default();
input1Time=7200; //定义7200秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xC1: //两小时半计时
led1Default();
input1Time=9000; //定义9000秒计时
input2Time=0;
lightUpInterval=(int) (input1Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount);
break;
case 0xB1: //开始计时
ledOff();
timesTotal=0;
timerFlag=true; //计时标志
totalTimerTicker.attach(1,gatherTimesTicker); //设置每隔1秒触发一次gatherTimesTicker计时函数
break;
default:
break;
}
}
}
if (input1Time > 0) { //A面计时
if (timerCount >= input1Time ) {
timerTicker.detach();
ledOff();
input1Time=0;
timerCount=0;
if (input2Time>0) {
switch (input2Time) {
case 60:
VoicePlay(0x09,0,0); //计时开始,发送语音告知
break;
case 90:
VoicePlay(0x0A,0,0); //计时开始,发送语音告知
break;
case 120:
VoicePlay(0x0B,0,0); //计时开始,发送语音告知
break;
case 300:
VoicePlay(0x07,0,0); //蒸后关火焖计时开始,发送语音告知
break;
default:
VoicePlay(0x08,0,0); //A面完成语音告知
break;
}
led2Default();
lightUpInterval=(int) (input2Time / NUM_LEDS);
timerTicker.attach(1, tickerTimerCount); //设置每隔1秒触发一次tickerTimerCount函数
}
else{
VoicePlay(0x01,0,0);
dhtTicker.attach(1, tickerDhtCount);
clockTicker.attach(1,tickerClockCount);
//delay(50);
//ledOff(); //再刷新一次
}
}
}
if ((input2Time > 0) && (input1Time == 0)) { //B面计时
if (timerCount >= input2Time) { // 当到达计时时间时
timerTicker.detach(); //关闭定时器
ledOff(); //熄灭最后一盏灯
timerCount = 0;
input2Time=0;
input1Time=0;
VoicePlay(0x01,0,0); //B面完成语音告知
dhtTicker.attach(1, tickerDhtCount);
clockTicker.attach(1,tickerClockCount);
}
}
if (timerFlag){ //正在计时中......
//ppLed();
timerLed();
}
if ((input1Time ==0 ) && (input2Time ==0)) {
//每隔2分钟DHT采集一次数据
if (dhtCount >= 120) {
//Serial.println("开始采集DHT信息... \n");
getDHTdata();
dhtCount=0;
}
bool wifiIsConnected = WiFi.isConnected();
if (wifiIsConnected){
//check OTA update progress
if (otaFlag == 1) {
ArduinoOTA.handle();
if (otaInProgress) {
return;
}
}
// put your main code here, to run repeatedly:
//每隔1分钟采集一次网络时间数据
if (clockCount >= 60) {
clockCount=0;
getNtpTime();
}
// HANDLE MQTT
static unsigned long lastMqttConnMillis = 0;
//Serial1.println("HANDLE MQTT....");
if (!mqttClient.connected()) {
Serial1.println(F("当前MQTT未连接"));
if (curMillis - lastMqttConnMillis > 3000) {
Serial1.println(F("Disconnected from MQTT"));
mqttConnect();
lastMqttConnMillis = curMillis;
}
}
else {
mqttClient.loop();
if(needTo_sendDHT) {
//MQTT发送数据
//String dhtData ="温度:"+String(sensor_tem) +"℃"+","+"湿度:"+ String(sensor_hum)+"%" ; //生成要传输的数据
//strcpy(c_DHT,dhtData.c_str());
sendDHTdata();
delay(100);
}
}
}
}
delay(50);
FastLED.show();
// 释放内存
//freeRam();
}
Comments