From dff0a27f67d09875714778351e887f2768da7ebc Mon Sep 17 00:00:00 2001 From: Marco Schwartz Date: Thu, 23 Mar 2017 13:11:23 +0100 Subject: [PATCH] added ESP32 support --- README.md | 20 ++++-- aREST.h | 42 ++++++++----- examples/ESP32/ESP32.ino | 88 ++++++++++++++++++++++++++ examples/ESP32_cloud/ESP32_cloud.ino | 94 ++++++++++++++++++++++++++++ library.properties | 2 +- 5 files changed, 225 insertions(+), 21 deletions(-) create mode 100644 examples/ESP32/ESP32.ino create mode 100644 examples/ESP32_cloud/ESP32_cloud.ino diff --git a/README.md b/README.md index 0bfd0c8..f2b3185 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A simple library that implements a REST API for Arduino & the ESP8266 WiFi chip. It is designed to be universal and currently supports REST calls via HTTP (using the CC3000 WiFi chip, the Arduino WiFi library or the Ethernet shield), via the Serial port (using the USB serial connection, Bluetooth, and XBee) and also via Bluetooth Low Energy. The library is also compatible with the Arduino MKR1000 board. -It also works with the ESP8266 WiFi chip using the ESP8266 processor, therefore working as an independent unit. +It also works with the ESP8266 WiFi chip using the ESP8266 processor, therefore working as an independent unit. It also works on the ESP32 WiFi chip. Boards running aREST can also be accessed from anywhere in the world via an API available at `cloud.arest.io`. Check the rest of this file and the examples ending with *_cloud* for more details. This currently only works with the Ethernet library for Arduino & the ESP8266 WiFi chip. @@ -27,9 +27,9 @@ If you want to know more about aREST, go over to [http://arest.io/](http://arest The library is at the moment compatible with the following Arduino boards: Uno, Mega, Due, Yun and Teensy 3.x. It is also compatible with the Arduino/Genuino MKR1000 board. -### ESP8266 +### ESP8266/ESP32 -The library is compatible with most of the ESP8266 modules & ESP8266 development boards. +The library is compatible with most of the ESP8266 modules & ESP8266 development boards, as well as most boards based on the ESP32 WiFi chip. ### HTTP @@ -57,6 +57,14 @@ To use the library with the ESP8266 WiFi chip you will need to install the requi 2. Enter `http://arduino.esp8266.com/package_esp8266com_index.json` into the Additional Board Manager URLs field. You can add multiple URLs, separating them with commas. 3. Open the Boards Manager from Tools > Board menu and install the esp8266 package (and after that don't forget to select your ESP8266 board from Tools > Board menu). +### For WiFi using the ESP32 chip + +To use the library with the ESP32 WiFi chip you will need to install the board definitions for the Arduino IDE. These are the steps to install support for the ESP32 chip inside the Arduino IDE: + +1. Follow the install instructions from [https://github.com/espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) +2. Restart the Arduino IDE +3. Select your ESP32 board from Tools > Board menu. + ### For WiFi using the CC3000 chip - [Adafruit CC3000 Library](https://github.com/adafruit/Adafruit_CC3000_Library) @@ -118,10 +126,10 @@ To install the library, simply clone this repository in the /libraries folder of 5. Type `/mode/8/o /` to set the pin as an output 6. Now type `/digital/8/1 /` and the LED should turn on -## Quick test (ESP8266) +## Quick test (ESP8266/ESP32) -1. Connect a LED & resistor to pin number 5 of your ESP8266 board -2. Open the ESP8266 example sketch and modify the WiFi SSID & password +1. Connect a LED & resistor to pin number 5 of your ESP8266/ESP32 board +2. Open the ESP8266/ESP32 example sketch and modify the WiFi SSID & password 3. Upload the sketch 4. Open the Serial monitor to get the IP address of the board, for example 192.168.1.103 5. Go to a web browser and type `192.168.1.103/mode/5/o` to set the pin as an output diff --git a/aREST.h b/aREST.h index 3bfb662..1b50891 100644 --- a/aREST.h +++ b/aREST.h @@ -7,9 +7,10 @@ This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License: http://creativecommons.org/licenses/by-sa/4.0/ - Version 2.4.2 + Version 2.5.0 Changelog: + Version 2.5.0: Added support for the ESP32 WiFi chip (local & cloud) Version 2.4.2: Added publish() support for MKR1000 Version 2.4.1: Additional fixes for Pro plans Version 2.4.0: Added support for aREST Pro & several fixes @@ -67,12 +68,12 @@ #define MQTT_MAX_PACKET_SIZE 512 // Using ESP8266 ? -#if defined(ESP8266) +#if defined(ESP8266) || defined(ESP32) #include "stdlib_noniso.h" #endif // Which board? -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266) || defined(ESP32) #define NUMBER_ANALOG_PINS 16 #define NUMBER_DIGITAL_PINS 54 #define OUTPUT_BUFFER_SIZE 2000 @@ -93,6 +94,8 @@ // Hardware data #if defined(ESP8266) #define HARDWARE "esp8266" +#elif defined(ESP32) +#define HARDWARE "esp32" #else #define HARDWARE "arduino" #endif @@ -116,7 +119,7 @@ // Default number of max. exposed variables #ifndef NUMBER_VARIABLES - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266)|| defined(ESP32) || !defined(ADAFRUIT_CC3000_H) #define NUMBER_VARIABLES 10 #else #define NUMBER_VARIABLES 5 @@ -125,7 +128,7 @@ // Default number of max. exposed functions #ifndef NUMBER_FUNCTIONS - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266) + #if defined(__AVR_ATmega1280__) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(CORE_WILDFIRE) || defined(ESP8266) #define NUMBER_FUNCTIONS 10 #else #define NUMBER_FUNCTIONS 5 @@ -284,6 +287,7 @@ void set_status_led(uint8_t pin){ pinMode(status_led_pin,OUTPUT); } +#if !defined(ESP32) // Glow status LED void glow_led() { @@ -294,6 +298,7 @@ void glow_led() { analogWrite(status_led_pin,j/8); } } +#endif // Send HTTP headers for Ethernet & WiFi void send_http_headers(){ @@ -979,7 +984,7 @@ void process(char c){ } // Check if variable name is in float array (Mega & ESP8266 only) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) for (uint8_t i = 0; i < float_variables_index; i++){ if(answer.startsWith(float_variables_names[i])) { @@ -995,7 +1000,7 @@ void process(char c){ #endif // Check if variable name is in float array (Mega & ESP8266 only) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) for (uint8_t i = 0; i < string_variables_index; i++){ if(answer.startsWith(string_variables_names[i])) { @@ -1229,7 +1234,9 @@ bool send_command(bool headers) { if (state == 'w') { // Write output value + #if !defined(ESP32) analogWrite(pin,value); + #endif // Send feedback to client addToBuffer(F("{\"message\": \"Pin D")); @@ -1256,7 +1263,7 @@ bool send_command(bool headers) { } // Float ariable selected (Mega only) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) if (command == 'l') { // Send feedback to client @@ -1272,7 +1279,7 @@ bool send_command(bool headers) { #endif // String variable selected (Mega & ESP8266 only) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) if (command == 's') { // Send feedback to client @@ -1460,7 +1467,7 @@ void variable(char * variable_name, int *variable){ } // Float variables (Mega & ESP only, or without CC3000) -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) void variable(char * variable_name, float *variable){ float_variables[float_variables_index] = variable; @@ -1471,7 +1478,7 @@ void variable(char * variable_name, float *variable){ #endif // String variables (Mega & ESP only, or without CC3000) -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) void variable(char * variable_name, String *variable){ string_variables[string_variables_index] = variable; @@ -1506,9 +1513,13 @@ void set_id(char *device_id){ strcpy(in_topic, inTopic.c_str()); strcpy(out_topic, outTopic.c_str()); + // inTopic.toCharArray(in_topic, inTopic.length()); + // outTopic.toCharArray(out_topic, outTopic.length()); + // Build client ID String clientId = randomId + String(id); strcpy(client_id, clientId.c_str()); + // clientId.toCharArray(client_id, clientId.length()); if (DEBUG_MODE) { Serial.print("Input MQTT topic: "); @@ -1516,6 +1527,9 @@ void set_id(char *device_id){ Serial.print("Output MQTT topic: "); Serial.println(out_topic); + + Serial.print("Client ID: "); + Serial.println(client_id); } #endif @@ -1621,7 +1635,7 @@ void addToBuffer(char * toAdd){ } // Add to output buffer -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) void addToBuffer(String toAdd){ if (DEBUG_MODE) { @@ -1901,14 +1915,14 @@ void setMQTTServer(char* new_mqtt_server){ #endif // Float variables arrays (Mega & ESP8266 only) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) uint8_t float_variables_index; float * float_variables[NUMBER_VARIABLES]; char * float_variables_names[NUMBER_VARIABLES]; #endif // String variables arrays (Mega & ESP8266 only) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(ESP8266) || defined(CORE_WILDFIRE) || !defined(ADAFRUIT_CC3000_H) || defined(ESP32) uint8_t string_variables_index; String * string_variables[NUMBER_VARIABLES]; char * string_variables_names[NUMBER_VARIABLES]; diff --git a/examples/ESP32/ESP32.ino b/examples/ESP32/ESP32.ino new file mode 100644 index 0000000..9a12956 --- /dev/null +++ b/examples/ESP32/ESP32.ino @@ -0,0 +1,88 @@ +/* + This a simple example of the aREST Library for the ESP32 WiFi chip. + See the README file for more details. + + Written in 2017 by Marco Schwartz under a GPL license. + +*/ + +// Import required libraries +#include +#include + +// Create aREST instance +aREST rest = aREST(); + +// WiFi parameters +const char* ssid = "your_wifi_network_name"; +const char* password = "your_wifi_network_password"; + +// Create an instance of the server +WiFiServer server(80); + +// Variables to be exposed to the API +int temperature; +int humidity; + +// Declare functions to be exposed to the API +int ledControl(String command); + +void setup() +{ + + // Start Serial + Serial.begin(115200); + + // Init variables and expose them to REST API + temperature = 24; + humidity = 40; + rest.variable("temperature",&temperature); + rest.variable("humidity",&humidity); + + // Function to be exposed + rest.function("led",ledControl); + + // Give name & ID to the device (ID should be 6 characters long) + rest.set_id("1"); + rest.set_name("esp32"); + + // Connect to WiFi + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.println("WiFi connected"); + + // Start the server + server.begin(); + Serial.println("Server started"); + + // Print the IP address + Serial.println(WiFi.localIP()); + +} + +void loop() { + + // Handle REST calls + WiFiClient client = server.available(); + if (!client) { + return; + } + while(!client.available()){ + delay(1); + } + rest.handle(client); +} + +// Custom function accessible by the API +int ledControl(String command) { + + // Get state from command + int state = command.toInt(); + + digitalWrite(6,state); + return 1; +} diff --git a/examples/ESP32_cloud/ESP32_cloud.ino b/examples/ESP32_cloud/ESP32_cloud.ino new file mode 100644 index 0000000..fd0d6b3 --- /dev/null +++ b/examples/ESP32_cloud/ESP32_cloud.ino @@ -0,0 +1,94 @@ +/* + This a simple example of the aREST Library for the ESP32 WiFi chip. + This example illustrate the cloud part of aREST that makes the board accessible from anywhere + See the README file for more details. + + Written in 2017 by Marco Schwartz under a GPL license. + +*/ + +// Import required libraries +#include +#include +#include + +// Clients +WiFiClient espClient; +PubSubClient client(espClient); + +// Create aREST instance +aREST rest = aREST(client); + +// Unique ID to identify the device for cloud.arest.io +char* device_id = "unique_device_id"; + +// WiFi parameters +const char* ssid = "your_wifi_network_name"; +const char* password = "your_wifi_network_password"; + +// Variables to be exposed to the API +int temperature; +int humidity; + +// Declare functions to be exposed to the API +int ledControl(String command); + +// Functions +void callback(char* topic, byte* payload, unsigned int length); + +void setup() +{ + + // Start Serial + Serial.begin(115200); + + // Set callback + client.setCallback(callback); + + // Init variables and expose them to REST API + temperature = 24; + humidity = 40; + rest.variable("temperature",&temperature); + rest.variable("humidity",&humidity); + + // Function to be exposed + rest.function("led",ledControl); + + // Give name & ID to the device (ID should be 6 characters long) + rest.set_id(device_id); + rest.set_name("esp32"); + + // Connect to WiFi + WiFi.begin(ssid, password); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.println("WiFi connected"); + +} + +void loop() { + + // Connect to the cloud + rest.handle(client); + +} + +// Handles message arrived on subscribed topic(s) +void callback(char* topic, byte* payload, unsigned int length) { + + rest.handle_callback(client, topic, payload, length); + +} + +// Custom function accessible by the API +int ledControl(String command) { + + // Get state from command + int state = command.toInt(); + + digitalWrite(6,state); + return 1; +} diff --git a/library.properties b/library.properties index 6584e5e..8f16831 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=aREST -version=2.4.2 +version=2.5.0 author=Marco Schwartz maintainer=Marco Schwartz sentence=RESTful API for the Arduino platform.