Introduction: ESP32 WIFI Autoconnect and UDP Broadcast

Currently, our ESP32 Hub must be pre-programmed with the WIFI SSID and password, which means it is not very easy to change. To make it easier the ESP32 can be programmed to start up as a WIFI Access Point which the user is able to connect to. This will then bring up a “login page” that allows them to enter the SSID and Password of the network we would like to connect to.

Once the device has the WIFI details entered, they are saved into the memory, and the next time it is powered it will automatically try to connect. If it is unable to connect, then it will switch back to Access Point (AP) mode.

If the device connects to the WIFI network successfully, we should be able to talk to the hub using our app, but we still have the problem of needing the IP address of the hub. We get around this by programming the hub to transmit UDP messages announcing its IP address on the WIFI after connection, which we can read using our app and then connect to.

Step 1: Arduino Code

We will use a library called ESPAsyncWifiManager which can be found here:

https://github.com/tzapu/WiFiManager

Download the library as a zip and add to your Arduino IDE. This is what will handle connecting to a saved network and if there is no available connection, switch the device into AP mode and launch a “captive portal” which will allow the user to enter the network details that we would like the device to connect to.

The other library we will need is AsyncUDP, which should be included with the ESP32 Board package.

This is what we will use to broadcast the HUB IP address on the WIFI network so that we don’t have to know it beforehand in order to connect to the hub from our app. (This is not the most secure method, but for the purpose of keeping the tutorial simple, this is how we will do it).

The remainder of the Arduino code remains largely the same as in Tutorial 3, but now we don’t need to specify a SSID and Password or tell the WIFI to begin. This is now handled by the ESPAsyncWiFiManager library.

We also add to the main loop, a timer to periodically broadcast its IP address.

The updated variable declarations, setup and main loop are given on the following page. The remainder of the program is unchanged.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"

#include "ESPAsyncWiFiManager.h" //https://github.com/tzapu/WiFiManager #include "AsyncUDP.h"

#define HC12 Serial2 //Hardware serial 2 on the ESP32

const char* ssid = "FARMERSCLUB 3"; //Change this to your router SSID. const char* password = "farmersclub"; //Change this to your router password.

AsyncWebServer server(80); //Initialise server on port 80. DNSServer dns;

byte incomingByte; String readBuffer = ""; String readString;

String lastMsgTP = ""; //Store Last Message fron Each Sensor Type

unsigned long previousMillis = 0; // will store last time LED was updated const long interval = 5000; // interval at which to send udp boadcast (milliseconds)

String ipaddress = ""; const char* udpMsg; AsyncUDP udp;

void setup() { //Pull the HC12 SET pin high (LOW for AT Commands). pinMode(5, OUTPUT); digitalWrite(5, HIGH);

//Start serial ports. Serial.begin(115200); HC12.begin(9600);

//Try to connect to WIFI if not, start as AP. AsyncWiFiManager wifiManager(&server,&dns); wifiManager.autoConnect("AutoConnectAP"); Serial.println("Connected to WIFI!");

//Once connected to WIFI, set up and launch webserver. AsyncServerSetup(); server.begin();

//Print IP address to terminal. ipaddress = "HUB|"+ WiFi.localIP().toString(); Serial.println(); Serial.println(ipaddress); Serial.println("Listening...");

//Connect to UDP Port. udp.connect(IPAddress(192,168,1,255), 19700); }

//Main loop to check radio and broadcast UDP message. void loop() { unsigned long currentMillis = millis(); CheckRadio(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; udp.broadcastTo(ipaddress.c_str(), 19700); } }

Upload the program and power up your ESP32 Hub, now on your phone, check for a WIFI network called AutoConnectAP, connect to it, and your phone should automatically bring up the “captive portal” press the configure WIFI button and then enter your WIFI network details. The device should then reboot and connect before running the Arduino program as before.

Step 2: DroidScript Code

Now we need to add the ability to read UDP messages on the port we specified in the Arduino code. Open your app from tutorial 3 in the web editor and in the OnStart() function, add the line as follows after the Tab setup functions are called:

//Called when application is started.
function OnStart() { //Get last hub IP saved from text file. url = "http://" + app.ReadFile( ipfile ); //Create a layout with objects vertically centered. lay = app.CreateLayout( "linear", "VCenter,FillXY" ); app.AddLayout( lay ); //Create tabs. tabs = app.CreateTabs( "Temp,Relay,Settings", 1, 1, "VCenter" ); tabs.SetOnChange( tabs_OnChange ); lay.AddChild( tabs ); RelayTabSetup(); TempTabSetup(); SettingsTabSetup(); //Create UDP network object. net = app.CreateNetClient( "UDP" ); //Check for connection to hub, then again every 10s. //HubStatus(); Update(); setInterval(Update ,30000); }

Next open your Settings.js file, in here we will add a button to bring up a dialogue box and start scanning for UDP messages. Any messages received will be displayed in a log window and a connect button will save the IP address received in the last UDP message.

To add the scan button, update your SettingsTabSetup() function as follows (creating a new button horizontally aligned with the save button):

function SettingsTabSetup()
{

laySET = tabs.GetLayout( "Settings" ); layhoriz = app.CreateLayout( "linear", "horizontal" ); laySET.AddChild( layhoriz ); txtLabel = app.CreateText( "HUB STATUS: " ); txtLabel.SetTextSize( 15 ); txtLabel.SetMargins(0, 0.03); layhoriz.AddChild( txtLabel ); txtStatus = app.CreateText( "" ); txtStatus.SetTextSize( 15 ); txtStatus.SetMargins(0, 0.03); txtStatus.SetTextColor("red"); txtStatus.SetText("Disconnected"); layhoriz.AddChild( txtStatus );

txtLabel = app.CreateText( "HUB IP:" ); txtLabel.SetTextSize( 15 ); txtLabel.SetMargins(0, 0.05); laySET.AddChild( txtLabel ); //Create an text edit box. edtIP = app.CreateTextEdit( app.ReadFile( "/sdcard/hubip.txt" ), 0.9, 0.06 ); edtIP.SetMargins( 0, 0.05, 0, 0 ); laySET.AddChild( edtIP ); laybuthoriz = app.CreateLayout( "linear", "horizontal" ); laySET.AddChild( laybuthoriz ); //Create a button to send IP. btnIPSave = app.CreateButton( "Save", 0.3, 0.1 ); btnIPSave.SetMargins( 0, 0.05, 0, 0 ); btnIPSave.SetOnTouch( btnIPSave_OnTouch ); laybuthoriz.AddChild( btnIPSave ); //Create a button to scan for UDP Messages. btnIPScan = app.CreateButton( "Scan", 0.3, 0.1 ); btnIPScan.SetMargins( 0, 0.05, 0, 0 ); btnIPScan.SetOnTouch( btnIPScan_OnTouch ); laybuthoriz.AddChild( btnIPScan ); }

Next is the function to create the dialogue box and to handle the connect button press:

function btnIPScan_OnTouch()
{ //Create dialog window. dlgTxt = app.CreateDialog( "Scanning for Hub..." ); dlgTxt.SetOnCancel(function(){clearInterval(timer)} ) //Create a layout for dialog. layDlg = app.CreateLayout( "linear", "vertical,fillxy,left" ); layDlg.SetPadding( 0.02, 0.02, 0.02, 0.02 ); dlgTxt.AddLayout( layDlg );

//Create a scroller for log window. scroll = app.CreateScroller( 0.85, 0.2 ); scroll.SetBackColor( "black" ); layDlg.AddChild( scroll ); //Create a read-only edit box to show espruino responses. txtReply = app.CreateText( "", 0.85,-1, "Log,Monospace" ); txtReply.SetBackColor( "black" ); txtReply.SetLog( 100 ); scroll.AddChild( txtReply ); //Create an connect button. btnConnect = app.CreateButton( "Connect", 0.23, 0.1 ); btnConnect.SetOnTouch( btnConnect_OnTouch ); layDlg.AddChild( btnConnect ); //Show dialog. dlgTxt.Show(); //Start timer to check for incoming messages. timer = setInterval( CheckForMsg, 200 ); }

function btnConnect_OnTouch() { clearInterval(timer); edtIP.SetText(txtReply.GetText()); dlgTxt.Hide(); btnIPSave_OnTouch(); }

And finally, we need to add a function to check for the UDP messages:

//Called by our interval timer.
function CheckForMsg() { //Try to read a packet for 1 millisec. var packet = net.ReceiveDatagram( "UTF-8", 19700, 1 ); if( packet ) { //Extract original parts. parts = packet.split("|"); var id = parts[0]; msg = parts[1]; //Show the message if not sent by this device. if( id == "HUB" ) { //app.ShowPopup( msg); txtReply.SetText(msg); } } }

Now you should have everything you need. Launch the app and go to the settings tab, press the scan button and within a few seconds you should see an IP address appear.

The full SPK is available for download:

http://androidscript.org/tutorials/Easy-IOT/Easy-I...