Loading...
 

IoT with EPOS

. Guided Tutorial

If you prefer, you can follow a guided tutorial here.

. EPOS @ EPOSMote III

EPOSMote III is one of the main target platforms for EPOS 2. You can follow the User’s Guide to download, compile, and run it. Aspects of EPOS pertaining only to EPOSMote III are covered in this section.

. Running EPOS for EPOSMote III on QEMU

Before running your code on the real EPOSMote III device, you may run it on the QEMU emulator. EPOSMote III is not directly supported by QEMU, but there is a similar machine with the same processor (ARM Cortex-M3) called Stellaris LM3S811 which is supported. To compile your program to this machine and run it on QEMU, adjust your application’s traits file to use it instead of EPOSMote III (see the line marked with // <- Here):

template<> struct Traits<Build>
{
    enum {LIBRARY, BUILTIN, KERNEL};
    static const unsigned int MODE = LIBRARY;

    enum {IA32, ARMv7};
    static const unsigned int ARCHITECTURE = ARMv7;

    enum {PC, Cortex_M, Cortex_A};
    static const unsigned int MACHINE = Cortex_M;

    enum {Legacy_PC, eMote3, LM3S811};
    static const unsigned int MODEL = LM3S811; // <- Here

    static const unsigned int CPUS = 1;
    static const unsigned int NODES = 1;
};
run make veryclean and compile and run the application with
$ make APPLICATION=the_name_of_your_application run

Note: do not include the final .cc in the_name_of_your_application
Keep in mind that there are differences between EPOSMote III and LM3S811. For instance, LM3S811 does not feature any radio interface.

. Running EPOS on EPOSMote III

Adjust your application’s traits file to use EPOSMoteIII (see the line marked with // <- Here):

template<> struct Traits<Build>
{
    enum {LIBRARY, BUILTIN, KERNEL};
    static const unsigned int MODE = LIBRARY;

    enum {IA32, ARMv7};
    static const unsigned int ARCHITECTURE = ARMv7;

    enum {PC, Cortex_M, Cortex_A};
    static const unsigned int MACHINE = Cortex_M;

    enum {Legacy_PC, eMote3, LM3S811};
    static const unsigned int MODEL = eMote3; // <- Here

    static const unsigned int CPUS = 1;
    static const unsigned int NODES = 1;
};


run make veryclean and compile the application with

$ make APPLICATION=the_name_of_your_application

Note: do not include the final .cc in the_name_of_your_application


If your device is loaded with an EPOS Bootloader (which is the default), you can program your EPOSMote III device via USB. You will need python3 with the pyserial module for this. To install on Ubuntu execute the following commands:

$ sudo apt-get install python3-pip
$ sudo apt-get install python3-serial


Note: when using EPOSMote III with USB, the modemmanager Linux service might get in the way. It is recommended to stop this service. In Ubuntu, you can do this with the command:

$ sudo stop modemmanager

You can also disable this service permanently with:

# echo "manual" > /etc/init/modemmanager.override

Note: you may need to grant your user permission to access the serial port.


Bootable ROM images of EPOS for EPOSMote III must be in Intex HEX format. In order to convert the ELF files produced during the compilation of EPOS, use

$ make APPLICATION=the_name_of_your_application flash

Note: do not include the final .cc in the_name_of_your_application


The resulting bootable ROM image will be saved as img/the_name_of_your_application.hex.
This command line will also call EPOS flasher script to upload the image just created to EPOSMote III’s flash memory. The script will stop with the following message:

Waiting for /dev/ttyACM0 to appear

The next steps depend on which method you are using to program.

  • If your EPOSMote is loaded with the USB Bootloader (default), simply plug it into the USB port (the device is assumed to appear on /dev/ttyACM0) and the image just compiled will be flashed. When it is done, execution starts immediately on the device.
  • If you are using EPOS Radio Bootloader, you need two devices: a programmer and a target. Simply plug the programmer into the USB port (the device is assumed to appear on /dev/ttyACM0) and wait until you see the following messages:
    /dev/ttyACM0 found, trying to open it 
    /dev/ttyACM0 Opened. Sending handshake messages until a response is detected
    ===== This is what the mote said =====
    Then turn on (or reset) your target device and it shall be programmed by the programmer via radio. When it is done, execution starts immediately on the target device.

If your device is appearing at a port other than ACM0, say ACM2, you can inform that with the ACM argument when running make, for example:

$ make APPLICATION=hello ACM=2 flash


Your application should now be running!
Every time the mote is reset, the bootloader will run and wait for a handshake for one second. If none is received and there is an image already loaded in flash memory, it will start executing that image.

. Using JTag

You only need this method if you have a device that has never been programmed before. In case your device already has a bootloader, you can upload your image using the bootloader. You need to use JTag to accomplish one of the following:

  • Load a stand-alone image, with no bootloader;
  • Load EPOS’ USB bootloader;
  • Load EPOS’ Network bootloader.

You will need JLinkExe to perform these actions. You can install it from the “J-Link Software and Documentation Pack” available for download at SEGGER’s website. It is convenient to follow the steps in the .tgz’s README to enable user-level access to the JTag device on Linux. This tutorial was last verified with the following JLinkExe version:

SEGGER J-Link Commander V6.14h (Compiled May 10 2017 18:39:45)
DLL version V6.14h, compiled May 10 2017 18:39:37

. Load an image directly

To load an image directly with JTag, you can issue the following JLinkExe commands:

$ JLinkExe
J-Link>Device = cc2538sf53
J-Link>connect
TIF>J
JTAGConf><Enter>
Speed><Enter>
J-Link>h
J-Link>erase
J-Link>loadbin <application>.hex, 0
J-Link>exit

If everything was successful, you should see a message like this after the loadbin command:

Downloading file [<application>.hex]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Flash programming performed for 2 ranges (10240 bytes)
J-Link: Flash download: Total time needed: 0.122s (Prepare: 0.022s, Compare: 0.004s, Erase: 0.000s, Program: 0.081s, Verify: 0.001s, Restore: 0.012s)
O.K.

Note: EPOS memory map for EPOSMote III assumes there will be a bootloader in place. If you are loading an image that will stand alone, without a bootloader, then the memory map must be adjusted accordingly. Edit include/machine/cortex_m/emote3_traits.h to make the following modifications and remember to run make veryclean after.

MEM_BASE  = 0x20000000;

APP_LOW   = 0x20000000;
APP_CODE  = 0x00200000;
APP_DATA  = 0x20000000;

PHY_MEM   = 0x20000000;

SYS       = 0x00200000;
SYS_CODE  = 0x00200000; 
SYS_DATA  = 0x20000000;

. Load EPOS’ USB bootloader

Get the latest version of EPOS’ USB bootloader:

$ svn export https://epos.lisha.ufsc.br/svn/epos2/branches/emote3_bootloader/img/emote3_usb_bootloader.hex .

and then upload it using JLinkExe.

. Load EPOS’ Network bootloader

Get the latest version of EPOS’ Network bootloader:

$ svn export https://epos.lisha.ufsc.br/svn/epos2/branches/emote3_bootloader/img/emote3_nic_bootloader.hex .

and then upload it using JLinkExe.

To use the Network bootloader, you will also need a separate mote to act as a Network programmer. Get the latest version of EPOS’ Network programmer:

$ svn export https://epos.lisha.ufsc.br/svn/epos2/branches/emote3_bootloader/img/emote3_nic_programmer_via_jtag.hex .

and then upload it using JLinkExe.

. Interacting with EPOSMote III via Serial

It is often useful to interact with the mote from a serial (e.g. USB) of a PC. This section explains how to accomplish that using minicom or stty. There are other alternatives such as cutecom, which should follow a similar procedure.

Note: when using EPOSMote III with USB, the “modemmanager” Linux service present in some distributions (such as Ubuntu) might get in the way. It is recommended to stop this service. In Ubuntu, you can do this with the command bellow. Note the #, which means that you need root privilege (e.g. prepending sudo to the command).

# stop modemmanager

You can also disable this service permanently with:

# echo "manual" > /etc/init/modemmanager.override

Compiling EPOS with USB or UART support

Adjust your application’s traits file to use either USB (default) or UART to output data (e.g. anything your application writes to cout) by selecting the according ENGINE for the Serial Display:

template<> struct Traits<Serial_Display>: public Traits<void>
{
    static const bool enabled = true;
    enum {UART, USB};
    static const int ENGINE = USB; // <- Here
    static const int COLUMNS = 80;
    static const int LINES = 24;
    static const int TAB_SIZE = 8;
};

If using USB, the Linux host will recognize the EPOSMote III as an Abstract Control Model (ACM) device using a default driver. If using UART, you will need to connect the mote’s UART pins to a device such as the FTDI FT232R to interface with the host.

Permissions

To be able to access the serial port without “sudo” on Ubuntu, add your user to the groups “uucp” and “dialout”. Some distributions require that you logout and login again to these configurations take effect.

$ sudo usermod -a -G dialout,uucp <username>

Launching Minicom

Assuming EPOSMote III is listed as /dev/ttyACM0, launch minicom with:

$ minicom -D /dev/ttyACM0

Typing <Ctrl+a> + z shows all available commands.

Serial port Configuration

The default serial port configuration for EPOSMote III is “115200 8N1”:

  • Baud rate: 115200
  • Data bits: 8
  • Parity bits: 0
  • Stop bits: 1

One option is to use stty to configure these parameters via command-line. Use the following command:

$ stty -F /dev/ttyACM0 ispeed 115200 ospeed 115200 cs8 -cstopb -parenb -crtscts

Then you can interact with the mote using command-line tools such as cat.

Alternatively, to configure these parameters in minicom, launch minicom, type <Ctrl+a> + p, and follow the menu. In minicom, you will also need the following steps:

Disabling Hardware flow control

This is necessary for writing in the serial port. In minicom, type <Ctrl+a> + o, select “Serial port setup” and press f.

Saving Configurations

Once you do all the steps above, you can save your minicom setup. To do so, type <Ctrl+a> + o and “Save setup as dfl”. This will create a file in your home named “.minirc.dfl”, which will be loaded every time minicom is called without overriding options.

Sending cr/lf

To send a carriage return (a.k.a. cr or \r), press <Enter>
To send a linefeed (lf, or \n), press <Ctrl+j>

. iot.lisha.ufsc.br REST API

Developer’s guide here.

. Query data

Method: POST
URL: https://iot.lisha.ufsc.br/api/get.php
Body:

{
    "series" : Object
    {
        "version" : string
        "unit" : unsigned int
        "x" : int
        "y" : int
        "z" : int
        "r" : unsigned int
        "t0" : unsigned int
        "t1" : unsigned int
        "dev" : unsigned int
        "signature" : unsigned int
        "workflow": unsigned int
    }
    "credentials" : Object
    {
        "domain" : string
        "username" : string
        "password" : string
    }
}

Optional properties: workflow, credentials, domain, username, password.

. Create or Attach series

  • Create will create a series only if it does not already exist (identical parameters).
  • Attach will create a series only if there is no series containing it (space and time).

Method: POST
URL for create: https://iot.lisha.ufsc.br/api/create.php
URL for attach: https://iot.lisha.ufsc.br/api/attach.php
Body:

{
    "series" : Object
    {
        "version" : string
        "unit" : unsigned int
        "x" : int
        "y" : int
        "z" : int
        "r" : unsigned int
        "t0" : unsigned int
        "t1" : unsigned int
        "dev" : unsigned int
        "signature" : unsigned int
        "workflow": unsigned int
    }
    "credentials" : Object
    {
        "domain" : string
        "username" : string
        "password" : string
    }
}

Optional properties: workflow, credentials, domain, username, password.

. Insert data

Method: POST
URL: https://iot.lisha.ufsc.br/api/put.php
Body:

{
    "smartdata" : Array
    [
        {
            "version" : string
            "unit" : unsigned int
            "value" : double
            "error" : unsigned int
            "confidence" : unsigned int
            "x" : int
            "y" : int
            "z" : int
            "t" : unsigned int
            "dev" : unsigned int
            "signature" : unsigned int
            "workflow": unsigned int
        }
    ]
    "credentials" : Object
    {
        "domain" : string
        "username" : string
        "password" : string
    }
}

Optional properties: credentials, domain, username, password.

. Properties

Each property is briefly explained next. For further details, see the Smart Data documentation.

Common properties to smartdata and series:

  • version: The SmartData version. Possible values:
    • "1.1": Version 1, Static. Data from a sensor that is not moving.
    • "1.2": Version 1, Mobile. Data from a sensor that is moving.
  • unit: The SI (or digital) unit of the data. See typical units or the full documentation.
  • dev: (optional) An identifier for multiple transducers of the same unit in the same coordinate (e.g., 3-axis accelerometer)
  • workflow: (optional) Executes a server side code, identified by an integer, with the series in insert operations. The integer should be specified in the field workflow of the attach operation. Currently, this code could be user defined but need to be installed by system administrators and the first insert of a series should not use a workflow in its respective attach. The semantics of query operations (get.php) with workflow specified is to return only data inserted using that workflow. If query operations (get.php) do not specify a workflow, they return all data that were inserted with and without workflow specified.
  • signature: (only for mobile version) An identifier for mobile version of SmartData (version 1.2)


Specific properties:

  • smartdata: Array of one or more elements, each containing information about a particular measurement (data point).
    • value: The data value itself (e.g. the temperature measured by a thermometer).
    • error: The detected measurement error.
    • confidence: The level of confidence in this measurement.
    • x, y, z: The absolute coordinates where the measurement was taken.
    • t: The time when the measument was taken, in UNIX epoch microseconds.

  • series: Information about data to be fetched.
    • x, y, z: The absolute coordinates of the center of the sphere of interest.
    • d: User-defined tag, normally used as a disambiguator of unit.
    • r: The radius of the sphere in which all data points of interest are contained.
    • t0: The start time of data to be fetched, in UNIX epoch microseconds.
    • t1: The end time of data to be fetched, in UNIX epoch microseconds.

  • credentials: Optional information about data domain and user.
    • domain: A data domain to be queried. Defaults to “public”. (obligatory for non-certificated access or for certificates with multi-domain access)
    • username: Used when accessing a private domain.
    • password: Used when accessing a private domain.

. Typical units representation

  • 2224441636 : Length
  • 2224212260 : Mass
  • 2224183588 : Time
  • 2224180004 : Current
  • 2224180004 : Electric Current
  • 2224179556 : Temperature
  • 2224179500 : Amount of Substance
  • 2224179493 : Luminous Intensity
  • 2224703780 : Area
  • 2224965924 : Volume
  • 2224437540 : Speed
  • 2224437540 : Velocity
  • 2224433444 : Acceleration
  • 2224199972 : Irradiance
  • 2223941924 : Pressure
  • 2224723748 : Electric Potential
  • 2224961828 : Water Flow

. Response codes

The HTTP response codes are used to provide a response status to the client.

Possible response codes for an API request:

  • 200:
    • get.php: it means that a query has been successfully completed and the response contains the result (which may be empty)
  • 204:
    • create.php: it means that the series has been created successfully (there is no content in the response).
    • attach.php: it means that the series has been attached successfully (there is no content in the response).
  • 400: it means there is something wrong with your request (bad format or inconsistent field).
  • 401: it means that you are not authorized to manipulate your domain.

. Examples

The following python code queries luminous intensity data at LISHA from the last 5 minutes.

#!/usr/bin/env python3
import time, requests, json

get_url ='https://iot.ufsc.br/api/get.php'

epoch = int(time.time() * 1000000)
query = {
        'series' : {
            'version' : '1.1',
            'unit'    : 2224179493,
            'x'       : 741868770,
            'y'       : 679816011,
            'z'       : 25285,
            'r'       : 10*100,
            't0'      : epoch - (5*60*1000000),
            't1'      : epoch,
            'dev'   : 0
        },
        'credentials' : {
        	'domain' : 'smartlisha',
                'username' : 'smartusername',
                'password' : 'smartpassword'
        }
    }
session = requests.Session()
session.headers = {'Content-type' : 'application/json'}
response = session.post(get_url, json.dumps(query))

print("Get [", str(response.status_code), "] (", len(query), ") ", query, sep='')
if response.status_code == 200:
	print(json.dumps(response.json(), indent=4, sort_keys=False))

. Plotting a dashboard with Grafana

To plot a graph, do the following:

  • 1. Inside Grafana’s interface, go to Dashboards => Create your first dashboard => Graph.
  • 2. Now that you are seeing a cartesian plane with no datapoints, click on Painel Title => Edit.
  • 3. This should take you to the Metrics tab. Now you can choose your Data Source and put it’s due information.
  • 4. If you are using SmartData UFSC Data Source, fill the Interest and Crendential fields with the information used in section 2.4.
  • 5. You can tweak your plotting settings by using the Axes, Legend or Display tabs. Save your Dashboard by hitting Ctrl+S.

After doing these steps, information should be shown instantly.

. iot.lisha.ufsc.br Binary API

. Create or Attach series

  • Create will create a series only if it does not already exist (identical parameters).
  • Attach will create a series only if there is no series containing it (space and time).

Method: POST
URL for create: https://iot.lisha.ufsc.br/api/create.php
URL for attach: https://iot.lisha.ufsc.br/api/attach.php
Body: Series

Byte 36 32 28 24 20 16 8 0
version unit x y z r t0  t1

. Insert data

Method: POST
URL: https://iot.lisha.ufsc.br/api/put.php
Body: Smart Data

Byte 50 46 38 37 36 32 28 24 16 0
version unit value error confidence x y z t mac

. Version format

The version field has 8 bits and is composed of a major and a minor version. The major version is related to the API compatibility. On the other hand, the minor version defines some properties of the Smart Data. For instance, the minor version 1 defines a static Smart Data, while the minor version 2 defines a mobile Smart Data.

enum {
    STATIC_VERSION = (1 << 4) | (1 << 0),
    MOBILE_VERSION = (1 << 4) | (2 << 0),
};

. IoT client authentication using certificates

The EPOS IoT API infrastructure supports authentication with client certificates. In order to implement it, you should request a client certificate to LISHA in the Mailing List.

If you are using the eposiotgw script to send smartdata from a TSTP network to IoT API infrastructure, you should do the following steps to authenticate with the client certificate.

  • 1. Use eposiotgw with SVN revision greater than 4693
  • 2. Copy the files .pem and .key provided by LISHA to the same directory of the eposiotgw script
  • 3. Call eposiotgw using the parameter -c with the value equal the name of the certificate file WITHOUT the extension. Both files (.pem and .key) should have the same basename. For example, with the files client-1-A7B64D415BD3E97B.key and client-1-A7B64D415BD3E97B.key, you should call the -c parameter using the value client-1-A7B64D415BD3E97B.


If you are using esp8266 with axTLS library, you should convert the certificates to a suitable format, with two .der files. To do this follow the instructions below:

openssl pkcs12 -export -clcerts -in client-6-A7B64D415BD3E980.pem -inkey client-6-A7B64D415BD3E980.key -out client.p12
openssl pkcs12 -in client.p12 -nokeys -out cert.pem -nodes
openssl pkcs12 -in client.p12 -nocerts -out key.pem -nodes
openssl x509 -outform der -in cert.pem -out cert.der
openssl rsa -outform der -in key.pem -out key.der