i am trying to Turn an LED from a hosted website, though Arduino using the CC3000 wifi shield. It is working as it should. but i have to questions about optimising my code :
1) the Part where i parse my JSON is kind of sloppy, what is the right way to Parse the code so i can turn the LED on and off when clicking on the website buttons ?
2) i need to keep the arduino connected to the website, so i can always control the LED. Do i need to close the connection at the end ? if so, how can i activate the connection only when clicking the button on the website to active the LED.
#include <ArduinoJson.h>
// Include Libraries
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
// Define Pins
#define ADAFRUIT_CC3000_IRQ 3
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Define Variables
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER);
#define WLAN_SSID "MyWeb"
#define WLAN_PASS ""
#define WLAN_SECURITY WLAN_SEC_UNSEC // Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
uint8_t dhcpTimeout;
#define host "mygarden.comli.com" // Your domain
uint32_t ip;
String path = "/light.json";
int port = 80;
int pin = 9;
void setup(void)
{
Serial.begin(115200);
delay(10);
pinMode(pin, OUTPUT);
pinMode(pin, HIGH);
// Connect to Wifi
cc3000.begin();
Serial.println(F("Initialising the CC3000"));
if (!cc3000.begin())
{
Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
while(1);
}
/* Delete any old connection data on the module */
Serial.println(F("Deleting old connection profiles"));
if (!cc3000.deleteProfiles()) {
Serial.println(F("Failed!"));
while(1);
}
// Connect to Network
beginning:
Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
Serial.println(F("Connected"));
//Wait for DHCP to complete
Serial.println(F("Requesting DHCP"));
while (!cc3000.checkDHCP()) {
delay(500);
Serial.print(F("."));
dhcpTimeout ++;
if (dhcpTimeout == 60) {
Serial.println(F(""));
Serial.println("DHCP Timeout! Attempting to reconnect.");
dhcpTimeout = 0;
goto beginning;
}
}
Serial.println(F(""));
Serial.println(F("DHCP complete"));
//get website IP
ip = 0;
Serial.print(host); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(host, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);
Serial.println("");
}
void loop(void) {
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
client.print(String("GET ") + path + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: keep-alive\r\n\r\n");
delay(500); // wait for server to respond
Serial.println(F("----------"));
while (client.connected()) {
String response = "";
bool begin = false;
while (client.available() || !begin) {
char c = client.read();
if (c == '{') {
begin = true;
}
if (begin) response += (c);
if (c == '"}') {
break;
}
delay(1);
}
int start = response.indexOf("light\":\"") + 12;
int end = start + 3;
String LED_Control = response.substring(start, end);
if (LED_Control == "onn") {
digitalWrite(pin, HIGH);
Serial.println("LED ON");
}
else if (LED_Control == "off"){
digitalWrite(pin, LOW);
Serial.println("led OFF");
}
}
delay(1000);
Serial.println(F("\n\nClosing the connection"));
client.close();
cc3000.disconnect();
}
And this is my JSON output
{"light": "off"}
2 Answers 2
Assuming that String response
will contain the json {"light": "off"}
and your program is ready to use the ArduinoJson library (#include <ArduinoJson.h>
on top), a simple solution could be:
Step1 - declare and initialize StaticJsonBuffer
object.
StaticJsonBuffer<80> jsonBuffer;
Step2 - deserialize the json from response
.
JsonObject& root = jsonBuffer.parseObject(response);
Step3 - if the deserialization doesn't succeed, warn and break,
if (!root.success())
{
Serial.print("parseObject(");
Serial.print(response);
Serial.println(") failed");
break;
}
Step4 - otherwise, use json object to get the LED_Control
.
Is the json will really contain
{"light": "onn"}
or is a typo ?
String LED_Control = root["light"];
if (LED_Control == "onn") { // 'on' or 'onn' ??
digitalWrite(pin, HIGH);
Serial.println("LED ON");
}
else if (LED_Control == "off"){
digitalWrite(pin, LOW);
Serial.println("led OFF");
}
If the response from the web server is just a boolean value, the 'right' way would IMHO be to return e.g. just a 0 and 1 instead of JSON encoded data. That saves you from parsing JSON on the Arduino completely. Instead you can simply read one character of the response and check for '0' or '1'.
HTTP is a request-response based protocol and not suitable for staying connected to the server. If you need immediate reaction from the Arduino to server-side changes and your web server supports WebSockets, you could use any of the WebSocket libraries for the Arduino. Otherwise, you can use HTTP and poll the web server at a set interval to get the current value of the switch. And if you don't implement HTTP keep-alive, you will have to close the TCP connection and make a new connection for each HTTP request.
response
equal to your json{"light": "off"}
?