Your first Ingescape agent

Your first Ingescape agent

This article gives you an introduction to the Ingescape library, in order to create a first software agent to be integrated in any Ingescape environment.

Creating your own agents is the key step to building the services that will make your future systems based on Ingescape.

Forewords

Our main goal when building the Ingescape API was to make it extremely simple for most usual situations, and very progressive when fine-tuning and advanced features become necessary.

Below is a first example producing a fully functional agent, with a very simple behavior. But before jumping into the code, we need to explain the core concepts of an agent: its name, its inputs, its outputs and its parameters.

The name of the agent is how it is addressed by other agents in your system and seen in the Ingescape editor. We advise it to be unique in a given system, even Ingescape supports multiple agents with the same name, as it may be useful and relevant in some contexts.

Inputs, Outputs and Parameters : the IOPs

Inputs, Outputs and Parameters, often abbreviated as IOPs by the Ingescape community, are all managed in the same way. They all carry a name, a type and a value. Giving a value when creating an IOP is optional.

Here are the supported IOP types:

  • Impulsion : the simplest of all, inspired from the electronic world,
  • BooleanInteger and Double : the numeric types,
  • String : the string of characters,
  • Data : raw binary information agnostically handled by Ingescape.

Even though they are manipulated in the same way, the IOPs do not share the same semantics:

  • Inputs enable the agents to receive information. When written, they shall trigger your agent’s internal behavior and optionally write to outputs.
  • Outputs enable agents to distribute information (i.e. output values) to other agents.
  • Parameters enable users of your agent to change its internal behavior. Exposed parameters are optional and shall be chosen and handled carefully as they are your agent’s configuration settings.

The whole set of IOPs for an agent is called the agent’s definition. Definitions can be created programmatically but also by writing JSON files or even by using the editor. Definitions can be enriched with a name (that can be different from the agent name), a version and a description. We’ll come back to this in further articles.

Agents are connected to one another by mapping outputs from agents to inputs of other agents. The set of mappings in a system composes the actual system communication architecture. We’ll come back to this in further articles. The concept of mapping is not mandatory to understand this first example.

The code

Here we are, this is all you need to know to design your first agent. The example below is developed in C. The code is filled with comments enabling to understand each function and each code block. Just after the code example are several resources to help you compile it on different operating systems and developing environments.

We recommend that you immediately copy and paste this code in your favorite C code editor.

#include <stdio.h> #include <ingescape/ingescape.h> //this is the only include required for ingeScape /* This is a callback function that runs everytime the input "input1" is written. The callback is linked to the input by the use of igs_observeInput below. The behavior of this agent is very simple: - reading the changed input - printing the new value - multiplying the value by 2 and writing the result to the output */ void myIOPCallback(iop_t iopType, const char* name, iopType_t valueType, void* value, size_t valueSize, void* myData){ /* This callback is fed with all the information necessary: - the IOP type : input, output or parameter - the IOP name - the IOP value type (impulsion, boolean, etc.) - a pointer to the value - the actual memory size of the value - optional data passed from the call to observeInput */ int r = igs_readInputAsInt(name); printf("%s changed to %d\n", name, r); igs_writeOutputAsInt("output1", 2*r); } /* This is the main function. It initializes the agent and makes a call to getchar so that the agent does not terminate right away. Agent termination is achieved by entering any character on the keyboard and pressing enter. */ int main(int argc, const char * argv[]) { /* Use ingeScape function to find compatible network devices on your computer. You need to use one of the returned results in the igs_startWithDevice call below for your agent to start on the network. */ char **devices = NULL; int nb = 0; igs_getNetdevicesList(&devices, &nb); for (int i = 0; i < nb; i++){ printf("device: %s\n", devices[i]); } igs_freeNetdevicesList(devices, nb); //set the agent name if (argc == 2){ //either by using the argument on the command line igs_setAgentName(argv[1]); }else{ //or by giving a default name if no argument was passed igs_setAgentName("simpleDemoAgent"); } //Create an input and an ouput: both are of integer type //with default value set to zero. igs_createInput("input1", IGS_INTEGER_T, 0, 0); igs_createOutput("output1", IGS_INTEGER_T, 0, 0); //Set the definition information (optional) igs_setDefinitionName("myDef"); igs_setDefinitionVersion("1.0"); igs_setDefinitionDescription("Definition for our first agent."); //Attach the callback to our agent's input //NB: callbacks can be attached to any IOP igs_observeInput("input1", myIOPCallback, NULL); //Actually and finally start the agent //First argument is the network device name to use //Second argument is the network port used by all the agents of your system igs_startWithDevice("en0", 5670); getchar(); //Stop the agent properly before terminating the program igs_stop(); return 0; }
Code language: PHP (php)

For a more thorough example, including compilation projects for various platforms, go to our first complete agent example.

Compile on UNIX systems

As a prerequisite, you need to have the Ingescape library and its dependencies installed on your computer. We suppose the Ingescape headers are installed in /usr/local/include/ and the libraries in /usr/local/lib/, which is pretty standard on most Linux and macos environments.

In case you are doing this on macos and you do not have Xcode installed, open the Terminal app, found in /Applications/Utilities/ and type the following command:

xcode-select --install

Then, simply follow the instructions on the screen.

When ready, copy the code in a main.c file and type the following commands in a terminal where your main.c file is located:

gcc -W -Wall -g -I/usr/local/include/ -std=gnu99 -o main.o -c main.c gcc -o myFirstAgent main.o -L/usr/local/lib -lingescape
Code language: PHP (php)

In case you are doing this on macos and you do not have Xcode installed, open the Terminal app, found in /Applications/Utilities/ and type the following command:

xcode-select --install

Then, simply follow the instructions on the screen.

Compile on Microsoft Windows

You can download Visual Studio Community 2017 C++ here.

Depending on your Windows platform, Ingescape is installed either in C:\Program Files\Ingescape or in C:\Program Files (x86)\Ingescape. In any case this folder contains an include and a lib subfolders which will be included in your project.

Using Visual Studio, you will need to follow these steps:

  • Create a new C++ project
  • Add the IngeScape\include folder to the include folders of your project
  • Add the Ingescape\lib folder to the libraries folders of your project
  • Include ingescape.lib as a library to be linked by your project