Home AMX User Forum NetLinx Studio

Question About Writing Modules

Greetings,

When writing a comm module, how do you get a string to come from the virtual device back to your main program?

For example, the physical device spits out a string saying that its power is on. How can the module say to the main program "POWER=1"

Thanks.

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    When writing a comm module, how do you get a string to come from the virtual device back to your main program?
    You do a SEND_STRING to the virtual device that was passed in by the main program to your module.

    Main Program
    DEFINE_DEVICE
    
    dvReceiver	= 5001:1:0	//RS-232 Port 1
    vdvReceiver	= 33001:1:0	//Virtual device for receiver
    
    DEFINE_MODULE 'TestModule' mdlTest(vdvReceiver,dvReceiver)
    
    DEFINE_EVENT
    
    DATA_EVENT[vdvReceiver] {
    
       STRING: {
          IF(DATA.TEXT = ?POWER=1?) {
    	 SEND_STRING 0, 'Comm module told me that power is on'
          }
       }
       
    }
    


    Module Code
    MODULE_NAME='TestModule' (DEV vdvRecvr, DEV dvRecvr)
    
    DEFINE_EVENT
    
    DATA_EVENT[dvRecvr] {
    
       ONLINE: {
          //set baud rate
       }
       
       STRING: {
          //if the real device tells us that power is on
          //then we'll tell the main program by sending
          //a string to the virtual device
          IF(DATA.TEXT = ?'[PON]'") {
    	 SEND_STRING vdvRecvr, 'POWER=1'
          }
       
       }
       
    }
    

    HTH
  • vincenvincen Posts: 526
    You can also if it's just some simple states, declare a common virtual device between main program and module and you change states of channels of virtual device to pass simple infos between main and module programs ;)

    Vinc
  • TurnipTruckTurnipTruck Posts: 1,485
    Joe Hebert wrote:
    You do a SEND_STRING to the virtual device that was passed in by the main program to your module.

    Thank you. That's simple enough!
  • DHawthorneDHawthorne Posts: 4,584
    It's a good habit to use SEND_COMMAND to send instruction to your virtual device, and then used SEND_STRING for feedback from the virtual. The work the exact same way, but SEND_COMMAND uses the COMMAND handler to "catch" the instruction instead of STRING. You could use just SEND_STRING, but then you have to include something in the syntax where it originated, and since AMX nicely gave us two separate handlers for that purpose, it's convenient to use them that way.
  • TurnipTruckTurnipTruck Posts: 1,485
    DHawthorne wrote:
    You could use just SEND_STRING, but then you have to include something in the syntax where it originated

    What kind of something are you referring to? I'm thinking you mean a flag to determine which way the string is going, but I don't see why that would be necessary.
  • TurnipTruckTurnipTruck Posts: 1,485
    What about variables? Can the same variable name be declared in a module as in the program that runs the module?
  • Spire_JeffSpire_Jeff Posts: 1,917
    What about variables? Can the same variable name be declared in a module as in the program that runs the module?

    As I understand it, the module variables have a module indentifier automatically added to the variables so that there is no interference between the main program and the module (or even between multiple instances of the same module). If I had to speculate, I would guess that this addition is based on the Instance Name you provide when you declare the module (hence the instance name needing to be different for each module).

    As for why you would need an identifier on the SEND_STRING command if you were using it for control and feedback, an event would be generated in both the main and module for the string event regardless of who sent it. By not seperating the flow of commands and feedback, you have to be conscious of possible false postives when handling the events in the main and the module. You will also be processing the information twice and it will add to overhead. If the module only monitors the COMMAND: portion of the event, and the main only monitors the STRING: portion of the event, the code is only being run when necessary.

    I think I typed what I am thinking, but feel free to ask for clarification. I'm also sure that someone out there has more details than I, and will probably correct something I typed.

    Jeff

    P.S.
    The new Java modules use COMMAND for both sending and receiving in some of the modules I have used. This does not seem to have the same problem because the Java modules seem to have more intimate control over events being generated in the netlinx portion of code. (This is only my interpretation and not based on any tech docs :) )
  • What about variables? Can the same variable name be declared in a module as in the program that runs the module?
    Yes. The module will not affect any variable, constant, Timeline, etc with same names or IDs outside. You can also use the same module in multiple instances without any influences between them, if the module is designed for that. The only parameters which are variable are the parameters you optionally can pass thru the module call (in most cases this is a virtual and the physical device like in the common control modules for projectors, players, etc).
    This is one of the biggest advantages of the modules against System_Calls.

    One word to differencing COMMAND and STRING level for modules.
    The problem is that you'll get echoed back your commands and strings if sending them into a virtual device. So if you have a DATA_EVENT..COMMAND or STRING inside AND outside the module on the same virtual device, in worst case your system locks up.
    You can see this for example if you do device notification on a virtual device and check STRING FROM and STRING TO for it, and then send a string to the virtual device.

    A DUET device will not echo back, and this is why the DUET modules are working on COMMAND level in both ways.
  • DHawthorneDHawthorne Posts: 4,584
    What kind of something are you referring to? I'm thinking you mean a flag to determine which way the string is going, but I don't see why that would be necessary.

    OK, you have a module that you are passing commands to, and receiving feedback from a virtual device. If you use STRING for both, there is going to be a DATA_EVENT with a STRING handler in your module for receiving commands, and there is going to be a STRING handler in your main code for feedback. Both of these handlers are going to see all SEND_STRINGs regardless of whether they originated in your main code or from the module.

    For example, I frequently use a virtual device to communicate between masters on a multi-master system. It's typical for me to have a multi-room audio system, and a local theater. Even if they are on the same master, I like to make the theater code a module, so it applies the same to that. The theater is a zone on the multi-room system, but the theater code doesn't duplicate the control code on the multi-room, I use a virtual device for the theater to talk to the other system. So, lets say my theater wants to access the media server on the multi-room; I can send a string to the virtual device that says "THEATER=MEDIA_SERVER," and the multi-room switches the appropriate zones. Well, then how does the multi-room inform the theater it actually switched? Send another string that says "THEATER=MEDIA_SERVER?" It would itself see this as another command and create a loop. So you have to identify what the strings are as they go out. Your zone could say, "COMMAND:THEATER=MEDIA_SERVER", and the feedback could be "FEEDBACK:THEATER=MEDIA_SERVER." However, if you just use SEND_COMMAND for commands to the virtual, and SEND_STRING for feedback, you know everything in the STRING handler is feedback, there is no need to prefix it or add any other indication. The command and the feedback can take the exact same form, and how they appear in the handler determines what your code does with them - act or update feedback.

    I know, it's not a major big thing. You may even prefer to differentiate between your commands and feedback in the actual strings for readability's sake. But it is a convention AMX uses in their modules, and I like to follow it as well.
  • JasonSJasonS Posts: 229
    This is where the undocumented command "Translate_Device" comes in handy. it is kind of like a crossover cable that connects to virtual devices together. So you use the "Dynamic_Virtual_Device" command to define a Virtual device inside the module and then use Translate_Device to link the two virtual devices together. Any Send_Command sent to your internal virtual device will come out the passed virtual device as a Command Event, any Command sent to the passed virtual device will come out the dynamic virtual device. This works with Commands, Strings and Channels. When I write my comm modules I write a basic UI module in the same module, I hate having a seperate UI module and passing Integer arrays to it.

    Code:
    MODULE_NAME='Example'(DEV Virtual, DEV RS232)
    
    DEFINE_DEVICE
    
        vdvModule = DYNAMIC_VIRTUAL_DEVICE
    
    DEFINE_START
    
        TRANSLATE_DEVICE (Virtual, vdvModule)
    
    DEFINE_EVENT
    
        DATA_EVENT [vdvModule]
        {
    	COMMAND:
    	{
                            //Parse commands sent to passed virtual device from main program
                     }
        }
    
    
Sign In or Register to comment.