Home AMX User Forum AMX General Discussion

help with conditional statement

I'm a newbie and I new some help to understand how to parse info from the device and use that info in a conditional stament. I'm working on a project right now where I need to now the input status of the display and change it to either the Tuner A for cable and the cameras modulated from channel 102 to 122 and Input 1 which is the component input. This is what I got and I would like to know if I'm in the right direction.

With the help of Danny which is a member of this forum that had help me to learn a lot I got this data event to get a variable(nTVInput) to track the input state of the TV.
DATA_EVENT[vdvTV]
{
    STRING:
    {
        STACK_VAR char sName[32]                                                // a temporary variable that only exists for the life of the data_event

                       
        sName = REMOVE_STRING (DATA.TEXT,'=',1)                        // assumes the command comes back as command=value, pulls off the command= and just leaves

                                                                                                    // the value in DATA.TEXT
        SWITCH (sName) 
        {
            CASE 'ASPECT=' :            
            {
                nTVAspect = ATOI(DATA.TEXT) 
            }

                        
            CASE 'INPUT=' :
            {
                nTVInput = ATOI(DATA.TEXT) 
            }
            
            CASE 'POWER=' :
            {
                nTVPower = ATOI(DATA.TEXT)
            }

 

       }   

}

Then, If I were to use the value of nTVInput and nTVPower to track the status of the TV when I want to go to the camera in Channel 104 of the TV; I would have a Button Event to do something like this.
if (nTVPower)                                         // Power On

 {

     If (nTVInput = " 'Input-InpA,1' " )                // go to Tuner A

     {

        send_command vdvTV," 'XCH-104' "      // Gate camera

        else

        {

          send_command vdvTV, 'INPUT-INPA,1'  // TV to Tuner A

          wait 40

          {

             send_command vdvTV," 'XCH-104' "      // Send TV to Channel 104

          }

      }

   }

 else

  {

     pulse[vdvTV,27]                                   //Turn TV On. Of course I could have done another If statement after I Power Up the TV to find out in which input is at
     wait 50

     {

       send_command vdvTV, 'INPUT-INPA,1'                       //go to Tuner A 
        wait 40

        {
          send_command vdvTV,"'XCH-104'"                           //Gate Camera

        }

      }

   }

Am I in the right track here?

Comments

  • NMarkRobertsNMarkRoberts Posts: 455
    sName = REMOVE_STRING (DATA.TEXT,'=',1)
    

    My instinct would be to copy data.text into a local variable before manipulating it like that. data.text is voodoo and best not messed with.

    You can't be absolutely sure that you have the whole input string, or only one input string, so it's best to buffer data.text and search for string terminators:
    data_event[dDevice]                                               
      {
      string:
        {            
        sBufferedReply = "sBufferedReply,data.text"
        HandleIncomingString()
        } 
    
    define_function HandleIncomingString   ()
    {                           
    stack_var char    sMyReply[100]
    
    while (find_string(sBufferedReply,"sTerminator",1))
      {
      sMyReply = remove_string(sBufferedReply,"sTerminator",1)
      ParseReply(sMyReply)
      }
    }
    

    The TV handling code appears to mix application-layer (what do I want the user to experience) with device-driver (how do I turn on the TV). It would be normal practice to separate those two chunks of code in different modules.

    Your "wait 40" looks fairly arbitrary - it's better to wait for the ACK that all serial-controlled devices give, and then send the next command.

    I wonder why your output command is upper case and the reply is not.

    The tracking of TV state is a good approach but the industrial-strength way is to do it like this:
    define_function ReviewTVState()
    {
    if (ReportedPowerState <> RequestedPowerState)
      {
      if (RequestedPowerState = PowerStateOn)
        {
        QueueCommand(PowerOn)
        }
      else
        {
        QueueCommand(PowerOff)
        }
      return;
      }
    
    if (ReportedPowerState = PowerStateOff)
      {
      (* Nothing else we can do *)
      return;
      }
    
    if (ReportedInputState <> RequestedInputState)
      {
      // etc
      return;
      }
    }
    

    Call ReviewTVState only when there is nothing in the command queue and you've received the ACK from the last command.

    The advantage of this approach is that you can change requested state anywhere in your code without having to think about timing. So for instance, if the user selects a source then changes his mind and switches off, the issued command sequence will be

    power on - power off

    instead of

    power on - input select - power off

    or worse

    power on - input select - what was I supposed to do next?

    This is particularly important for things that take a long time to power up or need to be told a lot of stuff to do.
  • mpullinmpullin Posts: 949
    My instinct would be to copy data.text into a local variable before manipulating it like that. data.text is voodoo and best not messed with.

    You can't be absolutely sure that you have the whole input string, or only one input string, so it's best to buffer data.text and search for string terminators:
    If you're dealing with a module's virtual device, as I assume he is based on the name vdvTV, then you can be fairly sure each DATA event will give you an entire string - assuming the module was written decently.

    In dealing with DATA.TEXT, you should be careful not to throw away information you'll need later. But I think it's fine to use DATA.TEXT, in fact I usually do SWITCH(REMOVE_STRING(DATA.TEXT,'=',1)){ case 'POWER=': //etc } without an intermediary variable.

    Dealing with direct output from devices is a different animal. You have no idea what you're getting in each handful. It's like putting your hand into a cookie jar (serial port), as opposed to putting your hand into a package of cookies (virtual device). You should really build a buffer, and parse the buffer every once and a while looking for complete strings (see the previous post).
  • flcusatflcusat Posts: 309
    Ok, here is the issue I'm having right now. The info retrieved from the data.text it is not valid for the conditional statement. If I send a command to the module in this form:
    send_command vdvtv, "'INPUT-INPUT,1'"
    
    

    the display changes to the Input 1 without a problem. However in the diagnostics I'm getting back this:
    Line      4 :: Command To [41001:1:1]-[INPUT-INPUT,1'] - 08:03:14
    Line      5 :: Command From [41001:1:1]-[INPUT-INPUT,1'] - 08:03:14
    Line      6 :: Command From [41001:1:1]-[UNKNOWN-INPUT-INPUT,1'] - 08:03:14
    
    

    Also, in the diagnostic options I have all of them checked but notice that there is not string from the device returned either.
  • NMarkRobertsNMarkRoberts Posts: 455
    You state that the device itself is not replying and yet the input change happens.

    Have you watched the input LEDs just to be sure?

    Have you tried connecting directly from a PC and talking to it with a terminal emulator?

    You may have a cable fault preventing the reply getting through, try a different cable.

    The lack of a reply may explain why the module is giving you an "UNKNOWN" message.

    Your fallback would be to ignore the replies from the module and just trust it to send the commands and get no reply.

    Have you considered writing your own module? Try watching the strings sent to the device and ask yourself how hard it would be to send those yourself.
  • flcusatflcusat Posts: 309
    You state that the device itself is not replying and yet the input change happens.

    Have you watched the input LEDs just to be sure?

    Have you tried connecting directly from a PC and talking to it with a terminal emulator?

    You may have a cable fault preventing the reply getting through, try a different cable.

    The lack of a reply may explain why the module is giving you an "UNKNOWN" message.

    Your fallback would be to ignore the replies from the module and just trust it to send the commands and get no reply.

    Have you considered writing your own module? Try watching the strings sent to the device and ask yourself how hard it would be to send those yourself.

    Thanks for your input. I will check in all of your suggestion and get back with the answers but regarding the last one, I wish I could but I'm not capable yet to do so; just yet.
  • flcusatflcusat Posts: 309
    You state that the device itself is not replying and yet the input change happens.

    Have you watched the input LEDs just to be sure?

    Have you tried connecting directly from a PC and talking to it with a terminal emulator?

    You may have a cable fault preventing the reply getting through, try a different cable.

    The lack of a reply may explain why the module is giving you an "UNKNOWN" message.

    Your fallback would be to ignore the replies from the module and just trust it to send the commands and get no reply.

    Have you considered writing your own module? Try watching the strings sent to the device and ask yourself how hard it would be to send those yourself.

    OK, I tried sending commands from telnet and also from the TP in both cases I can see the lights from the display answering back to the controller so the problem is not due to a bad cable. It has to be something in the module itself.
  • TonyAngeloTonyAngelo Posts: 315
    Do you have notifications set for the device or just the virtual device. If you want to see the strings that the device is sending you have to turn on the Device Notification options for the serial port the device is plugged into, the module won't show you these unless you send it a passback command.
  • TonyAngeloTonyAngelo Posts: 315
    flcusat wrote:
    OK, I tried sending commands from telnet and also from the TP in both cases I can see the lights from the display answering back to the controller so the problem is not due to a bad cable. It has to be something in the module itself.

    I've had modules that didn't work for any number of reasons, because they were sending the wrong baud rate to the port for instance. It didn't seem like that big of a deal to just send the correct baud rate except for the fact that the module would just randomly send the config info back to the port.

    My advice when dealing with modules is to test them out before spending too much time trying to make them work in your source code. The zip file should have a UI module and a source code that you can use with just the device to check it out.
  • flcusatflcusat Posts: 309
    TonyAngelo wrote:
    Do you have notifications set for the device or just the virtual device. If you want to see the strings that the device is sending you have to turn on the Device Notification options for the serial port the device is plugged into, the module won't show you these unless you send it a passback command.

    Tony, I had both notifications for the virtual device and the actual device and all of the options were checked for both of them.
  • flcusatflcusat Posts: 309
    TonyAngelo wrote:
    I've had modules that didn't work for any number of reasons, because they were sending the wrong baud rate to the port for instance. It didn't seem like that big of a deal to just send the correct baud rate except for the fact that the module would just randomly send the config info back to the port.

    My advice when dealing with modules is to test them out before spending too much time trying to make them work in your source code. The zip file should have a UI module and a source code that you can use with just the device to check it out.

    OK Tony, Let me start from the end first. Yes, I tried the module alone first and it worked rigth.
    Now, to the first part. The module is executing properly any commands I need; the problem that I'm having is trying to retrieve the status of the input. The way the actual module works for this is using a couple of variables which by the way goes way over my head:
    data_event[vdvDev]
    {
    	command:
    	{
    		if (find_string(data.text, '-', 1))
    		{
    			stack_var integer x
    			stack_var integer nTempDev
    			stack_var char sCmd[6]
    			
    			for (x = 1; x <= length_array(vdvDev); x++)
    			{
    				if (vdvDev[x] == data.device)
    				{
    					nTempDev = x
    					break
    				}
    			}
    			
    			sCmd = remove_string(data.text, '-', 1)
    			
    			switch (sCmd)
    			{
    				case 'INPUT-' :
    				{
    					sInputStore[nTempDev] = upper_string(data.text)
    					
    					if (nTempDev == nCurrOut)
    					{
    						if (find_string(sInputStore[nTempDev], 'INVALID', 1))
    						{
    							sInputStore[nTempDev] = 'Unknown Input'
    						}
    						send_command dvTP, "'^TXT-',itoa(nVTButtons[1]),',0,',sInputStore[nCurrOut]"
    						
    						for (x = 1; x <= nInputCount; x++)
    						{
    							[dvTP, nInputBtns[x]] = (sInputStore[nCurrOut] == sInputLabels[x])
    						}
    					}
    				}
    				case 'DEBUG-' :
    				{
    					nDbg = atoi(data.text)
    				}
    			}
    		}
    	}
    }
    
    button_event[dvTP, nOutputBtns]
    {
    	push:
    	{
    		stack_var integer x
    		nCurrOut = get_last(nOutputBtns)
    		send_command dvTP, "'^TXT-',itoa(nVTButtons[1]),',0,',sInputStore[nCurrOut]"
    		
    		for (x = 1; x <= nOutputCount; x++)
    		{
    			if (fnFBLookup(nOutputBtns[x]))
    			{
    				[dvTP, nOutputBtns[x]] = (nCurrOut == x)
    			}
    		}
    		
    		for (x = 1; x <= nInputCount; x++)
    		{
    			[dvTP, nInputBtns[x]] = (sInputStore[nCurrOut] == sInputLabels[x])
    		}
    	}
    }
    
    button_event[dvTP, nButtons]
    {
    	push:
    	{
    		stack_var integer nBtn
    		nBtn = get_last(nButtons)
    		
    		switch (nBtn)
    		{
    			case 1 :	// Cycle Input Source
    			{
    				pulse[vdvDev[nCurrOut], SOURCE_CYCLE]
    				fPrintf("'pulse[',dpstoa(vdvDev[nCurrOut]),', ',itoa(SOURCE_CYCLE),']'")
    			}
    			case 2 :	// Query Input Source
    			{
    				send_command vdvDev[nCurrOut], "'?INPUT'"
    				fPrintf("'send_command ',dpstoa(vdvDev[nCurrOut]),', ',39,'?INPUT',39")
    			}
    		}
    	}
    }
    
    button_event[dvTP, nInputBtns]
    {
    	push:
    	{
    		stack_var integer nBtn
    		stack_var integer x
    		nBtn = get_last(nInputBtns)
    		
    		sInputStore[nCurrOut] = sInputLabels[nBtn]
    		send_command vdvDev[nCurrOut], "'INPUT-',sInputLabels[nBtn]"
    		fPrintf("'send_command ',dpstoa(vdvDev[nCurrOut]),', ',39,'INPUT-',sInputLabels[nBtn],39")
    		send_command dvTP, "'^TXT-',itoa(nVTButtons[1]),',0,',sInputStore[nCurrOut]"
    		
    		for (x = 1; x <= nInputCount; x++)
    		{
    			[dvTP, nInputBtns[x]] = (sInputStore[nCurrOut] == sInputLabels[x])
    		}
    	}
    }
    

    Here is what I tried:
    DATA_EVENT[vdvTV]
    {
        
        STRING:
        {
            STACK_VAR char sName[32]                  // a temporary varible that only exists for the life of the data_event
    
    	SEND_STRING 0,"'TV STRING=',DATA.TEXT"
    	
            sName = REMOVE_STRING (DATA.TEXT,'-',1)   // assumes the command comes back as command-value, pulls off the command= and just leaves
    
    						  // the value in DATA.TEXT
            SWITCH (sName) 
            {
                CASE 'ASPECT-' :            
                {
                    sTVAspect =DATA.TEXT              // will contain DOT_BY_DOT, NORMAL, FULL, ZOOM, CINEMA, WIDESCREEN, or FULL2
                }
    
                            
                CASE 'INPUT-' :
                {
    
                    sTVInput = REMOVE_STRING (DATA.TEXT,',',1)    // removes everything left in data text up to and including the ,
    
                    SET_LENGTH_STRING (sTVInput, LENGTH_STRING(sTVInput) - 1)  // reduces length of sTVInput by 1, eliminating the ,
    
    									   // sTVInput will now contain INPUT, COMPUTER, INPA, INPB or ILINK
    
    
                    nTVInput = ATOI(DATA.TEXT)                                  // will contain 1, 2, 3, or 4
                }
    	}
        }   
    }
    
    

    Now for some reason the value that nTVInput is getting is not a good value. When I send a send_command vdvtv, "'INPUT-INPUT,1'"( change to input 1), or any other change input command this is what I get on the diagnostics:
    Line      1 :: Command To [41001:1:1]-[input-input,2'] - 08:02:38
    Line      2 :: Command From [41001:1:1]-[input-input,2'] - 08:02:38
    Line      3 :: Command From [41001:1:1]-[UNKNOWN-input-input,2'] - 08:02:38
    Line      4 :: Command To [41001:1:1]-[INPUT-INPUT,1'] - 08:03:14
    Line      5 :: Command From [41001:1:1]-[INPUT-INPUT,1'] - 08:03:14
    Line      6 :: Command From [41001:1:1]-[UNKNOWN-INPUT-INPUT,1'] - 08:03:14
    Line      7 :: Command To [41001:1:1]-[INPUT-INPA,1] - 08:04:31
    Line      8 :: Command From [41001:1:1]-[INPUT-INPA,1] - 08:04:31
    Line      9 :: Command From [41001:1:1]-[UNKNOWN-INPUT-INPA,1] - 08:04:31
    Line     10 :: Command From [41001:1:1]-[INPUT-INPA,1] - 08:04:31
    Line     11 :: Command From [41001:1:1]-[XCH-] - 08:04:31
    
    

    Remember that I'm a newbie that have only been to programer I, so my experience is very limited. All kind of suggestions that my look pretty obvious to you, are more than welcome.
  • TonyAngeloTonyAngelo Posts: 315
    Try putting DATA.TEXT into a global variable that you can look at in the debug window to make sure that you're getting info. My suspicion is that this code needs to go under COMMAND in the DATA_EVENT, not STRING.
Sign In or Register to comment.