Create Apps

These are the basic steps to build an app written in C that logs Hello World. when the process it's in starts up:

Then you're ready for the next level: Add Things, Use IPC, and Deploy Multiple Components.

Sample Directories and Files

Typical apps have directories and files that look this:

helloWorld/
├── helloComp
│ ├── Component.cdef
│ └── hello.c
└── helloWorld.adef

Create Component

Complete these steps to create a component: Create Directory, Create C Source File, and Create cdef File

Create Directory

1. Create a directory: the directory name will become the component name:

$ mkdir helloComp

Create C Source File

2. Create source (implementation) file hello.c:

$ gedit helloComp/hello.c

It should contain the following:

#include "legato.h"
{
LE_INFO("Hello world.\n");
}

This looks similar to the original C hello, world program from Kernighan's and Richie's "The C Programming Language", except that:

  • #include <stdio.h> is replaced with #include "legato.h"
  • main() is replaced with COMPONENT_INIT

In fact, legato.h will include stdio.h, along with a bunch of other system headers and Legato framework headers. This reduces the amount of time you have to spend including header files to get access to the functions and data types you need.

The build tools figure out what language the source code is written in by looking at the filename extension. So, because our file hello.c ends in .c, the build tools will try to use a C compiler to compile it into a library when it gets included in an executable.

Component Initializer

The COMPONENT_INIT macro is used to identify your component initializer. Every component must have a component initializer.

By using component initializers instead of having each component implement their own main() function, it's possible to run multiple components in the same executable and even share a thread between those components.

The main process thread (the main() function auto-generated by the build tools) will automatically call the component's initializer at the appropriate time during the process start-up sequence (based on the inter-dependencies between components). If component A is used by component B, then component A's initializer will be run before component B's initializer. Then component B can safely call the API functions of component A knowing that component A has already been initialized. This won't work if both components depend on each other (directly or indirectly through other components). That's one reason why dependency loops are not permitted between components. The framework will detect inter-component dependency loops at build time and terminate the build.

Component initializers don't take any parameters and don't return anything, but they must always return . Unless they experience a fatal error, in which case they must terminate the process with a non-zero exit code (which can be done using LE_FATAL(), LE_ASSERT(), etc. ).

Note
If a component's initializer doesn't return, the process will not be able to finish initializing all the components that have been deployed to it and the process's main thread will never process any events that are queued to it.

In our "Hello World" example, we just use our component initializer to print Hello world to the log using LE_INFO().

Create cdef File

3. Create a cdef file called Component.cdef like this:

$ gedit helloComp/Component.cdef
 sources:
 {
     hello.c
 }

See Definition Files for complete info.

Create App

You need to create an adef file before you can build you app.

4. Create an adef file called helloWorld.adef like this:

executables:
{
    helloWorld = ( helloComp )
}

processes:
{
    run:
    {
        (helloWorld)
    }
}

This defines one executable called helloWorld implemented by helloComp and then starts one instance of the helloWorld executable.

If your executable has multiple components, add more components inside the parentheses after the executable name: "helloWorld = ( helloComp foo bar )".

Build App

5. Run mkapp to build the executable and bundle it into an app:

Use the -t option to build for a target other than the default "localhost" target.

This is how to build the helloWorld app to install on the Sierra Wireless WP85 module:

$ mkapp -t wp85 helloWorld.adef
Note
If you're building an AR7, substitute ar7 in the mkapp run command.

Install App to Target

6. Use instapp to install the app on your target:

$ instapp helloWorld.wp85.update <ip addr>

The second argument is the target device's IP address where to install the app. This will connect to the target and install the app.

Usage

These usage tips are based on running a secure shell (SSH) to interface with the target. See Setup Target Device if you need to setup your target device and communications.

Target Login

Login to your target using a secure shell connection:

ssh root@192.168.1.2

Target Start App

Start your application using the app start command:

app start helloWorld

View Logs

Your installed app's LE_INFO log message will appear in the system log ("syslog") on the target device.

Run logread (on the target) to view the system log.

# logread

Use logread's -f option to start monitoring the logs and display messages as they are logged.

# logread -f

Here's a code sample accessing the logs on a target device with IP address 192.168.1.2 through an ssh connection:

ssh root@192.168.1.2 '/sbin/logread -f'

Remove App

From the host PC, run rmapp to uninstall the app:

$ rmapp helloWorld.wp85 <ip addr>

From the target run:

app remove <app name>

List App

Use lsapp to list the apps installed on a target.

$ lsapp <ip addr>

Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.