B4R Question How do I remove an object from array?

Discussion in 'B4R Questions' started by Kevin, Jun 15, 2018.

  1. Kevin

    Kevin Well-Known Member Licensed User

    I used the ESP Configurator to get me started with communicating with my ESP-12E.

    When I then tried using the B4A client example to communicate with it, it ended up screwing up the WiFi settings on the ESP. I quickly realized why after looking at the code.

    So now I intend to add a "header" so to speak when communicating from a B4J or B4A app. In other words, I intend to first send a description of what the app is doing, such as "CONFIG" when sending WiFi configuration stuff or "DATA" when sending other config type things, such as setting the status of a relay.

    I have worked out a way to take the incoming bytes and break it down into objects, then re-convert the objects back into bytes and send that on to where it saves the network details. This is working, so I think I am on the right path. But if I send a "header" part, I want to be able to remove that before handling it in the proper way.

    Any suggestions or examples on how to do this? I can either remove the first object or create an all-new array of objects but leave out the first (the "header").

    Code:
    Private Sub Astream_NewData (Buffer() As Byte)
        
    Log("New data arrived...")
        
    Log("Data length: ", Buffer.Length)
     
        
    Dim Objects() As Object = serializator.ConvertBytesToArray(Buffer,ObjectsBuffer)
        
    Log("Reading data: ")
        
    For Each o As Object In Objects
            
    Log("Incoming Object: ", o)
        
    Next
     
        
    ' How to remove the first object above and pass on the rest below?

        
    Dim FinalData() As Byte = serializator.ConvertArrayToBytes(Objects)
         
        Main.SaveNetworkDetails(FinalData) 
    ' Originally Main.SaveNetworkDetails(Buffer)
     
    End Sub
     
  2. tigrot

    tigrot Well-Known Member Licensed User

    I use the byteconverter class. Substrimg an substring2 is used to copy part of array/string to another.
     
  3. Kevin

    Kevin Well-Known Member Licensed User

    I think I looked into that but nothing was clicking for me. I'll have another go at it in a bit. Would you happen to have an example?
     
  4. tigrot

    tigrot Well-Known Member Licensed User

    Tomorrow I'll send some code. I'm upgrading my pc disk to SSD so it's not usable.
     
  5. Kevin

    Kevin Well-Known Member Licensed User

    I thought I may have been making some progress (and maybe I did) but I seem to have completely broken the communication between B4R and B4J. I don't get any data arrival events. :(

    At this point, I'll take all the help I can get. I think I am just not understanding the idea of bytes.

    Code:
    Private Sub Astream_NewData (Buffer() As Byte)  '<---- No longer seems to fire when sending data from the B4J config utility after attempting to insert a "CONFIG" header/variable before the "Board Name" text.
        Log("New data arrived...")
        
    Log("Data length: ", Buffer.Length)
        
        
    Dim Objects() As Object = serializator.ConvertBytesToArray(Buffer,ObjectsBuffer)
        
    Log("Reading data: ")
        
    For Each o As Object In Objects
            
    Log("Incoming Object: ", o)
        
    Next
        
        
    Dim bc As ByteConverter
        
    Dim FinalObjects() As Object
        
        
    'Need to detect Object #0 then remove it from the array and act accordingly
        Select Case Objects(0)
            
    Case "CONFIG"
                
    'Remove first object and handle Config stuff  ' <---- Am I close on how to remove the first object?
                For i = 1 To Objects.Length-1
                    bc.ObjectSet (Objects(i),FinalObjects(i-
    1))
                
    Next
                
    Dim FinalData() As Byte = serializator.ConvertArrayToBytes(FinalObjects)
                
    'Main.SaveNetworkDetails(FinalData) 'Disable until I know this is working 'Originally Main.SaveNetworkDetails(Buffer)
            Case "DATA"
                
    'Remove first object and handle Data stuff
                For i = 1 To Objects.Length-1
                    bc.ObjectSet (Objects(i),FinalObjects(i-
    1))
                
    Next
                
    Dim FinalData() As Byte = serializator.ConvertArrayToBytes(FinalObjects)
                
    ' Handle DATA request
            Case Else
                
    ' Unknown or no header, so assume it is Config stuff (eventually this shouldn't happen
                ' so we should then ignore it
                
                
    'Main.SaveNetworkDetails(FinalData) ' Originally Main.SaveNetworkDetails(Buffer)           
        End Select   
        
        
    'Temporary logging - eventually shouldn't get to this part of the sub
        For Each o As Object In FinalObjects
            
    Log("Final Object: ", o)
        
    Next
        
    Log ("Byte Array = [", FinalData, "]")
        
    End Sub
    On the plus side, I managed to add a functioning clock to my project. :D
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    Why aren't you adding the header field as the first element in the array sent from B4A?
     
  7. Kevin

    Kevin Well-Known Member Licensed User

    Wouldn't Objects(0) be the first element in the array? It's possible that my Select Case code is not properly removing the header, but that may be part of my issue.

    For now I am using B4J as the client as it is easier and quicker to test, but eventually will use B4A.

    I'm working on it again now with fresh eyes. Some things are just a bit foreign to me, particularly bytes as well as the sheets & metadata in B4J.
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    It doesn't matter.
    I previously didn't understand how you are adding the header.

    The simplest way that you can implement it with a generic solution where you don't know the number of items is to serialize the data that should be saved before you send it.
    Now you have an array of bytes.
    Create an array with the header and this array of bytes, serialize it and send it.

    In B4R you only need to read the header and take the second item which is the array of bytes that should be saved and save it as-is.
     
  9. Kevin

    Kevin Well-Known Member Licensed User

    Out of curiosity, will my Select Case code actually work regarding reading the value of the first object, as it is? Or do I need to do any conversions to a string first?

    Code:
    Select Case Objects(0)
            
    Case "CONFIG"  ' <------ WIll this work or does it need converting to a string first?
     
  10. Erel

    Erel Administrator Staff Member Licensed User

    You need to convert it to a string first.
     
  11. Kevin

    Kevin Well-Known Member Licensed User

    I got it sorted out. I saw another thread (but since lost it) where you (Erel) suggested sending the data in separate chunks. Following that idea, I was able to get it working. Thanks for all the help in this thread and all of the valuable information in the many other threads here in this forum. :)

    Below are the relevant parts in case it might help others:

    B4R (WiFiServer module)
    Code:
    Sub Process_Globals
        
    Private Astream As AsyncStreams   
        
    Private server As WiFiServerSocket
        
    Private serializator As B4RSerializator
        
    Private ObjectsBuffer(10As Object
        
    Private HeaderReceived As Int  '<---- New, to keep track of the last header received as an integer
    End Sub

    Private Sub Astream_NewData (Buffer() As Byte)
        
    Log("New data arrived...")
        
    Log("Data length: ", Buffer.Length)
        
        
    Dim Objects() As Object = serializator.ConvertBytesToArray(Buffer,ObjectsBuffer)
        
    Log("Reading data: ")
        
    For Each o As Object In Objects
            
    Log("Incoming Object: ", o)
        
    Next
            
        
    Select Case Objects(0)
            
    Case "CONFIG"
                HeaderReceived = 
    1 'CONFIG
                Return
            
    Case "DATA"
                HeaderReceived = 
    2 'DATA
                Return
            
    Case Else ' Not a header, so process the data based on the last header received
                Select Case HeaderReceived
                    
    Case 0 'No header received or detected (shouldn't happen)
                        If Main.Logging Then Log ("Data was received before a header!")
                    
    Case 1 'CONFIG
                        Delay (500)
                        Main.SaveNetworkDetails(Buffer)
                        
    If Main.Logging Then Log ("CONFIG SETTINGS SAVED")
                    
    Case 2 'DATA
                        If Main.Logging Then Log ("DATA handling not finished yet!")
                        
    ' Do something here
                    Case Else
                        
    If Main.Logging Then Log("Unknown data received!")
                
    End Select
                HeaderReceived = 
    0 'Reset Header to nothing, wait for next header
        End Select
    End Sub
    B4J Configurator Example (Main module)
    Code:
    Sub Connect (Get As Boolean)
        SetBusy(
    True)
        
    Try
            Disconnect
            
    Dim sock As Socket
            sock.Initialize(
    "sock")
            sock.Connect(txtIP.Text, 
    5104110000)
            
    Wait For sock_Connected (Successful As Boolean)
            
    If Successful Then
                astream.InitializePrefix(sock.InputStream, 
    False, sock.OutputStream, "astream")
                
    If Get Then
                    
    Wait For astream_NewData (Buffer() As Byte)
                    
    If Buffer(0) = 0 Then
                        rec.BoardName = 
    "PoolMinder"
                    
    Else
                        
    ' We recieved a 1 as the first byte sent, which means it has been configured
                        Log ("Board appears to have been configured")
                        
    Wait For (astream) AStream_NewData(Data() As Byte)
                        
    Dim ObjectsReceived() As Object = (ser.ConvertBytesToArray(Data))
                        
    Log (ObjectsReceived(0))
                        
    If ObjectsReceived(0) = "CONFIG" Then
                            
    Log ("Config Header received")
                            
    Wait for astream_NewData (Buffer() As Byte)
                            rec = ObjectsToRecord(ser.ConvertBytesToArray(Buffer))
                        
    End If
                    
    End If
                    sheet.Set(rec, meta)
                
    Else 'Put mode, so send the header followed by field values to the B4R project
                    Dim HeaderObj As Object = Array ("CONFIG")
                    astream.Write(ser.ConvertArrayToBytes(HeaderObj))
                    Sleep(
    1500)
                    astream.Write(ser.ConvertArrayToBytes(RecordToObjects(rec)))
                    Sleep(
    1500)
                
    End If
            
    Else
                cutils.ShowNotification2(
    "Failed to connect""", cutils.ICON_ERROR, MainForm)
            
    End If
            Disconnect
        
    Catch
            
    Log(LastException)
        
    End Try
        SetBusy(
    False)
    End Sub
     
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