Indigresso Wiki

Open Source Stuff for DASH7

User Tools

Site Tools


API Quickstart Guide

This is a “quickstart” users' guide for working with the client-server OpenTag API. The main focus is to give developers the information they need to control an OpenTag device (server) from another device (client). As such, it deals primarily with the Messaging (ALP) API as used over MPipe, but it does also describe the C API (OTAPI) to a limited degree.

Note: Developers may also find it valuable to look at the DASH7 Registry Guide. It contains information about how values in the registry files affect the way DASH7 devices behave.

1. Building an Application

See also Toolkit pages for: TI CCS, RIDE, GNU ARM

1A. Obtain OpenTag Codebase

The OpenTag codebase can be downloaded as an archived download, or the latest code can be downloaded directly from the git repository. For this quickstart, it is assumed that all readers know how to download and unpackage a tar.gz archive. Put the main directory (OpenTag_M2) in a convenient place on your Linux/Mac/Windows PC. This location will be referred to in the rest of this quickstart as: OT_ROOT/. In reality, you've probably stored it somewhere like: ~/Projects/OpenTag_M2. Once you have extracted and moved the codebase, verify that it contains a directory structure like the one shown below. If it does not, you have somehow downloaded the wrong thing.

1B. Open Example Application

This quickstart will refer to the Opmode Demo Application, which is stored inside OT_ROOT/Apps/Demo_Opmode. This demonstration runs a scan+beacon cycle and has some asynchronous dialog routines that can be activated by pushing buttons.

Verifying your board
Demo_Opmode is available for most officially supported boards. Verify that your board is supported by checking in OT_ROOT/Board/ to see if your board is officially supported at all, and then check in OT_ROOT/Apps/Demo_Opmode/Code/platform_config.h to see if this application supports your board.

If your board is unsupported
If the Demo_Opmode application does not support your board, you can try continuing this quickstart with another app that does. Most of the quickstart is common and consistent, and not dependent on the application you pick. On the other hand, if your board is not supported at all, this is a bigger problem. You can attempt to make a new board support file, or you can obtain a supported board.

Opening the project file
Inside the OT_ROOT/Apps/Demo_Opmode directory there is a subdirectory called Code and several other subdirectories. Each of these “other” subdirectories contains project files needed for one of the supported cross-compiler toolchains (most are IDEs). So, you will need a supported cross-compiler toolchain as well. This quickstart assumes you are using RIDE (ARM) or CCSv5 (MSP430) (users of a GNU-based toolchain are expected to know how to configure it). Go into the subdirectory with the name of your toolchain and open the project file with the name of your Platform. Example: /Apps/Demo_Opmode/Proj_RIDE7/STM32F10x.rprj

1C. Compiling the Project

If you are using RIDE, there isn't much to do. If you are using CCS (or another Eclipse-based toolchain), you'll need to account for the fact that Eclipse sucks, which means that you'll need to fix a lot of project settings that get lost during archival.

Platform Configuration

In the file OT_ROOT/Apps/Demo_Opmode/platform_config.h, find the section at the top of the file that contains a list of supported boards. Comment-out the boards you are not using, and un-comment the board you are using. Then SAVE.

RIDE Setup

Set Compiler Flags
There are compiler pre-processor includes to define the chip family (sub-platform), the endianness, debugging blocks, and whatever else you want to include. The form of these is: \OPTION\ (two underscores on each side). Go to: …. and change the includes to suit your needs. You can remove the DEBUG option to remove debugging features built-in to the code, and you should always make sure that the chip family of your board's chip is accurately represented.

After this, build the code using “Project→Make Project” from the menu. Everything should build without issue. If something does not build properly, it is probably due to an unresolved link. The file links in the project should be relative, but if there is an absolute file link, locate the file in the codebase directory structure (in the left window pane of RIDE), select it, and change the file link to match the placement of the OpenTag_M2 directory on your system.

After all of the boards, tools, and cables are connected, and after the project is built (4.1.1), simply use the menu option Debug→Start. RIDE7 will begin loading the project binary onto the board. Use the menu option Debug→Run to initiate the runtime. To cease the runtime, use the menu option Debug→Stop and, after this, Debug→Terminate.

After the project binary is loaded to the board, anytime you turn-on the board it will begin running the program. This is true if you used pre-complied code or code that was built with RIDE. After the program is loaded, RIDE does not need to be open and the R-Link does not need to be connected. However, if you wish to use the debugging features of RIDE, you will need to keep RIDE open and the R-Link connected.

CCS Setup

To be completed.

2. Connecting with OTcom

OTcom Article
After step 1, the Opmode Demo should be running. There should be some LEDs blinking, indicating that the device is doing some listening and transmitting (conventionally, green=listen and orange=transmit). The device is also sending logger packets out of its MPipe port. On all officially supported boards, the MPipe port is either a USB-CDC port or a TTY UART. Check the board documentation and make sure that this MPipe port is connected.

If you have a board that supports MPipe over USB, you may need a driver (check the board documentation). You will also need to make sure the client (e.g. a PC) properly discovers the MPipe USB device, which usually happens immediately after the device is attached.

If you are using a UART interface for MPipe, it will use a standard TTY or COM port driver. The TTY setting on OpenTag is by default: 115200 bps, 8N1, no handshaking.

Connecting After Reset
Every time you reset the device you will need to reconnect OTcom, because the port driver will drop the connection when the device is reset. The one exception is if a UART MPipe is attached to an additional UART-USB converter. In this case, the converter will remain connected and it will manage the MPipe connection transparently. Some boards have a UART-USB convertor on-board.

2A. Establishing Connection

  1. Configure OTcom for 115200 bps
  2. Select the “COM” port that matches the MPipe port's COM association. If you are using Linux/Mac, please refer to the OTcom documentation on how to associate a “COM” number to the MPipe Port.
  3. Select the “Print NDEF/OT” formatting option from the pull-down box on the bottom.
  4. Press the “Start Logging” button

If the board is working and you have done everything correctly, the OTcom window might look something like the screenshot below (in the screenshot, the port has been disconnected after reading-in some logs). There will be a stream of log packets coming onto the screen at the same rate as the LED blinking.

2A. Reading/Deciphering Output

Logger OTAPI Article
Most of the logs that will be coming into OTcom are via the function otapi_log_hexmsg. They include a sort UTF-8 (text) label and then a dump of hex data. The best way to view the logs is with the “Print NDEF/OT” formatting option.

OT/NDEF mode

The OTcom “Print NDEF/OT” formatting option will strip-away the NDEF header that is always used with messages transmitted over MPipe. Three data elements will be printed for each received packet

  1. The sequence number from the MPipe footer
  2. A code-word that matches the record's ALP ID. In the example above, the packets are Logger packets (ALP ID = 3) and, as we would expect, the code-word in each case is “LOG.”
  3. The payload

In the current version of OTcom, the Logger ALP command ID is ignored, and “Print NDEF/OT” will always reproduce data as text. In later versions, more advanced formatting will be added, and the command ID will need to be 1, 3, 5, or 7 in order to have the same formatting as the current version implements in all cases.

Raw Mode

When OTcom is put into raw formatting mode, each received byte of the packet is printed on the screen as hex. Raw mode is a good way to analyze NDEF headers and MPipe footers. Raw mode is not very useful if the application code uses otapi_log_hexmsg as this logger function converts to hex-represented text on the server-side.

2B. Sending API Commands over OTcom

ALP API main article
ALP API commands can be sent over OTcom via the input box at the bottom of the screen. There is not yet a GUI toolset for point-and-click API command generation, although this is a planned feature for a future release. Altering registry data is one useful and fairly easy way to use the API-input box, and some examples are presented.

OTAPI Basics

OTAPI main article
OTAPI is the C API that exists on the server, and it is directly mapped to certain ALPs (i.e. ALPs 0x03, 0x80, 0x81, 0x82). ALP commands of these types are received by the server are converted directly into OTAPI function calls. OTAPI functions can, of course, also be called as C functions in server-side code. Some ALPs are specified by DASH7, most notably the Filedata ALP. These ALPs do not necessarily have matching OTAPI C functions, but of course they are implemented in C somewhere within OTlib. For example, the Veelite Module implements everything required of the Filedata ALP.

Command Packing

NDEF main article
For current versions of OTcom and OpenTag, it is advisable to send only one record per message. Therefore, the NDEF flags byte will always be 0xDD. However, certain ALP commands – especially those in the Filedata ALP – have an SIMD-like design. For example, it is possible to batch-read several files with a single command.

OTcom Syntax for API Entry

[Description of input syntax]
[Image of OTcom being used to enter API commands]

2C. Some Examples

Some examples of ALPs being used for API features.

Reading data from several files

The next section covers the Filedata ALP in more detail, but here is a preview of an ALP request to read data from several files (ISF 3,4,5) and the expected response.
[Tables of Input and Output, and OTcom entry string]

Writing data to a file

The next section covers the Filedata ALP in more detail, but here is a preview of an ALP request to write data to ISF 0, and the expected response.
[Tables of Input and Output, and OTcom entry string]

Re-initializing the Kernel: otapi_sys_init()

After modifying ISF 0 (the network settings registry file), the kernel should be reset so it can take the new settings. Here is how to do it.
[Tables of Input and Output, and OTcom entry string]

Preparing a dialog: sys and m2qp call series

It is possible to prepare any sort of dialog over the ALP API, although it requires multiple calls (see section 4 for information on how to build your own wrapper ALP that bundles all of these commands into a single call). The example below prepares an anycast query that searches for all devices that have been given VIDs (VID != FFFF)
[Tables of Input and Output, and OTcom entry string]

3. Working with Filedata API Commands

DASH7 Filesystem Article, DASH7 Filedata ALP Article
The filedata ALP is very important, because it gives administrators the ability to change the contents of the registry (see DASH7 Filesystem). The values in the registry affect the way OpenTag devices (and all DASH7 devices) behave. You can change addresses, subnets, duty cycles, channels, and basically every other MAC feature. By doing nothing other than modifying the filesystem correctly, you can change a device from being a very simple beaconing-device to a sophisticated device implementing a synchronized MAC not unlike GSM.

OTcom contains a special command syntax for using Filedata ALP commands, so it is not difficult to read and write file data from the console. This section contains several examples of Filedata API usage, including descriptions of exactly what is happening.

3A. Reading Commands

The Filedata ALP commands that are capable of reading data from the filesystem are structured as a request and a response. The request contains information about which files and which data should be read, and the response contains the data.

File Read Commands

  • Read File Permissions: Takes a list of File IDs, returns the permissions of each File ID
  • Read File Headers: Takes a list of File IDs, returns the header of each File ID
  • Read File Data: Takes a list of File-Read-Templates (ID + offset + read length), returns the corresponding data from each one
  • Read File Header & Data: Takes a list of File-Read-Templates (ID + offset + read length), returns the corresponding header and data from each one

Example: Read File Headers

General Syntax OT+RH <filetype> <id_a> <id_b> …
Example Input OT+RH ISFB 00 01 04
Example Output OT+RH ISFB 00 34 00 0A 00 0A 01 24 00 30 00 30 04 34 00 04 00 20

Your output may be slightly different, depending on the way the files are set-up on your system, although it should be the same as above. The File Header is a 6-byte field designed as [ID][Permissions][Length][Allocation]. ID and permissions are 1 byte each, and the length and allocation are 2-byte big endian. So, looking at the return from file 04 (sleep scan series), we can see that it has permissions = 0x34 (rw-rw-r–), length = 0x0004, allocation = 0x0020 (32).

Example: Read File Data

General Syntax OT+R <filetype> <id_a>,[off],[len] <id_b>,[off],[len] …
Example Input OT+R ISFB 00,0000,00FF
Example Output OT+R ISFB 00 00 00 00 0A 1D B0 11 11 08 4F 00 01 00 04

Your output may be slightly different, depending on how ISF 00 (network configuration settings) is configured. For more information on the structure of this file, check DASH7 Mode 2 Spec article. The important things to know are the input and output formats. The input uses a 5-byte control field structured as [ID][offset][data length] (offset and data length fields are 2-byte big endian). The output uses the same 5-byte control field, followed by the data. You may notice that the input control is 00 00 00 00 FF and the output control is 00 00 00 00 0A. If you remember from the past example (reading file headers), the length of ISF file 00 is 0A (10), so the output is adjusted to not exceed the file length. Following the control field are the 10 bytes of file data.

Example: Read File Data, With an Error

General Syntax OT+R <filetype> <id_a>,[off],[len] <id_b>,[off],[len] …
Example Input OT+R ISFB 57,0000,0040
Example Output none

Unless you have added a file 0x57 to the ISFB, there will be no file 0x57 and therefore nothing to read. The DASH7 specification for the filedata ALP leaves the behavior of read errors undefined, but it suggests that they may be ignored. OpenTag adheres to the policy of ignoring read errors. In the case where the read command is a batch read, successful reads are returned, and unsuccessful reads are ignored.

3B. Writing Commands

The Filedata ALP commands that are capable of writing data to the filesystem are structured as a request and a response. The request contains information about which file (or files) should be written, as well as the data that is to be written. The response contains a set of errors or acknowledgements.

File Write Commands

  • Write File Permissions: Takes a list of File-Permissions-Write-Templates (File ID + Permissions), returns errors/ACKs
  • Write File Data: Takes a list of File-Write-Templates (File ID + offset + write length + data), returns errors/ACKs
  • Create File (optional): Takes a list of File Headers, returns errors/ACKs
  • Delete File (optional): Takes a list of File IDs, returns errors/ACKs

Example: Write File Data

General Syntax OT+W? <filetype> <id_a>,[off],[len] <data> <id_b>,[off],[len] <data> …
Example Input OT+W? ISFB 05,00,04 12 1F 01 00
Example Output OT+ERR ISFB 05 00

This example writes a new, 4-byte scan period to the Hold Scan Series. This period will replace whichever scan period used to be first in the series, because it is being written to offset 0 of the file. The example implements a 60ms (64 tick) foreground scan on channel 12, followed by 256 tick idle period until the next scan. The format is: [1B: channel ID for scan][1B: scan code][2B: time until next scan]. The “time until next scan” is a big endian number in units of 1/1024 sec (1 tick). The scan code is an exponent + mantissa control value explained in the DASH7 Mode 2 data element spec.

The output of the example is the error command, which returns 05 00, indicating that the write on file 05 had no error (and thus succeeded). If you use OT+W instead of OT+W?, there will be no error reporting and no output. If you batch-write to multiple files in a single command, the output error list will be streamed in the same order as the input.

Example: Create & Delete File

Note: Create & Delete File commands are not always implemented. If they are not implemented, an error of type 255 (Unknown Error) will be returned. Even if they are implemented, use them sparingly because the filesystem implementation (Veelite) is not optimized for dynamic file management.

Create File

General Syntax OT+NEW? <filetype> <id_a>,[perm],[len],[alloc] <id_a>,[perm],[len],[alloc] …
Example Input OT+NEW? ISFB 88,34,0000,0040
Example Output OT+ERR ISFB 88 00

In the example above, we create ISF file 0x88. It has permissions 0x34 (rw-rw-r–), initial length is 0, and the allocation is 0x0040 (64 bytes). If files are created without initial length = 0, latent data in the memory will be readable in the file, so it is always best to use length = 0 when creating files unless you have some special hack.

Delete File

General Syntax OT+DEL? <filetype> <id_a> <id_b> …
Example Input OT+DEL? ISFB 88
Example Output OT+ERR ISFB 88 00

In the delete example, we delete the file we just created. The syntax should be self explanatory. Note that files defined at compile time CANNOT be deleted – only files created during runtime can be deleted.

4. Making a New ALP and a Custom Command

OTAPI Main Article, ALP OTlib Article
A well-publicized feature of the OpenTag API is the ability to add more OTAPI and ALP features. The OTAPI C API is very low-level, so if any abstraction is desired in the application, the developer will need to build an API wrapper on the client-side or the server-side. In this section, a server-side API will be added to OpenTag that wraps the sequence of ALP calls shown in “Preparing a dialog” of 2C. into a single ALP call.

OTAPI Extensions

OTAPI is a C-language API, consisting of C functions of a common form. Developers can add new functions that follow this form, and they can put them anywhere inside the codebase. Generally, these custom OTAPI functions should be stored in the OT_ROOT/Apps/[App Name]/Code directory or somewhere inside OT_ROOT/OTlibext if they are part of an official experiment or extension. Developers can of course call these functions from anywhere inside their app code.

ALP API Extensions

In order for ALP API extensions to be made, the corresponding OTAPI extensions must first be made. Then, two modifications must be made.

1. Enable ALPEXT in app_config.h
In the file OT_ROOT/Apps/Demo_Opmode/Code/app_config.h, make sure the line below is present. It should be towards the top of the file, in a bank of OT_FEATURE_… macros.


2. Implement alp_proc_user()
In the file OT_ROOT/OTlib/OTAPI.h the function otapi_alpext_proc() is defined. All ALPs that are received by OpenTag by any means (MPipe, DASH7, whatever) are processed by alp_proc(). ALP frames with unrecognized ALP IDs are sent to otapi_alpext_proc(), so the user-custom ALP that is shown in this example is given an arbitrary, unused ALP ID. It is best practice to pick ALP IDs in the range 0x90-0xFE. For some ideas how to implement sophisticated ALP parsers, the Filedata ALP implementation is a good reference (OT_ROOT/OTlib/alp_filedata.c) as is the Query ALP implemented in OT_ROOT/OTlib/alp_api_server.c.

4A. Some Example Code

This example will implement the features of the mode buttons in the Opmode Demo as an ALP API. This is a fairly simple demonstration of ALP, and much more sophisticated protocols are possible. This protocol contains no payload data, just a command code indicating which function to do.

  1. Set mode to Gateway
  2. Set mode to Endpoint
  3. Prepare and send asynchronous beacon
  4. Prepare and send asynchronous query (Gateway mode only)

Example ALP specification

We could pick different values, but here is how this example is implemented.

Opmode Demo ALP API (ID = 0x90)
Payload Len ALP ID ALP Cmd Function
0 0x90 0x00 Set mode to gateway
0 0x90 0x01 Set mode to endpoint
0 0x90 0x02 Prepare and send asynchronous beacon
0 0x90 0x03 Prepare and send asynchronous query (Gateway mode only)

The functions “Set mode to gateway” and “Set mode to endpoint” are implemented using system layer functions, which is an exposed low-level interface. The other two, however, are purely OTAPI wrappers. They could be sent over ALP using sequences of default OTAPI functions. For example, ALP [0x90,0x03] (Prepare and send asynchronous query) could be constructed from the following inputs into OTcom:

RAW_ 81,02 00 00 00 00 00 0010          #otapi_new_session(...)
RAW_ 81,03 80 00 00 00 00 00            #otapi_open_request(ADDR_anycast, ...)
RAW_ 82,01 20 06 00                     #otapi_put_command_tmpl(...)
RAW_ 82,02 0080 0000                    #otapi_put_dialog_tmpl(...) 
RAW_ 82,03 26 01 02                     #otapi_put_query_tmpl(...)
RAW_ 82,06 00 07 0000                   #otapi_put_isf_comp(...)
RAW_ 82,07 00 0D 0020 0000              #otapi_put_isf_call(...)
RAW_ 81,04                              #otapi_close_request() 
RAW  81,06                              #otapi_start_dialog()

As you might deduce from the example, ALP-OTAPI was never meant to be used in a console like this. It is much easier to use when you have a sophisticated client with GUI features and stored scripts (which would look like above). Alternatively, the stream of commands can be implemented in C, using OTAPI on the server-side, and the resulting wrapper function can be given its own ALP ID and CMD. Using that model, all of the above is just going to be wrapped into the following, simple command, and it will be expanded on the server-side:

RAW 90,03

Much easier!


The otapi_alpext_proc() function is already implemented in OT_ROOT/Apps/Demo_Opmode/Code/main.c and it just needs to be uncommented. The code is also shown below:

void otapi_alpext_proc(alp_record* in_rec, alp_record* out_rec, Queue* in_q, 
                        Queue* out_q, id_tmpl* user_id) {
/// For this example, the directive ID is 0x90 and the commands are 0-3.  You
/// can change these values simply by changing the implementation of this 
/// function.

    if (in_rec->dir_id == 0x90) {
        switch (in_rec->dir_cmd) {
            case 0: sys.loadapp = &app_send_query;      break;
            case 1: sys.loadapp = &app_send_beacon;     break;
            case 2: sys.loadapp = &app_goto_gateway;    break;
            case 3: sys.loadapp = &app_goto_endpoint;   break;
           default: return;
        /// Write back success (1) if respond (CMD bit 7) is enabled
        alp_load_retval(    (in_rec->dir_cmd & 0x80), 
                            (in_rec->dir_cmd | 0x40), 
                            1, out_rec, out_q           );

4B. Putting the Code into OpenTag

If you are using the Opmode Demo, the main app C file has the implementation of otapi_alpext_proc() already there, and you just need to uncomment it. You will also need to make sure to have #define OT_FEATURE_ALPEXT ENABLED inside app_config.h (see the first part of this chapter for more implementation notes). After you make these two small changes, you will be able to send short API commands from OTcom to the Opmode Demo to do the same thing as the mode buttons do.

4C. Using the New Command

opentag/api/quickstart.txt · Last modified: 2012/04/04 23:54 by jpnorair