Modules

What are MaCI Modules?

MaCI is split in two parts; Drivers and Interfaces. Drivers are used for communicating with hardware on a local machine and Interfaces are used for distributing this information and control to the GIMnet.

Either part is nothing alone, so we have Modules. Modules bind together a driver and interface. Module basically contains the code to access the device driver and communicate its data to any number of interfaces required. For example; ESC629 module (PC104 based Motor controller card) uses ESC629 device drivers and maps its services in two Interfaces: 'SpeedCtrl' and 'Position'. Much of MaCIs flexibility is because the module writer is allowed to bind any number of interfaces to any number of hardware devices. For information on how this is done, keep reading.

Using MaCI modules

  • FIXME: Fill in information about using existing modules and module groups.

Creating MaCI modules

Modules should be placed in subdirectories named after the set of required Server interfaces. For example; module requiring 'Position' and 'SpeedCtrl' interfaces should be placed in directory 'MaCI/modules/Position_SpeedCtrl'. (Interface names order alphabetically). This helps keeping the module source tree somewhat cleaner.

  • FIXME: Info about creating new MaCI modules.

Creating MaCI module configurations

All modules must have a configuration file (with a postfix .conf) to have full MaCI features available. In "MaCI/machines/template/somemodule.conf" is an example of an module configuration file, also all existing modules have an example of a module configuration file in "MaCI/conf" directory. In this section we will split the template module configuration in parts and describe each part in detail.

<?xml version="1.0"?>
<module version="0.4">

This part contains the 'root' key of the configuration XML-document. The version property is optional, but should be defined to make it easier to track problems with future Launcher versions and old configuration files.

<!--  Freeform name of module  -->
<name>Some Module</name>

<!--  Freeform description of module  -->
<description>This is an template for creating your own module configurations</description>

The part above describes a name for the module and a short description. The name is also used when using dPrint-style printing. Launcher add the module name before the debug print to know which module is actually printing the message.

<!-- Executable module file definition. -->
 <executable>../../../modules/Misc/MaCICtrl_Dummy</executable>

 <!-- Command to run if Launcher was started in Build mode. If this is defined, -->
 <!-- launcher will execute this line as-is with system()-call -->
 <build>cd ../../../modules/Misc/; make MaCICtrl_Dummy</build>

 <!-- Execute the binary using this as working directory -->
 <!-- If this is empty or unspecified, the machine default wd will be used -->
 <workdir></workdir>

Between executable element, the path to the executable is defined.Build element defines the build rule for the executable. The Launcher uses this line with system()-call. If you want to change the working directory where the module wants to be launch put it between <workdir>.

<!-- Flags modifying the Launcher behaviour. If this is empty or -->
  <!-- missing, no flags will be set. (The launcher will work in full -->
  <!-- MaCI-module compatible mode) The ignore_* flags are set when defined, -->
  <!-- and unset when undefined (Can be commented as in the example)  -->
  <flags>
    <!-- Ignore GIMnet parameters; don't pass any 'GIMnet_.*' parameters to binary -->  
    <ignore_param>GIMnet</ignore_param>

    <!-- Ignore MaCI specific parameters; don't pass any MaCI related parameters to binary -->  
    <ignore_param>MaCI</ignore_param>

    <!-- Ignore ModuleConf. Don't pass the '-f file' to binary. -->
    <ignore_param>ModuleConf</ignore_param>

    <!-- Ignore extra 'param's. Don't pass the 'param' tag contents to binary. -->
    <ignore_param>Extras</ignore_param>

    <!-- This marks that this module does not require root permissions to run properly. -->
    <!-- If this is set, the Launcher will attempt to set UID/GID to normal user id as possible -->
    <!-- If this is NOT set, the launcher will not alter UID/GID:s of the child process. -->
    <drop_root_privileges/>

    <!-- This flag (with value) marks that if this process exits, it should be -->
    <!-- restarted again with same parameters, after waiting for 'delay_ms' milliseconds. -->
    <respawn_process delay_ms="5000"/>
  </flags>

Above, there are examples how to modify the Launcher behaviour by giving different flags. They are basically to drop down unwanted features. These parameters can be ignored if not used. Between <ignore_param> element, you can define different parameters to be ignored. These are, GIMnet for not to pass any GIMnet parameters, MaCI for not to pass any MaCI parameters, ModuleConf for not to pass "-f file" and Extras for not to pass extra parameters (between <param>) to the binary. By default all these are commented out to be able to use all features of Launcher.

Some modules may need the root privileges to run properly(i.e. for accessing hardware), but most of them don't. To launch the module with root privileges remove <drop_root_privileges/> node.

The Launcher have a feature to relaunch the module after exiting. The respawn time for the module can be set by changing the attribute of <respawn_process delay_ms="5000"/> element.

<!-- Path to external configuration/data/whatever file to be passed on the module through parameter '-f' -->
  <!-- If this parameter is omitted, the '-f' parameter will not be used. You can also -->
  <!-- pass this current file as parameter if you have embedded the settings here.  -->
  <moduleconf>somemodule_own_configuration_file.xml</moduleconf>

If you want to pass a configuration file to your module, it can be passed with <moduleconf> element. The module configuration file can be passed also (and is passed in most of existing modules) by by giving the filename.

<!-- Start delay in milliseconds. If this value is specified, the launch of this module -->
  <!-- is delayed the specified amount. Processes with same delay value are started at the same -->
  <!-- moment (As accurately as possible) -->
  <startdelay>0</startdelay>

In complex systems modules are depending on each other. In a case where module A depends on module B, module A can be launch only when module B is running. For these cases a delay for starting modules can be given with startdelay element.

<!-- Any string to be passed on the module commandline _after_ the '-f' parameter. -->
  <!-- param can be specified multiple times. Each instance represents one 'parameter' -->
  <!-- NOTE: Contents of tag are passed _as_single_entry_, so if you define flags with values -->
  <!-- you will need to define '-<flag>' and 'data' as separate 'param' tags. -->
  <param>-v</param>
  <param>-v</param>

Modules may need some specific parameters for running. These can be passed between <param> element.

<!-- CSettings compatible configuration, these keys will be listed as: -->
 <!-- 'mymoduleconf.bar', 'mymoduleconf.foobar', etc. in the CSettings value tree. -->
 <group name = "mymoduleconf">
   <value key = "bar" data = "15000"/>
   <value key = "foobar" data = "0x280"/>
   <value key = "barfoo" data = "0.025 0.005 0.010 0.500"/>
 </group>

Finally, if you want to use the same configuration file for your module specific configuration, you can add them here. These can be read normally by using the CSettings class found in GIM/utils folder. As an example above there is some configurations that are listed as mymoduleconf.bar ,mymoduleconf.foobar etc.

</module>

You must close the module section at the end of the file.