weirddave

Binary Data for UDP

14 posts in this topic

I want to construct a data payload based on a whole load of things which set the individual bits in the bytes.

Ideally I'd like to access the bytes in the form:

$TxData [ $ByteNo ]

Followed by:
UDPSend ( $TxSocket, $TxData )

How do I specify $TxData[] as an array of bytes?

 

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

DLLstructCreate assigns a struct to a variable, which can contain lots of bytes. However if you're using fewer than 33 flags, I would just store a single (32-bit) integer in a variable and set its individual bits with $var=BitOr($var,2^<yourbit>).

Edited by RTFC
typo

Share this post


Link to post
Share on other sites

Thanks for the replay :)
I shall take a look at DLLstructCreate, I have 54 bytes (some are values, others are flag bits) at the moment and that is likely to increase.

Had a look, would:

$TxData = DLLStructCreate ( "struct; byte myTxData[54] ;endstruct" )

do the trick? Set the bytes like so:

DllStructSetData ( $TxData, myTxData, n )

where 'n' is the byte I want to set. I assume this starts at 0?
When receiving packets, what should I do to read individual bytes?

Share this post


Link to post
Share on other sites

See DllstructGetData. The index is base-1 though, and refers to the entire chunk of bytes you defined. If you want 54 separately addressable bytes you need to define them individually (byte;byte;byte...). Then you could also name each flag individually (byte flag1; byte flag2...). But you're still wasting bandwidth by a factor 8 this way; I would define two dwords or one int64 instead (= 64 bit flags), and set/test/reset their individual bits (and not use entire bytes). Up to you, of course.

Share this post


Link to post
Share on other sites

The flags are grouped into bytes already, there's only a few spare bits in those 54 bytes.

I can see how to use  DllstructGetDat, but how do I get the data into it from UDPRECV()? I will probably want to check the IP address so my command was going to be along the lines of:

$sReceived = UDPRECV( $RxSocket, $RxDataLength, 3 )

The autoit examples really aren't helping me :(

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

2 hours ago, weirddave said:

The flags are grouped into bytes already

That's a lot of flags!:blink:

Yeah, the examples tend to show the most basic usage only. Having had to write several Help docs for my own software, I can relate to the inclination to leave it at that.;)

There's some user-generated content on UDP on the forum (google: "site:autoitscript.com UDP"), or you could study my fairly densely annotated Pool environment (link in signature) for example, which does UDP (amongst a few other things). It's neither small nor simple though, so maybe you'd best study some of the other examples instead/first.

Edited by RTFC

Share this post


Link to post
Share on other sites

A lot of the data is just values, there's only about 40 flags ;) 
The 'other end' will be an arduino style device (based on the Due micro), connected to a FPGA which in turn communicates with a bunch of other stuff, hence all the data and flags.
I took a little look at Pool, I think I need to keep it light, I'm aiming for 1ms loop times. 'This end' will be replaced with Arduino style hardware as well, the purpose of the autoit code is to emulate either end to help debug it :) 

I shall see what google throws my way...

Cheers.

Share this post


Link to post
Share on other sites

I've managed to send some data using:

$TxStruct = String("struct;byte myTxData[54];endstruct")
$TxData = DLLStructCreate ( $TxStruct )
$BinTxData = DLLStructGetData($TxData, "myTxData")
UDPSend($TxSocket, $BinTxData)

Is that the right way to do it?

If I were to create a more meaningful structure, such as:

$TxStruct = String("struct;byte flags;byte data;endstruct")

how would I send the whole structure?

Google really isn't finding the information I want :(

Share this post


Link to post
Share on other sites
Global $tData = DllStructCreate("byte myTxData[54]")

Global $tMeaningfulStruct = DllStructCreate("byte flags[6];byte data[6]", DllStructGetPtr($tData)) ; point to the data struct

DllStructSetData($tMeaningfulStruct, "flags", _SetBit(0, 0), 2) ; set bit 0 of second flag byte
DllStructSetData($tMeaningfulStruct, "flags", _SetBit(0, 1), 3) ; set bit 1 of third flag byte

DllStructSetData($tMeaningfulStruct, "data", 0xff, 2) ; set 0xff to second data byte


Global $bData = DllStructGetData($tData, "myTxData")
ConsoleWrite($bData & @CRLF)


Func _SetBit($bVal, $iPos)
    Return BitOR($bVal, 2^$iPos)
EndFunc

 

2 people like this

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites

I'm speechless, thanks for that, you've helped massively.
If I have received a block of data, can I use the same method?

Global $tDataRx = DllStructCreate("byte myRxData[4]")

$sReceived = UDPRECV($RxSocket, $RxDataLength, $RxUDPStyle); this contains the data block (4 bytes)
$tMeaningfulStructRx = DllStructCreate("byte flagsRx[2];byte dataRx[2]", DllStructGetPtr($sReceived)) ; point to the data struct

$temp = DllStructGetData($tMeaningfulStructRx, "dataRx",1) ; get the first data byte
msgbox(0,"",$temp)

 

Share this post


Link to post
Share on other sites

I think I have that all wrong :D

Global $tDataRx = DllStructCreate("byte myRxData[4]")
$tMeaningfulStructRx = DllStructCreate("byte flagsRx[2];byte dataRx[2]", DllStructGetPtr($tDataRx)) ; point to the data struct

$sReceived = UDPRECV($RxSocket, $RxDataLength, $RxUDPStyle); this contains the data block (4 bytes)
DllStructSetData($tDataRx, "myRxData", $sReceived) ;

$temp = DllStructGetData($tMeaningfulStructRx, "dataRx",1) ; get the first data byte
msgbox(0,"",$temp)

I think this is the right way to do it. Hopefully I can write a piece of test code to prove it :)

 

Share this post


Link to post
Share on other sites

Looks good.

1 person likes this

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites

I've created a file with all the byte names in which I read in to create the struct so that I can change things without diving into the code. This appears to be working but has the side effect of creating the 'meaningful' struct first then using its pointer for the packet data struct (I need the length from the meaningful struct before I can create the packet struct). I think this works because the structs are 'real' and not some autoit version of reality, is this correct?

Share this post


Link to post
Share on other sites

You are right. It does not matter what structure points to the other one. DllStructCreate without pointer allocates the real memory. DllStructCreate with pointer points to the real memory location allocated first.

1 person likes this

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

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