B4J Question Facing Problem with Jserial...Receiving Data is not in proper format

embedded

Active Member
Licensed User
Longtime User
Working on a modbus RTU project on which i send a predefined command of few bytes and in response also few bytes are send by the MODBUS RTU (REMOTE TERMINAL UNIT).Reponse length of bytes is not uniform for each command. sometime it length is 8 bytes..sometime 13 .While receiving AStream_NewData (Buffer() As Byte) sub is fired....what is happening here sometime whole data is receive properly...sometime only part of data is received remaining part is received in next event fired. i cannot use prefix mode here because there is no control on modbus RTU.

Please give me any solution for that.
 

emexes

Expert
Licensed User
sometime only part of data is received remaining part is received in next event fired.

That is precisely correct. On the bright side, knowing the problem is half of the solution = Don't Panic! (yet)

One day I will get around to writing up the generic solution to this. Maybe even today, if I can find a readable MODBUS format specification.

In the meantime, if you're keen to get a move-on, here is a recent solution for a similar problem with the same cause:

Rather than relying on the network chunking aligning with your packets, instead just treat it as a stream of bytes.

Usually you'd do this by, for each incoming VB data_received event:
- append the received data to a string buffer
- while the string buffer contains an end-of-packet marker
- cut the (potential) packet from the front of the string buffer into maybe_packet
- if maybe_packet contains a start-of-packet marker then
- cut off any guff from the front of maybe_packet up to the start-of-packet marker
- handle maybe_packet

might be a useful starting point for others, so:

If you use this packet parsing routine:
B4X:
Sub HandleIncomingData(Chunk As String)
    LogColor("In = " & Chunk.Replace(CRLF, "CRLF"), 0xFFc0c0c0)
    PacketBuffer = PacketBuffer & Chunk
 
Upvote 0

emexes

Expert
Licensed User
Could you please post the output of 20-30 packets logged using:

B4X:
Sub AStream_NewData (Buffer() As Byte)
    Dim AllBytes As String = ""
    For I = 0 to Buffer.Length - 1
        AllBytes = AllBytes & " " & Bit.And(Buffer(I), 255)    'convert signed -128..127 to unsigned 0..255
    Next

    Log(DateTime.Now & Tab & Buffer.Length & Tab & AllBytes.Trim)
End Sub
 
Upvote 0

emexes

Expert
Licensed User
if I can find a readable MODBUS format specification

Assuming that your MODBUS is ASCII, this might both fix up your split packets, and parse out the packets for you:

B4X:
Sub Process_Globals
    Dim StartOfPacket As String = ":"    'MODBUS ASCII packets start with colon
    Dim EndOfPacket As String = Chr(13) & Chr(10)    'MODBUS ASCII packets end with CR LF
    Dim PacketBuffer As String = ""
End Sub

Sub AStream_NewData (Buffer() As Byte)
    dim bc as ByteConverter
    PacketBuffer = PacketBuffer & bc.StringFromBytes(Buffer, "ISO-8859-1")    '1:1 byte:char conversion (UTF-8 also works for ASCII)

    Do While True
        Dim P As Int = PacketBuffer.IndexOf(EndOfPacket)    'check for packet in PacketBuffer
        If P < 0 Then Exit    'exit if not
   
        P = P + EndOfPacket.Length    'point to end of packet, not start of EndOfPacket marker
        Dim Packet As String = PacketBuffer.SubString2(0, P)    'copy packet from front of buffer
        PacketBuffer = PacketBuffer.SubString(P)    'remove packet from buffer
   
        P = Packet.LastIndexOf(StartOfPacket)
        If P > -1 Then    'if packet present
            If P <> 0 Then    'if guff before StartOfPacket
                Packet = Packet.SubString(P)    'then chop it off
            End If
            HandlePacket(Packet)
        End If
    Loop
End Sub

Sub HandlePacket(Packet As String)
    Dim Temp As String = Packet.Replace(Chr(13), "<CR>"),Replace(Chr(10), "<LF>")
    Log(DateTime.Now & Tab & Packet.Length & Tab & Temp)
ENd Sub

We're not quite at the finish line, but we're coming 'round the home turn. 🍻
 
Last edited:
Upvote 0

embedded

Active Member
Licensed User
Longtime User
Assuming that your MODBUS is ASCII, this might both fix up your split packets, and parse out the packets for you:

B4X:
Sub Process_Globals
    Dim StartOfPacket As String = ":"
    Dim EndOfPacket As String = Chr(13) & Chr(10)
    Dim PacketBuffer As String
End Sub

Sub AStream_NewData (Buffer() As Byte)
    dim bc as ByteConverter
    PacketBuffer = PacketBuffer & bc.StringFromBytes(Buffer, "UTF8")

    Do While True
        Dim P As Int = PacketBuffer.IndexOf(EndOfPacket)    'check for packet in PacketBuffer
        If P < 0 Then Exit    'exit if not
     
        P = P + EndOfPacket.Length    'point to end of packet, not start of EndOfPacket marker
        Dim Packet As String = PacketBuffer.SubString2(0, P)    'cut off front bit
        PacketBuffer = PacketBuffer.SubString(P)    'keep the rest
     
        P = Packet.LastIndexOf(StartOfPacket)
        If P > -1 Then    'if packet present
            If P <> 0 Then    'if guff before StartOfPacket
                Packet = Packet.SubString(P)    'then chop it off
            End If
            Log(DateTime.Now & Tab & Packet.Length & Tab & Packet.Replace(Chr(13), "<CR>"),Replace(Chr(10), "<LF>")
        End If
    Loop
End Sub

We're not quite at the finish line, but we're coming 'round the home turn. 🍻
Thanks for your reply....i am out of home ...after coming back giving you feed back
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Please give me any solution for that.
Check
- In other cases you should use AsyncStreams in regular mode. This means that there is no guarantee that each sent message will be received as a single message. In fact it is more or less guaranteed not to happen. So your code is responsible for correctly collecting and receiving the message.
You can use BytesBuilder class to collect and parse the messages.
 
Upvote 0
Top