/**
* ESP8266 自动配网 MQTT
*/
// https://github.com/tzapu/WiFiManager/
#include <WiFiManager.h>
/**
* MQTT
*/
//PubSubClient by Nick O`Leary
#include <PubSubClient.h>
#include <ArduinoJson.h>
/**
* ws2812 led
*/
#include <Adafruit_NeoPixel.h>
// mqtt 参数
char* mqtt_server ="192.168.0.200";
char* mqtt_port = "1883";
WiFiClient espClient;
PubSubClient mqtt_client(espClient);
#define RING_LED_PIN 2
#define NUMPIXELS 24
#define BRIGHTNESS 50
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, RING_LED_PIN, NEO_GRB + NEO_KHZ800);
StaticJsonDocument<256> jsonState; //设备状态
/*============================================== web 配网 下===========================================================*/
/**
* 初始化wifimanager
*/
void initWifi()
{
WiFiManager wifiManager; // 创建 wifimanager 对象
// wifiManager.resetSettings(); // 重置保存的修改
wifiManager.setConnectTimeout(10); // 配置连接超时
wifiManager.setDebugOutput(true); // 打印调试内容
wifiManager.setMinimumSignalQuality(30); // 设置最小信号强度
//设置AP
IPAddress _ip = IPAddress(192, 168, 4, 1); // 设置固定AP信息
IPAddress _gw = IPAddress(192, 168, 4, 1); // 设置固定AP信息
IPAddress _sn = IPAddress(255, 255, 255, 0); // 设置固定AP信息
wifiManager.setAPStaticIPConfig(_ip, _gw, _sn); // 设置固定AP信息
// 回调
wifiManager.setAPCallback(configModeCallback); // 设置进入AP模式的回调
wifiManager.setSaveConfigCallback(saveConfigCallback); // 设置点击保存的回调
wifiManager.setBreakAfterConfig(true); // 设置 如果配置错误的ssid或者密码 退出配置模式
// 自定义参数
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6);
wifiManager.addParameter(&custom_mqtt_server);
wifiManager.addParameter(&custom_mqtt_port);
// 尝试连接网络,失败去到配置页面
if (!wifiManager.autoConnect("ESP8266_AP", ""))
{
Serial.println("failed to connect and hit timeout");
ESP.reset(); // 重置并重试
delay(1000);
}
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println("== WIFI CONNECT SUCCESS ! ==");
Serial.print("IP Address : ");
Serial.println(WiFi.localIP());
// 读取配置页面配置好的信息
strcpy(mqtt_server, custom_mqtt_server.getValue());
strcpy(mqtt_port, custom_mqtt_port.getValue());
}
// 配置进入AP模式通知回调
void configModeCallback(WiFiManager *myWiFiManager)
{
Serial.println("Entered config mode"); //进入配置模式
Serial.print("Wifi Name : ");
Serial.println("Wifi Name : " + myWiFiManager->getConfigPortalSSID());
Serial.print("Wifi IP : ");
Serial.println(WiFi.softAPIP());
// 附加参数
Serial.print("MQTT Server : ");
Serial.println(mqtt_server);
Serial.print("MQTT Port : ");
Serial.println(mqtt_port);
}
// 设置点击保存的回调
void saveConfigCallback()
{
Serial.println("Should save config");
}
/*============================================== MQTT 下===========================================================*/
/* 初始化设备属性状态*/
void initState()
{
jsonState["name"] = "ESP8266";
jsonState["led"] = "OFF";
jsonState["mode"] = "0";
jsonState["update_time"] = random(100);
}
void initMQTT(){
mqtt_client.setServer(mqtt_server, atoi(mqtt_port));
mqtt_client.setCallback(mqtt_callback);
}
void mqtt_reconnect() {
String clientId = "ESP-01A-" + String(random(0xffff), HEX);
if (mqtt_client.connect(clientId.c_str())) { //连接成功
Serial.println("=== MQTT CONNECT SUCCESS ! ===");
String msg;
serializeJson(jsonState,msg);
Serial.println(msg);
mqtt_client.publish("hass/sensor/esp8266_1/led/state",msg.c_str()); // 连接成功发送初始状态信息
mqtt_client.subscribe("hass/sensor/esp8266_1/led/set");
} else {
delay(5000); // Wait 5 seconds before retrying
}
}
/**
* MQTT 接收数据
*/
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
Serial.print("接收消息:");
DynamicJsonDocument doc(200);
deserializeJson(doc, payload);
serializeJson(doc,Serial);
Serial.println("");
// 业务处理
String key = doc["key"];
String value = doc["value"];
// 更新状态
jsonState[key] = value;
jsonState["update_time"] = random(100);
String msg;
serializeJson(jsonState,msg);
Serial.print("更新状态:");
Serial.println(msg);
mqtt_client.publish("hass/sensor/esp8266_1/led/state",msg.c_str()); // 状态信息
}
/*============================================== 环形灯===========================================================*/
void initRingLED(){
strip.setBrightness(BRIGHTNESS);
// 初始化Adafruit_NeoPixel库
strip.begin();
// 初始化时关闭所有LED
strip.show();
}
/**
* 模式: 颜色擦除
*/
void colorWipe(uint32_t c, uint8_t wait) {
strip.clear();
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
/**
* 彩虹呼吸
*/
void rainbow(uint8_t wait) {
uint16_t i, j;
for (j = 0; j < 256; j++) {
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i + j) & 255 ));
}
strip.show();
delay(wait);
}
}
/**
* 彩虹呼吸-旋转
*/
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
for (i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}
/**
* 走马灯
*/
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
/**
* 走马灯-彩虹
*/
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
delay(wait);
for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}
uint32_t Wheel(byte WheelPos) {
if (WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if (WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
//----------------------------------------------- 程序入口 ---------------------------------------------------
void setup()
{
Serial.begin(9600); // 初始化串口设置
pinMode(LED_BUILTIN, OUTPUT); // 设置 LED_BUILTIN(GPIO-16) 为输出功能
digitalWrite(LED_BUILTIN, HIGH); // 默认关闭
// 配置状态信息
initState();
// 自动配网
initWifi();
// 配置MQTT
initMQTT();
// 配置环形灯
initRingLED();
}
void loop()
{
// mqtt
if (!mqtt_client.connected()) {
mqtt_reconnect();
}
mqtt_client.loop();
// LED
if (jsonState["led"] == "OFF") { // 通过接收的信息 '1' 来控制开或关
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
// ring led
if(jsonState["mode"]== "0"){ strip.clear(); }
else if(jsonState["mode"]== "1"){ colorWipe(strip.Color(150, 150, 150), 20); }// BlueWite
else if(jsonState["mode"]== "2"){ rainbow(5);}
else if(jsonState["mode"]== "3"){ rainbowCycle(1);}
else if(jsonState["mode"]== "4"){ theaterChase(strip.Color(127, 127, 127), 50);}
else if(jsonState["mode"]== "5"){ theaterChaseRainbow(5);}
}