ImtsSrl / KUKAVARPROXY

Robot KUKA variables TCP server
118 stars 46 forks source link

What does Split message means ? #3

Open lionpeloux opened 5 years ago

lionpeloux commented 5 years ago

Hello,

I'm working on a C# client for KukavarProxy. So far I came up with a yet almost working solution using the sparse info I've found on the net about this tool (specially here).

My first question is would you be able to share in few lines the structure of the TCP packets that we should adopt to discuss with KukavarProxy ? For readquery, writequery and answer ? So far, I came up with this :

readquery

writequery

answer

=> Can you confirm I've correctly understood all this ? => Can you tell us more about the tail ? Is it always 011 ? Does it have any meaning or is it just a separator ?

=> When I send very fast requests to the server, In the debug window I see some messages are "Split". When I read the answers back, wherever a message were marked "Split" the Id is not incremented correctly. How can I prevent this to happen other than slowing down my queries ?

This what I send to the proxy :

Query 1 : 01 03 0 00
Query 2 : 02 03 0 00
Query 3 : 03 03 0 00
Query 4 : 04 03 0 00
Query 5 : 05 03 0 00 => Message Split
Query 6 : 06 03 0 00 => Message Split
Query 7 : 07 03 0 00
Query 8 : 08 03 0 00 => Message Split
Query 9 : 09 03 0 00 => Message Split
Query 10 : 10 03 0 00

When I read back the stream I get :

Msg[1] with Id = 1 : 01 06 0 00 110 
Msg[2] with Id = 2 :  02 06 0 00 110 
Msg[3] with Id = 3 :  03 06 0 00 110  
Msg[4] with Id = 4 :  04 06 0 00 110 
Msg[5] with Id = 4 :  04 06 0 00 110 
Msg[6] with Id = 4 :  04 06 0 00 110 
Msg[7] with Id = 7 :  07 06 0 00 110 
Msg[8] with Id = 7 :  07 06 0 00 110 
Msg[9] with Id = 7 :  07 06 0 00 110 
Msg[10] with Id = 10 :  10 06 0 00 110 

capture d ecran 2019-01-25 a 11 44 26 capture d ecran 2019-01-25 a 12 35 59

nowire commented 5 years ago

Ciao Lionel,

sorry for the delay. Currently I do not have time to check, but I have shared the sources on github

Massimiliano

Il giorno ven 25 gen 2019 alle ore 12:37 Lionel du Peloux < notifications@github.com> ha scritto:

Hello,

I'm working on a C# client for KukavarProxy. So far I came up with a yet almost working solution using the sparse info I've found on the net about this tool (specially here https://github.com/akselov/kukavarproxy-msg-format).

My first question is would you be able to share in few lines the structure of the TCP packets that we should adopt to discuss with KukavarProxy ? For readquery, writequery and answer ? So far, I came up with this : readquery

  • 2 bytes ID (uint16)
  • 2 bytes content length (uint16)
  • 1 byte for read (0) or write (1) mode
  • 2 bytes for the variable name length (uint16)
  • N bytes for the variable name to be read (ASCII -> bytes)

writequery

  • 2 bytes ID (uint16)
  • 2 bytes content length (uint16)
  • 1 byte for read (0) or write (1) mode
  • 2 bytes for the variable name length (uint16)
  • N bytes for the variable name to be read (ASCII -> bytes)
  • 2 bytes for the variable value length (uint16)
  • M bytes for the variable value to be written (ASCII -> bytes)

answer

  • 2 bytes ID (uint16)
  • 2 bytes content length (uint16)
  • 1 byte for read (0) or write (1) mode
  • 2 bytes for the variable value length (uint16)
  • M bytes for the variable value to be written (ASCII -> bytes)
  • 3 bytes tail [0, 1, 1]

=> Can you confirm I've correctly understood all this ? => Can you tell us more about the tail ? Is it always 011 ? Does it have any meaning or is it just a separator ?

=> When I send very fast requests to the server, In the debug window I see some messages are "Split". When I read the answers back, wherever a message were marked "Split" the Id is not incremented correctly. How can I prevent this to happen other than slowing down my queries ?

This what I send to the proxy :

Query 1 : 01 03 0 00 Query 2: 02 03 0 00 Query 3 : 03 03 0 00 Query 4 : 04 03 0 00 Query 5 : 05 03 0 00 => Message Split Query 6 : 06 03 0 00 => Message Split Query 7 : 07 03 0 00 Query 8 : 08 03 0 00 => Message Split Query 9 : 09 03 0 00 => Message Split Query 10 : 10 03 0 00

When I read back the stream I get :

Msg[1] with Id = 1 : 01 06 0 00 110 Msg[2] with Id = 2 : 02 06 0 00 110 Msg[3] with Id = 3 : 03 06 0 00 110 Msg[4] with Id = 4 : 04 06 0 00 110 Msg[5] with Id = 4 : 04 06 0 00 110 Msg[6] with Id = 4 : 04 06 0 00 110 Msg[7] with Id = 7 : 07 06 0 00 110 Msg[8] with Id = 7 : 07 06 0 00 110 Msg[9] with Id = 7 : 07 06 0 00 110 Msg[10] with Id = 10 : 10 06 0 00 110

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ImtsSrl/KUKAVARPROXY/issues/3, or mute the thread https://github.com/notifications/unsubscribe-auth/AKYlDSFRo4aHe8MQkDGN3Z2hOWpm1llMks5vGuxmgaJpZM4aStxf .

-- Massimiliano Fago Senior Software Engineer massimiliano.fago@gmail.com skype: massimomfa

lionpeloux commented 5 years ago

Ok, so looking carefully at the code I think I effectively found a bug !

Split message is when the buffer is filled with several messages so the byte stream is "splitted" between each messages. Nothing wrong with that.

However, while the variable nMsg is correctly incremented, the string to write is built each time with sMsgID which is set at the beginning of the loop but is never updated when splits occurred.

I'll try to make a pull request for that next week.

Private Sub sockServer_Read(Index As Integer, DataLength As Integer, IsUrgent As Integer)
    Dim strBuffer As String
    Dim cchBuffer As Integer

    Static bReadPending As Boolean

    On Error GoTo errRead

    ' read the first 2048 bytes in the socket buffer 
    ' put the received bytes (n <= 2048) in strBuffer
    cchBuffer = sockServer(Index).Read(strBuffer, 2048)

    If (cchBuffer < 0) Then

        'If a would block error occurs exit the sub and let
        'another read event read when the client is ready
        If (sockServer(Index).LastError = WSAEWOULDBLOCK) Then
            Exit Sub
        End If

        'If an in progress error occurs exit the sub and let
        'another read event read when the client is ready
        If (sockServer(Index).LastError = WSAEINPROGRESS) Then
            Exit Sub
        End If

        'There has been an error in the read
        'print the error and quit
        DropClient Index, "Error occurred durring the read event: Error #", sockServer(Index).LastError
        UpdateForm
        Exit Sub
    End If

    Dim sValueToWrite As String             
    Dim lLunghezzaBlocco As Long            ' Length of the bloc
    Dim lLunghezzaBloccoToWrite As Long     ' Length of the bloc to write 
    Dim sAzione As String                   ' Action
    Dim lMsgID As Long                      ' Msg Id
    Dim sMsgID As String
    Dim nFunction As Integer

    ' the first 2 bytes indicate the ID of the received message
    lMsgID = CLng(Asc(Mid(strBuffer, 1, 1))) * &H100 + Asc(Mid(strBuffer, 2, 1))
    sMsgID = Mid(strBuffer, 1, 2)

    ' the next 2 bytes indicate the length of the bloc
    lLunghezzaBlocco = Asc(Mid(strBuffer, 3, 1)) * &H100 + Asc(Mid(strBuffer, 4, 1))

    ' then walk byte by byte until the end of the bloc
    nMsg = 0

    While Len(strBuffer) >= lLunghezzaBlocco
        'DoEvents
        nMsg = nMsg + 1

        ' extract the message content as a string (froom byte 6 to byte lLunghezzaBlocco) 
        strMsg = Mid(strBuffer, 6, lLunghezzaBlocco)

        ' extract the query function (0=READ, 1=WRITE)
        nFunction = CInt(Asc(Mid(strBuffer, 5, 1)))

        If Not bReadPending Then 

            ' is this a lock to prevent concurrent reading operations ?
            ' shouldn't we wait here until bReadPending = false ?

            ' gets the lock ?
            bReadPending = True 

            ' read the msg
            If readMsg(nFunction, strMsg, sValueToWrite, sAzione) Then

                lLunghezzaBloccoToWrite = Len(sValueToWrite)
                sValueToWrite = sMsgID & longToWord(lLunghezzaBloccoToWrite) & sValueToWrite

                If frmMain.sockServer(Index).Write(sValueToWrite, Len(sValueToWrite)) < 0 Then
                    DropClient Index, "Error occurred durring the read event: Error #", sockServer(Index).LastError
                End If

                If frmMain.chkDebug.Value = 1 Then
                    addMessage "ID=" & lMsgID & " " & sAzione
                End If

            End If

            bReadPending = False

        Else

            addMessage "!!Lettura pendente!!"

        End If

        ' remove the message from strBuffer (msg = ID + Len + bloc) / even if we skip the read because bReadPending was true ?
        strBuffer = Right(strBuffer, Len(strBuffer) - (lLunghezzaBlocco + 4))

        ' if they are enough bytes in the buffer => should be > 3 no ?
        If Len(strBuffer) > 2 Then

            ' the first 2 bytes indicate the ID of the received message
            lMsgID = CLng(Asc(Mid(strBuffer, 1, 1))) * &H100 + Asc(Mid(strBuffer, 2, 1))

            ' the next 2 bytes indicate the length of the bloc
            lLunghezzaBlocco = Asc(Mid(strBuffer, 3, 1)) * &H100 + Asc(Mid(strBuffer, 4, 1))

            ' display debug msg
            If frmMain.chkDebug.Value = 1 Then
                addMessage "Split msg: " & nMsg & " ID=" & lMsgID & " " & sAzione
            End If

            Debug.Print "Msg separato numero " & nMsg & ": " & strMsg
        End If

    Wend

    'Debug.Print "Lunghezza attesa: " & lLunghezzaBlocco & " lunghezza ricevuta: " & Len(strBuffer)

    'memorizzo il tempo di arrivo del messaggio
    lLastReciveTime(Index) = GetTickCount()

    On Error GoTo 0
    Exit Sub

errRead:
    On Error GoTo 0

    addMessage "Errore in Read"
    addMessage "Msg ID " & lMsgID
    addMessage "Msg Len " & lLunghezzaBlocco
    addMessage "Buffer Len " & Len(strBuffer)
    addMessage strMsg

    bReadPending = False

End Sub