B4R Question Create array from GlobalStore slots

bdunkleysmith

Active Member
Licensed User
Longtime User
I am trying to set a UDP broadcast address derived from the string returned by wifi.localIP and understand I'll need to use GlobalStore slots as a means of transferring variable data between subs. Below is the code, with the two commented lines being the problematic ones:

B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Private usocket As WiFiUDP
    Private wifi As ESP8266WiFi
    Private port As UInt = 3661
    Private astream As AsyncStreams
    Private bc As ByteConverter
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    astream.Initialize(Serial1.Stream, "astream_NewData", "astream_Error")
    If wifi.Connect2("Telstra1943", "********") = False Then
        Log("Error connecting to network")
        Return
    Else
        Dim index As UInt = 1
        For Each s() As Byte In bc.Split(wifi.localIP, ".")
            Log(s)
            GlobalStore.Put(index, s)
            index = index + 1
        Next
'        GlobalStore.Put(0, Array As Byte(192, 168, 0, 255))
'        GlobalStore.Put(0, Array As Byte(GlobalStore.Slot1, GlobalStore.Slot2, GlobalStore.Slot3, 255))
    End If
    usocket.Initialize(51042, "usocket_PacketArrived")
End Sub

Sub astream_NewData (Buffer() As Byte)
    usocket.BeginPacket(GlobalStore.slot0, port)
    For Each s() As Byte In bc.Split(Buffer, CRLF)
        If s.Length <> 0 Then
            usocket.Write(s)
            usocket.SendPacket
        End If
    Next
End Sub

While I can split out the elements of the IP address:

B4X:
Dim index As UInt = 1
        For Each s() As Byte In bc.Split(wifi.localIP, ".")
            Log(s)
            GlobalStore.Put(index, s)
            index = index + 1
        Next

and while:

B4X:
GlobalStore.Put(0, Array As Byte(192, 168, 0, 255))

passes the broadcast address successfully to:

B4X:
usocket.BeginPacket(GlobalStore.slot0, port)

all variants of:

B4X:
GlobalStore.Put(0, Array As Byte(GlobalStore.Slot1, GlobalStore.Slot2, GlobalStore.Slot3, 255))

which I've tried to create the IP address array dynamically from the collected elements do not work.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
This case is simpler as the ip address is 4 bytes. No need to work with strings.

You need to convert each bytes array to a string and then you can convert the string to number:
B4X:
Sub Process_Globals
   Public Serial1 As Serial
   Private ip(4) As Byte
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   Dim sip As String = "100.244.111.222"
   Dim c As Int = 0
   Dim bc As ByteConverter
   For Each s() As Byte In bc.Split(sip, ".")
       Dim b As Byte = bc.StringFromBytes(s)
       ip(c) = b
       c = c + 1
   Next
   Log(ip(0), ".", ip(1), ".", ip(2), ".", ip(3))
End Sub
 
Upvote 0

bdunkleysmith

Active Member
Licensed User
Longtime User
Thanks Erel :)

I knew I was headed down the wrong path when I found the code was becoming increasingly complex. I have a life principle which says if the solution to a problem is becoming complex then invariably it's not the correct solution. That certainly applied in this case. I'm still coming to grips with the different approach required in B4R compared to B4J/B4A which I'm more familiar with.

With this problem resolved, my Arduino UNO with ESP8266 WiFi shield proof of concept project is functioning well. Currently for test purposes it uses a hard coded password to log onto the strongest AP. So all I need to do now is decide on a user interface to allow selection from the list of SSIDs of the scanned networks and then entry of the AP password. An LCD touch screen sounds good, but I don't think I've enough data pins on the ESP8266.

Just for the record here's the complete code to date, which incorporates Erel's solution to my problem:

B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Private usocket As WiFiUDP
    Private wifi As ESP8266WiFi
    Private Credentials(2) As String    'SSID & password
    Private ip(4) As Byte
    Private port As UInt = 3661
    Private astream As AsyncStreams
    Private bc As ByteConverter
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    ScanNetworks    'Find SSID of strongest WiFi access point
    If wifi.Connect2(Credentials(0), Credentials(1)) = False Then
        Log("Error connecting to network")
        Return
    Else
        Log("Connected to network:", Credentials(0))
        Log("My IP address: ", wifi.LocalIp)
        Dim index As UInt = 0
        For Each s() As Byte In bc.Split(wifi.localIP, ".")
            Dim b As Byte = bc.StringFromBytes(s)
            ip(index) = b
            index = index + 1
        Next
        ip(3) = 255
        Log("Broadcast IP address: ", ip(0), ".", ip(1), ".", ip(2), ".", ip(3))
    End If
    astream.Initialize(Serial1.Stream, "astream_NewData", "astream_Error")
    usocket.Initialize(51042, "usocket_PacketArrived")
End Sub

Sub astream_NewData (Buffer() As Byte)
    usocket.BeginPacket(ip, port)
    For Each s() As Byte In bc.Split(Buffer, CRLF)
        If s.Length <> 0 Then
            usocket.Write(s)
            usocket.SendPacket
        End If
    Next
End Sub

Sub usocket_PacketArrived (Data() As Byte, ip1() As Byte, port1 As UInt)
    'not used
    Log("Packet arrived")
End Sub

Sub astream_Error
    Log("Error")
End Sub

Private Sub ScanNetworks
    Dim numberOfNetworks As Byte = wifi.Scan
    Log("Found ", numberOfNetworks, " networks")
    Dim RSSI As Int = -255
    Dim strongest As Byte = 0
    For i = 0 To numberOfNetworks - 1
        Log("SSID: ", wifi.ScannedSSID(i), "|RSSI: ", wifi.ScannedRSSI(i))   
        If wifi.ScannedRSSI(i) > RSSI Then
            RSSI = wifi.ScannedRSSI(i)
            strongest = i
        End If
    Next
    Log("Strongest SSID: ", wifi.ScannedSSID(strongest), "|RSSI: ", wifi.ScannedRSSI(strongest))
    Credentials(0) = wifi.ScannedSSID(strongest)
    Credentials(1) = "********"
End Sub
 
Upvote 0
Top