Sign in to follow this  
Followers 0
p3c

Binary over TCP

8 posts in this topic

Hiya folks. First time poster but long time reader of the boards. :) First of, wanted to thank the Devs and ALL the board rats that help make AutoIt the fantastic tool that it is!!!

I have been working on a script the performs diagnostics of system components over both serial and ethernet links. The script works great over both my serial links, but I am having a problem with one of the Ethernet devices.

Essentially what I am trying to do is send numerical status query commands to a device on a remote computer via TCP. I can open the sockets fine, but when I try to send the query status commands, I am getting errors. The command structure for the device by the specs I have is 4 byte Little Endian. Byte 3 and 2 are zeros and 1 and 0 I assume contain the command instruction since the largest command I need to send is "710".

Please know I an a definite newb when it comes to binary data so kindly be gentle. hehe. I was fiddling around with this using AutoIt V3.2.2.2 with the older Binary functions and had "limited" success getting a status from the remote PC device. I was working on my issues when I saw Jon's post about the latest AutoIt version addressing the way Binary data was handled. So I installed it assuming it would fix my "limited success" problem. Now all I get are command errors showing on the remote PC server. Again, I have good socket comms open and running.

Prior to the AutoIt upgrade I was having that limited success by TCPSending the raw data read from my input box (ex. "710") which would error out on my remote client, but then I would immediately TCPSend the same data using $data = BinaryString($data), and I would get a good status reply. If I didn't use that exact sequence, I would only see errors on my TCP server. And in my .log file I create, during those successful command sends I would see the data that was sent would be of the scrambled "Binary" type ie non ASCII characters, at least none you can read. The new Binary() function does not seem to work the same way and that approach no longer works at all.

My question is, how would I take a number (command) for example "710" and covert it to the Little Endian Binary my documentation says the remote device accepts, so I can TCPSend it ? I have searched the boards for the last week and the closest post I saw was from Falcon88 <sp>??, talking about a similar problem with the new Binary() function, though that thread didn't nail it for me. He did indicate he used to be able to "see" the scrambled "Binary" stuff with the old command and not the new one. As did I before when I could actually get a good command across the connection and then reading the traffic data in my .log. I have also read Qwer85's post and Siao's answer about "Endian-ity" and have that info once I can figure out a way to get the Binary right.

I sincerely apologize for this rather "long winded" post. Especially since it's my first one, but I wanted to include as much detail as possible. And again, I want to thank all of you for the amazing work you do here. Any thoughts on this at all would be greatly appreciated.

Share this post


Link to post
Share on other sites



And to top off your 1st post, could we have some code to play with? :) Welcome to the forums BTW.

Thanks for the reply Bert. ;) I would have posted some code, as I have seen the "rack" that newbs get when they don't hehe, but all I was using was $data = BinaryString($data) for my TCPSend command as listed in my previous post when it worked. And then tried the new $data = Binary($data) which didn't work. I could post the .log file of the old data that was good if needed??

Share this post


Link to post
Share on other sites

How about StringToBinary ( "String to Send" , 2 )

Tried that as well ChrisL. But that resulted in a value whose BinaryLen was 6 Bytes? and didn't work :)

Share this post


Link to post
Share on other sites

How about StringToBinary ( "String to Send" , 2 )

The log file when it worked using command "701" showed:

2007-09-28 02:39:01 : Sending string ... 701 ... to Port #1: 6545 Socket: 272

2007-09-28 02:39:03 : Sending string ... ½ ... to Port #1: 6545 Socket: 272

2007-09-28 02:39:03 : Data received from Port #1: ¥x T | H >

I use "... " and " ..." preceding and following the $data variable so I know when I have data.

Share this post


Link to post
Share on other sites

And to top off your 1st post, could we have some code to play with? :) Welcome to the forums BTW.

And thx for the welcome :P Here is the portion of code in AutoIt V3.2.2.2 (may have been 3.2.2.0.. but similar I believe?) that gave me the "limited" success as described in my first post. The first TCPSend would fail, but the 2nd using BinaryString would get me data back from the server as shown in the log snippet above.

If $c[1]="yes" And $c[2]="yes" Then
    $data = Int(GUICtrlRead($send))
    If $data <> "" Then
        send_data()
        GUICtrlSetData($send,"")
    EndIf
Else
    MsgBox(0, "Error", "Please connect as a client or server before attempting to send data.")
EndIf
        

Func send_data()
    MsgBox(0,"DEBUG", "Sending Read Command = " & $data)
    $ret = TCPSend($ConnectedSocket[$port], $data) ; try sending raw read
    _FileWriteLog(@DesktopCommonDir & "\TCP.log","Sending string ... " & $data & " ... to Port #" & $port & ": " & $TCP_PORT[$port] & " Socket: " & $ConnectedSocket[$port])
    Sleep(500)
    rcv_data()  
    $data = BinaryString($data)
    MsgBox(0,"DEBUG", "Sending Read Command = " & $data)
    $ret = TCPSend($ConnectedSocket[$port], $data) ; try sending as binary
    _FileWriteLog(@DesktopCommonDir & "\TCP.log","Sending string ... " & $data & " ... to Port #" & $port & ": " & $TCP_PORT[$port] & " Socket: " & $ConnectedSocket[$port])
    Sleep(500)
    rcv_data()
EndFunc

Func rcv_data()
    $recv = TCPRecv($ConnectedSocket[$port], 2048)
    If @error Then
        $c[$port] = "no"
        GUICtrlSetData($status_light[$port], "Fault")
        GUICtrlSetFont($status_light[$port], 12, 800)
        GUICtrlSetColor($status_light[$port], 0xFFFF00) ; Yellow
        GUICtrlSetBkColor($status_light[$port], 0xFF0000) ; Red
        _FileWriteLog(@DesktopCommonDir & "\TCP.log","Error in TCPRecv from selected IP: " & $test_IP & " Port #" & $port & ": " & $TCP_PORT[$port] & " Socket: " & $ConnectedSocket[$port]) ; debug log
        MsgBox(0,"ERROR",  "Receive Error from " & $test_IP & " Port: " & $TCP_PORT[$port])
    ElseIf $recv <> "" Then
        GUICtrlSetData($rcv_box[$port], " > " & $recv & @CRLF & GUICtrlRead($rcv_box[$port]))
        _FileWriteLog(@DesktopCommonDir & "\TCP.log","Data received from Port #" & $port & ": " & $recv) ; debug log
    EndIf
EndFunc

Replacing the BinaryString() function with the newer Binary() function just errors out on my server and nothing is returned to my TCPRecv. Any ideas at all totally welcomed ;)

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

After much playing around with variations of Int, Dec, Hex, Binary, BinarytoString, StringtoBinary to try to nail down what is going on when I GuiCtrlRead an input box, I came up with the following. That works ... kinda.. :P

If $c[1]="yes" And $c[2]="yes" Then
    $data= GUICtrlRead($send)&BinaryToString(Int(GUICtrlRead($send)))
    If $data <> "" Then
        send_data()
        GUICtrlSetData($send,"")
    EndIf
Else
    MsgBox(0, "Error", "Please connect as a client or server before attempting to send data.")
EndIf

Func send_data()
        $port = 1
        MsgBox(0,"DEBUG", "Sending Command  = " & $data)
        $ret = TCPSend($ConnectedSocket[$port], $data) 
        _FileWriteLog(@DesktopCommonDir & "\TCP.log","Sending string ... " & $data & " ... to Port #" & $port & ": " & $TCP_PORT[$port] & " Socket: " & $ConnectedSocket[$port])
        Sleep(50)
        rcv_data()      
EndFunc

Func rcv_data()
    $recv = TCPRecv($ConnectedSocket[$port], 2048)
    $recv = BinaryToString($recv)
    If @error Then 
        $c[$port] = "no"
        GUICtrlSetData($status_light[$port], "Fault")
        GUICtrlSetFont($status_light[$port], 12, 800)       
        GUICtrlSetColor($status_light[$port], 0xFFFF00) ; Yellow
        GUICtrlSetBkColor($status_light[$port], 0xFF0000) ; Red     
        _FileWriteLog(@DesktopCommonDir & "\TCP.log","Error in TCPRecv from selected IP: " & $test_IP & " Port #" & $port & ": " & $TCP_PORT[$port] & " Socket: " & $ConnectedSocket[$port]) ; debug log
        MsgBox(0,"ERROR",  "Receive Error from " & $test_IP & " Port: " & $TCP_PORT[$port])
    ElseIf $recv <> "" Then 
        $t=1
        GUICtrlSetData($rcv_box[$port], " > " & $recv & @CRLF & GUICtrlRead($rcv_box[$port]))
        _FileWriteLog(@DesktopCommonDir & "\TCP.log","Data received from Port #" & $port & ": " & $recv) ; debug log
    EndIf
EndFunc

For some reason sending a command with AutoIt to my server (non-AutoIt), I have to concat a standard guictrlread with the Int of a BinaryToString read to get any kind of response from it. Using this method, I was able to get the results similar to the older AutoIt V3.2.2.x functions.

Even so, this method doesn't work 100%, as successive sends of commands error out on the server every other time as shown by the client log below.

2007-10-01 14:23:15 : Sending string ... 701½

2007-10-01 14:23:16 : Data received from Port #1: 0xA506780000000000540000007C00000048000000

2007-10-01 14:23:38 : Sending string ... 701½

2007-10-01 14:23:45 : Sending string ... 701½

2007-10-01 14:23:46 : Data received from Port #1: 0xA506780000000000540000007C00000048000000

2007-10-01 14:23:56 : Sending string ... 701½

2007-10-01 14:24:03 : Sending string ... 701½

2007-10-01 14:24:04 : Data received from Port #1: 0xA506780000000000540000007C00000048000000

2007-10-01 14:24:19 : User closed program.

Though the script itself is now usable as a diagnostic tool, I would still very much appreciate if anyone could explain what I am doing wrong? :)

<edit>

And a cookie goes out to anyone ;) that can help me figure out why my recv_data function doesn't grab data from my server unless the response is greater than some unknown amount. For example the "701" command requests a long status message and is able to get all the data as shown above. But other commands I send only request maybe a few digits of data and I am not getting those short bursts, though I can see my server send them and it doesn't error out.

Edited by p3c

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0