Home AMX User Forum AMX General Discussion

Parsing a response w/ no set terminator, varying length?

In the Pelco D protocol, the response string from the device contains no set termination character, the message can be of varying length (either 4,7,18 bytes), and the STX value ($FF) is sometimes used in the response string as data as well. What would be a good way to approach parsing this?

NDA prevents me from posting the whole protocol but here's an example of the 7 byte response messages. The 18 byte response is the same except it includes data 3..17:

EXTENDED RESPONSE

byte .....1..... |.....2.....|.....3.....|.....4..... |..... 5.....|.....6.....|.....7
........sync.....|... addr...|....resp1..|....resp2...|...data1....|...data2..|..chksm
........0xFF.....|...*var*...|....*var*..|....*var*..|...*var*....|...*var*...|..add bytes 2..6



So far the solution I'm going to use is to take the incoming message, throw it into a queue, test for the STX character ($FF), then keep looking at the 4th, 7th, and 18th characters to see if they add up to a checksum for the previous bytes. It just seems like a lot of testing overhead and a lot of room for errors. I'm wondering if there's a more efficient way of handling it.

Thanks!


--John

Comments

  • Actually, this particular protocol seems a bit more convoluted. The checksum calculation I listed above isn't correct. It's actually the sum of the previous bytes PLUS the original command that caused the response to be generated. So for instance, if I initiate a command, it will respond with a response string terminated with a checksum equal to the sum of the previous bytes (minus the STX) plus the value of the original command byte to which this is a response.

    --John
  • jjamesjjames Posts: 2,908
    Just curious - is this worth anything to ya?

    http://www.232analyzer.com/RS232_Examples/CCTV/Pelco_D_Pelco_P_Examples_Tutorial.HTM

    Might help others in helping you too - dunno!
  • AuserAuser Posts: 506
    In the Pelco D protocol, the response string from the device contains no set termination character, the message can be of varying length (either 4,7,18 bytes), and the STX value ($FF) is sometimes used in the response string as data as well. What would be a good way to approach parsing this?

    If it is possible to make the assumption that each response will (in general) be received in a single data event, you could use create_multi_buffer and get_multi_buffer_string to retrieve each response and process it in turn until the buffer is emptied.

    The general process would be:

    while(len(buffer))
    {
    get_multi_buffer_string
    if(valid and complete response)
    {
    do something...
    }
    }

    On occasion responses from the device may be split across two data events, but it may be acceptible to discard these fragmented packets if you're polling the device.
  • Why not parse it byte by byte?
  • a_riot42a_riot42 Posts: 1,624
    Can't you continually fill a buffer with whatever comes in until you hit another xFF? Then you know you have an entire command and can parse the individual bytes. Maybe I am misunderstanding your question.
    Paul
  • On occasion responses from the device may be split across two data events, but it may be acceptible to discard these fragmented packets if you're polling the device.
    After reading the protocol more carefully it appears that I should be able to predict what the length of the response message is. I'll explain it a little more below. Before figuring it out though, I was trying to do it without having to discard any data.
    Why not parse it byte by byte?
    That's originally what I was planning to do, but it just seems like there would be room for error as far as finding the end of the message.
    Can't you continually fill a buffer with whatever comes in until you hit another xFF?
    The $FF can actually appear as data as well as the STX. For instance if the address of the camera responding is 255, the first two bytes of the response string would be $FF$FF (the message is formatted as "STX, Address, xx,xx,xx,..."). Plus, if there's only one response string and another one didn't come up for a while I could conceivably end up with the first $FF and not get another $FF for a while.


    I think the fact that this device doesn't send unsolicited feedback helps out in this case. In the _comm module that I wrote for it, I actually parse commands from my UI module and each part of the parse builds the command string. The command string is STX, CamAddress, Cmd1, Cmd2, Data1, Data2, Checksum. Because of the way I build the command string I actually have the cmd1 byte, and the cmd2 byte stored . After reading more carefully it looks like I'll know what length the of the response should be based on the type of command I sent. Now I'm thinking that I can build a conditional or lookup table that parses the response string's expected length based on the value of cmd1 and cmd2.

    This is an interesting situation though, having variable length messages with no ETX or delimiting character. I think this is the first time I've run across this, and it makes for an interesting exercise.

    If anyone needs help with Pelco, I think I might be able to help out now :)

    --John
  • If anyone needs help with Pelco, I think I might be able to help out now :)

    Hello John,

    yes, i think i need help with Pelco-D. I want to control a camera with a NI2100. The comport is set to 2400 baud,N,8,1 485 enable. Pin 1 is strapped to 9 (RS485 A) and pin 4 is strapped to 6 (RS485 B). I only need to control the zoom, no feedback needed.
    The string for zoom tele should be "$FF,$01,$00,$20,$00,$00,$21", zoom wide should be "$FF,$01,$00,$40,$00,$00,$41".
    When i send this, nothing happens.
    To find the error i got a cameracontroller wich supports pelco-D. All zoom functions work fine with this. I read the strings from the controller to the camera, for zoom tele i found this in my buffer: "$00,$7F,$7E,$FE,$FE,$7A,$00".
    This is totally different to my string and to the Pelco-D protocol, but it works! When i send the same, nothing works.

    Any Idea???

    Thanks for your help.
  • DHawthorneDHawthorne Posts: 4,584
    I'd parse it byte-by-byte. Build a temporary string, and add each byte to it as it comes in, then generate a checksum. As soon as a byte comes in that matches my checksum, I know I have the whole thing. The problem with that would be if there really is an error and the checksum never matches ... however, I've found that modern serial chips rarely have such errors. In such cases you would have to throw the whole thing out once it reaches a certain length beyond what is possible.
  • SendString wrote: »
    The comport is set to 2400 baud,N,8,1 485 enable. Pin 1 is strapped to 9 (RS485 A) and pin 4 is strapped to 6 (RS485 B).
    It looks like a cabling issue as far as I see. The protocol and wiring is actually RS422.

    I don't have my notes on the cabling with me but if I recall correctly the cabling was like this:

    Netlinx Master.................Camera
    RX - (Pin 1)...................TX -
    TX + (Pin 4)...................RX+
    GND (Pin 5)....................GND
    RX+ (Pin 6)....................TX+
    TX- (Pin 9)....................RX-

    Your command string for zoom is correct, I'm not sure what the string was that you pulled into the buffer but it actually looks like a response string. I don't have time to confirm it right now though. I would change the port initialization string to:
    DATA_EVENT[dvPTZCamera]
    {
      ONLINE:
      {
    	 SEND_COMMAND dvPTZCamera,'SET BAUD 2400,N,8,1 485 Disable'
      }
    }
    

    I'm willing to share the module I wrote a little later if anyone would like it... but there may be no comments on my programming style :).




    --John
Sign In or Register to comment.