NOTE: We've changed one API to avoid ambiguity, if you are using the older version of client library, you might need to fix your code.
The Arduino library is used to send/receive data to/from AT&T's M2X service from Arduino based devices.
NOTE: Unless stated otherwise, the following instructions are specific to Arduino Uno boards. If you are using other boards, the exact steps may vary.
- Signup for an M2X Account.
- Obtain your Master Key from the Master Keys tab of your Account Settings screen.
- Create your first Data Source Blueprint and copy its Feed ID.
- Review the M2X API Documentation.
- Obtain an Arduino with built-in wifi or ethernet, or a separate wifi or ethernet shield and set it up. These docs were written for an Arduino Uno with a wifi or ethernet shield but the instructions can be adapted for other Arduino models.
Please consult the M2X glossary if you have questions about any M2X specific terms.
This library depends on jsonlite, the installation steps are as follows:
-
Clone the jsonlite repository.
NOTE: Since we are now using the old v1.1.2 API (we will migrate to the new API soon), please use the fork version of jsonlite listed above instead of the original one.
-
Open the Arduino IDE, click
Sketch->Import Library...->Add Library...
, then navigate toamalgamated/jsonlite
folder in the cloned jsonlite repository. The jsonlite library will be imported to Arduino this way.NOTE: If you cloned the jsonlite library, there will be three (3) folders named jsonlite:
jsonlite
: the repo folderjsonlite/jsonlite
: the un-flattened jsonlite source folderjsonlite/amalgamated/jsonlite
: the flattened jsonlite source for arduino
You should use the final library listed here as the first two won't work!
-
Use the instructions outlined in Step 2 above to import the
M2XStreamClient
library in the current folder. -
Now you can find M2X examples under
File->Examples->M2XStreamClient
The Arduino website has a very good tutorial on setting up the Arduino board. It contains detailed instructions on how to install the Arduino IDE, sets up your board for initial testing. Feel free to proceed to the Arduino site to get a basic idea on Arduino.
If you are using an Arduino Yun board instead of an Arduino Uno board, you can skip this section since the Yun board already has a Wifi adapter onboard.
To send data to the AT&T M2X service, or receive data from the AT&T M2X service, your Arduino board needs a connection to the Internet. Hence, an Arduino Wifi Shield or Ethernet Shield is needed to give your board the power to connect to the Internet. To install the shield, hook the shield onto your Arduino board — you can use the pins on the shield the same way as the real pins on the Arduino boards.
Different sensors can be hooked up to an Arduino board to provide different properties including temperatures, humidity, etc. You can use a breadboard as well as wires to connect different sensors to your Arduino. For a detailed tutorial on connecting different sensors, please refer to the Arduino Examples page.
If you are using a 3G GSM/GPRS shield with your Arduino, the M2X Arduino SIMCOM module can be used to connect your device to the AT&T cellular data network.
In order to run the given examples, different variables need to be configured. We will walk through those variables in this section.
If you are using a Wifi Shield, the following variables need configuration:
char ssid[] = "<ssid>";
char pass[] = "<WPA password>";
Just fill in the SSID and password of the Wifi hotspot and you should be good to go.
For an Ethernet Shield, the following variables are needed:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,17);
For a newer Ethernet Shield, the MAC address should be printed on a sticker on the shield. However, some old Ethernet Shields have no MAC address shown on the board. In this case, you can use any MAC address, as long as it does not conflict with another network device within the same LAN.
The IP address here is only used when DHCP fails to give a valid IP address. It is recommended, though not required, to provide a unique IP address.
Once you register for an AT&T M2X account, an API key is automatically generated for you. This key is called a Primary Master Key and can be found in the Master Keys tab of your Account Settings. This key cannot be edited or deleted, but it can be regenerated. It will give you full access to all APIs.
However, you can also create a Data Source API Key associated with a given Data Source (Feed), you can use the Data Source API key to access the streams belonging to that Data Source.
You can customize this variable in the following line in the examples:
char m2xKey[] = "<M2X access key>";
A feed is associated with a data source. It is a set of data streams, such as streams of locations, temperatures, etc. The following line is needed to configure the feed used:
char feedId[] = "<feed id>";
A stream in a feed is a set of timed series data of a specific type (i,e. humidity, temperature). You can use the M2XStreamClient library to send stream values to M2X server, or receive stream values from M2X server. Use the following line to configure the stream if needed:
char streamName[] = "<stream name>";
The M2X Arduino library can be used with both a Wifi connection and an Ethernet connection. For a Wifi connection, use the following code:
WiFiClient client;
M2XStreamClient m2xClient(&client, m2xKey);
For an Ethernet connection, use the following code:
EthernetClient client;
M2XStreamClient m2xClient(&client, m2xKey);
If you are using an Arduino Yun board, you should use the following code:
YunClient client;
M2XStreamClient m2xClient(&client, m2xKey);
In the M2XStreamClient, 4 types of API functions are provided here:
send
: Send stream value to M2Xreceive
: Receive stream value from M2XupdateLocation
: Send location value of a feed to M2XreadLocation
: Receive location values of a feed from M2X
For all those functions, the HTTP status code will be returned if we can fulfill an HTTP request. For example, 200
will be returned upon success, and 401
will be returned if we didn't provide a valid M2X API Key. A full-list of M2X API error codes can be found here: [M2X API Error Codes] (https://m2x.att.com/developer/documentation/overview#Client-Errors)
Otherwise, the following error codes will be used:
static const int E_NOCONNECTION = -1;
static const int E_DISCONNECTED = -2;
static const int E_NOTREACHABLE = -3;
static const int E_INVALID = -4;
static const int E_JSON_INVALID = -5;
The following functions can be used to post a value to a stream, which belongs to a feed:
template <class T>
int post(const char* feedId, const char* streamName, T value);
Here we use C++ templates to generate functions for different types of values, feel free to use values of float
, int
, long
or even const char*
types here.
M2X also supports posting multiple values to multiple streams in one call. To do so, use the following function:
template <class T>
int postMultiple(const char* feedId, int streamNum,
const char* names[], const int counts[],
const char* ats[], T values[]);
Please refer to the comments in the source code for additional information on how to use this function. Essentially, you will need to provide the list of streams you want to post to, and values for each stream.
Since an Arduino board contains very limited memory, we cannot put the whole returned string in memory, parse it into JSON representations and read what we want. Instead, we use a callback-based mechanism here. We parse the returned JSON string piece by piece. Whenever we got a new stream value point, we will call the following callback functions:
typedef void (*stream_value_read_callback)(const char* at,
const char* value,
int index,
void* context,
int type);
The implementation of the callback function is left for the user to fill in. You can read the value of the point in the value
argument, and the timestamp of the point in the at
argument. We even pass the index of this data point in the whole stream as well as a user-specified context variable to this function, so that you can perform different tasks.
type
indicates the type of value stored in value
: 1 for string, 2 for number. However, keep in mind that value
will always be a pointer to an array of char, even though type
indicates the current value is a number. In this case, atoi
or atof
might be needed.
To read the stream values, all you need to do is call this function:
int fetchValues(const char* feedId, const char* streamName,
stream_value_read_callback callback, void* context,
const char* startTime = NULL, const char* endTime = NULL,
const char* limit = NULL);
Besides the feed ID and stream name, only the callback function and a user context needs to be specified. Optional filtering parameters such as start time, end time, and limits per call can also be used here.
You can use the following function to update the location for a data source (feed):
template <class T>
int updateLocation(const char* feedId, const char* name,
T latitude, T longitude, T elevation);
Different from stream values, locations are attached to feeds rather than streams.
The reason we are providing templated function is due to floating point value precision: on most Arduino boards, double
is the same as float
, i.e., 32-bit (4-byte) single precision floating number. That means only 7 digits in the number are reliable. When we are using double
here to represent latitude/longitude, it means that only 5 digits after the floating point are accurate, which means we can represent as accurate to ~1.1132m distance using double
here. If you want to represent coordinates that are more specific, you need to use strings here.
Similar to reading stream values, we also use callback functions to read datasource locations. The only difference is that different parameters are used in the function:
void (*location_read_callback)(const char* name,
double latitude,
double longitude,
double elevation,
const char* timestamp,
int index,
void* context);
Due to memory space consideration,we only provide double-precision when reading locations. An index of the location points is also provided here together with a user-specified context.
This API is also slightly different, in that the stream name is not needed here:
int readLocation(const char* feedId, location_read_callback callback,
void* context);
You can use the following function to delete values within a stream by providing a from
and end
date/time:
int deleteValues(const char* feedId, const char* streamName,
const char* from, const char* end);
The timestamps from
and end
need to be in an ISO 8601 format: yyyy-mm-ddTHH:MM:SS.SSSZ. Note the Z for Zulu time.
We provide a series of examples that will help you get an idea of how to use the M2XStreamClient
library to perform all kinds of tasks.
Note that the examples may apply to certain types of boards. For example, the ones with Uno
in the name apply to Arduino Uno
boards only, while the ones with Yun
only apply to Arduino Yun
boards.
Note that the examples contain fictionary variables, and that they need to be configured as per the instructions above before running on your Arduino board. Each of the examples here also needs either a Wifi Shield or an Ethernet Shield hooked up to your device.
In the UnoPost
, EthernetUnoPost
and YunPost
, a temperature sensor, a breadboard and 5 wires are also needed to get temperature data, and you will need to wire the board like this before running the code.
After you have configured your variables and the board, plug the Arduino board into your computer via a Micro-USB cable, click Verify
in the Arduino IDE, then click Upload
, and the code should be uploaded to the board. You can check all the outputs in the Serial Monitor
of the Arduino IDE.
This example shows how to post temperatures to M2X. Before running this example, you will need to have a valid M2X Key, a feed ID and a stream name. The Arduino board needs to be configured like this. In this example, we are using an Arduino Uno board. If you are using other boards, keep in mind that we are reading from A0
in the code and the wiring should be similar to this one shown in the illustration.
This example shows how to post multiple values to multiple streams in one API call.
This example reads stream values from M2X server and prints the stream data point to Serial interface. You can find the actual values in the Arduino Serial Monitor
.
This example is similar to the UnoPost
, except that EthernetClient is used instead of WifiClient. If you are using an Ethernet Shield instead of a Wifi Shield, you can use this example.
This example is similar to the UnoReceive
, except that EthernetClient is used instead of WifiClient.
This example sends location data to M2X. Ideally a GPS device should be used here to read the coordinates, but for simplicity, we just use pre-set values here to show how to use the API.
This example reads location data of a feed from M2X, and prints them to Serial interface. You can check the output in the Serial Monitor
of the Arduino IDE.
This example shows how to delete values within a stream by providing a date/time range.
This example works like YunPost
, except that it works on an Arduino Yun board instead of an Arduino Uno board.
This library is released under the MIT license. See M2XStreamClient/LICENSE
for the terms.