Arduino WiFi Twitter Read Only, App Read Permission

arduino
tls

#1

So here is what I am trying to do. The program below was pulled from Github and works to allow me to connect to an HTTPS server using the fingerprint of the server’s cert as validation. I’m now trying to modify this to work with my ESP8266 based breakout board (Hazzah by Adafruit). I have successfully connected to the website that is commented out in the code, as well as a few other test sites.

My ultimate goal is to read a Twitter account string (my own), then depending up either a hashtag or perhaps just a specific string, I would like to activate a stepper motor. In my .ino that has all of my other code, the sketch is working on all accounts, with the exception of connecting to Twitter.

Here’s what I’ve learned in my Red Bull fulled craze last night. I need to get a “bearer token” and also validate 3 certs as well as supply my own? I suspect I could get a generic cert for my application from somewhere (know I stumbled upon it last night) but I’m not sure that would help me much. I’ve tried 5 different fingerprints for the Twitter cert; 3 from my inspection via Chrome while on my timeline, 2 from the Twitter Devs api support page; all failed, I assumed because of the bearer token.

I also (this was a challenge since I don’t know PHP) tried to set up a PHP script last and server last night. I failed horrible at this. Next I tried to use a google script someone created to create an RSS feed to read my twitter, but have had no luck with that. I’m honestly completely confused by the HTTP syntax and such as this is my first forary into this arena. Below is a link to a thread on Arduino where I have been asking for assistance.

Arudino Forum

I’m thinking the best way to do this is to create the secure connection, get my bearer token, then dump the memory to make room for the incoming tweets.

Finally, when I had some code in line to get my error codes, I kept getting an error code of 400 returned.

// (c) Copyright 2010-2012 MCQN Ltd.
// Released under Apache License, version 2.0
//
// Simple example to show how to use the HttpClient library
// Get's the web page given at http://<kHostname><kPath> and
// outputs the content to the serial port

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

// This example downloads the URL "http://arduino.cc/"

 // Network Connection Settings
  const char* ssid = "Work Sucks, Quit Now";
  const char* password = "Seriously Quit Now";

// On board LED Setup
  int LEDblue = 2;
  int LEDred = 0;

// Use web browser to view and copy SHA1 fingerprint of the certificate
const char* fingerprint = "‎DDFB16CD4931C973A2037D3FC83A4D7D775D05E4";

// Name of the server we want to connect to
const char kHost[] = "api.twitter.com";
// Path to download (this is the bit after the hostname in the URL
// that you want to download
const char kPath[] = "";//twitter-oauth/status.php?username=Tipsez&access_token=252204173-Ngm9ZeI6W63B3nRGYDQSFUN8UJR1V0f2LniRPy2U&access_token_secret=VI";
const int httpsPort = 443;

// Number of milliseconds to wait without receiving any data before we give up
const int kNetworkTimeout = 30*1000;
// Number of milliseconds to wait if no data is available before trying again
const int kNetworkDelay = 1000;

void setup()
{
  // Initialize serial port for debugging  
  Serial.begin(115200);
  delay(100);
  
  // First connect WiFi
  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("WiFi Connected! :) ");
    Serial.print ("IP address: ");
    delay(10000);
    Serial.print (WiFi.localIP());
    Serial.println ("");    
  }
   // Prep Onboard LED, blink if not connected otherwise stay on if connected
   // will swap this for power saving once debugging complete
    if (WiFi.status() == WL_CONNECTED)
    { 
      pinMode (LEDblue, HIGH);
    }
    else 
    {
      pinMode (LEDred, HIGH);
      Serial.println ("WiFi is not connected");
     } 
 // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(kHost);
  delay(10000);
  if (!client.connect(kHost, httpsPort)) {
    Serial.println("connection failed");
    return;
  } 
 if (client.verify(fingerprint, kHost)) {
    Serial.println("certificate matches");
  } else {
    Serial.println("certificate doesn't match");
  }
  
}

  
void loop()
{
  int err =0;
  
  WiFiClient c;
  HttpClient http(c);
  
  err = http.get(kHost, kPath);
  if (err == 0)
  {
    Serial.println("startedRequest ok");

    err = http.responseStatusCode();
    if (err >= 0)
    {
      Serial.print("Got status code: ");
      Serial.println(err);

      // Usually you'd check that the response code is 200 or a
      // similar "success" code (200-299) before carrying on,
      // but we'll print out whatever response we get

      err = http.skipResponseHeaders();
      if (err >= 0)
      {
        int bodyLen = http.contentLength();
        Serial.print("Content length is: ");
        Serial.println(bodyLen);
        Serial.println();
        Serial.println("Body returned follows:");
      
        // Now we've got to the body, so we can print it out
        unsigned long timeoutStart = millis();
        char c;
        // Whilst we haven't timed out & haven't reached the end of the body
        while ( (http.connected() || http.available()) &&
               ((millis() - timeoutStart) < kNetworkTimeout) )
        {
            if (http.available())
            {
                c = http.read();
                // Print out this character
                Serial.print(c);
               
                bodyLen--;
                // We read something, reset the timeout counter
                timeoutStart = millis();
            }
            else
            {
                // We haven't got any data, so let's pause to allow some to
                // arrive
                delay(kNetworkDelay);
            }
        }
      }
      else
      {
        Serial.print("Failed to skip response headers: ");
        Serial.println(err);
      }
    }
    else
    {    
      Serial.print("Getting response failed: ");
      Serial.println(err);
    }
  }
  else
  {
    Serial.print("Connect failed: ");
    Serial.println(err);
  }
  http.stop();

  // And just stop, now that we've tried a download
  while(1);
}


#2

Been a while since I’ve tried to do this, although I recently obtained a Huzzah board so should have a go at it for myself.

In the meantime, there are a couple of other threads that might be useful. As you’ll see, I usually recommend against trying to do this from the embedded board directly due to the complexities of the OAuth dance that you’re hitting, but it’s potentially doable if all of the right pieces are in place.


#3

Thank you for the reply. I think I’m going to just try to figure out the Node Red for the time being to get it working (really want to do some reliability testing in winter weather) then try to figure out how to get my HTTPS connection to Twitter. Can you tell me the general flow that would be required for HTTPS to Twitter using OAUTH for an application only read? As I understand it, from my reading, it would be something like:

  1. Establish secure connection to api.twitter.com using something like:

client.println (“GET /twitter-oauth/status.php?username=” + sUsername + “&access_token=” + kAccessToken + “&access_token_secret=” + kAccessTokenSecret + “&count=” + sCountStatus + " HTTP/1.1");
client.println(“https://api.twitter.com/1.1/statuses/show.json”);

  1. Get bearer token – Not sure how to about this
  2. Resubmit my GET?

#4

Node Red links broken for Windows download; oi vey. Maybe I’ll try Google Plus or just send an email to my Arduino for now.


#5

That’s a shame about the Windows link, maybe Tweet @nodered as the team there are usually pretty helpful. Sorry for all the hassle!


#6

I may do that in a few. I’m working through figuring out ThingSpeak now. I started to go this route right from go, but really wanted to do this as a standalone. But alas, I’m not wise enough apparently. :slight_smile: