Introduction
This document contains topical guides that are helpful for embedded engineers implementing host applications that interface with the ACA.
ACA Overview
The Arrayent Connect Agent (“ACA” or “the Agent”) is a cross-platform embedded software library that abstracts and simplifies a connected device’s session with the Arrayent Connect Cloud (“ACC”, “the cloud”, or “the Arrayent Cloud”).
In contrast with the Arrayent Connect Module, the ACA is software-only. The host application of the device includes the ACA as a library, and interacts with the ACA via the ACA’s high-level API, written in C. Device credentials that uniquely identify each unit are flashed into non-volatile memory at the time of manufacture. To create a device session in the Arrayent Cloud, the host application of a device reads its credentials from nonvolatile memory, configures the ACA with these credentials, and then initializes the ACA. The ACA is responsible for connecting to the cloud, maintaining a device session, and sending and receiving messages on behalf of the host application. When the host application wishes to send its status to the Arrayent Cloud, it assembles the message as a key-value pair and submits the message to the ACA. The ACA transmits the message to the Cloud on behalf of the host application. Receiving messages from the cloud is implemented as a pull model. The host application polls the ACA to determine if it has received any messages from the Cloud. The ACA returns any queued messages to the host application. From there, it is the responsibility of the host application to parse the received message and execute any operations contained in the message. Most host applications implement a separate thread that is constantly listening for incoming messages.
ACA is written in C, and presented as a single static archive. The ACA archive contains object code for two layers, including a platform-abstracting layer called the Board Support Package (“BSP”) that abstracts the networking, operating system, and hardware resources of the computing platform which the ACA and host application will run on top of. For this reason, each supported platform is distributed as a separate archive file. The Arrayent Connect Agent API which the host application interacts with is consistent across all supported computing platforms. This enables Arrayent Customers to leverage different computing platforms for different products, while developing and reusing generic C libraries across those projects.
The block diagram below illustrates the general high-level interface between an ACA, a host application, and the platform that the ACA and host application are running on top of.
The host application uses the functions and data structures defined in the header file aca.h
to interact with the ACA. The ACA draws directly on the operating system and network resources of the computing platform which is hosting it. For instance, on the Broadcom WICED platform, the ACA accesses network and operating system libraries through the WICED SDK.
Guidelines and Best Practices
This section explains how to responsibly and efficiently implement the ACA in the host application of your device.
Pre-Initialization
“Pre-initialization” refers to the procedures that the host application must execute before using the Arrayent Connect Agent (ACA).
- Initialize the operating system and networking resources.
- Seed the pseudorandom number generator (PRNG). The ACA uses the PRNG for AES encryption.The seed must be sufficiently random. A common approach for ensuring a sufficiently random seed is to sample the current value of a physical resource on your device, such as a floating pin. E.g.
srand(read_adc(floating_pin))
. Failing to generate a sufficiently random seed for the pseudorandom number generator can compromise the network security of your devices. - Establish a connection to a Wi-Fi Access Point. The ACA does not manage Wi-Fi connectivity for the host application.
Configuration
The ACA does not internally store the configuration attributes which it needs to establish a device session in the Arrayent Cloud. Rather, the host application supplies them to the ACA. The ACA takes the attributes provided by the host application and attempts to create a device session in the Arrayent Cloud.
The data structure which defines the ACA configuration attributes is called arrayent_config_t, which is located in aca.h. These attributes include the Device Code which uniquely identifies the unit, the URL of the Arrayent Cloud, the TCP/UDP port that is used to connect to the cloud, and so on. Most of these attributes are static (or “global”), meaning that the value of the attributes are the same for all units. For example, the TCP/UDP port that the ACA connects to is the same for all units. Some of the attributes are unique to individual units, such as the Device Code, which is the unique identifier for an individual unit.
In a production scenario, you must flash the ACA configuration attributes into non-volatile memory of the units during the manufacturing process. To initiate a cloud session, the host application reads the attributes from flash, populates the Arrayent configuration structure (arrayent_config_t), and then passes the populated configuration structure to the ACA.
Initialization
“Initialization” referes to the procedures the host application must execute in order to bring up the ACA into its normal operating state.
After initializing the operating system and networking resources, you can initialize the ACA.
- Initialize an arrayent_return_e enumerator. You will use this to monitor the result of each Arrayent function that you call.
arrayent_return_e arrayent_return_code;
- Initialize an arrayent_config_t struct.
arrayent_config_t arrayent_config;
- Call
ArrayentSetConfigDefaults
, passing the arrayent_config_t struct by reference. This will populate the struct with default configuration attributes. This is only available for ACA versions 1.3 and later.
ArrayentSetConfigDefaults(&arrayent_config);
- Populate the arrayent_config_t struct with the unique configuration attributes for this particular device. See configuration above.
- Call
ArrayentConfigure
, passing the arrayent_config_t struct by reference.
arrayent_return_code = ArrayentConfigure(&arrayent_config);
- If the configuration was successful then initialize the ACA.
if (arrayent_return_code == ARRAYENT_SUCCESS) { ArrayentInit(); }
Connection Status
The procedure below explains how to check if the ACA is connected to the Arrayent Cloud.
- Create an arrayent_net_status_t struct. arrayent_net_status_t is a bitmask of information related to the current network status of the ACA:
arrayent_net_status_t arrayent_status;
- Call
ArrayentNetStatus
, passing the arrayent_net_status_t struct by reference:ArrayentNetStatus(&arrayent_status);
- Check the value of arrayent_net_status_t.connected_to_server. When connected_to_server equals
1
the ACA is connected to the Arrayent Cloud:if (arrayent_status.connected_to_server == 1) { // ...
If the ACA remains unconnected after 15 minutes, you may call ArrayentReset
once.
Mutli-Threaded Host Applications
It is safe to call ACA receive functions (ArrayentRecvMultiAttribute
, ArrayentRecvData
, ArrayentRecvProperty
) on one thread while simultaneously calling send functions (ArrayentSetMultiAttribute
, ArrayentSetProperty
, ArrayentSendData
) on another thread.
It is NOT safe to simultaneously call any send functions (ArrayentSetMultiAttribute
, ArrayentSetProperty
,ArrayentSendData
) from different threads.
It is NOT safe to simultaneously call any receive functions (ArrayentRecvMultiAttribute
, ArrayentRecvData
,ArrayentRecvProperty
) from different threads.
For ACA versions 1.5.1 and below it is NOT safe to simultaneously call ArrayentNetStatus
and any send functions (ArrayentSetMultiAttribute
, ArrayentSetProperty
, ArrayentSendData
) from different threads. It is safe in ACA versions 1.5.2 and above.
It is NOT safe to call ArrayentInit
more than once. After device powerup and once the ACA successfully connects to the Cloud, the host application should never call ArrayentInit
again.
Multi-Attribute Messages
Unless specifically instructed by Arrayent, all host applications should communicate with the ACA in multi-attribute message format.
Configuration
The host application must specifically configure the ACA to send and receive messages in multi-attribute format.
- When configuring the arrayent_config_t struct, set the device_can_multi_attribute member of arrayent_config_t to
1
.
arrayent_config_t arrayent_config; ArrayentSetConfigDefaults(&arrayent_config); arrayent_config.device_can_multi_attribute = 1; // ... set the rest of the arrayent_config_t members ... ArrayentConfigure(&arrayent_config);
Sending Multi-Attribute Messages
Use ArrayentSetMultiAttribute
to send data to the Arrayent Cloud. This function enables you to update the value of multiple device attributes with a single message.
Do not use ArrayentSetProperty
to send data to the Arrayent Cloud. This function can only update the value of a single device attribute.
Warning
Only call ArrayentSetMultiAttribute
from a single thread. Never call it from more than one thread.
If ArrayentSetMultiAttribute
returns an error DO NOT RETRY calling it. Instead check for the connection to the cloud first and wait at least 3 seconds before calling this function again
Receiving Multi-Attribute Messages
Use ArrayentRecvMultiAttribute
to receive data from the Arrayent Cloud.
Do not use ArrayentRecvProperty
to receive data to the Arrayent Cloud. This function can only return the value of a single device attribute.
Warning
Only call ArrayentRecvMultiAttribute
from a single thread. Never call it from more than one thread.
Multi-Attribute Payload Format
Multi-attribute payloads are structured to the format outlined in this section.
NUM | Attribute 1 | Attribute 2 | Attribute … | Attribute N |
The first byte of the payload is an unsigned integer representing the number of attribute key-value pairs contained in the payload.
Each attribute key-value pair is structured as follows:
Enumerated Alias | Data Type | Attribute Value |
Enumerated Alias is an unsigned integer byte which represents an attribute in your Device Type. This value must match the “Enumerated Alias” field of the Arrayent Cloud’s definition of the attribute.
Warning
If you have not defined an enumerated alias for the attribute, then this first byte will have a value of 0. The following data will be the null-terminated string name of the attribute.
Data Type is a single unsigned integer byte which represents the data type of the following attribute value.
Attribute Value contains the current value of the attribute. The length and format of this is dependent upon the data type of the value. Strings must be null terminated. All other value types are fixed length.
Warning
For Arrayent Cloud versions 1.3 and above: when sending a multi-attribute message from your embedded host application to the Arrayent Connect Agent or Arrayent Connect Module, the data type field and and attribute value fields in your multi-attribute payload must match the attribute’s data type as they are defined in the Arrayent Cloud.
See the Data Types Reference for more information on all of the available data types for Device Attributes.
Managing ACA Configuration Attributes
The general workflow for managing ACA configuration attributes is as follows:
- Implement a Device Attribute in your Device Type that corresponds to one of the ACA configuration attributes contained in arrayent_config_t.
- Modify the host application to be able to receive this attribute.
- Perform a verification test to ensure that the new configuration attribute is valid. Verification is performed by populating an arrayent_config_t struct with the newly received value, and then calling
ArrayentConfigure
with the new struct. If the ACA is able to reconnect, then you can assume that the new values are valid. - If valid, write the new value to non-volatile memory.
Connecting to Different Cloud Environments
It is common for Arrayent Customers to have multiple Arrayent Cloud environments: such as one for development, one for staging, and one for production. Sometimes, the Arrayent Customer needs to redirect or “repoint” a unit from development to staging, or from staging to production. This section explains how to implement this scenario.
In arrayent_config_t there is a member called load_balancer_domain_names. This member is an array of three elements, with each element representing one load balancer domain name that the ACA can potentially connect to (each cloud environment typically has three or more load balancers). The host application populates this array with three domain names. If you change the values of load_balancer_domain_names, you change the environment which the ACA attempts to connect to.
The procedure below outlines the recommened procedure for enabling ACA units to dynamically connect to different cloud environments.
- Using the Configurator, create a Device Attribute in your Device Type that will be used to send new load balancer domain names to the host application.
Note
The image above is an example only. The name “arrayent-load-balancers” and the enumerated alias “101” are not required. You can use any name to represent this attribute, and any enumerated alias between 100 and 200. As with all attributes, the attribute name and enumerated alias should be unique. For the rest of this section we will continue to use this example attribute name and enumerated alias.
- The typical usage of this type of attribute is to send all three domain names as the attribute value, delimiting each domain name with a space or comma or some other delimiting character. For example, after calling
ArrayentRecvProperty
the host application would expect a payload likearrayent-load-balancersDevKit-ds1.arrayent.com,DevKit-ds2.arrayent.com,DevKit-ds3.arrayent.com
. When the host application receives an update to the “arrayent-load-balancers” attribute it should expect the value to contain three domain names. The host application should drop the message if the value payload does not contain three domain names. - After parsing the three domain names, the host application populates an arrayent_config_t struct with the new load balancer domain names.
- The host application then calls ArrayentConfigure, passing the modified configuration struct that contains the new load balancer domain names.
Note
When a host application calls ArrayentConfigure
after calling ArrayentInit
, the ACA will automatically attempt to reconnect using the new configuration attributes. There is no need for the host application to call ArrayentReset
after ArrayentConfigure
.
- The host application must then verify that the ACA was able to successfully reconnect using the new load balancer domain names. If the ACA reconnects, the new values are valid.
- After verifying that the new domain names are valid, write the new load balancer domain names to non-volatile memory.
ACA Internal Attributes
The ACA supports numerous internal attributes which you may find useful. The sections below describe how to define each attribute and what they are used for.
These attribute names and enumerated aliases cannot be used by your host applications since that would conflict with the special functionality described below.
sys-version
sys-version
reports the version of the ACA that is running on your device. The ACA reports this value after it first connects to the Arrayent Cloud.
The version is reported in the following format: aca-1.6.2.4(Nov5,2014)
sys-stats-ival
sys-stats-ival
sets the reporting interval of a specified ACA metric. Arrayent will provide you more information on this attribute as needed.
Known Issue: Attribute Alerts and online attribute
Attribute alerts that are triggered on the online
attribute do not work.
Suppose that you created an alert that is triggered when online==1
. The alert is supposed to set Device Attribute led1
on the same device to 1
.
Here is what happens:
- ACA logs in to cloud.
- Arrayent Cloud sets
online
to1
. online
alert is triggered. Arrayent Cloud sendsled1=1
command to the device.- The ACA either drops the message (v1.5.2 and beyond) or gets thrown into an error state (v1.5.1 and below).
Generally speaking, the problem is that the Arrayent Cloud sends the command before the login sequence is complete.