Developing New Server Plugin Tutorial

From LintouchWiki

Jump to: navigation, search

Contents

[edit] About this Tutorial

After reading & practicing this tutorial, the readers should be able to wite new server plugin for Lintouch, compile and install it so that it can be used with the existing Lintouch installation. They will understand the concepts of lintouch variables, real values, requested values, and varsets.

The readers should be able to write & compile C code, it is useful but not mandatory to understand autoconf/automake programs that are used to compile & install software on Linux systems. The readers should also understand the whole architecture of Lintouch, namely the roles of Lintouch Server, Lintouch Runtime, and Lintouch Editor.

[edit] Goal of this Tutorial

The goal of this tutorial is to write a simple Lintouch Server Plugin that will generate samples of mathematical function sinus. The amplitude, frequency, and phase shift can be configured from within Lintouch Editor.

[edit] Definition of Lintouch related Terms

[edit] Lintouch Server Plugin

Lintouch Server Plugin is a .dll or .so file that can be loaded dynamically into the Lintouch in order to provide new functionality. Server Plugins define new communication protocols for the Lintouch Server.

Server Plugins are usually written in plain C language and linked with several shared libraries shipped with Lintouch. Let's see what is inside the plugin. As an example, we will use the Loopback plugin from lsp-basic.

The list of public symbols exported by the plugin, basically the API used by Lintouch Server to communicate with the plugin.

 $ nm --dynamic /usr/lib/lintouch/server-plugins/Loopback.so |grep ' T '
 00000e70 T create
 00001574 T _fini
 00000f80 T init
 00000b68 T _init
 00000e50 T lt_version_info
 00001060 T run

We can safely ignore the underscore prefixed methods, since these are created automatically when linking a shared object file on Linux. The remaining methods have to be implemented by us, so there is their brief description:

lt_version_info 
returns a string identifying the version of Lintouch and some other important libraries this plugin has been linked against. This method is used to ensure that the plugin loading will not crash the rest of Lintouch. This method can be created automatically by including proper C header file.
create 
allocates new instance of the plugin. Two instances of the Loopback plugin living within the same Lintouch Project need to have their own memory structures. This method in fact represents the new statement used in C++ or Java.
init 
initializes the data structures of the allocated plugin instance. This method is synonymum for Java/C++ constructor method.
run 
should execute forever (or until terminated) and handle the communication between lintouch and outer world.

TODO: describe how plugin interacts with the Lintouch (via varset), with the rest of the world (sockets, pipes, files, serial line), how it can be customized (plugin properties, variable properties)

[edit] Lintouch Varset

TODO: set of lintouch variables, each plugin instance has its own varset

[edit] Lintouch Variable

TODO: variable: name, type (bit,number,string), real value, requested value, dirty flag for real value, dirty flag for requested value

[edit] Real Value

[edit] Requested Value

[edit] Plugin Property

TODO: role of a plugin property, defined as string, some examples, SNMP Server IP, Modbus/TCP port, etc.

[edit] Variable Property

TODO: role of a variable property, defined as string, some examples, Modbus/TCP address, Generator min/max/inc/random properties

[edit] Taking Off

[edit] Checking the necessary dependencies

 $ gcc --version
 gcc (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)
 Copyright (C) 2005 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 $ pkg-config --list-all |grep lintouch-server
 lintouch-server             Lintouch Server (lintouch-1.8.1 release) -
 $ apr-config --version
 0.9.6
 $ apu-config --version
 0.9.6

[edit] Creating the plugin source code

Create a directory where you will be developing your brand new server plugin and within that directory, plase prepare the file sinus.c with the following contents:

First of all we will need some standard headers:

#include <stdio.h>

#include "lt/server/plugin.h"
#include "lt/server/logger.h"

Then we have to define the lt_version_info method described above, we will use the helper macro:

/* automatically define mandatory plugin symbols */
LT_SERVER_PLUGIN_EXPORT;

The following are standartized macros that declare the public symbols of the plugin, these can be copy-pasted from another plugin source file.

lt_server_plugin_info_t *
PLUGIN_EXPORT LT_SERVER_PLUGIN_CREATE( apr_pool_t * pool );
lt_server_status_t
PLUGIN_EXPORT LT_SERVER_PLUGIN_INIT( lt_server_plugin_t * plugin );
lt_server_status_t
PLUGIN_EXPORT LT_SERVER_PLUGIN_RUN( lt_server_plugin_t * plugin );

Let's now define the body of our allocator method.

lt_server_plugin_info_t *
LT_SERVER_PLUGIN_CREATE( apr_pool_t * pool )
{
    /* create plugin meta-info and return it back */
    return lt_server_plugin_info_create(
            "John Doe <john@doe.com",                   /* author */
            "1.0",                                      /* version */
            "2006-01-01",                               /* date */
            "Sinus Generator",                          /* shortdesc */
            "Sinus Generator Lintouch Server Plugin",   /* longdesc */
            NULL,                                       /* default props */
            NULL,                                       /* default varprops */
            NULL,                                       /* plugin data */
            pool );
}

We don't need any initialization for the moment.

lt_server_status_t
LT_SERVER_PLUGIN_INIT( lt_server_plugin_t * plugin )
{
    return LT_SERVER_SUCCESS;
}

We will be only running and waiting actively (read: eating 100% CPU power) for the termination signal.

lt_server_status_t
LT_SERVER_PLUGIN_RUN( lt_server_plugin_t * plugin )
{
    while( lt_server_plugin_should_run( plugin ) ) {
        lt_server_logger_print( PRIO_PLUGIN, "Sinus: running...\n" );
    }
    lt_server_logger_print( PRIO_PLUGIN, "Sinus: exiting...\n" );

    return LT_SERVER_SUCCESS;
}

[edit] Compiling the plugin

Having a standard Linux distribution underneath, the following command should produce Sinus.so shared object file from our sinus.c source code.

$gcc `pkg-config --cflags --libs lintouch-server` -shared sinus.c -o Sinus.so

Let's verify that our symbol file looks like it should.

$ nm --dynamic Sinus.so |grep ' T ' 
00000660 T create
00000734 T _fini
00000690 T init
00000530 T _init
00000650 T lt_version_info
000006a0 T run

[edit] Installing the plugin

Lintouch will try to load all server plugins that are installed with a given directory. Let's copy our resulting server plugin there. Note that I am using sudo in order to have write access to this directory.

$ sudo cp Sinus.so /usr/lib/lintouch/server-plugins/

We can now start lintouch-editor and see whether our new plugin is listed within the connectivity options:

  1. Project->New
  2. Ctrl-K (for Dialogs->Variables)
  3. Edit Connections
  4. New

[edit] Speeding Up

[edit] Defining the plugin properties

TODO: sleep: how often the plugin should wake up and generate new sinus sample TODO: variables

  1. myvar: number -> will have the current sample value * 1000 (3 digits precision)
  2. myvar.amplitude: number -> will hold the amplitude
  3. myvar.frequency: number -> in Hz
  4. mywar.phase: number -> in degrees

[edit] Defining the plugin work-cycle

TODO: sleep, for each variable without dot in a name: check requested values of amplitude, fequency, phase & update internals, generate new real value

[edit] Final Touches

[edit] Making the compilation/installation polite

TODO: provide autoconf/automake integration, mention lsp-bootstrap

[edit] Distributing the plugin

TODO: versioning, author name, changelog, etc.

[edit] Summary

TODO: what we have learned.

Personal tools