Using AT&T's M2X With the CC3000

This Tutorial is Retired!

This tutorial covers concepts or technologies that are no longer current. It's still here for you to read and enjoy, but may not be as useful as our newest tutorials.

Pages
Contributors: Shawn Hymel
Favorited Favorite 5

Introduction

M2X is AT&T's Machine-to-Machine (M2M) cloud solution. You can set up any number of "streams" on https://m2x.att.com/ and post, fetch, delete data from any number of Internet-connected devices.

Great, but what does all that mean? Well, let's say you have a sensor (temperature, pressure, carbon monoxide, wind speed, etc.), and you want to log all that data to somewhere on the Internet. M2X allows you to post that sensor data and view that data from any computer or smart phone connected to the Internet.

Office temperature logging

Logging the temperature in my office for about 3 hours on M2X

Conversely, we can control a device connected to M2X from anywhere (as long as we have Internet access). While M2X is not explicitly set up to push data to connected devices, we can write a program for the device that polls an M2X stream for data and performs some action based on that data.

Lighting up an LED using M2X

All of this falls under the umbrella of Internet of Things (IOT), in which Internet-connected embedded systems can communicate with Internet services, such as web sites or other connected devices.

In this tutorial, we use a SparkFun RedBoard (an Arduino Uno R3 will work, as well) and a CC3000 Shield to connect to M2X via WiFi. A temperature sensor, level shifter, LED, and resistor will also be needed for the tutorials. The specific components will be covered in each section.

We show how to set up an M2X account, create a stream, post sensor data to that stream, and control an LED from a stream. Keep in mind that these are just starting points for projects; if you want to monitor your oven or control your refrigerator, go for it!

Note: At the time of this tutorial's publication, M2X is still in beta form. You may find some bugs along the way. Feel free to ask questions or post bugs on the M2X Forums. Also, expect things to change as AT&T improves the M2X service.

Suggested Reading

M2X Setup

In order to use the M2X streams, we need to set up an AT&T M2X account.

Navigate to m2x.att.com.

M2X Site

Click on the "Sign Up" button.

M2X Sign Up

Follow the instructions on the screen to sign up for an account using your GitHub or email. If you use your email, you will need to verify your account through a link in an email from the M2X site.

Once you click on the link, you will be presented with your dashboard and a "Welcome to M2X" pop-up. Feel free to read the welcome messages or click "Skip."

After you are done with the welcome screen, you will see your dashboard.

M2X Dashboard

Click "Create Data Source Blueprint." Blueprints are a collection of data sources (streams) that can be multiplied and scaled to handle production data (known as a "batch").

M2X Blueprint info

You will be asked to give your Blueprint some information. Fill out whatever you like in the Name and Description fields. For now, leave the Visibility at "Private." Click "Create." You will be presented with the dashboard for your Blueprint.

M2X Blueprint Dashboard

And that's it! We created a blueprint, which will hold our data streams for the tutorials. Before we can add data, we need to install a few Arduino libraries.

Install Libraries

In order to use the CC3000 and M2X with Arduino, we need to install a few libraries. Make sure you do not have the Arduino IDE open at this time.

SFE_CC3000

Download the SFE_CC3000_Library from GitHub: https://github.com/sparkfun/SFE_CC3000_Library. You can clone the library or download a ZIP of the whole library here.

If you downloaded the ZIP, extract the folder.

Extract ZIP file

Navigate to \\libraries (e.g. C:\Program Files (x86)\Arduino\libraries in Windows) and create a folder named "SFE_CC3000_Library."

Create library folder

Navigate back to the downloaded library and copy all of the files inside SFE_CC3000_Library-master/SFE_CC3000_Library-master to \\libraries\SFE_CC3000_Library.

Copy library files

jsonlite

Just like we did with the CC3000 library, clone or download the ZIP file for the jsonlite library. The ZIP can be downloaded here.

If you downloaded the ZIP, extract it.

Create a folder named "jsonlite" in \\libraries. Copy in the contents from the downloaded jsonlite-master\jsonlite-master\amalgamated\jsonlite directory.

Copied jsonlite library files

M2XStreamClient

Clone or download the ZIP file for the m2x-arduino library. The ZIP can be downloaded here.

If you downloaded the ZIP, extract it.

Create a folder named "M2XStreamClient" in \\libraries. Copy in the contents from the downloaded m2x-arduino-master\m2x-arduino-master\M2XStreamClient directory.

Copied m2x-arduino library files

Note: AT&T maintains their own m2x-arduino library, but at the time of this writing, that library did not have a "Delete" function, which is necessary for one of the tutorials. We forked the git repository and added a "Delete" function. If "Delete" is added to the AT&T library, we will update this tutorial to use theirs.

Post Temperature Data

The first logical step in using the M2X service is to create a data stream and post information to it. In this tutorial, we connect a temperature sensor to an Arduino equipped with a CC3000 shield and send temperature readings to our M2X stream. This stream will automatically display the data in an easy-to-read chart for us to look at.

Posting temperature and humidity data to M2X

Required Materials

The Circuit

Connect the CC3000 shield to the Arduino, and connect the level shifter and temperature sensor as shown.

Fritzing of CC3000 with HTU21D

Example Code

Open up the Arduino IDE and paste in the following code:

language:c
/****************************************************************
M2X_CC3000_Post.ino
Post temperature data to AT&T's M2X
Shawn Hymel @ SparkFun Electronics
August 19, 2014

Manually connects to a WiFi network and an M2X stream. Reads 
temperature data from an HTU21D temperature and posts it to the
M2X stream.

Change AP_SSID, AP_PASSWORD, AP_SECURITY, FEED_ID, STREAM_NAME,
and M2X_KEY to match your WiFi and M2X parameters.

The security mode is defined by one of the following:
WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA, WLAN_SEC_WPA2

Resources:
Include SPI.h, SFE_CC3000.h, SFE_CC3000_Client.h, jsonlite.h,
M2XStreamClient.h, Wire.h, HTU21D.h

Development environment specifics:
Written in Arduino 1.0.5
Tested with Arduino UNO R3

This code is beerware; if you see me (or any other SparkFun 
employee) at the local, and you've found our code helpful, please
buy us a round!

Distributed as-is; no warranty is given.
****************************************************************/

#include <SPI.h>
#include <SFE_CC3000.h>
#include <SFE_CC3000_Client.h>
#include <jsonlite.h>
#include <M2XStreamClient.h>
#include <Wire.h>
#include <HTU21D.h>

// Parameters
#define POST_DELAY_MS   10000 // Post to stream every 10 seconds
#define DEGREE_SYMBOL   176   // Degree symbol for Serial.write

// Pins
#define CC3000_INT      2   // Needs to be an interrupt pin (D2/D3)
#define CC3000_EN       7   // Can be any digital pin
#define CC3000_CS       10  // Preferred is pin 10 on Uno

// Connection info data lengths
#define IP_ADDR_LEN     4   // Length of IP address in bytes

// WiFi Constants
#define AP_SSID         "<SSID>"      // SSID of network
#define AP_PASSWORD     "<PASSWORD>"  // Password of network
#define AP_SECURITY     WLAN_SEC_WPA2 // Security of network
#define TIMEOUT         30000         // Milliseconds

// M2X Constants
#define FEED_ID         "<FFED ID>"
#define STREAM_NAME     "<STREAM NAME>"
#define M2X_KEY         "<M2X MASTER KEY>"

// Global Variables
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
M2XStreamClient m2x_client(&client, M2X_KEY);
HTU21D sensor;
float temp;
int g_response;

// Setup. Configure HTU21D, WiFi, and M2X.
void setup() {

  g_response = 0;

  // Initialize UART for debugging
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("SparkFun CC3000 - M2X Post"));

  // Initialize HTU21D
  sensor.begin();

  // Initialize CC3000 (configure SPI communications)
  if ( wifi.init() ) {
    Serial.println(F("CC3000 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during CC3000 init!"));
  }

  // Connect using DHCP
  Serial.print(F("Connecting to SSID: "));
  Serial.println(AP_SSID);
  if(wifi.connect(AP_SSID, AP_SECURITY, AP_PASSWORD, TIMEOUT)) {
    Serial.println(F("Connected!"));
  } else {
    Serial.println(F("Error: Could not connect to AP"));
  }
}

// Main loop. Post sensor readings at regular intervals.
void loop() {

  // Read sensor
  temp = sensor.readTemperature();

  // Print reading to console with degree symbol and 'C'
  Serial.print(F("Temperature: "));
  Serial.print(temp, 2);
  Serial.write(176);
  Serial.println("C");

  // Post data to your stream
  g_response = m2x_client.post(FEED_ID, STREAM_NAME, temp);

  // If we fail to receive a response, stop running
  Serial.print(F("Post response: "));
  Serial.println(g_response);
  if ( g_response == -1 ) {
    while(1);
  }

  // Wait to post to stream again
  delay(POST_DELAY_MS);
}

Before you can run the code, you will need to update a few variables:

  • \<SSID> should be changed to your WiFi network name (SSID)
  • \<PASSWORD> is your WiFi password
  • Make sure AP_SECURITY matches your WiFi security type (e.g. WPA, WEP)
  • Change \, \, and \ to match your M2X stream information (see next section)

Make a Data Stream

Log in to https://m2x.att.com/.

M2X Main Dashboard

Click on the Blueprint that we created ("CC3000 Test").

M2X Blueprint Dashboard

Click on "Add Stream" and fill out some information about your stream. We call it "temperature." Under "Units & Symbol," start typing "Celsius," and you will be presented with a drop-down list. Select "degree Celsius."

M2X Add a Stream

Click "Add Stream." You will be returned to your Blueprint dashboard with a new "temperature" stream added. Click "temperature" to drop down your stream data. There should not be anything in it right now (don't worry, we are about to add some data!).

m2x new stream with no data

Scroll up on that same page to find your "FEED ID." Copy that long string and paste it into our M2X_CC3000_Post sketch (replace \).

M2X Feed ID

Replace \ in our code with the name of the stream ("temperature" in this case).

Back on the M2X site, click "ACCOUNT" to go to your account settings.

M2X Account Page

Click on "MASTER KEYS" to see your M2X Master Key. Copy that string and paste it into your code (replace \).

M2X Master Key

Run Your Program

Verify that AP_SSID, AP_PASSWORD, AP_SECURITY, FEED_ID, STREAM_NAME, and M2X_KEY are correct in your code. Click "Upload" and wait for the Arduino IDE to upload the code to your Arduino or RedBoard. Open a Serial Monitor, and you should see temperature data being posted to your M2X stream!

Note: the response should be "204." If you see "404" or "-1" it means there was an error connecting to your WiFi or to the M2X service. If you see "422" it means that your M2X_KEY, FEED_ID, or STREAM_NAME is incorrect. To learn more about response codes, see the M2X API documentation.

Temperature data logging

Temperature data logged to M2X

Public Data Stream

If you want others to be able to view your data, you can make your Blueprint (and associated streams) public. On the Blueprint dashboard, click the "Edit" button next to your Blueprint name and change the visibility from "Private" to "Public." Click "Save" and wait a few minutes for this to update (this can take upwards of 15 minutes).

Underneath your Blueprint name on the dashboard, click the link "Preview Public Page URL." This will take you to a separate page where you can view the streams associated with that Blueprint. If you made your Blueprint public, you can share this URL with anyone.

M2X Public Blueprint

Controlling a Device From M2X

Sending information to M2X is great for logging sensor data, but we can also control hardware devices from M2X. This technique requires a bit of trickery, as there is no way to push data to the Arduino (without turning the Arduino into a web server). So, we have the Arduino poll an M2X stream every few seconds looking for data. If it sees a "0" it will turn off the LED. If it sees any other value, it will turn the LED on. Any time the Arduino reads data from the stream, it immediately deletes all data on the stream.

Circuit for controlling an LED from M2X

Required Materials

The Circuit

Connect the CC3000 shield to the Arduino, and connect the resistor and LED as shown.

Fritzing of the CC3000 with LED

Make M2X Stream

Rather than use our "temperature" stream, we are going to make another stream in the same Blueprint. We will poll this stream from the Arduino, read values, and delete entries as we read them.

Log in to your AT&T M2X account.

Click on your Blueprint (e.g. "CC3000 Test").

Scroll down, and click on "Add Steam." Name the stream something memorable (we'll call ours "control"). Pick any Unit and Symbol (it really does not matter. "Barn" seemed like a silly unit, so we used that).

Add a control stream to your Blueprint

Click "Add Stream." Don't add any values! We will add some data later.

Blank control data stream

Adjust Serial Buffer

Sadly, the poor Arduino UNO (i.e. ATmega328P) simply does not have enough RAM to control the CC3000 and process the incoming M2X data. To free up some space in the RAM, we are going to reduce the size of the Serial buffer. Don't forget to change it back for your other projects!

Navigate to \\hardware\arduino\cores\arduino and open up HardwareSerial.cpp with your favorite text editor.

Note: If you are using a different Arduino with more RAM (e.g. the Arduino Mega), then you don't need to perform this step.

HardwareSerial.cpp location

Scroll down and change SERIAL_BUFFER_SIZE from 64 to 32.

HardwareSerial change serial buffer size

Example Code

Open up the Arduino IDE and paste in the following code:

language:c
/****************************************************************
M2X_CC3000_LED.ino
Control an LED with AT&T's M2X
Shawn Hymel @ SparkFun Electronics
August 19, 2014

Manually connects to a WiFi network and performs a GET to the
provided M2X stream. It reads the last data point available
and deletes all data points. This acts as a "producer-consumer"
model.

IMPORTANT: This WILL cause an Uno to run out of RAM. You need to
change SERIAL_BUFFER_SIZE from 64 to 32 in HardwareSerial.cpp,
which can be found in:
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino

Change AP_SSID, AP_PASSWORD, AP_SECURITY, FEED_ID, STREAM_NAME,
and M2X_KEY to match your WiFi and M2X parameters.

The security mode is defined by one of the following:
WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA, WLAN_SEC_WPA2

Resources:
Include SPI.h, SFE_CC3000.h, SFE_CC3000_Client.h, jsonlite.h,
M2XStreamClient.h

Development environment specifics:
Written in Arduino 1.0.5
Tested with Arduino UNO R3

This code is beerware; if you see me (or any other SparkFun 
employee) at the local, and you've found our code helpful, please
buy us a round!

Distributed as-is; no warranty is given.
****************************************************************/

#include <jsonlite.h>
#include <SPI.h>
#include <SFE_CC3000.h>
#include <SFE_CC3000_Client.h>
#include <M2XStreamClient.h>

// Parameters
#define POLL_DELAY_MS   1000 // Poll M2X stream every 1 second

// Pins
#define CC3000_INT      2    // Needs to be an interrupt pin (D2/D3)
#define CC3000_EN       7    // Can be any digital pin
#define CC3000_CS       10   // Preferred is pin 10 on Uno
#define LED_PIN         9    // LED (we can't use pin 13!)

// Connection info data lengths
#define IP_ADDR_LEN     4    // Length of IP address in bytes
#define TIME_LEN        25   // Length of timestamp string

// WiFi Constants
#define AP_SSID         "<SSID>"      // SSID of network
#define AP_PASSWORD     "<PASSWORD>"  // Password of network
#define AP_SECURITY     WLAN_SEC_WPA2 // Security of network
#define TIMEOUT         30000         // Milliseconds

// M2X Constants
#define FEED_ID         "<FFED ID>"
#define STREAM_NAME     "<STREAM NAME>"
#define M2X_KEY         "<M2X MASTER KEY>"
#define FROM_TIME       "1970-01-01T00:00:00.000Z"

// Global Variables
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
M2XStreamClient m2x_client(&client, M2X_KEY);
uint8_t g_new;
int g_response;
int g_index;
char g_time[TIME_LEN];
uint8_t led_state;

// M2X fetch callback. This is called for each entry found.
void on_data_point_found( const char* at, \
                          const char* value, \
                          int index, \
                          void* context) {

  // Index 0 is the most recent. Save the timestamp so we can
  // delete all the entries up to that point. If the value is
  // exactly 0, turn off the LED. Otherwise, turn it on.
  if ( index == 0 ) {
    g_new = 1;
    strncpy(g_time, at, TIME_LEN);
    if ( strcmp(value, "0") == 0 ) {
      led_state = 0;
    } else {
      led_state = 1;
    }
  }
}

// Setup. Configure WiFi and M2X connections.
void setup() {

  g_response = 0;
  g_new = 0;

  // Initialize LED
  led_state = 0;
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  // Initialize UART for debugging
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("SparkFun CC3000 - M2X LED"));

  // Initialize CC3000 (configure SPI communications)
  if ( wifi.init() ) {
    Serial.println(F("CC3000 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during CC3000 init!"));
  }

  // Connect using DHCP
  Serial.print(F("Connecting to SSID: "));
  Serial.println(AP_SSID);
  if(wifi.connect(AP_SSID, AP_SECURITY, AP_PASSWORD, TIMEOUT)) {
    Serial.println(F("Connected!"));
  } else {
    Serial.println(F("Error: Could not connect to AP"));
  }
}

// Main loop. Poll M2X stream, update LED, and delete entries.
void loop() {

  // Fetch values from M2X stream
  g_response = m2x_client.fetchValues(FEED_ID, \
                                      STREAM_NAME, \
                                      on_data_point_found, \
                                      NULL);

  // If we fail to receive a reponse, stop running
  Serial.print(F("Fetch response: "));
  Serial.println(g_response);
  if ( g_response == -1 ) {
    while(1);
  }

  // Update LED and delete entries if there was a new value
  if ( g_new ) {

    // Update LED state
    digitalWrite(LED_PIN, led_state);
    Serial.print(F("LED: "));
    Serial.println(led_state);

    // Fetch drops last 4 chars. Add some so we can delete entries.
    strncpy(g_time + 20, "999Z", 5);

    // Delete all entries
    g_response = m2x_client.deleteValues( FEED_ID, \
                                          STREAM_NAME, \
                                          FROM_TIME, \
                                          g_time);

    // If we fail to receive a reponse, stop running
    Serial.print(F("Delete response: "));
    Serial.println(g_response);
    if ( g_response == -1 ) {
      while(1);
    }

    // Reset new flag
    g_new = 0;
  }

  // Wait to poll stream again
  delay(POLL_DELAY_MS);
}

Don't forget to update the WiFi and M2X stream parameters:

  • \<SSID> should be changed to your WiFi network name (SSID)
  • \<PASSWORD> is your WiFi password
  • Make sure AP_SECURITY matches your WiFi security type (e.g. WPA, WEP)
  • Change \ and \ to match your M2X information (see the Post Temperature Data example)
  • Change \ to your new stream name (e.g. "control")

Run Your Program

Upload your program to the Arduino. Open up a Serial Monitor, and you should see the Arduino connect to WiFi and start to poll your M2X stream.

Arduino and CC3000 connected to M2X control stream

While your Arduino is polling the M2X stream, go back to your M2X Blueprint in your browser and expand our new data stream.

Expanded data stream

Click the "Edit" button and enter a value (anything other than "0") into the "Log a Value" field.

M2X log a value

Click "Save Stream." In a few seconds, your Arduino should see that a value was logged to the stream and turn on the LED as a result.

LED on

To turn off the LED, click on "Edit" again for your data stream. This time, set "Log a Value" to 0 and click "Save Stream." Your LED should turn off within a few seconds.

LED off

So What?

OK, so blinking an LED might seem a little simplistic. However, being able to control a microcontroller from the Internet is a pretty big thing (and will garner the admiration of all your geek friends).

You could write a phone app to control the lights in your house by posting and reading values in M2X. You could remotely start your car, computer, stereo, etc. as long as there is Internet connectivity. The list goes on.

Resources and Going Further

We showed you how to set up an M2X account, connect your Arduino to an M2X stream to post some values, and even how to control an LED from M2X. These examples are really just the first few steps in the Internet of Things world.

Beyond the Tutorial

Resources