On 2/19/2012 9:05 PM, Mark Wieder wrote:
Len-
Sunday, February 19, 2012, 5:23:11 PM, you wrote:
Related to my problem with reading binary data from a socket, how do I
handle a variable number of numbers that will come in with binaryDecode?
To explain, I get a number in the packet header that tells me there are
x number of bytes to follow in this packet. I know the first byte is a
remote ID and the second is a function code. Based on the function
code, the number of two byte integers that follows is going to be (the
number of bytes in the message / 2) - 1 (for the function code and
remote ID). One time there might be 2 integers to follow, another there
might be 10. There is a "number of words" number that is part of the
command so I know how many words there will be but the binaryDecode
function requires that I specify a name for each variable that is going
to get a value.
Ideally, I'd like to put all of these words in an array so I can process
them, but this doesn't seem to be an option for the binaryDecode
command. Should I build up a string that has
"...,var[0],var[1],...,var[x] in it to account for all the variables and
then use a "do" or "dispatch" to actually do the binaryDecode?
Also, if I use var[0], var[1], etc., do I need to create ALL of the
indexes first (for binaryDecode) or will just creating the first one
(var[0]) be sufficient?
I think I'd do something like:
read from socket for 1 bytes
put it into tRemoteID
read from socket for 1 bytes
put it into tFunctionCode
switch tFunctionCode
case kFunc1
put 2 into tWordCount
break
case kFunc2
put 10 into tWordCount
break
case -- ok - you get the idea
break
end switch
read from socket for (2*tWordCount) bytes
put it into tData
put binaryDecode("m3", tData, tSeq, tProto, tBytes) into tActual
if tActual is not tWordCount then
-- oops
end if
...and yes, you do need to have the maximum number of variables
already defined. There's no penalty for having extra compartments in
the binaryDecode line, but you don't want to have too few.
Thanks for the reply Mark but it's not quite the problem. The order
that the data comes in is:
tSequence, tProto, tBytes (all 16 bit), tRemoteID, tFunctionCode, xxxxx
After the function code, if you are doing a "write multiple registers"
for example, you will have a beginning register, and the count of
registers, followed by the actual data you are trying to write. This is
where things start to fall down for me because of this variable number
of items and the requirement to have a predefined variable for each
possible answer. I know when I get to the data portion exactly how many
registers I'm going to have to read (and therefore how many variables
I'm going to need). Based on your last paragraph though, it appears
that I'll have to either have a separate case for each possible number
of data words, or read them one at a time in a loop and assign them to a
variable in the loop. Neither of those is the optimal way to go but one
must do what one must do. :-)
So by the time you get to tFunctionCode you know how many bytes will
be coming in the stream, right? That's the xxxxx data? I still think
something like this is the easiest and most maintainable way to go.
How many functionCodes are you dealing with?
local tData1, tData2, tData3, tData4, ...
read from socket for 6 bytes
put it into tData
get binaryDecode("m3", tData, tSequence, tProto, tBytes)
read from socket for 1 byte
put it into tRemoteID
read from socket for 1 byte
put it into tFunctionCode
switch tFunctionCode
case kFunc1
put 2 into tWordCount
break
case kFunc3
case kFunc4
put 3 into tWordCount
break
case kFunc2
put 10 into tWordCount
break
case -- ok - you get the idea
break
end switch
read from socket for (2*tWordCount) bytes
put it into tData
put binaryDecode("m3", tData, tData1, tData2, tData3, tData4, etc.) into tActual
if tActual is not tWordCount then
-- oops
end if
Mark,
As it turns out, there are only two function codes I have to worry about
(i.e., ones we actually use): FC 3 - Read multiple registers, and FC 16
- write multiple registers. FC3 is easy (on the way in) because it has
a fixed length. The RESPONSE however will be variable depending on how
many registers the Master controller wants to read. It can be up to 100
at a time but all of our commands read 80 registers so this could be
almost hard coded.
FC 16 on the other hand gives me the number of words to write and then
that many words which I have to read, convert to ASCII and send out a
serial port. The response is easy since it only tells me how many
registers it actually wrote (which should be the same). So, I "pay for
it" either coming or going depending on the command.
I've managed to get it to work by getting the number of registers to
write and then in a loop:
create the next index value (tArray[i])
convert 1 word into tArray[i]
delete the first two characters of tData
repeat the process for each of the words
This gets me what I want although it seems a little brute force. Thanks
for your help and suggestions though.
len
_______________________________________________
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode