Home AMX General Discussion

Module command handler buffer problem?

maxifoxmaxifox Junior MemberPosts: 209
I have a module that process' strings inside command (not string!) handler.

When I send a command (via send_command) the command handler is fired but there is nothing inside the buffer to parse and array length is zero.

Looks like buffers created with "create_buffer" keeps only strings sent with send_string (?):

I issued send_command dev, "com" and got
Line      1 :: GOT COMMAND:  - 11:16:01

Then I issued send_string dev, "str" and got
Line      2 :: GOT STRING: str - 11:16:11

finally send_command dev, "com2"
Line      3 :: GOT COMMAND: str - 11:16:20

Is that behavior normal that I cannot use buffers with create_buffer for command handler? I would like to use the technic described in TN616 for command handlers as well...

Here is the master code:
PROGRAM_NAME='master_test'

DEFINE_DEVICE

vdv = 33001:1:0;

DEFINE_START

DEFINE_MODULE 'mtest' mdl_test(vdv);

DEFINE_PROGRAM

and module code
MODULE_NAME='mtest'(dev ddd)

DEFINE_VARIABLE

char buf[128];

DEFINE_EVENT

DATA_EVENT[ddd] {
	COMMAND : {
		SEND_STRING 0, "'GOT COMMAND: ', buf";
	}
	STRING : {
		SEND_STRING 0, "'GOT STRING: ', buf";
	}
}

DEFINE_START

CREATE_BUFFER ddd, buf;

DEFINE_PROGRAM


I am running NI-4000 v3.00.316, Netlinx Studio build 2.4.0.123.
Thanks in advance.

Comments

  • ldeblank@jnv.nl[email protected] Junior Member Posts: 58
    command

    Hello maxifox,

    I never use create buffer but alway's date.text. See sample below:

    DATA_EVENT[dev]
    {
    COMMAND:
    {
    IF(FIND_STRING(DATA.TEXT,'com',1))
    {
    SEND_STRING 0,"DATA.TEXT"
    }
    }
    }
    Works well for me.
    Hopes it is usefull for you
  • Marc ScheibeinMarc Scheibein Junior Member Posts: 669
    A CREATE_BUFFER only can receive Strings.
    The Data on Command Level can only be received by DATA.TEXT.

    This works as designed. A COMMAND is always a complete instruction and is received in the DATA_EVENT handler at one step. This works because a COMMAND level instruction is an NetLinx internal handling and these type of data is always a full instruction.

    But with strings (like from serial port or ethernet) , you MAY have received a complete instruction, but this is not sure. So if working with serial ports or - much more critical - with data via TCP (where almost every character triggers a data event), you should use a CREATE_BUFFER to receive and store the user data. and then work with the buffer array. The DATA_EVENTs STRING handler in this case is more or less only a trigger to launch the buffer parsing.
    DEFINE_VARIABLE
    CHAR sVCR_BUFF[300]
    
    DEFINE_START
    CREATE_BUFFER dvVCR,sVCR_BUFF
    
    
    DEFINE_EVENT
    
    DATA_EVENT[dvVCR]
      {
      ONLINE:
        {
        // when serial device goes online, set its com parameters
        SEND_COMMAND dvVCR,'SET BAUD 9600,0,7,1'
        }
      STRING:
        {
        (* Panasonic strings are like "$02,'OPL',$03", "$02,'OSP',$03", etc *)
        (*
        This is the most common way to operate received data.
        When data was received, nromally the string handler is executed only one time, so
        it could take some time to parse a buffer.
        With the WHILE loop, the buffer will be serviced as long as the condition is true,
        Here: 5 Bytes are the minimum length of a response
        *)
        WHILE(LENGTH_STRING(sVCR_BUFF) >= 5) // shortest complete answer from VCR has 5 bytes
          {
          CALL 'DO PANASONIC'(sVCR_BUFF,nVCR_STATUS)
          }
        (*
        The condition for the WHILE depends on the controlled equipment.
        WARNING: in NetLinx, a WHILE doesn't have a timeout, so it's on you, to get a state
        where the WHILE condition is false.
        *)
        }
      }
    

    I hope this helps.

    Regards,
  • maxifoxmaxifox Junior Member Posts: 209
    Yes, DATA.TEXT works. I recall there is a discussion that it is still more safe to use buffers (what if the command will not fit DATA.TEXT default array size?). That is why I would like to use the same buffer technic as with string handlers...

    I agree the question is more theoretical than practical but what is going with the buffers for command handlers? Does it work?

    EDITED: Thank you, Marc. This is what I suspected - it is by design...
  • maxifox wrote:
    Yes, DATA.TEXT works. I recall there is a discussion that it is still more safe to use buffers (what if the command will not fit DATA.TEXT default array size?). That is why I would like to use the same buffer technic as with string handlers...

    I agree the question is more theoretical than practical but what is going with the buffers for command handlers? Does it work?

    EDITED: Thank you, Marc. This is what I suspected - it is by design...

    By design, a Send_Command payload has a maximum number of characters that should always fit into the DATA.TEXT default array size. And there is the advantage that it can be completely parsed in a single data event. I believe the maximum size of a Send_Command is approximately 2000 characters. Perhaps someone here knows the exact number.

    Keep in mind all you are doing is shuffling data between one memory location to another. No data enters or leaves the box as with a physical com port.
  • DHawthorneDHawthorne Junior Member Posts: 4,584
    You can always manage your own buffer. Create a CHAR array of the appropriate size; let's call it sBuffer[1024] for the sake of discussion. Then in your DATA event:
    DATA_EVENT [dvDevice] {
    COMMAND : {
    sBuffer = "sBuffer, DATA.TEXT" ; } }
    You can then treat sBuffer as you would a buffer created and maintained by CREATE_BUFFER.

    However, I've found that it's not necessary to buffer SEND_COMMANDs, at least not in any application where I've used them. As Marc said, the whole thing is going to be there, just by the nature of how they work in the first place.
  • maxifoxmaxifox Junior Member Posts: 209
    Thank you all very much for the input. Really learned a lot from the that.
  • jjamesjjames AMX Sustaining Engineer Posts: 2,901
    I believe the limit may be 2005 characters. I'm currently running into this problem with my XML Parser Module, and I'm trying to send around 3700 chars to the module, and I get this error:
    Line     12 :: SendTheMessage packet too large wCmd=1d3691d len=3776 src=3 - 10:01:25.957
    

    Not sure if this is certain though.
  • Marc ScheibeinMarc Scheibein Junior Member Posts: 669
    jjames wrote:
    I believe the limit may be 2005 characters. I'm currently running into this problem with my XML Parser Module, and I'm trying to send around 3700 chars to the module, and I get this error:
    Line     12 :: SendTheMessage packet too large wCmd=1d3691d len=3776 src=3 - 10:01:25.957
    

    Not sure if this is certain though.


    DATA.TEXT has a size of 2048 Characters.
    See definition in the NetLinx.AXI
    (*------------------------------------------------------------------------------------------------*)
    STRUCTURE TDATA
    {
      DEV      DEVICE;
      LONG     NUMBER;
      CHAR     TEXT[2048];
      CHAR     SOURCEIP[32];
      INTEGER  SOURCEPORT;
      DEV      SOURCEDEV;
    }
    

    The largest hardware buffers in NetLinx have 2048 bytes (NXI and NXC-COM2).

    On Ethernet, afaik the master has a larger hardware buffer, but still can only pick up 2048 bytes in one block to software. So like I recommended earlier in this thread, depending on the data awaited i.e. HTML or XML, I'll create a (HUGE (why not 30000 bytes) ;)) software buffer with CREATE_BUFFER for Ethernet handling.
Sign In or Register to comment.