Results 1 to 26 of 26

Thread: tochararray from string and failed...

  1. #1

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    tochararray from string and failed...

    Guys,
    totally new in vb.net... migrated from 6....

    OK, so I am planning to receive the string from my arduino.. arduino sends:
    Code:
    &1;0;0;0;0;0;1;0;0;0;$
    and I can read that in a text box easily. Bascally it is sending the GPIO status of the arduino with wrapper for start and stop .

    Code:
    Function ReceiveGPIOSerialData() As String
            Dim IncomingGPIO As String
            Try
                IncomingGPIO = globalConfig.GPIOSerialPort.ReadExisting()
                If IncomingGPIO Is Nothing Then
                    Return "nothing" & vbCrLf
                Else
                    Return IncomingGPIO
                End If
            Catch ex As TimeoutException
                Return "Error: GPIO Port read timed out."
            End Try
        End Function
    Now,
    Code:
    Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
    
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
    
    
        End Sub
    polls for the serial data and displays it nicely. But as said, i need to get the individual of them, like if start with & then for GPIOdata[1] = 1 and so on... so from this string, I need to split out each int values... any idea how?? I failed to use the substring for no reason...

  2. #2
    PowerPoster
    Join Date
    Sep 2005
    Location
    Modesto, Ca.
    Posts
    5,196

    Re: tochararray from string and failed...

    If you want to split a string
    Code:
            Dim str As String = "a;b;c"
            Dim arr As String() = str.Split(";"c)
            MessageBox.Show(arr.Count.ToString)

  3. #3
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,929

    Re: tochararray from string and failed...

    One way is to use SubString to remove the first and last characters, then split the remaining text on semi-colons, eg:
    Code:
    Dim GPIOdata as String() = receivedGPIOData.SubString(1, receivedGPIOData.Length -2).Split(";"c)

  4. #4

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Quote Originally Posted by wes4dbt View Post
    If you want to split a string
    Code:
            Dim str As String = "a;b;c"
            Dim arr As String() = str.Split(";"c)
            MessageBox.Show(arr.Count.ToString)
    exactly... then i changed it to:
    Code:
    Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
            Dim i As Integer
            Dim GPIOdata() As String
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            Dim dataStrArray As String() = receivedGPIOData.Split(New Char() {";"c})
            'GPIOdata = receivedGPIOData.Split(New Char() {";"c})
            For i = 0 To dataStrArray.Length - 1
                GPIOdata(i) = dataStrArray(i)
            Next
            If StrComp(GPIOdata(0), "&1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
            If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "Door Closed"
            End If
        End Sub
    But now only first one i can read, not the whole... but i need the whole and then I can make my status elaborations... idas??

  5. #5
    PowerPoster
    Join Date
    Sep 2005
    Location
    Modesto, Ca.
    Posts
    5,196

    Re: tochararray from string and failed...

    Not sure what your saying.
    But now only first one i can read, not the whole..
    The "first one" what??
    The "whole" what???

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: tochararray from string and failed...

    You can write that more simply with just .Split(";"c). You don't need that New Char() stuff in there.

    What's the point of the GPIOdata array? All you are doing is copying one array into the other. Why not just use one and skip the copying?

    I also don't know what it is you can't do, but the code is suggestive. For one thing, you don't need to split the string at all based on the code you showed. After all, the array is only local, so nothing outside that event handler can get to any of the data, and all you do inside the event handler is look for what amounts to two items. You could use String.StartsWith("&1") in place of the first check, and a SubString in place of the other, and skip the Split entirely.

    Therefore, it seems like what you really want is something more than just looking at the first two characters, and one other in the string. Perhaps that is what the question is that you are getting at, but I still can't say I understand what result you ultimately want.
    My usual boring signature: Nothing

  7. #7

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Quote Originally Posted by Shaggy Hiker View Post

    Therefore, it seems like what you really want is something more than just looking at the first two characters, and one other in the string. Perhaps that is what the question is that you are getting at, but I still can't say I understand what result you ultimately want.
    NO!!

    Basically
    Code:
    &1;0;0;0;0;0;1;0;0;0;$
    is the output sent from my arduino serial. ecept the first 2 char, &1, rest until $ is the gpio pin status.. if gpio pin reads high it sends 1, if low, it sends 0. i need to read these values. Then i have to put each gpio status into it's own variable as then i can do my manipulation in the app. in arduino, i have read all the values of gpio using a char array, data[10], for pin 1 = data[0] and so on. Now in vb, i need them back as that way, so i can get them individually. comma /semicolon deliminated data is the best method for me to send data here. Thus now i need to get them back as individually. Hence i tried to split... Ideas???

    Mishu~

  8. #8

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    even
    Code:
    Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
            Dim i As Integer
            'Dim GPIOdata() As String
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            Dim GPIOdata As String() = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Split(New Char() {";"c})
            If StrComp(GPIOdata(0), "&1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
            If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "Door Closed"
            End If
        End Sub
    is not helping

    in vb6 i have done this with full success and it was based on ethernet...
    Code:
    Private Sub socket1_DataArrival(ByVal bytesTotal As Long)
        Dim InBuffer As String, rcvdString() As String
        
        localTimestamp = Format(Now, "dd/MM/yy hh:mm:ss AM/PM")
        socket1.GetData InBuffer, vbString
        rcvdString() = Split(InBuffer, ";")
        txtDebug.Text = txtDebug.Text + localTimestamp + ">>" + InBuffer + vbCrLf
        
        txtDebug.SelStart = Len(txtDebug.Text)
        indoorTemp = Int(rcvdString(0))
        finsTemp = Int(rcvdString(1))
        outTemp = Int(rcvdString(2))
        targetTemp = Int(rcvdString(3))
            
        If (StrComp(rcvdString(4), "C0", vbTextCompare) = 0) Then
            compressorOn = False
        ElseIf (StrComp(rcvdString(4), "C1", vbTextCompare) = 0) Then
            compressorOn = True
        End If
        If (StrComp(rcvdString(5), "F0", vbTextCompare) = 0) Then
            indoorFanOn = False
        ElseIf (StrComp(rcvdString(5), "F1", vbTextCompare) = 0) Then
            indoorFanOn = True
        End If
        If (StrComp(rcvdString(6), "D0", vbTextCompare) = 0) Then
            defrostOn = False
        ElseIf (StrComp(rcvdString(6), "D1", vbTextCompare) = 0) Then
            defrostOn = True
        End If
        
        Call showData
        
    End Sub

  9. #9
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: tochararray from string and failed...

    '&1;0;0;0;0;0;1;0;0;0;$
    Dim GPIOdata As String() = receivedGPIOData.Substring(3, receivedGPIOData.Length - 2).Split(";"c)

  10. #10

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Quote Originally Posted by .paul. View Post
    '&1;0;0;0;0;0;1;0;0;0;$
    Dim GPIOdata As String() = receivedGPIOData.Substring(3, receivedGPIOData.Length - 2).Split(";"c)
    and the gentleman is saying:
    System.ArgumentOutOfRangeException: 'Index and length must refer to a location within the string.
    Parameter name: length'

    Here is the full code:
    Code:
    Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
            Dim i As Integer
            'Dim GPIOdata() As String
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            Dim GPIOdata As String() = receivedGPIOData.Substring(3, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Split(";"c)
            'GPIOdata = Split(receivedGPIOData, ";")
            For i = 0 To UBound(GPIOdata)
    
                Console.WriteLine(GPIOdata(i))
    
            Next i
    
            If StrComp(GPIOdata(0), "&1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
    
            If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
    
    
        End Sub

  11. #11
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: tochararray from string and failed...

    I feel like, in this thread, we're making the foolish assumption that your serial port code is reading all the data correctly. But there's definitely some language barrier.

    You say the code in #8 "is not helping". What does that mean? Is the right thing displayed in txtOutput? If not, then the parsing code doesn't matter, you aren't reading the right data.

    If it is right, what is inside the GPIOdata array? Is that what you expect? If not, that's the part of the code we'll focus on.

    I'm assuming the problem is you expect the StrCmp() to find "&1" at the start. But.

    Code:
    receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
    Don't cram everything onto one line. It hides things from you and makes debugging harder. Let's break it apart.
    Code:
    Dim dataLength As Integer = receivedGPIOData.Length
    Dim trimmedData As String = receivedGPIOData.Substring(1, dataLength - 2)
    Dim tokens() As String = trimmedData.Split(";"c)
    Now, let's say this is your input string, for simplicity:
    Code:
    &1;0;0;$
    OK. So.

    dataLength will be 8.

    Let's work out the next line:
    Code:
    Dim trimmedData As String = receivedGPIOData.Substring(1, dataLength - 2)
    Dim trimmedData As String = receivedGPIOData.Substring(1, 8 - 2)
    Dim trimmedData As String = receivedGPIOData.Substring(1, 6)
    Dim trimmedData As String = "&1;0;0;".Substring(1, 6)
    Dim trimmedData As String = "1;0;0;"
    Now let's see what tokens() becomes:
    Code:
    Dim tokens() As String = trimmedData.Split(";"c)
    Dim tokens() As String = "1;0;0;".Split(";"c)
    Dim tokens() As String = { "1", "0", "0" }
    Oh. Since the Substring() took the & off the front, you won't find "&1" as the first token. So when you get to:
    Code:
    If StrComp(GPIOdata(0), "&1", CompareMethod.Text) = 0 Then
    It fails.

    You should either make StrComp() look for "1" (but you shouldn't use StrComp()) or change your code to not take away the &:
    Code:
    Dim dataLength As Integer = receivedGPIOData.Length
    Dim trimmedData As String = receivedGPIOData.Substring(0, dataLength - 1)
    Dim tokens() As String = trimmedData.Split(";"c)
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  12. #12

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    okey, great intro... great approach... i liked it and thanks...

    now, updated this to
    Code:
    Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
            'Dim i As Integer
            'Dim GPIOdata() As String
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            Dim GPIOdata As String() = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Split(";"c)
            'GPIOdata = Split(receivedGPIOData, ";")
    
            If StrComp(GPIOdata(0), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
    
            If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "Door Open"
            End If
    
    
        End Sub
    and still getting the same error "System.ArgumentOutOfRangeException: 'startIndex cannot be larger than length of string.
    Parameter name: startIndex' "

  13. #13

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    It works... if i put the value manually, then it gives perfect... seeems somehow Serial read is not giving the whole damn thing perfectly...

    So now I need to focus on there actually... how???

    Code:
    Function ReceiveGPIOSerialData() As String
            Dim IncomingGPIO As String
            Try
                IncomingGPIO = globalConfig.GPIOSerialPort.ReadExisting()
                If IncomingGPIO Is Nothing Then
                    Return "nothing" & vbCrLf
                Else
                    Return IncomingGPIO
                End If
            Catch ex As TimeoutException
                Return "Error: GPIO Port read timed out."
            End Try
        End Function
    
        Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
            'Dim i As Integer
            'Dim GPIOdata() As String
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            'receivedGPIOData = "&1;0;0;0;0;0;1;0;0;0;$"
            Dim GPIOdata As String() = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Split(";"c)
            'GPIOdata = Split(receivedGPIOData, ";")
    
            If StrComp(GPIOdata(0), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
    
            If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "Door Open"
            End If
    
    
        End Sub
    is the serial port part... and arduino is sending them with a "serial.println()"...

  14. #14
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: tochararray from string and failed...

    So you need to validate your Serial read data before splitting it and assigning it to an array

  15. #15

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Quote Originally Posted by .paul. View Post
    So you need to validate your Serial read data before splitting it and assigning it to an array
    Any help on that??? I am reading it though... and can see a full form of what arduino is sending... It's an old topic though, I know serial just sends things... And thus I also added the bracketing like & and $ but still I need to put the whole thing inside a single shot... in arduino we use ReadStringUntil("\n") but here in vb.net, i dont know what to do...

  16. #16

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    this is now working... just that sometimes it is giving error... like the before, same error... it looks like sometimes it misses the reading...

    Serial.readline() was the key... now if I could make it without timer, rather kind if event driven, if serial buffer has something... then hope this will be OK...

    Help here???

  17. #17

  18. #18

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Yeah!! I also foudn it... but there are some people saying that this is not the good idea... So what is your opinion???


    Mishu~

  19. #19
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: tochararray from string and failed...

    Using an event is the correct way to go...
    A timer keeps ticking away regardless of whether any data has been received, whereas an event fires only when data has been received

  20. #20

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Quote Originally Posted by .paul. View Post
    Using an event is the correct way to go...
    A timer keeps ticking away regardless of whether any data has been received, whereas an event fires only when data has been received
    yeppp!! Indeed!!!

    But the worst part happened here... it hangs... yes, it gives output... but then 2 errors... any one of them... whatever they are, i have also found eventually the app gets hang and other buttons does not work. thus decided to use threading for serial read, so the button will be here. [button will send command via serial too].

    Now,
    Code:
    System.ArgumentOutOfRangeException: 'startIndex cannot be larger than length of string.
    Parameter name: startIndex'
    is what is the error for the threaded subroutine
    Code:
    Private Sub SerialPoll()
            'Dim i As Integer
            'Dim GPIOdata As String
    
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            'receivedGPIOData = "&1;0;0;0;0;0;1;0;0;0;$"
            Dim GPIOdata As String() = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = Split(receivedGPIOData, ";")
    
            If StrComp(GPIOdata(0), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
    
            'If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
            'lblStatus.Text = "Door Close"
            'End If
    
            'If StrComp(receivedGPIOData, "DRCLS", CompareMethod.Text) = 0 Then
            'lblStatus.Text = "Door Close"
            'End If
        End Sub
    with function:
    Code:
     Function ReceiveGPIOSerialData() As String
            Dim IncomingGPIO As String
            Try
                'IncomingGPIO = globalConfig.GPIOSerialPort.ReadLine()
                IncomingGPIO = globalConfig.GPIOSerialPort.ReadExisting()
                If IncomingGPIO Is Nothing Then
                    Return "nothing" & vbCrLf
                Else
                    Return IncomingGPIO
                End If
            Catch ex As TimeoutException
                Return "Error: GPIO Port read timed out."
            End Try
        End Function
    Now, yes, if we need to avoid timer and go for event based, I need a really guidance as microsoft guidance is like a clumsy to me... [head is jammed].

    Pathetic situation here...

  21. #21

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Here is the code pieces:

    Code:
     Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            timerSerialPoll.Enabled = False
            globalFunc.loadConfig()
    
            lblConfig.Text = "GSM port:" + globalConfig.GSMport + " GPIO Port:" + globalConfig.GPIOport 'for debug only.
    
            'Me.CheckForIllegalCrossThreadCalls = False
    
            AddHandler globalConfig.GPIOSerialPort.DataReceived, AddressOf DataReceivedHandler
    
        End Sub
    Code:
    Private Sub btnConnect_Click(sender As Object, e As EventArgs) Handles btnConnect.Click
    
    
            'thread = New System.Threading.Thread(AddressOf SerialPoll)
            'thread.Start()
    
            If (globalConfig.GSMSerialPort.IsOpen) Then
                globalConfig.GSMSerialPort.Close()
            End If
            If (globalConfig.GPIOSerialPort.IsOpen) Then
                globalConfig.GPIOSerialPort.Close()
            End If
            globalConfig.CommPortSetup()
            'My.Computer.Ports.OpenSerialPort(port)
            Try
                'globalConfig.GSMSerialPort.Open()
                globalConfig.GPIOSerialPort.Open()
                btnConnect.Visible = False
                lblConnStat.Text = "Connected"
                timerSerialPoll.Enabled = True
            Catch ex As Exception
                'globalConfig.GSMSerialPort.Close()
                globalConfig.GPIOSerialPort.Close()
                timerSerialPoll.Enabled = False
                lblConnStat.Text = "Disconnected"
                btnConnect.Visible = True
                MessageBox.Show(ex.Message)
            End Try
    Code:
    Private Shared Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
            Dim sp As SerialPort = CType(sender, SerialPort)
            Dim indata As String = sp.ReadExisting()
            Console.WriteLine("Data Received:")
            Console.Write(indata)
        End Sub
    now, i want to use these:
    Code:
    txtOutput.Text &= receivedGPIOData
            txtgpioout.Text = receivedGPIOData 'for dev debug
            'receivedGPIOData = "&1;0;0;0;0;0;1;0;0;0;$"
            Dim GPIOdata As String() = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = Split(receivedGPIOData, ";")
    
            If StrComp(GPIOdata(0), "1", CompareMethod.Text) = 0 Then
                lblStatus.Text = "OK"
            End If
    
            'If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
            'lblStatus.Text = "Door Close"
            'End If
    [here the receivedGPIOData will be replaced by appropriate variable, indata ]

    but can't.... any assistance??

  22. #22

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Guysm I'm avoiding any multithereading and event handlers... sticking with the timer tick. Now, normally I can see the data coming to me... that part is fully OK. The problem is after i try to make the substring, it does not work. Not just like thhat way...

    I have a button to send a Serial command. When I send that command, and then when the vb again receives the data, it gives an error...

    Here is the codes::
    Code:
    Private Sub timerSerialPoll_Tick(sender As Object, e As EventArgs) Handles timerSerialPoll.Tick
            'globalFunc.connectSerial()
            serialPoll()
            'globalConfig.GPIOSerialPort.Close()
    
    
        End Sub
    
        Private Sub serialPoll()
            'Dim i As Integer
    
            receivedGPIOData = ReceiveGPIOSerialData()
            txtOutput.Text &= receivedGPIOData
            'receivedGPIOData = "&1;0;0;0;0;0;1;0;0;0;$"
            'Dim GPIOdata As String() = receivedGPIOData.Substring(1, receivedGPIOData.Length - 2).Split(";"c)
            'GPIOdata = receivedGPIOData.Split(";"c)
            'GPIOdata = Split(receivedGPIOData, ";")
    
            processGPIO()
            'If StrComp(GPIOdata(0), "1", CompareMethod.Text) = 0 Then
            'lblStatus.BackColor = Color.Green
            'End If
    
            'If StrComp(GPIOdata(6), "1", CompareMethod.Text) = 0 Then
            'lblStatus.Text = "Door Close"
            'End If
    
    
    
        End Sub
    
        Private Sub processGPIO()
            Dim GPIOdata As String
            Dim doorOpenStat As Boolean
            GPIOdata = receivedGPIOData.Substring(1, 1)
            doorOpenStat = GPIOdata
            txtgpioout.Text = GPIOdata 'for dev debug
            If doorOpenStat = True Then
                lblStatus.Text = "Door Closed"
            End If
        End Sub
    
    Private Sub btnDooorClose_Click(sender As Object, e As EventArgs) Handles btnDooorClose.Click
            Dim cmd As String
            cmd = "close" + vbLf
    
    
            globalConfig.GPIOSerialPort.Write(cmd)
            Thread.Sleep(1000)
    
    
        End Sub
    and the error is:
    Code:
    System.ArgumentOutOfRangeException: 'startIndex cannot be larger than length of string.
    Parameter name: startIndex'
    plz, i need the support...

  23. #23
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: tochararray from string and failed...

    Time to do a bit of debugging.

    You didn't tell us which line the exception happens on, but it seems like the only one that isn't commented out, which can deliver THAT error, would be this one:

    GPIOdata = receivedGPIOData.Substring(1, 1)


    If that isn't the line with the error, then please tell us which it is. However, assuming that is the line with the error, then the error means that the string is a LOT shorter than you are expecting. This is where the debugging comes into it, as there could be 0 or 1 characters in receivedGPIOData, and which of those two it is would be quite important to know.

    So, if that is the line that is causing the exception, then put a breakpoint on the line. When execution stops on the breakpoint, take a look at what receivedGPIOData holds. Almost certainly, it will be empty. That's the more likely result, but also the more boring one. If it is NOT empty, then what does it hold? That character would be telling.

    If the string IS empty, then the problem is in ReceiveGPIOSerialData(), as that isn't returning what you want it to return. This may be happening EVERY time, or possibly just every now and then, or every other time, or some other pattern. You'd have to run the program a few times with a breakpoint in that function to see which it is.

    After looking back a few posts, I found the function body. You need to put a breakpoint in that function and see what the method is returning. I suspect that you'd learn more from that than from anything else.
    My usual boring signature: Nothing

  24. #24
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: tochararray from string and failed...

    It's sort of mental to try and avoid event handlers or multithreading. It's one of the tools you have to be ready to use with a serial port.

    Getting serial data is not too much unlike getting network data and way less reliable than getting file data. Let's talk about it.

    If I want to read "a file", it's easy. I ask Windows for the bytes from the file. I can ask in advance how many bytes there are, and ask for chunks of it if I want to. The only way this goes wrong tends to be situations where a file is deleted while you're using it or if the storage device explodes. They're rare enough we pretend they don't exist.

    If I want to read data from the network, there are a million things that can go wrong. "The connection is closed" might mean something went wrong and I lost the connection, or it might mean the other side sent me all it wanted to send. If I get some data, it might be all of the data for that particular transaction, or it might just be some of the data that was interrupted by the connection dropping. The serial port is just like the network.

    So when working with these unreliable data streams, we use protocols. Protocols are a set of rules about how data is transferred between two computers. If everyone follows the rules, we can tell the difference between "the connection was closed because there is no more data" and "the connection was terminated before everything was transferred".

    HTTP has that kind of protocol. Every transaction begins with headers. Each header must be a name-value pair terminated with CRLF. The headers are finished when a line is CRLF with no header. Generally, you get the headers all in one packet. But sometimes they're big enough you get them in chunks. If you get a chunk that ends with "Content-Enco", you know it's not the end of the headers because there's no CRLF terminator. So you wait for more data. Or, if the connection closes, you know something went wrong.

    The headers might include a Content-Length that tells you how many bytes to expect. They probably also include a Content-Encoding that can, in some cases, indicate a different way to describe the length of the data will be used. In either of these cases, since you're told the length to expect ahead of time, you know if you expected 300 bytes and only have 298 you should wait for more data. You also know if the connection terminates after 128 bytes, something went wrong. Sometimes there's no indication of length, and that's the worst case: you have to take the data and interpret any closed connection as "the end".

    It turns out this makes event-based and multithreaded approaches to device I/O more natural. Why?

    Let's work with a really simple protocol similar to yours. All messages are semicolon-delimited arrays that end with "$". This means I can tell lots of things apart:

    A complete message:
    Code:
    1;2;3;4$
    This has the "$" at the end, so I know it's a fully completed message.

    An incomplete message:
    Code:
    1;2;3
    I don't have a $ here, so I know this isn't all of the data. I have to wait to get more.

    Multiple messages:
    Code:
    1;2;3$7;8
    This has one complete message { 1, 2, 3 }. But there's part of another message that starts with { 7, 8, ??? } at the end. I can split out the first message and hold on to the "extra" data. This happens. It happens if the device sends 2 messages so close together they both (partially) happen between two timer ticks.

    So we can take two approaches. One uses ReadExisting() like you are using, the other uses events to process data as it comes in.

    With ReadExisting()
    Code:
    * let previous_data be an empty string.
    
    * on_timer():
        * let current_data = ReadExisting()
        * if current_data is empty/Nothing then quit.
        * let all_data = previous_data + current_data
        * let messages be the result of finding all "complete" messages in all_data.
        * for each message in messages:
            * Process(message)
        * let previous_data be all current_data past the last complete message.
    This is a little sticky to demonstrate in VB code because there's enough string manipulation to lose sight of the goal.

    It handles an "empty" case by quitting if ReadExisting() doesn't return anything.

    It handles the incomplete message I used as an example. Process() will get the data { 1, 2, 3 }. It stores "7;8" in previous_data. On the next timer tick, maybe ";9$" will have arrived. That means we'll do this:
    Code:
    * on_timer():
        * current_data = ";9$"
        * all_data = "7;8" + ";9$"
        * messages = { "7;8;9$" }
        * Process({ 7, 8, 9 })
        * all_data = ""
    Right now, your code expects it will ONLY get complete messages and that there will ALWAYS be a complete message every timer tick. Both of those assumptions are false, because that's what the errors you are getting indicate. You need your code to expect both of these cases, and I've just provided a pretty good example.

    Personally, I think the implementation is cleaner with event-based logic rather than timer ticks, but the core logic of "how do I safely read" is the same.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  25. #25
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: tochararray from string and failed...

    I suggest turning option script on for starters. Then learn the difference between a sub and a function.

  26. #26

    Thread Starter
    Lively Member
    Join Date
    May 2017
    Posts
    104

    Re: tochararray from string and failed...

    Quote Originally Posted by Sitten Spynne View Post
    It's sort of mental to try and avoid event handlers or multithreading. It's one of the tools you have to be ready to use with a serial port.

    ......
    ......

    Personally, I think the implementation is cleaner with event-based logic rather than timer ticks, but the core logic of "how do I safely read" is the same.
    Sir, First of all, you opened up a whole big ideas... and thanks for that large tutorial. This really helps me to understand so many things...

    Okey, so now let me explain a bit more: I'm here making a system where I need to read the GPIO status from an arduino. Based on that I will issue command... The string coming from arduino tells the status of the whole device...

    Code:
    <1000001000>
    is my string Here "<" is the header and ">" is the message footer, bracketing the whole hing as described earlier. The first bit is for device status... then next nits for different status of each GPIO. Now, as I will need only 1/0 only, then i have decided to make it more short and to make it like this. Always the first bit have to be 1 as 1 means the device is actually UP and running. Thus I will at worst case receive <10000....> but never <0000....>

    Now, I am using the GPIOSerialPort.ReadLine() because my arduino is sending me Strings with CRLF. (Serial.println()). Thus in other sense, All I am reading is just a string upto CRLF. But still I face the same issue, same error. Yes, this happens when my arduino starts 1 min before the app. And that is the problem, as in real life, arduino will start on power, (and technically i cant add any delay of 2 mins for safety)and then the problem is not solving...

    Event driven I will also need as I have to read from a gprs modem, but i will come to that part later on a different thread probably. But first thing first here...

    And below is the code:

    Code:
    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            frmGSMDbg.Show()
            frmGSMDbg.Visible = False
    
            Thread.Sleep(2000)
            RTC.Enabled = True
            globalFunc.loadConfig()
            globalFunc.connectSerial()
            ReceiveGPIOSerialData() 'intentional reading at startup for clearing any inbuffer
            Thread.Sleep(2000)
    
            Dim cmd As String
            cmd = "close" + vbLf
            globalConfig.GPIOSerialPort.Write(cmd)
            Thread.Sleep(500)
    
            timerGPIOPoll.Enabled = True
    
            lblConfig.Text = "GSM port:" + globalConfig.GSMport + " GPIO Port:" + globalConfig.GPIOport 'for debug only.
    
        End Sub
    Code:
    Function ReceiveGPIOSerialData() As String
            Dim IncomingGPIO As String
            Try
                IncomingGPIO = globalConfig.GPIOSerialPort.ReadLine()
                If IncomingGPIO Is Nothing Then
                    Return "nothing" & vbCrLf
                Else
                    Return IncomingGPIO
                End If
            Catch ex As TimeoutException
                Return "Error: GPIO Port read timed out."
            End Try
        End Function
    Code:
    Private Sub GPIOPoll()
    
            receivedGPIOData = ""
            receivedGPIOData = ReceiveGPIOSerialData()
            Thread.Sleep(50)
    
            txtOutput.Text &= receivedGPIOData + vbCrLf 'debug
    
            processGPIOData()
    
        End Sub
    
        Private Sub processGPIOData()
            Dim GPIOData As String
    
            If (receivedGPIOData.Substring(0, 1) Like "<" And receivedGPIOData.Substring(11, 1) Like ">") Then
                GPIOData = receivedGPIOData.Substring(1, 1) 'first value, represents IOC Status
                IOCStatus = GPIOData
                GPIOData = receivedGPIOData.Substring(6, 1) '6th valule, represents Door is Closing [0 means here undefined]
                doorClosingStat = GPIOData
                GPIOData = receivedGPIOData.Substring(7, 1) '7th valule, represents Door is Closed [0 means here undefined]
                doorCloseStat = GPIOData
                txtgpioout.Text = receivedGPIOData 'for dev debug
    
                If IOCStatus = True Then
                    lblIOCLink.BackColor = Color.Green
                Else lblIOCLink.BackColor = Color.Red
                End If
                If doorClosingStat = True Then
                    lblStatus.Text = "Door Closing"
                End If
                If doorCloseStat = True Then
                    lblStatus.Text = "Door Closed"
                End If
            Else
                lblStatus.Text = "Polling..."
            End If
    
        End Sub
    Code:
    Private Sub timerGPIOPoll_Tick(sender As Object, e As EventArgs) Handles timerGPIOPoll.Tick
            GPIOPoll()
        End Sub
    So from this point of view, i hope i will get some assistance as always... how exactly i can fix it...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width