A REST API for Arduino & the CC3000 WiFi Chip

IMG_7938 smallI was recently playing with the Arduino Yun for a whole set of new projects, and I discovered a sketch that implements a REST API for the Arduino Yun. We’ll see in more details what a REST API is, but for now let’s say it allows to standardise the communication between your Arduino and the external world via WiFi or Ethernet, and develop complex applications without having to modify your Arduino sketch every time.

So I told myself: why not create one REST API for the CC3000 WiFi chip ? That’s exactly what I did as a weekend project, and I wanted to share it with you. If you want to directly jump to the project files, go over to the GitHub repository of the project.

So what’s a REST API ?

You may wonder: what’s a REST API ? It’s actually a concept that is widely used by many web applications like SaaS. REST stands for REpresentational State Transfer, and is a communication architecture that was created back in 2000. It defines many constraints that the architecture has to follow, the most important features being:

  • A client/server communication: a client sends a request to a server, and the server answers accordingly
  • A stateless communication: every request has to contain all the information so the server can understand it, without having to rely on some information stored on the server
  • A uniform interface to easily identify resources on the server

This allowed to standardise communication between web applications, and made them more scalable, faster, and simplified the development of more complex applications. Many applications now propose a REST API, for example the eCommerce plugin I am using on this website.

Why do we need it for Arduino & the CC3000 WiFi chip ?

The problem that I encountered while developing web applications using the CC3000 is that I had to create a new Arduino sketch for every application, that needs to be coordinated with the rest of the application, for example an interface running on my computer.

And then, I discovered the REST API of the Arduino Yun. It is a simple sketch for the Arduino Yun that allows to make REST calls directly from your browser. For example:

http://arduinoyun.local/arduino/digital/8/1

will put the pin number 8 to a high state on my Arduino Yun. With this REST interface, it’s easy to load a sketch once for all on your Arduino, and then only work on the interface on your computer that makes REST calls on your Arduino board. And for now, this kind of interface was only available on the official Arduino boards, like the WiFi & Ethernet shields, and the Yun.

But I wanted to have the same on my CC3000 WiFi chip: make a sketch that will create a web server on the Arduino board, and then accept REST commands from an external client, like from an interface running on my computer. With this, I just have to build complex web applications on my computer, and then made them interact with the REST API of my Arduino board. And that’s what I built in this project.

The Arduino sketch

Let’s see the Arduino sketch first. If it’s not done yet, get the files by going to the GitHub repository of the project. You will also need the following libraries for this project:

You might also need additional software components to make the mDNS service work for your operating system. Please have a look at the GitHub repository of the project for more information. The Arduino sketch is actually close to the one from this project:

Wireless Relay Control with Arduino & the CC3000 WiFi chip

The sketch basically consists in connecting the WiFi chip to your network, creating a web server on the Arduino board, and listening for incoming connections. The main difference is that when a command is received from a client, it is processed by the aREST library to see which mode we are in, which pin we want to access, and check if we want to read from this pin of write.

I won’t detail all the code here, but as an example, I will take the case where we have a digital command coming in, for example digital/8/r. When we detect a client that connects to the Arduino board, inside the aREST library we read the request and store it in a String variable with:

We then check if we get a command (like “digital”), a pin (like “8”) and a value (like “1”). To detect all these values, we check when we encounter the “/” symbol:

We then need to detect that’s it is a digital command. This is done with:

At the next “/” that will be detected, we then check the pin number:

Finally, when we know which pin we want to access, we need to know if it’s a read command (for example digital/8/r) or if we want to write a given value. For example, reading is done by:

The same is done with other commands, like “analog” or “mode”. For the complete documentation about the REST API, you can check the GitHub repository of the aREST library.

A simple example for home automation

I want to finish this article by giving you a simple example you can use directly in home automation: controlling a relay and switching a LED on using a REST call. You will need the following hardware components to test this project:

The hardware configuration is the same as in this article:

Wireless Relay Control with Arduino & the CC3000 WiFi chip

Of course, you don’t even need to have anything connected to your Arduino (except the CC3000 chip) to test the project, as you will always have a confirmation message coming back from the Arduino inside your web browser. Once you assembled the hardware, we can test the sketch.

You first need to go into the sketch and modify your sketch by setting your SSID, password and security type of your WiFi network. You can then upload the sketch to your Arduino board, and wait a bit some it can connect to your local WiFi network. Now, you can simply go over to your favorite web browser, and type the following command to set the pin 8 to an output:

http://arduino.local/mode/8/o

You should instantly get the confirmation message right in your browser:

Setting pin D8 to output

We then need to set the value of pin number 8 to a high state, to turn the relay on:

arduino.local/digital/8/1

You should also have the confirmation message in your browser:

Pin D8 set to 1

In the same time, the relay should turn on, and power up the LED. If that works correctly, it means you successfully used the REST API on your project, and can start building more complex web applications for your Arduino.

If it doesn’t work at that point, it is probably because the mDNS service (that gives the arduino.local name to the board) is not working properly. One solution is to use the IP address of the board directly. To find it, simply open the serial monitor and reset the project: the IP address will be displayed once the CC3000 chip is connected to the WiFi network. You can then make calls like:

http://192.168.1.104/digital/8/1

Update 06/06/14: The project was updated and is now using the aREST library. It greatly simplified the code and made the project works more reliably. It also now works with other kind of hardware, like the Arduino Ethernet shield. The video is still using the old code, but the commands for the REST API and all the principles are exactly the same. Let me know if you encounter any issues with the new code!

I recorded a video to show you how the API works to control two LEDs connected to the Arduino board:

Future work

Of course, many things can still be done to improve the API. In the future I want to extend the API to get data from various sensor, like from the DHT sensor family. I also want to extend the API to communicate with I2C devices that are connected to the Arduino board. I will also rewrite some of the tutorials using the CC3000 chip to use this REST API. So please try it out, all the files you need can be found at the GitHub repository of the project and you can find the complete documentation of the API in the GitHub repository of the aREST library. If you do so and build exciting projects based on the API, please share here or on GitHub your experience with using this project!

  • afterthought

    I ran into trouble right at the beginning. I got this far:

    Initializing…
    Started AP/SSID scan
    Connecting to NETGEAR96…Waiting to connect…
    Listening for connections…

    Then it stops- in spite of entering “arduino.local/digital/8/1″ in the browser.

    Any suggestions?

  • http://www.marcoschwartz.com Marco Schwartz

    It seems that your Arduino server is working fine, but your computer cannot connect to it. I would try the following:

    – can you ping the Arduino board ? Try ping arduino.local in a terminal
    – check without the firewall on your computer. Also make sure that the port you use for the Arduino server is not blocked on your firewall or on your router
    – try to print out the IP of the board, and then ping this IP again in a terminal – it that works, it means that the MDNS library somehow doesn’t work correctly in your case

  • Mike D

    I think I found a Bug with the REST API. Let me start by saying I love it and it works great for most things. It doesn’t work 100% in Safari though. It will send the command to the Arduino but there is no web page response on Safari for Mac or Safari mobile for any iOS device. It does work on Chrome and Firefox on Mac and it works on Chrome for iOS. I’m running iOS 7.1 on all iOS devices and Mac OS X 10.9.2, 10.7.5 and 10.6.8 on my 3 Mac’s so tried it in multiple versions of Safari for Mac.

    • http://www.marcoschwartz.com Marco Schwartz

      Hello Mike,

      Thanks a lot for the feedback ! I just tested the code with Safari 7, the API was working but didn’t display any feedback on the browser. I looked into the code and now it is fixed! I also tested with Safari for IOS7, it works as well.

      • http://www.marcoschwartz.com Marco Schwartz

        Good point, I just added some extra links into the README file to make the mDNS work on other OS, and I added some extra lines of code so the sketch prints out the IP address of the board on the Serial monitor. I also updated the article accordingly.

  • Mike D

    Is there a way to use your REST API to send commands form one cc3000/arduino to another cc3000/arduino? Example: Say a button is pressed on one Arduino(arduino.local) that then send the command to a second arduino(arduino2.local) such as the following command: arduino2.local/digital/8/1

    • http://www.marcoschwartz.com Marco Schwartz

      In theory that should work, however that’s something I didn’t test yet. But would love to hear your feedback if you were testing that kind of applications.

      • Mike D

        If I ever can figure out how to do it I’ll post my results.

  • Pingback: How to make a REST API for Arduino & the CC3000 WiFi Chip #ArduinoD14 « adafruit industries blog

  • Mike D

    What is the max rate at which I can send it commands? I built 3 simple slider bar programs(JavaScript, iOS, Andriod) that change the brightness of an attached PWM LED and I think the rest API is dropping packets or can’t handle the amount of data Im sending it. It works great with an onmouseup or on touchup but not on an unevent change. If i slide the slider to the desired brightness and send “arduino.local/analog/8/xxx” value once I’m done moving the slider it works great but if i want to adjust the brightness/pwm of the LED on the fly i crash the API. (Near Real time adjustment of PWM as a move my finger or mouse along the slider). I don’t know if the REST API can handle this or not. Thanks again for a great API.

    • http://www.marcoschwartz.com Marco Schwartz

      Good point, and I am not really surprised by this kind of problem. Keep in mind that the Arduino Uno is nearly pushed to its maximum with the CC3000 library, so it is normal that it cannot sustain real-time changes like with a slider that creates many calls to the API. Would be interesting to test it with a more powerful Arduino system like a Due or a Teensy.

      Anyway, I am working on a new version of the API that is encapsulated in a library, and I will for sure test that with many boards. I’ll post a new article about it when it is ready !

      • Mike D

        I haven’t tried it on a due yet but I did try it on a mega 1280 and 2560 with the same results. Crashing on realtime updates. If u email me I’ll shoot you my slider source code

        • http://www.marcoschwartz.com Marco Schwartz

          No need, I already tested with a slider as well. Works well using Serial communication with my new library, but indeed it fails with WiFi. I’ll set up a test file to see how fast we can transmit events.

          • Mike D

            I’ve tried it with a JS HttpGetRequest and an fame request. the iframe works a bit better then the get for web. for Xcode i used an NSURL and for android I used a java call. it recovered the best from the web iframe.

            I also added a few calls to be able to get the current state of system from memory requests. I added a /Memory/”variable name”/”variable value”. This why my sliders on the web page would default to the current values of my PWM pins or any other data I wanted to send. This allowed me to remotely change the mDNS name of the device as well on the fly so they weren’t all called ardino.local and I could change the name of them over the network for my case where I have a few devices on the network.

  • Pingback: End of Month Research Roundup – April 2014 | endjin blog

  • Pingback: Arduino Blog » Blog Archive » A REST API for Arduino and the CC3000 WiFi Chip

  • Pingback: A REST API for Arduino and the CC3000 WiFi Chip | Faweiz Blog

  • Pingback: A REST API for Arduino and the CC3000 WiFi Chip | Linux-Support.com

  • Pingback: Electronic Hobbies | A REST API for Arduino and the CC3000 WiFi Chip

  • http://ericpeterson.mn Eric Peterson

    Checkout the Spark Core (https://www.spark.io/). It’s an arduino compatible device that has a CC3000 and ARM processor onboard for a total price of $39. It’s pretty sweet and would save you some money over buying a CC3000 and UNO together.

    • http://www.marcoschwartz.com Marco Schwartz

      Hello Eric,

      I am a big fan of the SparkCore, and I even got one myself. This project that I developed is more for people that already have some hardware and want to have a REST API as well. Note that the project also have two advantages over the SparkCore: it will work even if your Internet connection is down (there is no exchange of data with an external server), and you can mix different hardware solutions (WiFi with the CC3000 chip, but also Ethernet and Serial communications).

  • Pingback: Episode 4 - June 21, 2014

  • Edward

    Fantastic lightweight REST for Arduino! Thank you for sharing!
    I have it working on an Arduino Mega, running an array of various sensors.
    I store the sensor readings in an array of the form “sensorReading[x]” where “x” is a value of 0-15.

    I can retrieve the value of a specific sensor if I hard code the sensor index number as such:

    temperature = int(sensorReading[1]);
    Adafruit_CC3000_ClientRef client = restServer.available();
    rest.handle(client);

    and use the call “http://arduino.local/temperature”

    I would like to be able to pass the call with a parameter that designates the sensor to be read, instead of having to hard code 16 different JSON calls.
    Is there any way to do that now?

    • http://www.marcoschwartz.com Marco Schwartz

      Hello Edward, thanks! It is not possible at the moment to retrieve several variables at once or an array, but to get a specific sensor reading I would use a function and expose it to the API. You’ll find an example in every examples of the API, just pass the ID of the sensor to be read and use the function to assign the correct sensor reading to the temperature variable. Then make another API call to get the variable. Check the documentation at https://github.com/marcoschwartz/aREST. I also plan to include returning floats & arrays in the future, as well as returning int’s from function calls.

  • kay

    Hello, I have been implementing your library in my home automation project and it works pretty well but I am curious does it support PUT commands. If not how would I send HEX code or other data types to the server to do things like change the color of an RGB LED or control an IR transmitter to change settings on an AC or other IR controlled device?

    • http://www.marcoschwartz.com Marco Schwartz

      Hello Kay, thanks for your comment! It doesn’t support PUT commands yet, but it is planned for the future. Stay tuned!