2022/12/04

App Inventor #11自己來寫 App - 骰子遊戲 (Dice Game)

大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是 App Inventor 第10集 -  自己來寫 App - 骰子遊戲

這個影片適合稍進階同學來觀看&學習, 想要越級挑戰的朋也也歡迎拿來這個單元來學習 App Inventor 2! 

這是一個學習任意組件的好範例, Android, iPad 都可以使用!




本次教學你可以學到:

 * 本集會使用到:

 * 感測器 (Sensor)

 * 變數應用 (Variables)

 * 清單的應用 (List)

 * 圖片的應用 (Image)

 * 為APP加上音音效 (Audio)

 * 亂數的應用 (Randomized)

 * 用任意組件 (Any component)

 * 程序的應用 (Procedure)


參考資料: 

App inventor 語法 & 使用方式: http://ai2.appinventor.mit.edu/reference/blocks/ 

音效來源: https://pixabay.com/ 

圖片製作:  https://figma.com 


如果你時間不夠, 也可以從以下的時間軸挑選想看的部份即可! 


影片時間軸: 

00:00 開始

00:24 骰子 App 示範

01:20 App 畫面的配置 / 素材上傳

04:39 App 程式設計

05:18 如何使用變數/變數種子

06:31 設定音效

11:54 如何使用任意元件

15:22 使用任意組件來移除重複的運算

16:26 把骰子元件放入清單中

23:11 使用任意組件 vs 未使用任意組件


App Inventor 相關教學影片:


* App Inventor #11自己來寫 App - 骰子遊戲 (Dice Game)

https://youtu.be/2d6Si6u8FVE


* App Inventor #10 集 自己來寫 APP YouBike 2.0 (下). 

https://youtu.be/Cli-_lUPjgU


* App Inventor #9 集 - 自己來寫 APP YouBike 2.0 (上) 

https://youtu.be/D78-eDRFiXM


*App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧 (How to keep AI2 always connected for Android) https://youtu.be/_HeM9GyVmIE


* App Inventor #7 ESP32 語音辨識控制 IOT 專案, 使用 IoT Essential Library Example (CC available)  https://youtu.be/senjdb-cREY


* App Inventor #6 使用’ 繪圖動畫' 製作使用者介面 (App Inventor 2 UI design with Draw and Animation) https://youtu.be/RfYi8h9y6kE


* App Inventor #5 - “無線搖控 ESP32-CAM APP 下集 (Write ESP32-CAM remote APP 2/2) https://youtu.be/J8b3zWX1FXM


* App Inventor #4 無線搖控 ESP32-CAM APP 上集 (Write ESP32-CAM remote APP 1/2)

https://youtu.be/x545mFSZWgg


* App Inventor #3 “自己來寫APP 快篩何處買?” (How to process .csv files in App Inventor)

https://youtu.be/u5J4FJQ5UQQ


* App Inventor #2 “自己來寫mqtt APP Android & iOS都能用” (Create MQTT Apps with App Inventor 2)

https://youtu.be/kIONEfLO4sI


* MIT App Inventor 2 #1 - 語音辨識 (Voice Recognition)

https://youtu.be/msV4V6af6tA 

2022/11/06

Arduino #38 YouBike 2.0 餘車通知器 (Arduino #38 ESP32 1306 YouBik 2.0 remain notifier)

大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是Arduino 第38集 -  UBike 2.0 餘車通知器.



大多數坐捷運上下班的朋友, 一定有這樣的經驗:下班時,匆匆忙忙趕到捷運站,卻發現捷運站的Ubike已經都沒有了, 只好在那邊癡癡的等候.

如果下班之前, 看一下YouBike 2.0, 餘車通知器, 確定站點還有較多的Ubike, 這時候再過去牽車, 是不是很安心呢? 我們來看看怎麼做吧!


如果你時間不夠, 也可以從以下的時間軸挑選想看的部份即可! 

影片時間軸:

00:00 開始

00:43 UBike 2.0 餘車通知器使用方法

03:22 Google Sheet 設定

14:44 Google Sheet 發佈API設定

17:19 Google Script doPost(e) 程式解釋

20:27 Google Script doGet(e) 程式解釋

21:46 ESP32 程式解釋

26:51 ESP32 refreshYouBike2data (更新SHEET資料)

28:52 ESP32 goGetData 由Sheet取得資料

30:03 showUTF8String 顯示餘車資料


App Inventor 相關教學影片:

* App Inventor #11自己來寫 App - 骰子遊戲 (Dice Game)
https://youtu.be/2d6Si6u8FVE

* App Inventor #10 集 自己來寫 APP YouBike 2.0 (下).
https://youtu.be/Cli-_lUPjgU

* App Inventor #9 集 - 自己來寫 APP YouBike 2.0 (上)
https://youtu.be/D78-eDRFiXM

*App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧 (How to keep AI2 always connected for Android) https://youtu.be/_HeM9GyVmIE

* App Inventor #7 ESP32 語音辨識控制 IOT 專案, 使用 IoT Essential Library Example (CC available)  https://youtu.be/senjdb-cREY

* App Inventor #6 使用’ 繪圖動畫' 製作使用者介面 (App Inventor 2 UI design with Draw and Animation) https://youtu.be/RfYi8h9y6kE

* App Inventor #5 - “無線搖控 ESP32-CAM APP 下集 (Write ESP32-CAM remote APP 2/2) https://youtu.be/J8b3zWX1FXM

* App Inventor #4 無線搖控 ESP32-CAM APP 上集 (Write ESP32-CAM remote APP 1/2)

https://youtu.be/x545mFSZWgg

* App Inventor #3 “自己來寫APP 快篩何處買?” (How to process .csv files in App Inventor)

https://youtu.be/u5J4FJQ5UQQ

* App Inventor #2 “自己來寫mqtt APP Android & iOS都能用” (Create MQTT Apps with App Inventor 2)   https://youtu.be/kIONEfLO4sI

* MIT App Inventor 2 #1 - 語音辨識 (Voice Recognition)
https://youtu.be/msV4V6af6tA 

2022/10/23

App Inventor 第10集 - 自己來寫 YouBike 2.0 APP (下集)

 大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是 App Inventor 第10集 -  自己來寫 YouBike 2.0 APP (下集), 這個影片適合初學者來觀看學習, 想拿來這個單元來學習 App Inventor 2 也是很 Ok 的!  

上集影片請點此: https://youtu.be/D78-eDRFiXM 




對了,如果你沒有看過上一集, 請記得到右上角這邊, 按一下先觀看上集再來看下集.  那相信看過上一集的朋友都在等待這一集呢!   這個是一個專門為初學者來開發的一個系列, 所以會講的比較詳細, 相信各位只要仔細收看內容並進行實作, 一定會收獲滿滿滿。好, 那我們就開始吧今天的練習吧~


本集目標:

* 資料由政府資料開放平臺即時更新

* 美化使用者介面 (加入 Splash)

* 加入 App 開機畫面

* 移動 maker 更加順暢

* 打開 App 自動讀入 Json

* 取得手機所在位置定位

* 顯示附近 YouBike 車輛數目 (比對 YouBike 2.0 App 數量)


使用位置感測器, 注意權限:

* 位置權限要授權給 MIT App Companion 

* 若是下載為 APK, 位置權限要授權給 APK

* GPS 精準要打開


如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可! 

影片時間軸:

00:00 Start

00:37 本集可以學到什麼?

02:14 YouBike 2.0 App 示範

03:28 美化 YouBike 2.0 App

04:30 App 起始畫面 (Splash) 

14:25 直讀政府公開YouBike資料

22:34 設定位置感測器(GPS)

35:17 顯示所有站點及每一站點車輛數

47:54 在我位置做標記


上集影片請點此: https://youtu.be/D78-eDRFiXM 

App Inventor 相關教學影片: * MIT App Inventor 2 #1 - 語音辨識 (Voice Recognition) https://youtu.be/msV4V6af6tA * App Inventor #2 “自己來寫mqtt APP Android & iOS都能用” (Create MQTT Apps with App Inventor 2) https://youtu.be/kIONEfLO4sI * App Inventor #3 “自己來寫APP 快篩何處買?” (How to process .csv files in App Inventor) https://youtu.be/u5J4FJQ5UQQ * App Inventor #4 無線搖控 ESP32-CAM APP 上集 (Write ESP32-CAM remote APP 1/2) https://youtu.be/x545mFSZWgg * App Inventor #5 - “無線搖控 ESP32-CAM APP 下集 (Write ESP32-CAM remote APP 2/2) https://youtu.be/J8b3zWX1FXM * App Inventor #6 使用’ 繪圖動畫' 製作使用者介面 (App Inventor 2 UI design with Draw and Animation) https://youtu.be/RfYi8h9y6kE * App Inventor #7 ESP32 語音辨識控制 IOT 專案, 使用 IoT Essential Library Example (CC available) https://youtu.be/senjdb-cREY *App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧 (How to keep AI2 always connected for Android) https://youtu.be/_HeM9GyVmIE


2022/10/16

App Inventor 第9集, 自己來寫 YouBike 2.0 APP (上集)

大家好, 歡迎收看本週的Weekend project with Stonez56。
本周要進行的是 App Inventor 第9集 - 自己來寫 YouBike 2.0 APP (上集) 
這個影片適合初學者來觀看學習, 想拿來這個單元來學習 App Inventor 2 也是很 Ok 的!



上集內容主要包括程式流程:
  1. 讀入 YouBike 2.0 JSON 資料並做先期處理
  2. 把所有地區送入, 清單選擇器按鈕
  3. 使用者選擇某一地區後
  4. 在清單顯示器內顯示所有的站點, 位置, 總共單車量, 剩餘單車量
  5. 移動地圖到所選的地點, 並呈現出 YouBike 圖示

下集內容包括: (製作中, 敬請期待~ 10/22 TBD)
  1. 資料由政府資料開放平臺即時更新
  2. 更新程式流程並且美化使用者介面
  3. 取得手機所在位置定位
  4. 顯示附近 YouBike 車輛數目
YouBike 2.0 資料是由政府資料開放平臺的下載而來的, 每幾分鐘便會做更新. 本程式會把 YouBike 2.0 json 資料下載到電腦上, 以節省去一直查詢政府雲端資料庫的時間.

參考資料:

如果你時間不夠, 也可以從以下的時間軸挑選想看的部份即可!


影片時間軸:

00:00 開始
00:21 取得 YouBike 即時資訊
01:04 Json 線上編排後讀取 (Json Parser Online)
02:20 YouBike 2.0 APP 成果展示
03:32 開始APP頁面設計
07:23 簡化資料方便偵錯
17:52 開始程式設計
18:29 讀取上傳檔案的位置以 // 表示
29:50 如何取得站別的資訊 (Json)
55:19 如何移動地圖到 YouBike 站點
1:02:15 如何顯示 YouBike 圖示

App Inventor 相關教學影片:

* MIT App Inventor 2 #1 - 語音辨識 (Voice Recognition) https://youtu.be/msV4V6af6tA * App Inventor #2 “自己來寫mqtt APP Android & iOS都能用” (Create MQTT Apps with App Inventor 2) https://youtu.be/kIONEfLO4sI * App Inventor #3 “自己來寫APP 快篩何處買?” (How to process .csv files in App Inventor) https://youtu.be/u5J4FJQ5UQQ * App Inventor #4 無線搖控 ESP32-CAM APP 上集 (Write ESP32-CAM remote APP 1/2) https://youtu.be/x545mFSZWgg * App Inventor #5 - “無線搖控 ESP32-CAM APP 下集 (Write ESP32-CAM remote APP 2/2) https://youtu.be/J8b3zWX1FXM * App Inventor #6 使用’ 繪圖動畫' 製作使用者介面 (App Inventor 2 UI design with Draw and Animation) https://youtu.be/RfYi8h9y6kE * App Inventor #7 ESP32 語音辨識控制 IOT 專案, 使用 IoT Essential Library Example (CC available) https://youtu.be/senjdb-cREY *App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧 (How to keep AI2 always connected for Android) https://youtu.be/_HeM9GyVmIE

2022/10/01

App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧

大家好, 歡迎收看本週的Weekend project with Stonez56。

本周要進行的是 App Inventor 第8集 -   AI2 Companion 一直斷線怎麼辦?


在使用 App Inventor 時, 我比較喜歡是在手機上安裝 AI2 Companion 來測試 App 以確保App

的畫面設計與預期的相符合, 但是你是不是常常發生ai2 companion常常發生斷線的問題? 


斷線後, 你必須在App inventor裡, 重新產生QR Code, 掃描, 等待ai2 companion再次連線,

真的是很麻煩呢! 本集我們就來在Android手機上做一些設定讓ai2 companion永遠連線, 這樣子以後就很方便喔!


也可以從以下的時間軸挑選想看的部份即可! 


影片時間軸: 

00:00 開始

00:54 為什麼 AI2 會斷線?

01:31 Android 手機設定打開發人員選項

02:12 在版本號碼上點7次

03:04 打開螢幕不休眠選項


2022/09/04

App Inventor #7 ESP32 語音控制-IOT 專案必備程式庫範例 (Voice Control ESP32 with IoT Essential Code Base/Voice command )

 

前言:


大家好, 歡迎收看本週的Weekend project with Stonez56。
本周要進行的是 App Inventor 第7集 -  語音控制ESP32 - IOT 專案必備程式庫範例


本週要來示範如何設計App inventor 2 語音控制 APP, 只要加上我之前介紹的IoT專用必備程式庫, (請參考下方的#27連結), 為了讓初學者更好上手, 本次採用沒有放入MQTT的程式庫, 讓範例更簡單一點. 我們先來看一下實際的操作影片. https://www.youtube.com/watch?v=senjdb-cREY&t=40s


整個範例做完,你就可以以語音來控制遠端的 ESP32 了.  本次範例, 除了可以控制ESP32上的LED開 & 關, 也可以控制伺服馬達的開 & 關, 這集也加上了多語功能的控制, 中文和英文都可以喔. 範例中也設定了法文, 西班牙文, 和日文,有興趣的朋友可以自行加上這些語言的控制程式碼. 


#27 AsyncWifimanager ElegantOTA ESP32 (WiFi 密碼管理+ WiFi 韌體更新)
https://stonez56.blogspot.com/2021/07/asyncwifimanager-elegantota-esp32-wifi.html 


請先到上方的連結, copy 所有的程式嗎, 再複製到 Arduino 編輯程式中存檔.

也要記得把  esp32_servo.h 檔案給儲存下來.

好, 那我們就開始吧今天的練習吧~





Source code:


37_vioceControl_ESP32_ECBv1.ino

#include "esp32_servo.h" //------->
#define myLED 2          //------->

#include <AsyncElegantOTA.h>
const char *FOTA_USERNAME = "un"; 
const char *FOTA_PASSWORD = "pw"; 
/****************************************************************************************************************************
  Async_AutoConnect_ESP32_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !(defined(ESP32))
#error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h> //https://github.com/khoih-prog/ESPAsync_WiFiManager
AsyncWebServer webServer(80);

#define DEVICE_NAME "VoiceCommandESP32"  //------->
DNSServer dnsServer;

void setup()
{
    pinMode(myLED, OUTPUT);  //------->
    servo_setup();           //------->
    // put your setup code here, to run once:
    Serial.begin(115200);
    while (!Serial)
        ;
    delay(200);
    Serial.println("\nStarting Async_AutoConnect_ESP32_minimal on " + String(ARDUINO_BOARD));
    Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);

    ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, DEVICE_NAME);  //------->

    //ESPAsync_wifiManager.resetSettings();   //reset saved settings
    //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 132, 1), IPAddress(192, 168, 132, 1), IPAddress(255, 255, 255, 0));
    ESPAsync_wifiManager.autoConnect();
    if (WiFi.status() == WL_CONNECTED)
    {
        Serial.print(DEVICE_NAME);  //------->
        Serial.print(F(" Connected. Local IP: "));
        Serial.println(WiFi.localIP());
    }
    else
    {
        Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status()));
    }

    webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
        { request->send(200, "text/plain", "Hi! I am ESP32S. access to URL /update to update firmware"); });  //------->

    webServer.onNotFound([](AsyncWebServerRequest *request)   
        { request->send(404, "text/plain", "Page not found!"); });  //------->
    
    // move the motors  //-------> NEW ADDITION Codes
    webServer.on("/go", HTTP_GET, [](AsyncWebServerRequest *request)
        {
            String motor = "";
            String rotation = "";
            // Get input value from URL/go?motor=msg1&rotation=msg2
            if(request->hasParam("motor") && request->hasParam("rotation")){
                if(request->hasParam("motor")){
                    AsyncWebParameter* p = request->getParam("motor");
                    Serial.print(p->name().c_str());
                    Serial.println(p->value().c_str());
                    motor = p->value();
                }
                if(request->hasParam("rotation")){
                    AsyncWebParameter* p = request->getParam("rotation");
                    Serial.print(p->name().c_str());
                    Serial.println(p->value().c_str());
                    rotation = p->value();
                }

                if(rotation == "0"){
                    digitalWrite(myLED, LOW);
                }else if(rotation == "1"){
                    digitalWrite(myLED, HIGH);
                }else{
                    servo_spin(rotation.toInt());
                }
                request->send(200, "text/plain", "Command executed!");
            }else{
                request->send(200, "text/plain", "Error command!");
                Serial.println("Error commands!");
            }
        });
    
    //AsyncElegantOTA.begin(&webServer); // Start ElegantOTA WITHOUT username & password
    AsyncElegantOTA.begin(&webServer, FOTA_USERNAME, FOTA_PASSWORD); // Start ElegantOTA with username & password 

    webServer.begin();
    Serial.println("HTTP server started");
}

void loop() {

}


esp32_servo.h

// ESP32Servo by John K. Bennett,autoConnectKevin Harrington Version 0.11.0
// https://github.com/jkb-git/ESP32Servo/blob/master/src/ESP32_Servo.h
#include <analogWrite.h>
#include <ESP32PWM.h>
#include <ESP32Servo.h>
#include <ESP32Tone.h>

/** Define SERVO pins **/

#define SERVO_PIN2 13   //
Servo SERVO_LR; //left right

const int MAX_ANGLE = 170; //keep servo at minimum range
const int MIN_ANGLE = 10;
int SERVO_LR_POS = 90;

void servo_setup()
{
    SERVO_LR.setPeriodHertz(50); // standard 50 hz servo
    // http://yehnan.blogspot.com/2013/09/arduinotower-pro-sg90.html
    SERVO_LR.attach(SERVO_PIN2, 500, 2400);

    //init position 90 degree for LR & UD
    SERVO_LR.write(SERVO_LR_POS);
}

void servo_spin(int angle){
    // motor protection
    if(angle > MAX_ANGLE) angle = MAX_ANGLE;
    if(angle < MIN_ANGLE) angle = MIN_ANGLE;
    
    SERVO_LR.write(angle);
}



2022/08/14

Android #36 IoT 基本程式庫 Wifimanager FOTA MQTT (IOT Essential Code base with wifimanager, ElegantOTA, & MQTT)

Hi, Welcome to weekend project with Stonez56

This week's Arduino episode #37, "Essential IoT Code Base- Wifimanager FOTA + MQTT"

Here is the source code: https://stonez56.blogspot.com/2022/08/android-36-iot-wifimanager-fota-mqtt.html 


Today, I will show how to combine three commonly used IoT libraries;

WiFimanager, AsyncElegantOTA, and MQTT To become a common IoT code base. So, for our future projects, ESP8266 or ESP32, would have these basic functions.

Let's first look at these three libraries:

  • Wifimanager = Wi-Fi password management, no need to re-burn the code to change the Wi-Fi SSID & password
  • FOTA = Use Wi-Fi to update ESP32 code, you can burn code without connecting to USB
  • MQTT = Streamlined and lightweight communication protocol (Message Queueing Telemetry Transport)


This episode will only introduce how to integrate MQTT into Wifimanager + AsyncElegantFOTA.

To learn how to start Wifimanager + AsyncElegantOTA, Please watch Android #27 Wifimanager + OTA for ESP32/ESP8266 (ESPAsyncWifimanager / ESPAsyncElegantOTA)) https://youtu.be/UlRLTvl4DRc 


==References==

Arduino Library URL:


==Sample code URL==

ESPAsync_WiFiManager minimal: https://github.com/khoih-prog/ESPAsync_WiFiManager/blob/master/examples/Async_AutoConnect_ESP32_minimal/Async_AutoConnect_ESP32_minimal.ino 


ESP32 Async OTA : https://github.com/ayushsharma82/AsyncElegantOTA/blob/master/examples/ESP32_Async_Demo/ESP32_Async_Demo.ino 


If you don't have enough time, you can also select the part you want to watch from the timeline below!

Video Timeline: 00:00 Start 01:39 Demonstration of project results 01:57 mqttgo.io MQTT server, free, fast, & stable 05:52 Install three libraries 07:14 Added two ESP32 PINs as MQTT example 07:41 Encrypt the firmware update (ElegantOTA) page 11:44 Explain how the MQTT callback function works 13:07 Control ESP32 I/O pins with MQTT 15:16 Future program can be written from here

=====中文版本======

大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是 Arduino 第36集,"IoT 基本程式庫 - Wifimanager FOTA + MQTT”

今天來跟大家介紹如何把 一般的 IoT 專案常用到的三個程式庫,  WiFiManager 以及WiFi 韌體更新FOTA (Firmware Over the Air), 再加上 MQTT 三個整合在一起, 變成一個常用的 Code base.  往後你的 ESP32 IoT 專案呢, 就可以俱備這些基本功能了! 


  • Wifimanager = WiFi 密碼管理, 不用重新燒 Code 改 Wifi SSID & 密碼
  • FOTA = 用Wi-Fi更新ESP32程式碼, 不用接USB就可以燒Code
  • MQTT = 精簡輕量化的通訊協定(Message Queueing Telemetry Transport)


本集僅會介紹如何把 MQTT 整合到 Wifimanager + AsyncElegantFOTA

若想了解如何整合 Wifimanager + AsyncElegantOTA, 

請觀看 Arduino #26 AsyncWifimanager ElegantOTA ESP32 (WiFi 密碼管理+ WiFi 韌體更新) https://youtu.be/zepkinJ46Zg  




==參考資料==

Arduino Library URL: 


==Sample code URL==


如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可! 

影片時間軸:

影片時間軸: 00:00 Start 01:39 專案成果示範 01:57 mqttgo.io 快速免費的 MQTT 伺服器 05:52 安裝三支程式庫 07:14 加入兩個 ESP32 PIN做為MQTT範例 07:41 為韌體更新(ElegantOTA)頁面加密 11:44 說明MQTT callback 函數運作方式 13:07 MQTT由此控制ESP32 PIN 15:16 把你的程式可以寫在這裡


IoT基本程式庫原始程式:


/** 
 * Arduino code base for IoT Projects
 * By: Stonez56 aka Kevin Chen 2022-08-16
 * 
 * This source code combined three most common Arduino libraries for IoT Projects, 
 * ESPAsync_Wifimanager, AsyncElegantOTA, & Pubsubclient MQTT Client.
 * 
 * 1. ESPAsync_WiFiManager: https://github.com/khoih-prog/ESPAsync_WiFiManager 
 * 2. AsyncElegantOTA: https://github.com/ayushsharma82/AsyncElegantOTA 
 * 3. Pubsubclient MQTT Client: https://github.com/knolleary/pubsubclient 
 * 
 * YouTube video: https://youtu.be/giFHp9RSMvQ
 * Source code is available my blog: https://stonez56.blogspot.com/2022/08/android-36-iot-wifimanager-fota-mqtt.html 
 **/

/*
 * Define Relay pins as examples to send/receive MQTT messages
 * **/
#define RELAY_PIN_1 12
#define RELAY_PIN_2 14

/** 
 * Perform OTAs for ESP8266 / ESP32 Elegantly with password protection! 
 * https://github.com/ayushsharma82/AsyncElegantOTA
 * **/
#include <AsyncElegantOTA.h>
const char *FOTA_USERNAME = "un";
const char *FOTA_PASSWORD = "pw";

/** 
 * Add MQTT client here` PubSubClient V2.8 by Nick O'Leary
 * https://github.com/knolleary/pubsubclient 
*/
#include <WiFiClient.h>
#include <PubSubClient.h>
#define MSG_BUFFER_SIZE (1024)
char msg[MSG_BUFFER_SIZE];

/** Taiwan No. 1 Free MQTT Server!! **/
const char *mqtt_server = "mqttgo.io";
const int mqtt_port = 1883;

/****************************************************************************************************************************
  Async_AutoConnect_ESP32_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !(defined(ESP32))
#error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h> 
AsyncWebServer webServer(80);

//Start DNS server
DNSServer dnsServer;

//MQTT - Start WiFi client and connect to MQTT server
WiFiClient espClient;
PubSubClient mqtt_client(espClient);

//Define device name
String DEVICE_NAME = "Dual_Relay_Switch";
String home_page_message = "";

void setup()
{
    Serial.begin(115200);
    pinMode(RELAY_PIN_1, OUTPUT);
    pinMode(RELAY_PIN_2, OUTPUT);

    while (!Serial)
        ;
    delay(200);
    Serial.print("\nAsyncWifimanager started on " + String(ARDUINO_BOARD) + "\n");

    //Initialize ESPAsyncWifimanager instance and assign Wi-Fi Client name "AsyncAutoConnect"!
    //This name and IP address can be checked from the router
    ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "Dual_Relay_Switch");

    //####### RESET SAVED WIFI SETTINGS #############
    //ESPAsync_wifiManager.resetSettings();   

    //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 132, 1), IPAddress(192, 168, 132, 1), IPAddress(255, 255, 255, 0));
    //ESPAsync_wifiManager.autoConnect("Stonez_ESP32S", "AP-NAME", "AP-PASSWORD");
    
    ESPAsync_wifiManager.autoConnect("Dual_Switch_ESP32S");
    if (WiFi.status() == WL_CONNECTED)
    {
        Serial.print(DEVICE_NAME);
        Serial.print(" is on Local IP: ");
        Serial.println(WiFi.localIP());
    }
    else
    {
        Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status()));
    }

    //Setup home page access content when visite
    home_page_message = "<!DOCTYPE html><html><head><title>" + DEVICE_NAME 
        + "</title></head><body><p><h2> Hi! This is " + DEVICE_NAME + "</h2>"
        + "To update firmware, <a href='/update'>Click here!!</a><br/><span>Username & Password required!</span></p><body></html>";

    webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
                 { request->send(200, "text/html", home_page_message); });

    //AsyncElegantOTA.begin(&webServer); // Start ElegantOTA WITHOUT username & password
    AsyncElegantOTA.begin(&webServer, FOTA_USERNAME, FOTA_PASSWORD); // Start ElegantOTA with username & password
    webServer.begin();
    Serial.println("AsyncElegantOTA server started @URL/update");

    //MQTT starts here!
    mqtt_client.setServer(mqtt_server, mqtt_port);
    mqtt_client.setCallback(callback);
}

/**
//When MQTT lost connection, this function will be called to reconnect MQTT//
 * Modified to accept multiple MQTT topics 
 * https://www.baldengineer.com/multiple-mqtt-topics-pubsubclient.html
 */
void callback(char *topic, byte *payload, unsigned int length)
{
    //Print message received
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    for (int i = 0; i < length; i++)
    {
        Serial.print((char)payload[i]);
    }
    Serial.println();

    //Process multiple topics here//
    payload[length] = '\0';
    String message = (char*)payload;
    
    if (strcmp(topic, "studio/humd_switch") == 0)
    {
      if(message == "true"){
        digitalWrite(RELAY_PIN_1, HIGH);
        Serial.println("humd_switch true");
      }
      if(message == "false"){
        digitalWrite(RELAY_PIN_1, LOW);
        Serial.println("humd_switch false");
      }
    }
    if (strcmp(topic, "studio/humd_switch2") == 0)
    {
      if(message == "true"){
        digitalWrite(RELAY_PIN_2, HIGH);
        Serial.println("humd_switch2 true");
      }
      if(message == "false"){
        digitalWrite(RELAY_PIN_2, LOW);
        Serial.println("humd_switch2 false");
      }
    }
}

//============= MQTT ===================
//When MQTT lost connection, this function will be called to reconnect MQTT//
void reconnect(){
    //Loop while MQTT connected
    while (!mqtt_client.connected())
    {
        Serial.print("Attempting MQTT connection... ");
        // Create a random client ID
        String clientId = "Stonez_ESP32Client-";
        clientId += String(random(0xffff), HEX);
        // Attempt to connect
        if (mqtt_client.connect(clientId.c_str()))
        {
            Serial.print("connected to ");
            Serial.print(mqtt_server);
            // Once connected, publish an announcement...
            mqtt_client.publish("outTopic", "Hello world");
            // ... and resubscribe
            mqtt_client.subscribe("studio/humd_switch");
            mqtt_client.subscribe("studio/humd_switch2");
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}
void loop() {
    //============= MQTT ===================
    //if can't connect to MQTT server, then re-connect
    if (!mqtt_client.connected())
        { reconnect(); }
    //constantly check MQTT to see for messages sending/receiving
    mqtt_client.loop();

    /**
     * Write your own code here....
     * 
     */
}

Async_AutoConnect_ESP32_minimal.ino

/****************************************************************************************************************************
  Async_AutoConnect_ESP32_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !(defined(ESP32) )
  #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager
AsyncWebServer webServer(80);
DNSServer dnsServer;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200); while (!Serial); delay(200);
  Serial.print("\nStarting Async_AutoConnect_ESP32_minimal on " + String(ARDUINO_BOARD)); Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);
  ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP");
  //ESPAsync_wifiManager.resetSettings();   //reset saved settings
  ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192,168,132,1), IPAddress(192,168,132,1), IPAddress(255,255,255,0));
  ESPAsync_wifiManager.autoConnect("AutoConnectAP");
  if (WiFi.status() == WL_CONNECTED) { Serial.print(F("Connected. Local IP: ")); Serial.println(WiFi.localIP()); }
  else { Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); }
}

void loop() {  }

Async_AutoConnect_ESP8266_minimal.ino

/****************************************************************************************************************************
  Async_AutoConnect_ESP8266_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !( defined(ESP8266) )
  #error This code is intended to run on ESP8266 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager
AsyncWebServer webServer(80);
DNSServer dnsServer;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200); while (!Serial); delay(200);
  Serial.print("\nStarting Async_AutoConnect_ESP8266_minimal on " + String(ARDUINO_BOARD)); Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);
  ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP");
  //ESPAsync_wifiManager.resetSettings();   //reset saved settings
  //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192,168,186,1), IPAddress(192,168,186,1), IPAddress(255,255,255,0));
  ESPAsync_wifiManager.autoConnect("AutoConnectAP");
  if (WiFi.status() == WL_CONNECTED) { Serial.print(F("Connected. Local IP: ")); Serial.println(WiFi.localIP()); }
  else { Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); }
}

void loop() {  }