API info is here: swi_airvantage.h
The info here covers details on data connections with AirVantage.
The AirVantage Agent Connector library provides access to the AirVantage M2M platform. The Agent consists of a library and process that communicate through a dedicated IPC channel, most commonly a socket.
Communication with the server includes buffering and consolidating data on the embedded side, flushing them to the server according to customizable policies, subscribing to server-side or hardware events and value changes, acknowledge management.
The Agent naturally reasons by assets: connections to it are associated with a given asset when established, events and notifications are dispatched by asset, etc. The Agent's logical assets might map one-to-one with physical assets connected to the physical device, but they don't have to. Within an asset, data are organized into tree paths, and it is possible to subscribe to data or event limited to any arbitrary sub-path.
As a general principle, the Agent takes responsibility for the data that have been passed to it: it is in charge of optimizing their encoding and regrouping, of handling acknowledgements, of securing them in non-volatile memory if asked to, etc.
Creating a new asset is as simple as calling swi_av_asset_Create
with a mandatory asset id string. It returns an AirVantage asset object, which acts on behalf of the asset.
An asset does not necessarily represent a physical piece of hardware; it is merely a representation of the global application architecture.
At this point, the asset is created but is not ready to communicate with the Agent. To make it active, the swi_av_asset_Start
method must be called first, after any required event subscription has been performed.
The asset identifier is the root element of the message path. For instance, if the variable "foo" is written under path "bar" in the asset "myAsset", the complete path as seen by the server is "myAsset.bar.foo".
Data can be sent with two different APIs:
Why policies?
Policies introduce an indirection in the way data are flushed from the agent to the server. This indirection is extremely precious over the lifetime of an M2M application: policies can be changed remotely, by asking the server to update the agent's configuration. If data triggering were done explicitly by the application, adapting the reporting policy to changing conditions (bandwidth congestion and billing, change in usage patterns...) would require a full software update.
There are a couple of legitimate, very advanced cases where an application needs direct control over data sending policies, and this can be done by forcing the triggers on a manual-only policy. But it should be avoided in most reasonable use cases, and represents a liability for long term maintenance.
Noteworthy events are notified between the assets and the server by sending data. When designing an application, some conventions are taken about which paths represent "normal" data, and which ones will be used to represent events. The embedded application will subscribe to these paths and hook a proper handling function on them; symmetrically, the server will be configured to react to "event paths" by causing the appropriate notifications.
Both data sending APIs can be used (raw data or pre-declared tables). However, given the generally simple and immediate kind of data exchange suitable to event notifications, the raw data API will most often be the best choice.
Data is not normally sent to the server as soon as the user requests it. It is accumulated by the Agent to limit the number of connections, to optimize their encoding, and optionally to perform some data consolidation operations on them. Data emission is performed according to a policy, which can be:
cron="cron_config"
: The operation is performed at predefined dates, specified using the standard Unix cron syntax.latency=n
: The operation will be performed in n
seconds at most.manual=true
: The connection will be triggered by the application through an explicit call to swi_av_TriggerPolicy()
.onboot=n
: The operation will be performed n
seconds after the agent has been initialized.There can be multiple policies set up on a single device, and AirVantage APIs allow to choose according to which policy when each data is sent.
Policy Examples
If cron="*"
, the device will connect at the beginning of every hour if there is something to send. Even if a connection is forced at 8:59, the cron connection will still be forced at 9:00.
If latency=60*60
, the device will connect every one hour: the first connection will be done one hour after the device booted. However, if a periodic connection is due at 9:00, and a connection is forced at 8:59, the next connection will occur at 9:59 rather than at 9:00. This policy guarantees that data will not be buffered for more than 60*60 seconds before being sent to the server, and that no more than 60*60 seconds will pass between two connections. (Connections not only allow data to be sent to the server, but also to receive data sent by it).
onboot=n
policy rules are mostly useful if some unsent, persisted data might have been left unsent before a reboot. With such a policy, data unsent because of a shutdown will be sent when the device reboots.
Policy Configurations
To allow the handling of several policies, policy queues can be declared, in unlimited number, in the agent's configuration. They are indexed by name in "data.policy"
, and contain a table with one key and one value. The key is one of "cron", "latency", "manual"
. More than one pair can be given for a single policy.
Some policies must exist and have certain properties:
"default"
is the policy chosen when a data sending command is given with no explicit policy. Users can change the way this policy is triggered."never"
cannot be triggered: data associated with this policy are never sent."now"
is intended for data which are to be sent (almost) immediately. It must be configured to be sent with a latency, and in normal situations, this latency should be short, no more than a couple of seconds.Please note that even though basic knowledge on data policies is advised to correctly use AirVantage API, the policy configuration (creation/modification) demonstrated in this very section is optional. In basic use cases, using the default policies as provided by the agent will fulfill the needs.
There are several ways to access the Agent configuration: you can change the provisioning configuration, connect to the agent telnet console, use an API or even do it remotely using AirVantage platform.
In the following example, the programmatic approach is taken, using the dedicated API from swi_devicetree.h to access Agent parameters.
(You can have an overview of the swi_devicetree API by reading the section 5. Setting and Getting Agent Internal Variables
)
The path parameter specifies the datastore path under which data will be stored relative to the asset node, the last path segment will be used as a datastore key.
These functions send some data according to the specified policy (or the default policy if the policy is not specified).
Notice that for the server, all data is timestamped. If specific value SWI_AV_TSTAMP_NO
is used, no timestamp is put in the record sent to the server, it will be timestamped at the date of its reception by the server.
Examples
Data tables can be declared as follows:
A table is associated with a given path (relative to the asset's root) and policy (default policy if unspecified). It can also have either a STORAGE_RAM
or STORAGE_RAM"
mode. Finally, it predeclares the columns which it handles; all records later pushed in the table must conform to this set of columns. The parameter columnNamesPtr
is a list of column names as strings.
Using this API, if the data is meant to be timestamped on the device ( i.e. at sending/acquisition time) , then the table declaration must contain a column named "timestamp"
, later on filed with integers.
In the future, columns will support more advanced settings, including serialization policies which affect their bandwidth usage vs. data precision compromise.
The result of this function is a table proxy object table
, which supports methods swi_av_table_PushFloat
, swi_av_table_PushInteger
, and swi_av_table_PushString
, to fill a row with each column value, and finally swi_av_table_PushRow
to push the whole data row to the Agent.
Example
Push a row of data in a predeclared table. Keys must match the predeclared column names.
Example
All the data attached to a given policy can be flushed to the server immediately with function:
If policyPtr
is passed as NULL, the default policy is used. If the special name
is passed, all policies are flushed."*"
Writing Data
Registering a Function to handle data reception
Acknowledging Received Data
Received Data Sample
Setting and Getting Agent Internal Variables
AirVantage server is able to send data to a device in order to request some action on it: changing some configuration parameter, trigger some action etc. The data can be addressed to the AirVantage Agent or to another application, in any case the AirVantage Agent will receive the data first and then forward it to the appropriate application.
(FYI, AirVantage server can only modify data defined in the application data model as a setting, and not a variable.)
AirVantage Agent library provides API to enable your application to handle the reception of data coming from the AirVantage server.
Once a callback has been registered, it will be called each time the server sends some data to the application, alongside with customizable userdata.
The pathPtr
specifies the root path of the data, this way the application can determine what is the point the data being received. (e.g., the path can be "action1" or "action2" to provoke two different behavior of the application.)
The data
object is meant to iterate over the values received. As received data are completely dynamic from the library point of view, this object makes it possible to abstract any kind of data the application can receive (string, integer, float, ...).
The application have to iterate over the object to get all received values. Let's take one example: acting on a garage door of a house. The message from the server could trigger this action with two parameters : the direction and the speed. In that example, the pathPtr
could be "garageDoor", then the data
object could contain 2 items: the first one named "direction" and value "up", the second named "speed" with value "max".
Finally the ack_id
param is used to acknowledge the data, see the next section for that topic.
When the AirVantage server sends data, it can request to receive an acknowledge to confirm the correct processing of the data by the application. This acknowledgment takes place at an applicative level, meaning that it is up to the application to acknowledge the data, once the appropriate actions have been taken.
AirVantage Agent library provides this function to fulfill this need.
The Agent has a list of internal variables that can be manipulated by a user application. For instance, these variables allow to interact with the Agent configuration.
The provided "Get" and "Set" API allow to access those Agent internal variables.
The swi_dt_Get
API allows you to retrieve the value of a terminal variable as well as to retrieve and discover branches of the tree representation of variables.
The swi_dt_SetInteger
, swi_dt_SetFloat
, swi_dt_SetString
, swi_dt_SetNull
, swi_dt_SetBool
API allow you to set the value of a terminal variable and to create a new variable when it does not exist.
The swi_dt_Register
API allows you to subscribe to change on individual variables, on whole sub-trees, or on a mix thereof. It also handles passive variables: normally, when a callback is triggered because some registered variables changed, it only receives the variables whose values changed as parameters. If some passive variables are listed during the registration, their content is always passed to the callback, whether it changed or not. A change in a passive variable won't trigger the callback, though–unless it is also listed as an active one.
Copyright (C) Sierra Wireless, Inc. 2014. All rights reserved. Use of this work is subject to license.