Home AMX User Forum NetLinx Studio

Guidelines for Creating Modules?

I am about to program a number of systems using some Sanyo Projectors. The protocol seems fairly straightforward but I was contemplating the use of modules. AMX does not have a module for any of the Sanyo models I am using, so I was going to create them (a first for me).
I thought it would be nice to try to program to some standard that would allow a future projector to be upgraded with a standard AMX module (assuming that it would be available).

I know that AMX does not publish the source code of their modules, presumably to ensure that they do not get modified and stop working.
But do they publish some guidelines on how to create a compatible module?

I thought that one of the primary goal of modules is to provide this level of interchangeability between similar devices.

Does anyone have a module for Sanyo projectors (PLC-XT16, PLC-XP57L, and PLV-WF10) or some other rs232 controlled projector that could be modified with the appropriate protocol that they would not mind sharing the source code for, or have any suggestions on the best approach that I should take for getting into using modules.

Thanks
Keith McLane

Comments

  • TrikinCurtTrikinCurt Posts: 158
    Open "Standard Netlinx API Help" and you will find your answers, you will find a section for "Video Projector".

    Curt
    Trikin
  • KmclaneKmclane Posts: 33
    TrikinCurt wrote:
    Open "Standard Netlinx API Help" and you will find your answers, you will find a section for "Video Projector".

    Curt
    Trikin

    Thanks I will look at this, but it appears geared towards Duet modules, does it apply to standard Netlinx modules as well? I haven't had time to "digest" it yet, but it looks very different than netlinx
  • matt95gsrmatt95gsr Posts: 165
    I'm not sure what the official answer to your question is, as far as the SNAPI guidelines applying to NetLinx as well as Duet, but in my mind it makes sense to view it that way. The way that I have approached building my modules recently (which is also pretty new for me) is to follow the API as defined in the SNAPI help. I see it as being the only real standard moving forward, and if future Duet modules are to be built around that framework, then building new NetLinx modules around it now helps to create a more future-compatible program today using the NetLinx modules. Some of the nomenclature used in the SNAPI definitions is a little different than what we may be used to seeing in the NetLinx realm, but I am basically ignoring the actual "Name" and "Component" columns for now and utilizing the information present in the "Channel", "Level", "Command", and "Constant" fields to write the program-to-module comm part of the things. Perhaps someone has a better/more proper answer to this, but so far this approach seems to be working pretty well for me.
  • JustinCJustinC Posts: 74
    You should download a module that AMX has written for a projector and look at the WORD document that comes with it. This lists all the commands that are available and you can see the format that AMX uses to communicate between your code and the module, from there its simply talking between a virtual device using send commands and a real device using send strings.

    That is the easier way, IMO.
  • DHawthorneDHawthorne Posts: 4,584
    JustinC wrote:
    You should download a module that AMX has written for a projector and look at the WORD document that comes with it. This lists all the commands that are available and you can see the format that AMX uses to communicate between your code and the module, from there its simply talking between a virtual device using send commands and a real device using send strings.

    That is the easier way, IMO.
    That's what I have done in the past; however, making things Duet compatible is probably wise. Even if you don't write in Duet, following the API will allow for interchangeability in the future. It is, however, often a lot of work. Many times I have been forced to do the "quick and dirty" because of budget constraints or time pressure. But if you can, make it Duet compliant, and you will save yourself from having to do it again later.
  • JustinCJustinC Posts: 74
    I have never really used a Duet module before, since I don't know Java and I usually right my own modules. So I looked at a duet module for a NEC projector and realized how different they are in the sense of using Channel codes instead of commands. Personally I would rather use the older way of doing modules. However, I understand things change. It would seem that AMX is leading really hard towards Duet, even though they will tell you that they won't push it on anyone and that they want people to know Java to use it and people who don't not to. It seems to me now, that everything is written as a Duet module and they are converting everything to Duet modules if they are currently non-Duet.
  • Roll your own

    Maybe I haven't tried enough AMX standard modules, but almost every one I've used so far has proven unreliable in some way, large or small, and with no access to code that leaves me helpless.

    Consequently rolling my own is the only method I trust. Of course I make all my modules compatible with one another, but I see no mileage in making them compatible with anything else.

    If necessary it is easy to build a module which translates between one interface standard and another - I did exactly that very recently when I tried to use an AMX module. (Then it turned out to be useless so I rolled my own.)

    The AMX modules can be VERY valuable in one respect: they are quick to install and they work out of the box, so you can then watch what they send and receive to the device and reverse engineer the protocols that someone spent a week sussing out.

    This can be much easier than the same-old same-old struggle to understand the Engineerspeak, Swedlish or Japlish in the protocol manual that it took you a week to find that has no examples of what the strings actually look like and doesn't tell you which direction the bits and bytes are numbered and never explains that sometimes what looks like hex is meant to be ASCII hex and I could go on but I won't.
  • sethollesetholle Posts: 66
    Module writing

    I agree with the above discussion. Some of the amx modules can have problems some time. IT seems to really depend on the manufactor.
    This is definetly better than the old system calls. Some of the code I have had to modify has been full of system calls. These were very hard to deal with. I tend to always write a module for devices that I will use often. I include button arrays that can be sent in, all error correction, thus the module covers all the bases. IT makes it much quicker for doing similiar like systems.
    SEth C. Olle
  • billyungbillyung Posts: 16
    Simple Module question

    I am having a little trouble understanding the construction of modules. The need I have is very small. I am using the AMX MAX module. In the UI module (which I can modify as opposed to the accompanying comm module) I need to grab a variable. Specifically, I need to grab the disc ID and pass it back to the main program in response to a request from the main program. I suppose I should start by sending a send_command from the main program. I'm not clear on receiving and responding to that send_command from within the module or receiving the result in the main program. I know this is a simple matter. Gotta start somewhere though...

    Thanks for your help
  • ericmedleyericmedley Posts: 4,177
    billyung wrote:
    I am having a little trouble understanding the construction of modules. The need I have is very small. I am using the AMX MAX module. In the UI module (which I can modify as opposed to the accompanying comm module) I need to grab a variable. Specifically, I need to grab the disc ID and pass it back to the main program in response to a request from the main program. I suppose I should start by sending a send_command from the main program. I'm not clear on receiving and responding to that send_command from within the module or receiving the result in the main program. I know this is a simple matter. Gotta start somewhere though...

    Thanks for your help
    There are three steps to making this happen.

    1st is to initiate the kind of search you wish to do
    2nd is tell the MAX to make that search
    3rd is get the data

    Step 1
    You would send this command to the MAX_comm virtual device

    SEND_COMMAND vdvMEDIAPLAY , 'SEARCH= <SOME DATA>'

    Look in the MAX commands list to set this up. If you were looking for a specific disc. (Radiohead - OK Computer)

    Then the command would look like this
    SEND_COMMAND vdvMEDIAPLAY , 'SEARCH=TITLE:OK Computer:1'

    There will be no response from the MAX on this command.

    Step 2
    Send the ESEARCH command to initiate the response from the MAX,

    Step 3, the MAX will respond to this. get the data and go to it.

    If I may be so bold as to assume... You may want to think about how you program this thing. I went through a similar process myself since I was creating my own user interface. Our touch panels don't use multiple pages and AMX's stuff likes to use many pages. We pretty much had to retool the whole thing.

    I went through the process of creating a data management system in the Netlinx program and tried to figure out how to harvest all the data from the MAX into the tables I'd created in my program.

    However, that's just not how the MAX is set up to work. It's not set up to let you manage the data. It's set up to let you run its database management.

    The MAX has database management built into it. The best advice I can give is just create a interface that allows the MAX to manage the data. Don't spend a lot of time trying to get and store the data in the MAX

    From the example above, Let's say you sent the search "OKAY Comptuer" instead of "OK Computer" then the MAX wouldn't return anything. The best thing to do is let the user send a search that homes in on the title they're looking for and then let them select from a short list of discs in the MAX. (Not saying that your question indicated that this is what you wished to do... It's just an example)

    If this piques your interest, I'll elaborate. However, if not then I won't bore you with more typing.

    ejm
  • billyungbillyung Posts: 16
    Not exactly...

    Eric,
    Thanks for your reply. I have had great success with storing and retrieving many fields of data (40 or so) into the single keyword (kw) field in the MAX MySQL database using a pipe | for a field separator within the field. I have done this with an older MAX MMS-125. It's really working well with my DXHT projects in two separate installations. I'm now attempting to port my work over to a Design Express installation (not Home Theater) and it uses the AMX MAX UI module where the DXHT has all the UI code within the main program.

    My issue doesn't involve the MAX search functions. My question isn't really specific to the MAX at all. It's more about modules in general. What I need is for the main Netlinx program to be able to get the value of a variable that lives within a module.

    From the main program, I understand that I need to use a send_command to initiate the conversation. I don't know how to write the module code to receive that request and respond to it. In addition I'm not clear on having the main program receive that response. Any help you all could give would be appreciated.

    Thanks,


    Bill
  • DHawthorneDHawthorne Posts: 4,584
    billyung wrote:
    Eric,

    My issue doesn't involve the MAX search functions. My question isn't really specific to the MAX at all. It's more about modules in general. What I need is for the main Netlinx program to be able to get the value of a variable that lives within a module.

    From the main program, I understand that I need to use a send_command to initiate the conversation. I don't know how to write the module code to receive that request and respond to it. In addition I'm not clear on having the main program receive that response. Any help you all could give would be appreciated.

    This is one of my beefs with the way modules are implemented; there is no built in way to get data out of an internal variable. You have to create one when you write the module.

    By far, the easiest way to do it is simply take the variable out of the module DEFINE_VARIABLE section, and make it a parameter that the main program defines. However, you can't do this with structures, only intrinsic variable types. It also gets unwieldiy if you have a lot of data to pass back and forth ; I hate parameter lists that go on forever.

    To use the SEND_COMMAND method, you need to define a virutal device and pass that to the module as a parameter. In both sets of code, the module and your main program, create a DATA_EVENT with a COMMAND handler. DATA.TEXT within that handler will have the contents of any SEND_COMMAND sent to the virtual device. It works the same way a STRING handler does for a physical device (which also work with virtuals, by the way). SEND_COMMANDs are picked up by the COMMAND handler, and SEND_STRINGs by the STRING handler. If you just have one virtual device, you have to be careful there is no overlap so that both module and main program try to act on the same command. Or, you could define two virtuals, and make one the command receptor for the module, and the other the receptor for the main program. Both would have to be defined as module parameters for this to work. The advantage of using virtuals this way is that you can pass a lot of data back and forth, and it can vary widely. I often make such a virtual to create an entire menu of operations for my modules to facilitate remote troubleshooting ... like asking a multi-room audio system what zones are active, and what the volume levels are at, etc.
  • billyungbillyung Posts: 16
    More on Module Methods

    David,
    Thanks for the reply. That is what I'm looking for. I think I'd prefer the send_string method. I understand that I need to send the string to the virtual device of the module; however, when the module is replying back to the main program, what device do I send the reply to? Would it be 0? 5001?

    Thanks,


    Bill
  • JustinCJustinC Posts: 74
    You use SEND_COMMANDS to send a request or command to the module. It then returns SEND_STRINGS of data back to you. So you would just define a string hangler in your main program on the virtual device to get the data back from the module.


    Easy way to remember this

    You send "commands" to the virtual device and recieve "strings" from the virtual device.
  • billyungbillyung Posts: 16
    JustinC wrote:
    You use SEND_COMMANDS to send a request or command to the module. It then returns SEND_STRINGS of data back to you. So you would just define a string hangler in your main program on the virtual device to get the data back from the module.


    Easy way to remember this

    You send "commands" to the virtual device and recieve "strings" from the virtual device.

    Okay. That's not very intuitive though. It seems like either strings or commands should work in either or both directions. I don't need to belabor that point though. What I need to know is what device should the module send the command or string to in order for the main program to see the result? send_string 0? 5001? or would any other previously declared virtual device work?

    Thanks for all your help.
  • Sorry its not intuitive enough. I understand that you feel it should be strings or commands, but that just isn't the way modules work. However here is how you work with the data from the module.

    DEFINE_DEVICE
    
    dvDEVICE	=5001:1:1
    
    
    vdvVIRTUAL	=33001:1:1
    
    
    
    DEFINE_EVENT
    
    DATA_EVENT[vdvVIRTUAL]
    {
        STRING:
        {
    	SELECT
    	{
    	    ACTIVE(FIND_STRING(DATA.TEXT,"DATA LOOKING FOR",1)):
    	    {
    		//pass the data into variables or whatever you want in your code
    	    }
    	}
        }
    }
    
    
  • Maybe im misunderstanding the question. Are you wanting to know how to interface to the module or are you writing your own module and want to know how to send data back to the main program from the module ?
  • Sending Data Back from Modules
    JustinC wrote:
    Maybe im misunderstanding the question. Are you wanting to know how to interface to the module or are you writing your own module and want to know how to send data back to the main program from the module ?


    Exactly,
    I'm wondering how to send data back to the main program from a module.
  • DHawthorneDHawthorne Posts: 4,584
    JustinC wrote:
    You use SEND_COMMANDS to send a request or command to the module. It then returns SEND_STRINGS of data back to you. So you would just define a string hangler in your main program on the virtual device to get the data back from the module.


    Easy way to remember this

    You send "commands" to the virtual device and recieve "strings" from the virtual device.
    This is just a convention. You can send them either way in both directions. Sepoerating them like that just makes it easier not to confuse which you are working with. They both really do exactly the same thing. THe only difference is that SEND_STRINGs appear as data in a STRING event, and SEND_COMMANDs appear in the COMMAND event.
    Thanks for the reply. That is what I'm looking for. I think I'd prefer the send_string method. I understand that I need to send the string to the virtual device of the module; however, when the module is replying back to the main program, what device do I send the reply to? Would it be 0? 5001?
    Sending it to port 0, only a telnet session to the master would pick it up. Sending it to a port on 5001 would send it out to your device. You can send it right back to the same virtual, as long as you are careful processing it,or you can create a second virtual (not really the most elegant way). The convention Justin mentioned works well - use STRING for talking to your main program, and COMMAND for talking to the module. Then, a COMMAND event in the module will parse its commands, and the STRING event in the main program parses the feedback -all in the same virtual device.
  • DHawthorne wrote:
    This is just a convention. You can send them either way in both directions. Sepoerating them like that just makes it easier not to confuse which you are working with. They both really do exactly the same thing. THe only difference is that SEND_STRINGs appear as data in a STRING event, and SEND_COMMANDs appear in the COMMAND event.


    I can imagine using send strings back and worth would get quite confusing really fast when parsing data from the device.
  • Now I understand

    David, JustinC,

    Thanks for all your help. I finally get it. I was thinking you would use a separate virtual device to send things back to the main program. Now I understand that you use the same virtual device for messages sent to and from the module and distinguish the direction of the communication by the message type. Sorry if I didn't phrase my question clearly earlier on.

    Thanks,


    Bill
  • DHawthorneDHawthorne Posts: 4,584
    JustinC wrote:
    I can imagine using send strings back and worth would get quite confusing really fast when parsing data from the device.
    Well, we are talking about a virtual here, not the real device; and you could put syntactical differences in the to and from messages to distinguish them. I'm just saying what's possible, not necessary what would be a good idea :).
Sign In or Register to comment.