The above shows how to start the empty daemon, how to load a plug-in, how to subscribe to a data stream, and how to change parameters while the program is running.
(ssh to your target device if needed) git clone --depth=1 https://github.com/bob-linuxtoys/eedd.git cd eedd; make sudo make install # Start the empty daemon (background but not a daemon) export PATH=$PATH:/usr/local/bin eedd -ef & # Load the "hello, world" demo plug-in edloadso hellodemo.so # Subscribe to the message service of hellodemo edcat hello_demo message # "hello, world" once a second # Open a second terminal window, and subscribe again export PATH=$PATH:/usr/local/bin edcat hello_demo message # "hello, world" once a second # Open a third terminal window # Change the print period to 2 seconds export PATH=$PATH:/usr/local/bin edset hello_demo period 2 # Change the printed string to good-bye edset hello_demo messagetext good-bye # Display info about the system and about hellodemo edlist edlist hello_demo
edget <name|ID#> <resource_name>
edset <name|ID#> <resource_name> <value>
edcat <name|ID#> <resource_name>
Each of the above has an equivalent bash command that behind the scenes opens a TCP connection and sends the command. (You can use telnet to connect directly to the empty daemon if you wish.) You'll find that having Bash commands to get or change plug-in parameters makes it easy to use a script file to drive your project or to help automate its testing.
The edloadso command starts everything by loading a shared object plug-in. Every plug-in has an Initialize() routine that is called to allocate a block of memory for state information, open device files and register read/write callbacks for file descriptors and to define other callbacks for timers and to do edget/edset/edcat on the resources that the plug-in wants to expose. The plug-in's Initialize() routine is passed a pointer to a SLOT structure. The plug-in fills in the SLOT's name and void pointer fields before returning. (A follow-up article to this one will describe how to write plug-ins.)
Each time a plug-in is loaded it is given a slot ID. EEDD itself has slot ID zero and plug-ins are numbered sequentially starting from one. It is possible to load a plug-in twice. Since the two instances have the same name you'll want to use the slot ID to differentiate them in the get, set, and cat commands.
Resources are ASCII printable values stored in an instance of a plug-in. Resources can be read-only, read-write, or broadcast. You can view a readable resource's value with the edget command and set a read-write value with the edset command. You can subscribe to a broadcast stream with the edcat command. Callbacks in the plug-in are invoked when you get or set a resource, or start a stream.
Although resources are presented as a static values, callbacks for writing or reading a resource can be used as a command to the system. For example, setting robot's motor mode to BRAKE would trigger sending the underlying commands to stop the motor.
Another valuable feature of EEDD is its ability to load multiple, cooperating plug-ins. For example, imagine a plug-in that loads after hellodemo and opens a TCP connection to its own process and then starts sending commands to the hellodemo to change the message displayed. This plug-in might update the hellodemo message text to show the current temperature or disk usage.
The two plug-ins cooperate in the sense that second plug-in uses the edset command to change the message text. Opening a TCP connection to yourself might seem strange at first but it is actually not too inefficient, it makes it possible to distribute the load to several processes, and most importantly, it keeps the command syntax identical throughout the whole system.
If you have a PID loop controlling dual DC motors you might want to also
add parameters for the P, I, and D terms. When your motor plug-in is
working properly you should be able make your robot move in a square
with a simple Bash script such as this.
edset motors mode b # brake
edset motors speed 50
edset motors dir 50
edset motors mode f # and off we go...
edset motors dir 100
edset motors dir 50
Adjust the speed and first sleep to adjust the size of the square. Adjust
the second sleep until you get a 90 degree turn. If the second sleep time
is too short the turn is greater than 90 degrees and if too long it's less
than 90 degrees. (Can you rewrite the above to make the robot go in a
If you have dual DC motors with a PID loop controlling them you might want to name your .so file motors-dc2.so, while if you're using continuous rotation servos from a VeX kit you might name the plug-in motors-vex.so. Either way, the plug-in should register with the name "motors" and implement at least the mode, speed, dir, and watchdog parameters.
Testing your remote control plug-in is as easy as using edcat and watching the output as you move the controls on the VeX or PS2 controller. Testing the robologic plug-in is as easy as adding a print statement to show the edset commands as they go to the motors plugin.
If the motor plug-in parameters are common to both sets of motors and the broadcast data stream from the remote controls are the same, you should be able easily mix and match the motors and remote controls.
The EEDD API
The full API to the empty daemon has only nine calls. Below is a
brief description of each API routine.
Select Loop Routines
User Interface Routines
- If you want some CPU load balancing you may want to run multiple instances of the empty daemon. Don't be afraid to create symbolic links to the empty daemon to give your executables distinct and more descriptive names. You can use ssh port forwarding if you want to distribute the load over multiple computers on a network.
- Logging is not part of the first release of the empty daemon. When available it will probably appear as an eedd resource called "logging" and which takes values of None, Syslog, or Stderr. One day a plug-in will let you grep syslog for eedd commands and play them back into the system with the appropriate timing.
- EEDD is released under the GPLv2 and a github repository will be the official source code repository. If you would like to participate let me know and I'll give you commit access to the repository.
- The next article in this series will describe the APIs offer by EEDD and give a more detailed description of how to write a plug-in. However, if you are handy at reading and modifying code you'll find that the two demo plug-ins supplied with EEDD may be enough to get you started.
- While edset, get, and cat are the preferred way to pass information in the system they are not the only way. The void pointer that a plug-in registers usually points to a structure that is specific to that type of plug-in. If you want to pass high bandwidth data, say images, you can define a routine in one plug-in and make it callable from other plug-ins by passing its address as part of the structure registered in the Initialize() routine. Of course for this to work all the cooperating plug-ins must have access to the structure definition that has the routine address. An example of this will be given in the next article.