-->
Page 1 of 1

read dynamic data using http API

PostPosted: Mon Aug 08, 2016 3:02 pm
by MarinosK
Hi, I'm using the the following code to read random bits (0s and 1s) from a webpage and use them to blink a LED randomly. I've been trying to read such bits from random.org using their old html API - e.g. https://www.random.org/integers/?num=10 ... in&rnd=new - this will generate 100 binary 1-bit numbers. My problem is that the ESP8266 refuses to connect to this host - I get a 'connection failed' message.

am I missing something?

best

Code: Select all
#include <ESP8266WiFi.h>
 
const char* ssid     = "XXXXXXXXX";
const char* password = "XXXXXXXXXXX";
 
const char* host = "www.agxivatein.com";

WiFiClient client;
 
void setup() {
  Serial.begin(115200);
  delay(100);

  pinMode(0, OUTPUT);
 
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected"); 
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  delay(5000);
   
  Serial.print("connecting to ");
  Serial.println(host);
 
  // Use WiFiClient class to create TCP connections
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
 
  // We now create a URI for the request
  String url = "/test/bits.txt";
  Serial.print("Requesting URL: ");
  Serial.println(url);
 
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(500);
}
 
void loop() {
  // Read all the lines (each line only has a bit) of the reply from server and use them to blink a led
  if (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    digitalWrite(0, line.toInt());
  }
  delay(200);
}


m

Re: read dynamic data using http API

PostPosted: Mon Aug 08, 2016 10:46 pm
by rudy
I think your problem is https and the ESP connects with http, and sometime with difficulty, with https. It isn't something I have looked into yet. It seems to be a resource issue.

Maybe this will get you headed in the right direction.
viewtopic.php?f=6&t=3818

https://github.com/electronicsguy/ESP82 ... PSRedirect

Older threads may be dated since new capabilities keep being added.

Re: read dynamic data using http API

PostPosted: Tue Aug 09, 2016 11:27 am
by 8n1
Hi,

Yes, if you want to connect to random.org you must use a SSL connection. Fortunately that works (now) surprisingly good and reliable. Since I did exactly the same some time ago I have a working example for you to test and build upon.

But as "rudy" also mentioned the SSL connection uses quite some memory, keep that in mind.

Here is a small summary of the FreeHeap:
After connecting to the wifi network, getFreeHeap() shows "42.248 KB".
After creating the SSL connection only "25.736 KB" is left.
Directly after receiving the server response: "25.920 KB" (This is a the end of the setup() function)
After entering the loop() the free heap goes instantly up again to about "42.128 KB".


And here is the Arduino sketch: (For a first test only the ssid and password must be configured)
Code: Select all/*
 * random.org SSL example
 * JohSka, 17. Apr 2016
 *
 * What it does:
 * Connects to the wifi network and waits for a IP from the DHCP
 * Connects to random.org using a SSL connection
 * Requests this URL: /integers/?num=1&min=1&max=6&col=1&base=10&format=plain&rnd=new
 * Prints the server response
 *
 * Configuration:
 * For a first test only the ssid and password must be set
 *
 * How to get the SHA1 fingerprint of the certificate: (using a web browser)
 * 1. Open a browser and navigate to the website you want to connect to
 * 2. Open the "Page Info" window (using Strg + i or the context menu or...) and navigate to the Security tab
 * 3. Click on "View Certificate" and copy the SHA1 Fingerprint
 * 4. If the fingerprint has colons (:) in it replace them with spaces!
 *
 * random.org API infos:
 * API Guidelines, IMPORTANT!: https://www.random.org/clients/
 * HTTP Interface Description: https://www.random.org/clients/http/
*/

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>


// WIFI Config
const char* ssid      = "xxxxx";
const char* password  = "xxxxx";

// random.org API URL
const char* request_url = "/integers/?num=1&min=1&max=6&col=1&base=10&format=plain&rnd=new";


// random.org recommends to supply your email address in the User-Agent field
// so they can send you a email if your client is causing trouble instead of just banning your IP.
const char* user_agent = "your@emailaddress.com";

// SSL / Host Config
const char* host    = "www.random.org";
const int httpsPort = 443;

// SHA1 fingerprint of the random.org SSL certificate (Note: This may change!)
const char* fingerprint = "EC 1B 71 CC 42 EB 65 E9 01 60 83 1E 14 19 21 3E A7 1C 75 ED";


// Debug remaining memory
void printHeap() {
  Serial.printf("  Free heap: %i\n", ESP.getFreeHeap());
}

// SETUP
void setup()
{
  Serial.begin(115200);
  Serial.println("");
 
  // WIFI config
  WiFi.mode(WIFI_STA);
 
  // Connect to the ap
  Serial.print("Connecting to the wifi network...");
  WiFi.begin(ssid, password);
 
  // Wait for a IP
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
 
  // Wifi connectetd
  Serial.println("  WiFi connected");
  Serial.print("  IP address: ");
  Serial.println(WiFi.localIP());
 
  printHeap();
 
  // Connect to random.org
  Serial.print("\nConnecting to ");
  Serial.println(host);
 
  // Create the SSL connection
  WiFiClientSecure client;
  if (!client.connect(host, httpsPort)) {
    Serial.println("  Connection failed");
    return;
  }
 
  // Verify the certificate
  if (client.verify(fingerprint, host)) {
    Serial.println("  Done. Certificate matches");
  }
  else {
    Serial.println("  FAIL. certificate doesn't match");
  }
 
  printHeap();
 
  // Send the GET request
  Serial.print("Requesting URL: ");
  Serial.println(request_url);
  client.print(String("GET ") + request_url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  Serial.println("  Done.\n");
 
  // Handle client timeout
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  // If got a response print the server headers
  Serial.println("Server headers:");
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
    if (line == "\r") {
      Serial.println("End of headers");
      break;
    }
  }

  // Print the server message
  Serial.println("\nServer message: (Random number)");
  while (client.available()) {
    String line = client.readStringUntil('\n');
    Serial.println(line);
  }
  Serial.println("End of message");
  printHeap();
  Serial.println("");
}

void loop() {
  printHeap();
  delay(2000);
}


The Serial Monitor will show something like this:
Code: Select allConnecting to the wifi network........
  WiFi connected
  IP address: 192.168.1.37
  Free heap: 42248

Connecting to www.random.org
  Done. Certificate matches
  Free heap: 25736
Requesting URL: /integers/?num=1&min=1&max=6&col=1&base=10&format=plain&rnd=new
  Done.

Server headers:
HTTP/1.1 200 OK
Date: Tue, 09 Aug 2016 11:28:16 GMT
Content-Type: text/plain;charset=utf-8
Transfer-Encoding: chunked
Connection: close
Set-Cookie: __cfduid=d7e9f9de1133af27be28add4c83ec67b91470749295; expires=Wed, 09-Aug-17 13:28:15 GMT; path=/; domain=.random.org; HttpOnly
X-Powered-By: PHP/5.4.45-0+deb7u4
Set-Cookie: RDOSESSION=221c9qg24ij4amcnah7cir6732; path=/; domain=.random.org
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
RDO-Authenticated-Login: -
Access-Control-Allow-Origin: *
Vary: Accept-Encoding
Server: cloudflare-nginx
CF-RAY: 2cfb8cdb519c3934-VIE

End of headers

Server message: (Random number)
2
5

End of message
  Free heap: 25920

  Free heap: 42128
  Free heap: 42128
...

Two other things i noticed:
The fingerprint of the certificate has changed since I first tried this.
The response from random.org always contains two numbers and the first one is always a 2. I have no idea where the 2 is comming from. The actual random number is the second one.

PS: Thanks for the interessting link rudy. But at least on "www.random.org" and "www.googleapis.com" this HTTPSRedirect class is not needed. You have to use the right link though. ("random.org" or "gooogleapis.com" without the "www" doesn't work or they will return "301 Moved permanently" or "404 Not Found" resp. )

Re: read dynamic data using http API

PostPosted: Tue Aug 09, 2016 2:55 pm
by MarinosK
thx both of you!
8n1 your code works out of the box.. thx.