Dynamic device creation
wengerp
Posts: 29
Hi all
I'm looking for a way to dynamically create a (virtual) device by code without having to enter anything into the DEFIINE_DEVIICE section. I couldn't find any solution so far. Is this impossible or am I searching at the wrong places?
Thanks for any suggestions,
Patrick
I'm looking for a way to dynamically create a (virtual) device by code without having to enter anything into the DEFIINE_DEVIICE section. I couldn't find any solution so far. Is this impossible or am I searching at the wrong places?
Thanks for any suggestions,
Patrick
0
Comments
This may have some useful info: http://www.amxforums.com/showthread.php?8297-Dynamically-change-D-P-S&highlight=Dynamically+change+device
It might be more helpful if you describe what you wish to do. Quite often there's another way to approach the solution. While there are ways to create devices on the fly they are not emigrant and don't work as one might think. But, in most cases there really. Is no need to do this anyway and you can accomplish the same thing with more conventional methods.
I have my own framework which allows me to quickly setup a new system mainly by configuration. Since there are a lot of device id necessary and they all follow my own naming convention, it would be handy to generate them at first place. However, since this doesn't seem to be (reliably) possible, I know found another solution: I wrote a SUB that generates the necessary program code and writes it to a file on the controller (see sample below). I can then simply include this file in the master file.
Thanks,
Patrick
Sample of generated code for a minimal system:
Hi PhreaK
I'm totally aware of the fact that "include" is a compiler directive. As I said: since the dynamic creation of device definitions is NOT possible I had to find a workaround: first my program generates the necessary program code (at this time the icnlude file is emtpy) and writes it to a file on the controller. Second I drag&drop the code from the generated file to the include file (this is a manual action. I'm not aware of any way to let the program write its output directly to a file, which could be inlcuded by the compiler - after all the compiler runs on my local host while the program runs on the netlinx controller but there might be some creative way using shares or something). Finally I have to recompile the code (now with the correct instructions in the include file) and voilà.
This has nothing to do with "dynamic", I know ;-) But as I explained I was aiming for comfort and ease of use - and this is achived.
Patrick
This basically enables you to have a tool that runs locally, taking your NetLinx code that is sprinkled with whatever additionally syntactical sugar you desire, compile this down to valid NetLinx then pass the output of this to the nlrc.exe (the NetLinx command line compiler) for final compilation. Once it's set up its a single key press, you can even override F7 so all compiles run through this tool without you having to think about it.
I quite often use a strategy whereby I specify a pool of virtual devices and modules in code (at compile time) and then read in a configuration file which tells the control system what devices it should know about (what device type, so it knows which module to attach to the device and the physical port that it is connected to).
The drawback with this approach is that you have to pre-allocate a heap of memory for all of the virtual devices available in the pool, which may or may not be used. Unfortunately I have to live with the lack of ability to dynamically load NetLinx modules as there are a number of developers in our organisation and Duet isn't mature enough IMHO to get all of them licenses and train them up so that they can all support each other's work.
It occurs to me that it should be possible to create the virtual devs at run time instead of pre-defining them, but memory has never been an issue for me so I haven't bothered trying. Consider the following:
It compiles, but I haven't tried to see if it works as expected. It is my guess that while memory is allocated for all of the D:P:S addresses of the devices in the pool variables which are declared uninitialised, storage for all of the buttons/channels, etc associated with the devices is not (happy for someone to write some test code to find out) as the devices are not created until they are allocated.
Whilst my example is based around the use of modules, the key thing is that there is no requirement having to produce individual definitions for all of the virtual devices including names. I always find that manually declaring dozens if not hundreds of devices every time I produce a new system (such as below) is time consuming and prone to error. Better to let the control system do it itself at runtime...
I have been building configurable AMX systems for years. If you are not using Duet to solve these issues than you are sorely missing out.
Duet was designed for this, and is far from being immature. I may not do my implementation in the "AMX way" but duet framework provides for all the tools needed to do this correctly.
Just my two cents.
I used to do a lot with duet but due to the lack of proper documentation I finally gave it up. Here in Switzerland it seems to be impossible to get support for duet nor did I find any useful tutorials or other helpful stuff. That's why I changed all my code back to netlinx. It's a shame, isn't it?
This sounds very promising. However, I can't find any documentation about DYNAMIC_VIRTUAL_DEVICE or TRANSLATE_DEVICE in the netlinx documentation. What are these keywords doing exactly? Where can I found more information?
Both are "unsupported" by AMX. I learned about them in Programmer 3 class. Since DYNAMIC_VIRTUAL_DEVICE only works inside a module I think it is primarily intended for use with TRANSLATE_DEVICE.
DYNAMIC_VIRTUAL_DEVICE basically gives you a virtual device that is not being used, but it only works inside a module once.
TRANSLATE_DEVICE makes writing modules worth doing. It takes the virtual device you pass into the module and your DYNAMIC_VIRTUAL_DEVICE and cross-connects there inputs and outputs. Any Strings or Commands sent to the virtual device come out the DYNAMIC device and vice versa. Channels commands sent to the VIRTUAL device affect the DYNAMIC device and vice versa.
There have been several threads about TRANSLATE_DEVICE, I would search the forums.
Yes It is! BTW... Location does not help with duet support, support from the states are equally absent. But AMX uses publically available support libraries, like OSGi, and there are a good deal of documents from the providers. There are a few of us that have dug in and learned what we could, and making it work. It works well, too. AMX is still the only control manufacturer that has provided a system that can build configurable systems natively. They been doing it for years too!
My 60 seconds are up! Good luck with your design...
Pass the D:P:S into a module as a command parameter (ADDDEVICE-10001:4:1), parse the string into a DEV array and issue REBUILD_EVENT(). The device does not need to be in DEFINE_DEVICE. You do need LEVEL_EVENT[DEVARRAY[],0] in the module for REBUILD_EVENT to process and need to manipluate the DEV array before REBUILD_EVENT(), SET_LENGTH_ARRAY(DEVARRAY,MAX_VALUE + 1) SET_LENGTH_ARRAY(DEVARRAY,actualLengthArray) works as well as anything.
This allows you to _change_ an existing D:P:S but not _create_. You must register the module D:P:S in question (the one you are going to send the commnd to) in the DEFINE_DEVICE section and that's exactly what I was trying to avoid. But thanks anyway.
Here is the output:
(0000024525) Defined MANUFACTURER_STRING=AMX LLC
(0000024527) Defined MANUFACTURER=1
(0000024531) Defined DEVICE_ID_STRING=Virtual
(0000024531) Defined DEVICE_ID=65534
(0000024532) Defined VERSION=v4.1.400
(0000024532) Defined FIRMWARE_ID=380
(0000024532) Defined SERIAL_NUMBER=210515xXXXXXXX
(0000024533) Defined SOURCE_TYPE=0
(0000024533) Defined SOURCE_STRING=
(0000024533)
(0000024534)
(0000024534) Dynamic MANUFACTURER_STRING=3$CC7$CC3$CC3$CC3$CC3$CC3$103$CC3$CC3$C
C3$CC3$CC3$CC3$CC3
(0000024535) Dynamic MANUFACTURER=0
(0000024535) Dynamic DEVICE_ID_STRING=3$CC7$CC3$CC3$CC3$CC3$CC3$103$CC3$CC3$CC3$
CC3$CC3$CC3$CC3
(0000024535) Dynamic DEVICE_ID=0
(0000024537) Dynamic VERSION=3$CC7$CC3$CC3$CC3$CC3$CC3$103$CC3$CC3$CC3$CC3$CC3$C
C3$CC3
(0000024540) Dynamic FIRMWARE_ID=0
(0000024546) Dynamic SERIAL_NUMBER=3$CC7$CC3$CC3$CC3$CC3$CC3$103$CC
(0000024549) Dynamic SOURCE_TYPE=0
(0000024552) Dynamic SOURCE_STRING=