B4R Tutorial ESP8266 - WiFi Remote Configuration

Discussion in 'B4R Tutorials' started by Erel, Jul 3, 2016.

  1. Erel

    Erel Administrator Staff Member Licensed User

    Edit: A simpler and more powerful tool is available: https://www.b4x.com/android/forum/threads/esp-configurator-based-on-b4rserializator.81452/

    The attached project allows the user to configure the ESP8266 WiFi settings (SSID and password).

    When the program starts it does several things:
    1. Creates an access point named 'esp'.
    2. Creates a WiFiServerSocket that listens on port 80.
    3. Tries to connect to a network based on the last settings stored in the EEPROM (if such are available).

    The ip address of the device in the esp network is known. It is 192.168.4.1.
    This means that we can connect to the esp network and then access the board with this ip address from any browser.

    The server accepts two requests:
    http://192.168.4.1 - Shows the current status
    http://192.168.4.1/set/<ssid>/<password> - Sets the new ssid and password. Note that the password is optional.

    Examples:

    http://192.168.4.1/set/dlink
    http://192.168.4.1/set/iPhone (2)/12345678

    The SSID and password are stored in the EEPROM so the values are kept after a restart.

    Note that the #StackBufferSize attribute is set to 600 as the string related methods require a larger stack buffer.
     

    Attached Files:

    Last edited: Jul 9, 2017
  2. Cableguy

    Cableguy Expert Licensed User

    How do we know this? Is it hardcoded to the board when in AP mode?
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    This is the default ip address of the ESP8266 board in access point mode.
     
    Cableguy likes this.
  4. barx

    barx Well-Known Member Licensed User

    This is a good example and starting point for IoT projects. I didn't know whether the wemos had some built in EEPROM or not, I guess it does as it all seems to work. Thanks Erel for helping.
     
  5. Erel

    Erel Administrator Staff Member Licensed User

    It actually uses the flash for this.

    BTW, the more I work with the ESP8266 the more I like it. This is indeed a great board.
     
    max123, barx and Cableguy like this.
  6. Cableguy

    Cableguy Expert Licensed User

    The only tjing missing now is thé wps calls!
     
  7. barx

    barx Well-Known Member Licensed User

    I too feel the same, even though you are 1000 steps in fron tof me ;). At least it shows me there is still more good stuff to learn.

    I downloaded a book called Kolban's book on ESP8266. Only just started it really, but it's quite interesting and hopefully it will help unlock some of the mysterious boards secrets.
     
    pesquera likes this.
  8. Cableguy

    Cableguy Expert Licensed User

    A fail-safe should be introduced to the "set" procedure, as a blank set of credentials will make the board try to connect to a false network...
    Also, a limit number of tries should be introduced so that the board should revert to server mode if all times expired...

    I will try to add these myself, during the day...
     
  9. Cableguy

    Cableguy Expert Licensed User

    Here is my small optimisation of the WiFi Remote Config code module

    Code:
    'Jully 2016
    'Original Code by EREL
    'Small Optimisations by Cableguy

    'Call WiFiServer.Start(False) from your code
    'It will force the esp to first check the Board for saved SSID and Password
    'After 5 attemps, it will revert the board to AP mode
    '
    'SSID Checked for empty value
    Sub Process_Globals
        
    Private bc As ByteConverter
        
    Private Astream As AsyncStreams   
        
    Private server As WiFiServerSocket
        
    Private eeprom As EEPROM
        
    Private const MAGIC_EEPROM As Byte = 123
        
    Private APSSID As String = "esp"
        
    Private bc As ByteConverter
        
    Public WiFi As ESP8266WiFi
        
    Public esp As ESP8266
        
    Private NumberOfTries As Int
        
    Private MaxNumberOfTries As Int = 5
    End Sub

    Public Sub Start(AP As Boolean)
        
    If AP = False Then
            NumberOfTries = 
    0
            ConnectToNetwork
        
    Else
            
    Select WiFi.StartAccessPoint(APSSID)
                
    Case 1
                    
    Log("Access Point Initialisation Successful")
                    
    Log("SSID: ",APSSID)
                    
    Log("ip: ", WiFi.AccessPointIp)
                    
    server.Initialize(80"server_NewConnection")
                
    server.Listen
                
    Case 0
                    
    Log("Something Went wrong!")
                    WiFi.Disconnect
            
    End Select
        
    End If
    End Sub

    Private Sub Server_NewConnection (NewSocket As WiFiSocket)
        Astream.Initialize(NewSocket.Stream, 
    "astream_NewData""astream_Error")
    End Sub

    Private Sub Astream_NewData (Buffer() As Byte)
        
    Log(Buffer)
        
    If bc.IndexOf(Buffer, "GET") <> -1 Then
            
    If bc.IndexOf(Buffer, "/set") <> -1 Then
               
                
    Dim ssid = "", password  = "" As String
                
    Dim i1 As Int = 0
                
    Dim i2 As Int = 0
                
    For Each b1() As Byte In bc.Split(Buffer, " ")
                    
    If i1 = 1 Then
                        
    For Each b2() As Byte In bc.Split(b1, "/")
                            
    Select i2
                                
    Case 2
                                    ssid = bc.StringFromBytes(b2)
                                
    Case 3
                                    password = bc.StringFromBytes(b2)
                            
    End Select
                            i2 = i2 + 
    1
                        
    Next
                       
                    
    End If
                    i1 = i1 + 
    1
                
    Next
                
    Log("stact buffer :",StackBufferUsage)
                Astream.Write(
    "HTTP/1.1 200").Write(CRLF)
                Astream.Write(
    "Content-Type: text/html").Write(CRLF).Write(CRLF)
                Astream.Write(
    "<script>setTimeout(function(){location.href=""http://192.168.4.1""} , 20000);</script>")
                
    If ssid.Length = 0 Then
                    Astream.Write(
    "SSID is invalid, please try again")
                
    Else
                    Astream.Write(
    "WiFi set to: ").Write(ssid).Write(", password: ").Write(password).Write("<br/>Please wait...")
                    SaveNetworkDetails(ssid, password)
                    CallSubPlus(
    "ConnectWifi"5000)
                
    End If
            
    Else If bc.IndexOf(Buffer, " / ") <> -1 Then
                Astream.Write(
    "HTTP/1.1 200").Write(CRLF).Write(CRLF)
                
    If WiFi.IsConnected Then
                    Astream.Write(
    "Connected to network.").Write(CRLF)
                    Astream.Write(
    "ESP8266 IP address: ").Write(WiFi.LocalIp)
                
    Else
                    Astream.Write(
    "Not connected!")
                
    End If
            
    Else
                Astream.Write(
    "HTTP/1.1 404").Write(CRLF)
            
    End If
            CallSubPlus(
    "CloseConnection"2000)
        
    End If
    End Sub

    Private Sub ConnectWifi(u As Byte)
        Start(
    False)
    End Sub

    Private Sub CloseConnection(u As Byte)
        
    Log("close connection")
        
    If server.Socket.Connected Then
            
    server.Socket.Stream.Flush
            
    server.Socket.Close
        
    End If
    End Sub

    Private Sub AStream_Error
        
    Log("Disconnected")
        
    server.Listen
    End Sub

    Public Sub ReplaceString(Original() As Byte, SearchFor() As Byte, ReplaceWith() As Byte) As Byte()
        
    'count number of occurrences
        Dim bc2 As ByteConverter
        
    Dim c As Int = 0
        
    Dim i As Int
        
    If SearchFor.Length <> ReplaceWith.Length Then
            i = bc2.IndexOf(Original, SearchFor)
            
    Do While i > -1
                c = c + 
    1
                i = bc2.IndexOf2(Original, SearchFor, i + SearchFor.Length)
            
    Loop
        
    End If
        
    Dim result(Original.Length + c * (ReplaceWith.Length - SearchFor.Length)) As Byte
        
    Dim prevIndex As Int = 0
        
    Dim targetIndex As Int = 0
        i = bc2.IndexOf(Original, SearchFor)
        
    Do While i > -1
            bc2.ArrayCopy2(Original, prevIndex, result, targetIndex, i - prevIndex)
            targetIndex = targetIndex + i - prevIndex
            bc2.ArrayCopy2(ReplaceWith, 
    0, result, targetIndex, ReplaceWith.Length)
            targetIndex = targetIndex + ReplaceWith.Length
            prevIndex = i + SearchFor.Length
            i = bc2.IndexOf2(Original, SearchFor, prevIndex)
        
    Loop
        
    If prevIndex < Original.Length Then
            bc2.ArrayCopy2(Original, prevIndex, result, targetIndex, Original.Length - prevIndex)
        
    End If
        
    Return result
    End Sub

    Public Sub SaveNetworkDetails(SSID As String, Password As String)
        
    Log("Saving network data: ", SSID, ", ", Password)
        SSID = bc.StringFromBytes(ReplaceString(SSID, 
    "%20"" "))
        eeprom.WriteBytes(
    Array As Byte(MAGIC_EEPROM, SSID.Length + 1 + Password.Length), 0)
        
    Dim pos As Int = 2
        eeprom.WriteBytes(SSID, pos)
        pos = pos + SSID.Length
        eeprom.WriteBytes(
    Array As Byte(0), pos)
        pos = pos + 
    1
        eeprom.WriteBytes(Password, pos)
    End Sub

    Public Sub ConnectToNetwork
        
    Log("disconecting WiFi...")   
        WiFi.Disconnect
        
    'read settings from EEPROM
        Dim header() As Byte = eeprom.ReadBytes(02)
        
    Do Until NumberOfTries = MaxNumberOfTries
            
    Log("try number : ", NumberOfTries)
            
    If header(0) = MAGIC_EEPROM Then
                
    Dim data() As Byte = eeprom.ReadBytes(2, header(1))
                
    Log ("DATA LENGTH =",data.Length)
                
    Dim i As Int = bc.IndexOf(data, Array As Byte(0))
                
    If i = -1 Then
                    
    Log("Error parsing network data.")
                    
    Return
                
    End If
                
    Dim SSID As String = bc.StringFromBytes(bc.SubString2(data, 0, i))
                
    If SSID.Length = 0 Then Start(True)
                
    Dim Password As String = bc.StringFromBytes(bc.SubString(data, i + 1))
                
    If Password.Length = 0 Then Password = "none"
                
    Log("Trying to connect to: ", SSID, " password: ", Password)
               
                
    If WiFi.Connect2(SSID, Password) Then
                    
    Log("Connected successfully to: ", SSID)
                    
    Log(WiFi.LocalIp)
                    
    Else
                    
    Log("Failed to connect.")
                
    End If
            
    Else
                
    Log("Network data not found.")
            
    End If
            NumberOfTries = NumberOfTries + 
    1
        
    Loop
        
    If NumberOfTries = MaxNumberOfTries Then
            Start(
    True)
        
    End If
    End Sub

    What do my small changes do?

    Well, if you are as weird as me, when testing things out, you could be inclined to enter a blank SSID... the code now checks for that, since a SSID should never be empty!
    Wen you call WiFiServer.start(False), it will try to connect to the saved SSID for 5 times, and if unsuccessful, start in AP mode by calling WiFiServer.Start(true).
    AP mode is also started if no save data is found.

    Please test this last part as I had already something saved in the eeprom, and had no time to test the rest.
     
    pesquera, derez and Erel like this.
  10. techknight

    techknight Well-Known Member Licensed User

    I would add a reset button to the ESP to get it to go back into AP mode if the associated router/AP isnt available. I can see this exploited in a multitude of ways.
     
  11. derez

    derez Expert Licensed User

    The "Private Sub AppStart" is missing from your code...
     
  12. Cableguy

    Cableguy Expert Licensed User

    It's a Code Module!
     
  13. Gaver Powers

    Gaver Powers Member Licensed User

    New to the ESP8266 board... quick question for the experts here...
    In AP mode - can a browser connect directly to the board by entering the url http://192.168.4.1 ?

    G
     
  14. Cableguy

    Cableguy Expert Licensed User

    Yes, but, like in the example, you need to create your own html reply
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    Don't forget to first connect the computer to the ESP network.
     
  16. Gaver Powers

    Gaver Powers Member Licensed User

    I need to clarify my question...
    Can a browser in an android phone connect directly to the esp8266 while in AP mode without going thru a network router?
    Or must the esp8266 first connect to a network (router) ?

    G
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    I'm sorry but this is not the correct place to ask this question. Please start a new thread in the questions forum.
     
  18. Bangdido

    Bangdido Member Licensed User

    Hello Erel, thank you soo much for the Tutorial, i have a inssue, i'm using a ESP-01 and works fine, except i have the "headers" from the browser splited,
    i'm trying to get a header, for example :

    cookies: somecookie=somevalue;(crlf)
    otherhreader: other value(crlf)


    However sometimes I get something like the following
    cook(crlf)
    ies: somecookies=somevalue;(crlf)
    etc=etc
    etc=etc.
    othe(crlf)
    erheader=value(crlf)


    i'm trying to parse the headers using ByteConverter.split

    Regards
     
  19. Erel

    Erel Administrator Staff Member Licensed User

    Please start a new thread for this question.
     
  20. positrom2

    positrom2 Active Member Licensed User

    Running the code from this tutorial results in the creation of an open network named "esp".
    The B4r log shows this:
    "Network data not found.
    My AP ip: 192.168.4.1
    Network data not found.
    "
    Then I can connect to the "esp" network.
    Trying 192.168.4.1 from a browser the message is "no connection".
    What is going wrong?
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice