1. /**
    2. * ESP8266 自动配网 MQTT
    3. */
    4. // https://github.com/tzapu/WiFiManager/
    5. #include <WiFiManager.h>
    6. /**
    7. * MQTT
    8. */
    9. //PubSubClient by Nick O`Leary
    10. #include <PubSubClient.h>
    11. #include <ArduinoJson.h>
    12. /**
    13. * ws2812 led
    14. */
    15. #include <Adafruit_NeoPixel.h>
    16. // mqtt 参数
    17. char* mqtt_server ="192.168.0.200";
    18. char* mqtt_port = "1883";
    19. WiFiClient espClient;
    20. PubSubClient mqtt_client(espClient);
    21. #define RING_LED_PIN 2
    22. #define NUMPIXELS 24
    23. #define BRIGHTNESS 50
    24. Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, RING_LED_PIN, NEO_GRB + NEO_KHZ800);
    25. StaticJsonDocument<256> jsonState; //设备状态
    26. /*============================================== web 配网 下===========================================================*/
    27. /**
    28. * 初始化wifimanager
    29. */
    30. void initWifi()
    31. {
    32. WiFiManager wifiManager; // 创建 wifimanager 对象
    33. // wifiManager.resetSettings(); // 重置保存的修改
    34. wifiManager.setConnectTimeout(10); // 配置连接超时
    35. wifiManager.setDebugOutput(true); // 打印调试内容
    36. wifiManager.setMinimumSignalQuality(30); // 设置最小信号强度
    37. //设置AP
    38. IPAddress _ip = IPAddress(192, 168, 4, 1); // 设置固定AP信息
    39. IPAddress _gw = IPAddress(192, 168, 4, 1); // 设置固定AP信息
    40. IPAddress _sn = IPAddress(255, 255, 255, 0); // 设置固定AP信息
    41. wifiManager.setAPStaticIPConfig(_ip, _gw, _sn); // 设置固定AP信息
    42. // 回调
    43. wifiManager.setAPCallback(configModeCallback); // 设置进入AP模式的回调
    44. wifiManager.setSaveConfigCallback(saveConfigCallback); // 设置点击保存的回调
    45. wifiManager.setBreakAfterConfig(true); // 设置 如果配置错误的ssid或者密码 退出配置模式
    46. // 自定义参数
    47. WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
    48. WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 6);
    49. wifiManager.addParameter(&custom_mqtt_server);
    50. wifiManager.addParameter(&custom_mqtt_port);
    51. // 尝试连接网络,失败去到配置页面
    52. if (!wifiManager.autoConnect("ESP8266_AP", ""))
    53. {
    54. Serial.println("failed to connect and hit timeout");
    55. ESP.reset(); // 重置并重试
    56. delay(1000);
    57. }
    58. // WiFi连接成功后将通过串口监视器输出连接成功信息
    59. Serial.println("== WIFI CONNECT SUCCESS ! ==");
    60. Serial.print("IP Address : ");
    61. Serial.println(WiFi.localIP());
    62. // 读取配置页面配置好的信息
    63. strcpy(mqtt_server, custom_mqtt_server.getValue());
    64. strcpy(mqtt_port, custom_mqtt_port.getValue());
    65. }
    66. // 配置进入AP模式通知回调
    67. void configModeCallback(WiFiManager *myWiFiManager)
    68. {
    69. Serial.println("Entered config mode"); //进入配置模式
    70. Serial.print("Wifi Name : ");
    71. Serial.println("Wifi Name : " + myWiFiManager->getConfigPortalSSID());
    72. Serial.print("Wifi IP : ");
    73. Serial.println(WiFi.softAPIP());
    74. // 附加参数
    75. Serial.print("MQTT Server : ");
    76. Serial.println(mqtt_server);
    77. Serial.print("MQTT Port : ");
    78. Serial.println(mqtt_port);
    79. }
    80. // 设置点击保存的回调
    81. void saveConfigCallback()
    82. {
    83. Serial.println("Should save config");
    84. }
    85. /*============================================== MQTT 下===========================================================*/
    86. /* 初始化设备属性状态*/
    87. void initState()
    88. {
    89. jsonState["name"] = "ESP8266";
    90. jsonState["led"] = "OFF";
    91. jsonState["mode"] = "0";
    92. jsonState["update_time"] = random(100);
    93. }
    94. void initMQTT(){
    95. mqtt_client.setServer(mqtt_server, atoi(mqtt_port));
    96. mqtt_client.setCallback(mqtt_callback);
    97. }
    98. void mqtt_reconnect() {
    99. String clientId = "ESP-01A-" + String(random(0xffff), HEX);
    100. if (mqtt_client.connect(clientId.c_str())) { //连接成功
    101. Serial.println("=== MQTT CONNECT SUCCESS ! ===");
    102. String msg;
    103. serializeJson(jsonState,msg);
    104. Serial.println(msg);
    105. mqtt_client.publish("hass/sensor/esp8266_1/led/state",msg.c_str()); // 连接成功发送初始状态信息
    106. mqtt_client.subscribe("hass/sensor/esp8266_1/led/set");
    107. } else {
    108. delay(5000); // Wait 5 seconds before retrying
    109. }
    110. }
    111. /**
    112. * MQTT 接收数据
    113. */
    114. void mqtt_callback(char* topic, byte* payload, unsigned int length) {
    115. Serial.print("接收消息:");
    116. DynamicJsonDocument doc(200);
    117. deserializeJson(doc, payload);
    118. serializeJson(doc,Serial);
    119. Serial.println("");
    120. // 业务处理
    121. String key = doc["key"];
    122. String value = doc["value"];
    123. // 更新状态
    124. jsonState[key] = value;
    125. jsonState["update_time"] = random(100);
    126. String msg;
    127. serializeJson(jsonState,msg);
    128. Serial.print("更新状态:");
    129. Serial.println(msg);
    130. mqtt_client.publish("hass/sensor/esp8266_1/led/state",msg.c_str()); // 状态信息
    131. }
    132. /*============================================== 环形灯===========================================================*/
    133. void initRingLED(){
    134. strip.setBrightness(BRIGHTNESS);
    135. // 初始化Adafruit_NeoPixel库
    136. strip.begin();
    137. // 初始化时关闭所有LED
    138. strip.show();
    139. }
    140. /**
    141. * 模式: 颜色擦除
    142. */
    143. void colorWipe(uint32_t c, uint8_t wait) {
    144. strip.clear();
    145. for (uint16_t i = 0; i < strip.numPixels(); i++) {
    146. strip.setPixelColor(i, c);
    147. strip.show();
    148. delay(wait);
    149. }
    150. }
    151. /**
    152. * 彩虹呼吸
    153. */
    154. void rainbow(uint8_t wait) {
    155. uint16_t i, j;
    156. for (j = 0; j < 256; j++) {
    157. for (i = 0; i < strip.numPixels(); i++) {
    158. strip.setPixelColor(i, Wheel((i + j) & 255 ));
    159. }
    160. strip.show();
    161. delay(wait);
    162. }
    163. }
    164. /**
    165. * 彩虹呼吸-旋转
    166. */
    167. void rainbowCycle(uint8_t wait) {
    168. uint16_t i, j;
    169. for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    170. for (i = 0; i < strip.numPixels(); i++) {
    171. strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    172. }
    173. strip.show();
    174. delay(wait);
    175. }
    176. }
    177. /**
    178. * 走马灯
    179. */
    180. void theaterChase(uint32_t c, uint8_t wait) {
    181. for (int j=0; j<10; j++) { //do 10 cycles of chasing
    182. for (int q=0; q < 3; q++) {
    183. for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
    184. strip.setPixelColor(i+q, c); //turn every third pixel on
    185. }
    186. strip.show();
    187. delay(wait);
    188. for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
    189. strip.setPixelColor(i+q, 0); //turn every third pixel off
    190. }
    191. }
    192. }
    193. }
    194. /**
    195. * 走马灯-彩虹
    196. */
    197. void theaterChaseRainbow(uint8_t wait) {
    198. for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
    199. for (int q=0; q < 3; q++) {
    200. for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
    201. strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
    202. }
    203. strip.show();
    204. delay(wait);
    205. for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
    206. strip.setPixelColor(i+q, 0); //turn every third pixel off
    207. }
    208. }
    209. }
    210. }
    211. uint32_t Wheel(byte WheelPos) {
    212. if (WheelPos < 85) {
    213. return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
    214. } else if (WheelPos < 170) {
    215. WheelPos -= 85;
    216. return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
    217. } else {
    218. WheelPos -= 170;
    219. return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
    220. }
    221. }
    222. //----------------------------------------------- 程序入口 ---------------------------------------------------
    223. void setup()
    224. {
    225. Serial.begin(9600); // 初始化串口设置
    226. pinMode(LED_BUILTIN, OUTPUT); // 设置 LED_BUILTIN(GPIO-16) 为输出功能
    227. digitalWrite(LED_BUILTIN, HIGH); // 默认关闭
    228. // 配置状态信息
    229. initState();
    230. // 自动配网
    231. initWifi();
    232. // 配置MQTT
    233. initMQTT();
    234. // 配置环形灯
    235. initRingLED();
    236. }
    237. void loop()
    238. {
    239. // mqtt
    240. if (!mqtt_client.connected()) {
    241. mqtt_reconnect();
    242. }
    243. mqtt_client.loop();
    244. // LED
    245. if (jsonState["led"] == "OFF") { // 通过接收的信息 '1' 来控制开或关
    246. digitalWrite(LED_BUILTIN, HIGH);
    247. } else {
    248. digitalWrite(LED_BUILTIN, LOW);
    249. }
    250. // ring led
    251. if(jsonState["mode"]== "0"){ strip.clear(); }
    252. else if(jsonState["mode"]== "1"){ colorWipe(strip.Color(150, 150, 150), 20); }// BlueWite
    253. else if(jsonState["mode"]== "2"){ rainbow(5);}
    254. else if(jsonState["mode"]== "3"){ rainbowCycle(1);}
    255. else if(jsonState["mode"]== "4"){ theaterChase(strip.Color(127, 127, 127), 50);}
    256. else if(jsonState["mode"]== "5"){ theaterChaseRainbow(5);}
    257. }