Home AMX User Forum NetLinx Studio

Creating a Transmit Queue

Greetings,

I need to queue my commands to a slow serial device. I knew that sooner or later I would run into this.

Are there any generic methods for this? All of my commands end with a CR, so picking them from an outgoing buffer should be simple.

Thank you.

Comments

  • jjamesjjames Posts: 2,908
    How about something along the lines of:
    DATA_EVENT[vdvSERIAL]	// VIRTUAL DEVICE
    {
        COMMAND:
        {
            LOCAL_VAR BUFFER[100]
            STACK_VAR REPLY[100]
            WHILE (FIND_STRING (DATA.TEXT,"13",1))
            {
                Reply = "Buffer, REMOVE_STRING (DATA.TEXT,"13",1)"
                CLEAR_BUFFER Buffer
    			WAIT_UNTIL(RESPONSE='ACCEPTED') // SOMETHING TO SAY IT'S GOOD TO SEND A COMMAND
    				SEND_STRING dvREAL_DEVICE,"Reply,13"
            }
            Buffer = "Buffer,DATA.TEXT"
        }
    }
    
    
    BUTTON_EVENT[dvTP,1]
    {
    	PUSH:
    		SEND_COMMAND vdvSERIAL,"'COMMAND',13"
    }
    

    The logic should be there, but it's late and I'm programming off the top of my head. Need brain food (Taco Bell!!!)
  • YuriyYuriy Posts: 20
    I do it so:
    DEFINE_CONSTANT
    
    tlHandleQueue    = 1000
    
    DEFINE_VARIABLE 
    
    VOLATILE long SendRate[]        = {2000}   // 2 second 
    
    VOLATILE char cBuffer[200]     = ''      
    VOLATILE char cQueue[200]     = '' 
    
    DEFINE_CALL 'Add to Queue' (char cCmd[10])
    {
      cQueue = "cQueue,cCmd,$0D"
    }
    
    DEFINE_CALL 'Send' (char cCmd[10])
    {
      SEND_STRING dvDEV,"cCmd"
    }
    
    DEFINE_START
    
    CREATE_BUFFER dvDEV,cBuffer
    
    TIMELINE_CREAT (tlHandleQueue,SendRate,1,TIMELINE_RELATIVE,TIMELINE_REPEAT)
    
    DEFINE_EVENT
    
    TIMELINE_EVENT[tlHandleQueue] 
    {
      IF (LENGTH_STRING(cQueue))
      {
        STACK_VAR char cCmd[10]
        
        cCmd = REMOVE_STRING(cQueue,"$0D",1)
        CALL 'Send' (cCmd)
      }  
    }
    
    DATA_EVENT[vdvDEV]
    {
      COMMAND:
      {
        STACK_VAR char cCMD[100]
        STACK_VAR integer nFunc
        
        IF(FIND_STRING(DATA.TEXT,'=',1)) 
          cCMD = REMOVE_STRING(DATA.TEXT,'=',1)         
        ELSE 
          cCMD = DATA.TEXT      
        SWITCH(cCMD)
        {
          CASE 'POWER=':
          {
    	nFunc = ATOI(DATA.TEXT)
    	IF (nFunc = 1)
    	  CALL 'Add to Queue' ("$43,$30,$30")
    	ELSE
    	{
    	  CALL 'Add to Queue' ("$43,$30,$31")
    	}
    	CALL 'Add to Queue' ("$43,$52,$30")
    	BREAK 
          }
          CASE 'STATUS?':
          {
    	CALL 'Add to Queue' ("$43,$52,$30")
    	BREAK 
          }      
        }
      } 
    }
    
  • adysadys Posts: 395
    Yuriy wrote:
    I do it so:
    DEFINE_CONSTANT
    
    tlHandleQueue    = 1000
    
    DEFINE_VARIABLE 
    
    VOLATILE long SendRate[]        = {2000}   // 2 second 
    
    VOLATILE char cBuffer[200]     = ''      
    VOLATILE char cQueue[200]     = '' 
    
    DEFINE_CALL 'Add to Queue' (char cCmd[10])
    {
      cQueue = "cQueue,cCmd,$0D"
    }
    
    DEFINE_CALL 'Send' (char cCmd[10])
    {
      SEND_STRING dvDEV,"cCmd"
    }
    
    DEFINE_START
    
    CREATE_BUFFER dvDEV,cBuffer
    
    TIMELINE_CREAT (tlHandleQueue,SendRate,1,TIMELINE_RELATIVE,TIMELINE_REPEAT)
    
    DEFINE_EVENT
    
    TIMELINE_EVENT[tlHandleQueue] 
    {
      IF (LENGTH_STRING(cQueue))
      {
        STACK_VAR char cCmd[10]
        
        cCmd = REMOVE_STRING(cQueue,"$0D",1)
        CALL 'Send' (cCmd)
      }  
    }
    
    DATA_EVENT[vdvDEV]
    {
      COMMAND:
      {
        STACK_VAR char cCMD[100]
        STACK_VAR integer nFunc
        
        IF(FIND_STRING(DATA.TEXT,'=',1)) 
          cCMD = REMOVE_STRING(DATA.TEXT,'=',1)         
        ELSE 
          cCMD = DATA.TEXT      
        SWITCH(cCMD)
        {
          CASE 'POWER=':
          {
    	nFunc = ATOI(DATA.TEXT)
    	IF (nFunc = 1)
    	  CALL 'Add to Queue' ("$43,$30,$30")
    	ELSE
    	{
    	  CALL 'Add to Queue' ("$43,$30,$31")
    	}
    	CALL 'Add to Queue' ("$43,$52,$30")
    	BREAK 
          }
          CASE 'STATUS?':
          {
    	CALL 'Add to Queue' ("$43,$52,$30")
    	BREAK 
          }      
        }
      } 
    }
    


    I know its an old post, but I like this nice simple and elegant way to handle a queue.

    thanks for sharing.
  • YuriyYuriy Posts: 20
    Excellent example of programming of queue from Jeff Coffler
  • AMXJeffAMXJeff Posts: 450
    Queue.axi
    PROGRAM_NAME='Queue'
    (***********************************************************)
    (* System Type : NetLinx                                   *)
    (***********************************************************)
    (* REV HISTORY:                                            *)
    (***********************************************************)
    
    (***********************************************************)
    (*               CONSTANT DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_CONSTANT
    
    // MAX STUFF
    
    #IF_NOT_DEFINED MAX_CMD_LENGTH
    MAX_CMD_LENGTH  				= 50;
    #END_IF
    
    #IF_NOT_DEFINED MAX_QUEUE_ITEMS
    MAX_QUEUE_ITEMS					= 4;
    #END_IF
    (***********************************************************)
    (*              DATA TYPE DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_TYPE
    
    STRUCTURE _QUEUE
    {
    	CHAR cQueue[MAX_QUEUE_ITEMS][MAX_CMD_LENGTH];
    	CHAR cLastCommandSent[MAX_CMD_LENGTH];
    	CHAR cQueueHead;
    	CHAR cQueueTail;
    	CHAR cQueueBusy;
    	CHAR cQueueHasItems;
    	CHAR cQueueReady;
    }
    
    (***********************************************************)
    (*               LATCHING DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_LATCHING
    
    (***********************************************************)
    (*       MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW           *)
    (***********************************************************)
    DEFINE_MUTUALLY_EXCLUSIVE
    
    (***********************************************************)
    (*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
    (***********************************************************)
    (**************************************)
    (* Call Name: PushQueue               *)
    (* Function: Adds comamnd to the queue*)
    (* Return:   n/a 				 					    *)
    (**************************************)	
    DEFINE_FUNCTION ENQueue(_QUEUE uQueue,Char cCmd[])
    {    
      IF (uQueue.cQueueHead = MAX_LENGTH_ARRAY(uQueue.cQueue))
      {
        IF (uQueue.cQueueTail <> 1)
        {
          uQueue.cQueueHead = 1;
          uQueue.cQueue[uQueue.cQueueHead] = cCmd;
          ON[uQueue.cQueueHasItems];
        }
      }
      ELSE IF (uQueue.cQueueTail <> uQueue.cQueueHead + 1)
      {
        uQueue.cQueueHead++;
        uQueue.cQueue[uQueue.cQueueHead] = cCmd;
        ON[uQueue.cQueueHasItems];
      }
    }
    
    (**************************************)
    (* Call Name: PopQueue                *)
    (* Function: Removes from the queue   *)
    (* Return:   CHAR[]			 					    *)
    (**************************************)			
    DEFINE_FUNCTION CHAR[MAX_CMD_LENGTH] DEQueue(_QUEUE uQueue)
    {    
      IF (GetQueueReady(uQueue) == TRUE)
      {
    		SetQueueReady(uQueue,FALSE);
    		
        IF (uQueue.cQueueTail = MAX_LENGTH_ARRAY(uQueue.cQueue))
          uQueue.cQueueTail = 1;
        ELSE
          uQueue.cQueueTail++;
    			
        IF (uQueue.cQueueTail = uQueue.cQueueHead)
          OFF[uQueue.cQueueHasItems];
    		
    		uQueue.cLastCommandSent = uQueue.cQueue[uQueue.cQueueTail];
    		
    		RETURN uQueue.cLastCommandSent;
      }
    }
    
    (**************************************)
    (* Call Name: PeekQueue               *)
    (* Function: Shows Item from the queue*)
    (* Return:   CHAR[] 		 					    *)
    (**************************************)	
    DEFINE_FUNCTION CHAR[MAX_CMD_LENGTH] PeekQueue(_QUEUE uQueue)
    {    
    	STACK_VAR INTEGER nLastTail;
    	 
    	nLastTail = uQueue.cQueueTail
    	 
      IF (nLastTail = MAX_LENGTH_ARRAY(uQueue.cQueue))
    		nLastTail = 1
    	ELSE
    		nLastTail = nLastTail + 1
    		    
    	RETURN uQueue.cQueue[nLastTail];
    }
    
    (**************************************)
    (* Call Name: ForceQueueReady         *)
    (* Function: Forces Queue Ready       *)
    (* Return:   n/a 				 					    *)
    (**************************************)	
    DEFINE_FUNCTION SetQueueReady(_QUEUE uQueue,CHAR bBool)
    {    
    	IF (bBool == TRUE)
    	{
    		ON[uQueue.cQueueReady];
    		OFF[uQueue.cQueueBusy];
    	}	
    	ELSE	
    	{
    		OFF[uQueue.cQueueReady];
    		ON[uQueue.cQueueBusy];
    	}	
    }
    
    (**************************************)
    (* Call Name: InitQueue					      *)
    (* Function: Setup Queue				      *)
    (* Return:   n/a 				 					    *)
    (**************************************)	
    DEFINE_FUNCTION InitQueue(_QUEUE uQueue)
    {    
    	uQueue.cQueueHead  = 1;
    	uQueue.cQueueTail  = 1;
    	uQueue.cQueueBusy  = FALSE;
    	uQueue.cQueueReady = TRUE;
    }
    
    (**************************************)
    (* Call Name: GetQueueReady         	*)
    (* Function: Forces Queue Ready       *)
    (* Return:   n/a 				 					    *)
    (**************************************)	
    DEFINE_FUNCTION CHAR GetQueueReady(_QUEUE uQueue)
    {    
    	IF (uQueue.cQueueHasItems && uQueue.cQueueBusy == FALSE)
    		RETURN TRUE;
    	ELSE
    		RETURN FALSE;
    }
    
    (**************************************)
    (* Call Name: GetQueueEmpty         	*)
    (* Function: Test if Queue is Empty   *)
    (* Return:   n/a 				 					    *)
    (**************************************)	
    DEFINE_FUNCTION CHAR GetQueueEmpty(_QUEUE uQueue)
    {    
    	IF (uQueue.cQueueHasItems == FALSE)
    		RETURN TRUE;
    	ELSE
    		RETURN FALSE;
    }
    
    
  • jjamesjjames Posts: 2,908
    Like they say - many ways to skin a cat. I like to keep it simple with a timeline that checks a simple flag. I've not had a problem with it so far . . . ;)
  • AMXJeffAMXJeff Posts: 450
    Queue

    Nothing wrong with your example. Just a include file we use here at AMX full of helper functions. I thought it would be helpful...
  • jjamesjjames Posts: 2,908
    No no - I wasn't pickin' on yours or anything - lol. I'm sure it works wonders, and probably is great. I was just stating that I prefer to keep things simple. I may throw it in with some of my code to try it out - heck, I'm sure it'll be more slick than mine. I wasn't trying to bash yours or anything. :D Truly.

    BTW - the above example that I had - certainly not what I use now.
Sign In or Register to comment.