Time Capsule Post : Physically Manifesting Facebook Comments

At first, I managed to use the Temboo Facebook choreo to post a test message:

fbtest

Temboo provides much more Facebook functionality than that, so I wove together a couple more choreos to create the Time Capsule Post. This would consist of an Arduino which, when a button is pushed, would automatically post a status on Facebook. After 12 hours, this status would be automatically deleted, but not before all comments made on the post were downloaded onto the Arduino. As a result, the comments would no longer exist anywhere other than within the memory of the Arduino chip (and probably backed up deep in some Facebook server). Here was my attempted post :

fbtest2

Even though it was posted to my timeline and set to be visible to everyone, no account other than my own was able to view the post. I therefore posted some filler comments myself, and ran the autodelete/comment parsing code, returning this result:

fbtest3

While I never actually constructed the simple pushbutton circuit necessary to run the code, I did create an Arduino C program which would both send and receive data serially to/from my Processing sketch:

Processing:

import com.temboo.core.*;
import com.temboo.Library.Facebook.Deleting.*;
import com.temboo.Library.Facebook.Reading.*;
import com.temboo.Library.Facebook.Publishing.*;
import processing.serial.*;
Serial myPort;
String statid;
String[] results;
int startTime;
boolean posted = false;
int ValueIn;
int ValueOut;

TembooSession session = new TembooSession("hex", "facebooklikekeepingupwith", "4v2AjLyKERbZ8Ate9uuDXYGLINaujfjr");
void setup() {
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void collectInput()
{
  while(myPort.available () > 0 && posted == false)
  {
    char aChar = (char) myPort.read();
    if (aChar == 'o')
    {
      posted = true
      statid = runPostChoreo();
      startTime = hour();
    }
  }
}

void draw()
{
  collectInput();
  if (posted && (hour() == (startTime + 12) % 24 || keyPressed))
  {
    results = runCommentsChoreo();
    myPort.write(results);
    println(results);
    runDeleteStatusChoreo();
  }
}

String[] runCommentsChoreo() {
  Comments commentsChoreo = new Comments(session);

  commentsChoreo.setCredential("FacebookAccount");

  commentsChoreo.setObjectID(statid);

  CommentsResultSet commentsResults = commentsChoreo.run();
  
  println(commentsResults.getResponse());
  println(commentsResults.getHasNext());
  println(commentsResults.getHasPrevious());
  return parseComments(commentsResults.getResponse());
}

String runPostChoreo() {
  Post postChoreo = new Post(session);

  postChoreo.setCredential("FacebookAccount");

  postChoreo.setMessage("This is a Time Capsule Post. In 12 hours, this post will be deleted automatically. Any comments on this post will be archived in a digital capsule. This digital capsule will be buried on the Carnegie Mellon campus for the next 50 years, as a part of CMU's ongoing Social Archiving Initiative (SAI). Please comment, and your messages will be stashed away for posterity.");
  PostResultSet postResults = postChoreo.run();
  
  println(postResults.getResponse());
  return parseResults(postResults.getResponse());
}

void runDeleteStatusChoreo() {
  DeleteObject deleteObjectChoreo = new DeleteObject(session);

  deleteObjectChoreo.setCredential("FacebookAccount");

  deleteObjectChoreo.setObjectID(statid);

  DeleteObjectResultSet deleteObjectResults = deleteObjectChoreo.run();

  println(deleteObjectResults.getResponse());


}

String parseResults(String results)
{
  String digits = "0123456789_";
  while(results.indexOf("\"id\":\"") != -1)
  {
    results = results.substring(results.indexOf("\"id\":\"") + 6);
    for(int i = 0; i < results.length(); i++)
    {
      if (digits.indexOf(results.charAt(i)) == -1)
      {
        return results.substring(0,i);
      }
    }
  }
  return "-1";
}

String[] parseComments(String results)
{
  String[] comments = new String[results.split("from").length-1];
  if (comments.length == 0)
  {
    return new String[] {"no comments"};
  }
  String commenter = "", comment = "";
  int index = 0;
  while(results.indexOf("\"from\":") != -1)
  {
    results = results.substring(results.indexOf("\"from\":\"") + 8);
    results = results.substring(results.indexOf("\"name\":\"") + 8);
    for(int i = 0; i < results.length(); i++)
    {
      if (results.charAt(i) == '\"')
      {
        commenter = results.substring(0,i);
        println("commenter: " + commenter);
        break;
      }
    }
    results = results.substring(results.indexOf("\"message\":\"") + 11);
    for(int i = 0; i < results.length(); i++)
    {
      if (results.charAt(i) == '"')
      {
        comment = results.substring(0,i);
        println("comment: " + comment);
        break;
      }
    }
    comments[index] = commenter + ": " + comment;
    index++;
  }
  return comments;
}

Arduino C:

const int button = 2;
String inputString = "";         
boolean stringComplete = false;  
void setup()
{
  Serial.begin(9600);
  pinMode(button, INPUT);
}

void loop()
{
  int sensorReading = digitalRead(button);
  if(sensorReading == HIGH)
  {
    Serial.println("go");
  }
}

void serialEvent() 
{
  while (Serial.available())
  {
    char inChar = (char)Serial.read();
    inputString += inChar;
  }
}

Twitter Dongers

Sometimes we feel no particular inspiration to do more that is required of us. this is one of those times. I made a buttoned Arduino that posts dongers to twitter. Its turns out that using non-ASCII text in processing can get weird.

IMG_1131

IMG_1133

Screen Shot 2014-11-16 at 23.38.43

Arduino Code:

int pushButton = 2;
int buttonState = 0;
boolean pushed = false;




void setup() {
  Serial.begin(9600);
  Serial.println("in setup");
  pinMode(pushButton, INPUT);    
}




void loop() {
 
  buttonState = digitalRead(pushButton);
  
  if(buttonState == LOW && pushed == false){
    Serial.println("A");
    pushed = true;
  } else if(buttonState == HIGH && pushed) {
    Serial.println("B");
    pushed = false;
  } else {
    Serial.println("B");
  }
  delay(100);
}

 

Processing Code:

import com.temboo.core.*;
import com.temboo.Library.Twitter.Tweets.*;
import processing.serial.*;
Serial myPort;

// Create a session using your Temboo account application details
TembooSession session = new TembooSession("bruehausu", "TweetTest", "ce6b4e4e5a5547d4b5f4509719ebf417");
String dongers[] = {"╰༼ ・ิ ﹏ ・ิ ༽"
                   ,"ԅ[ •́ ﹏├┬┴┬┴╯"
                   ,"ᕦ༼ •́ – •̀ ༽ᕤ"
                   ,"[ ” ಠ ‸ ಠ ” ]"
                   ,"╏ ◔ _̀ ◔ ╏"};

int dongCount = 0;


ArrayList serialChars;      // Temporary storage for received serial data
int whichValueToAccum = 0;  // Which piece of data am I currently collecting? 
boolean bJustBuilt = false; // Did I just finish collecting a datum?

void setup() {
  // Run the StatusesUpdate Choreo function
  int nPorts = Serial.list().length; 
  for (int i=0; i < nPorts; i++) {
  println("Port " + i + ": " + Serial.list()[i]);
  } 
  
    String portName = Serial.list()[5]; 
  myPort = new Serial(this, portName, 9600);
  serialChars = new ArrayList();
}

void processSerial() {
 
  while (myPort.available () > 0) {
    char aChar = (char) myPort.read();
 
    // You'll need to add a block like one of these 
    // if you want to add a 3rd sensor:
    if (aChar == 'A') {
      runStatusesUpdateChoreo();
      dongCount = (dongCount + 1) % 5 ;
    }
  }
}


void runStatusesUpdateChoreo() {
  // Create the Choreo object using your Temboo session
  StatusesUpdate statusesUpdateChoreo = new StatusesUpdate(session);

  // Set inputs
  statusesUpdateChoreo.setAccessToken("2496575443-x8goxXtw4Dp5BatxwOxkm9IDHbI1tCwokTmQbet");
  statusesUpdateChoreo.setAccessTokenSecret("UmexeEsZnfhCySHdRESYFvj8fOuhPqk9GtAc7AumzQr1F");
  statusesUpdateChoreo.setConsumerSecret("gFzXagXdUhmnLPZOLuzIVEzU6ibf3F1u0asxUrflxlbzsuO0AU");
  statusesUpdateChoreo.setStatusUpdate(dongers[dongCount]);
  statusesUpdateChoreo.setConsumerKey("yLcaFxHKrDwX2C76zSelKFQEz");

  // Run the Choreo and store the results
  StatusesUpdateResultSet statusesUpdateResults = statusesUpdateChoreo.run();
  
  // Print results
  println(statusesUpdateResults.getResponse());

}

void draw() {
  processSerial();
}

 

Temboo and Twitter

Having already constructed a vision for my final, I used project 11 to play around and test some of the available components I will be using for my final. As a result I attempted to make a program that would tweet depending on whether or not a force resistor was pressed. I learned how to make arrays and how to store strings in them, and then created a list of a few things that I wanted the computer to tweet. After that I tested it by creating a interface on processing that changed the words depending on if you pressed the resistor or not. When I was finished with that I simply linked it to twitter instead of the interface. As I was testing it somehow, I ended up using all of my available data for Temboo. Luckily that data resets every month so for my final project I will test it simply using processing until my Temboo data limit refreshes. Below are some images of the tweets sent by the force resistor as well as the initial project to send a tweet just from Temboo’s processing code.

Tweeting through my aurdino and force resistor

As the values increase (as you press the resistor) it scrolls through the list of phrases to potentially say.
changing values twitter 3 good please

When you let go the visible phrase changes to the last one you stopped at. Once you hold the resistor down again the process continues.
vidddd2

 

 

The results can be seen on the screen and, as I programmed it to, as a tweet.
Screenshot_2014-11-16-23-35-22

My code can be seen down below.

Processing Code:

// This program will relay a series of six phrases when the user presses a pressure sensor
 
// Import the Serial library and create a Serial port handler
import processing.serial.*;
Serial myPort;   


import com.temboo.core.*;
import com.temboo.Library.Twitter.Tweets.*;

// Create a session using your Temboo account application details
TembooSession session = new TembooSession("ritznrubble", "myFirstApp", "1d8cccc701d3473282acd6d52044d86b");

 

int valueA;  // Sensor Value A
int valueB;  // Sensor Value B
 boolean a=false;
 float i; 
//------------------------------------
int y= 0;
int update=0;
int mapA;
int valA=0;
String[] sayings= new String[6];
//tracking if c is equal to y or if the value of y changes
int c=y;
int count=0;
void setup(){
  
  runStatusesUpdateChoreo();

  size(250,200);
  // List my available serial ports
  int nPorts = Serial.list().length; 
  for (int i=0; i < nPorts; i++) {
    println("Port " + i + ": " + Serial.list()[i]);
  }
  
   String portName = Serial.list()[0]; 
  myPort = new Serial(this, portName, 9600);
  serialChars = new ArrayList();
  
  //array of sayings
  
sayings [0]= "That hurts!";
sayings [1]= "Stop pushing!";
sayings [2]= "Pull back!";
sayings [3]= "Under Pressure";
sayings [4]= "So much stress!";
sayings [5]= "The pain!";
}

void draw(){
  processSerial();
 
background(0);
fill(255);
 println("check c", c, "check y", y, "check count:", count, "valueA", valueA, "ValA", valA, "mapA", mapA, "update", update);

   text(sayings[update],100,height/2);
//
 if (valueA==0){
  a=!a;
 } 
  

if (!a){
 
   i= random(6);
   y= (int)i;
 count=count+1; 
    c=y; 
    update=-1;
    
 
}else{
  a=false;
 update= c; 
 } while(update==c){
   runStatusesUpdateChoreo();
   
   
 }
   Math.round(y);
   
}



void runStatusesUpdateChoreo() {
  
 
  // Create the Choreo object using your Temboo session
  StatusesUpdate statusesUpdateChoreo = new StatusesUpdate(session);

  // Set credential
  statusesUpdateChoreo.setCredential("Test");

  // Set inputs
  statusesUpdateChoreo.setAccessToken("569521804-FioaGf2pkeT2DIECqmW1jqhrxnHLiaFepyUhnhSL");
  statusesUpdateChoreo.setAccessTokenSecret("M4DQwCeSZPJBN5Pn8YLmB3RLRXpXk3Ec9zx6AMoDOtCur");
  statusesUpdateChoreo.setConsumerSecret("4XapePIoUgWMEeRet54J7Vtnsvt8gYGBONqXNIeG8ZOKqQDjyn");
  statusesUpdateChoreo.setStatusUpdate(sayings[update]);
  statusesUpdateChoreo.setConsumerKey("PQZOI9BpDdu3txrFVSzVdQZfG");

  // Run the Choreo and store the results
  StatusesUpdateResultSet statusesUpdateResults = statusesUpdateChoreo.run();
  
  

}


//---------------------

ArrayList serialChars;      // Temporary storage for received serial data
int whichValueToAccum = 0;  // Which piece of data am I currently collecting? 
boolean bJustBuilt = false; // Did I just finish collecting a datum?
 
void processSerial() {
 
  while (myPort.available () > 0) {
    char aChar = (char) myPort.read();
 
    // You'll need to add a block like one of these 
    // if you want to add a 3rd sensor:
    if (aChar == 'A') {
      bJustBuilt = false;
      whichValueToAccum = 0;
    } else if (aChar == 'B') {
      bJustBuilt = false;
      whichValueToAccum = 1;
    } else if (((aChar == 13) || (aChar == 10)) && (!bJustBuilt)) {
      // If we just received a return or newline character, build the number: 
      int accum = 0; 
      int nChars = serialChars.size(); 
      for (int i=0; i < nChars; i++) { 
        int n = (nChars - i) - 1; 
        int aDigit = ((Integer)(serialChars.get(i))).intValue(); 
        accum += aDigit * (int)(pow(10, n));
      }
 
      // Set the global variable to the number we captured.
      // You'll need to add another block like one of these 
      // if you want to add a 3rd sensor:
      if (whichValueToAccum == 0) {
        valueA = accum;
        // println ("A = " + valueA);
      } else if (whichValueToAccum == 1) {
        valueB = accum;
        // println ("B = " + valueB);
      }
 
      // Now clear the accumulator
      serialChars.clear();
      bJustBuilt = true;
 
    } else if ((aChar >= 48) && (aChar <= 57)) {
      // If the char is between '0' and '9', save it.
      int aDigit = (int)(aChar - '0'); 
      serialChars.add(aDigit);
    }
  }
}

Aurdino Code:

// This Arduino program reads  signals, 
// such as from the force resistor 
 

int sensorValue1 = 0;  // variable to store the value coming from the other sensor
 
void setup() {
  Serial.begin(9600);  // initialize serial communications    
}
 
void loop() {
 
  // Read the value from the sensor 

  sensorValue1 = analogRead (A1);  // reads value from Analog input 1    
 

  Serial.print ("A"); 
  Serial.println (sensorValue1);  
 
  delay (50);   // wait a fraction of a second, to be polite
}
 
/*

*/

Earlier

For my initial test on using twitter (before making this program), I had processing tweet, “Well did it work?”.
Screenshot_2014-11-16-21-45-40

Temboo Location

location: 77 Greenwood Circle Womleysburg, PA
latitude: 40.255775
longitude: -76.90538

// More examples & getting started tutorials can be found at:
// https://temboo.com/processing
// Import the Temboo library core and appropriate Choreos
import com.temboo.core.*;
import com.temboo.Library.Google.Geocoding.*;

// Create a session using your Temboo account application details
// If you don't have a Temboo account, sign up here:
// http://temboo.com/signup
// If you do have a Temboo account, find your application details here:
// http://temboo.com/account/applications
TembooSession session = new TembooSession("salexy", "myFirstApp", "111dc69fd5864a3e95ef1ed410610654");

// Set up some global variables
String location = "77 Greenwood Circle Womleysburg, PA";
float latitude, longitude;

void setup() {
// Run the GeocodeByAddress Choreo function
runGeocodeByAddressChoreo();
}

void runGeocodeByAddressChoreo() {
// Create the Choreo object using your Temboo session
GeocodeByAddress geocodeByAddressChoreo = new GeocodeByAddress(session);

// Set inputs
geocodeByAddressChoreo.setAddress(location);

// Run the Choreo and store the results
GeocodeByAddressResultSet geocodeByAddressResults = geocodeByAddressChoreo.run();

// Save latitude and longitude as floats
latitude = float(geocodeByAddressResults.getLatitude());
longitude = float(geocodeByAddressResults.getLongitude());

// Print latitude and longitude
println("location: " + location);
println("latitude: " + latitude);
println("longitude: " + longitude);
}

Button That Tweets

Screen Shot 2014-11-16 at 2.23.12 PM

IMG_20141116_142030

 

Homework12B

 

Arduino Code

const int buttonPin = 7;    
 
// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
 
void setup() {
  Serial.begin(9600);  // initialize serial communications   
 
}
 
void loop(){
  buttonState = digitalRead (buttonPin);
  Serial.print (buttonState);  
 
  delay (10);   // wait some number of milliseconds
 
}

Processing Code

import com.temboo.core.*;
import com.temboo.Library.Twitter.Tweets.*;
import processing.serial.*;
 
Serial myPort;  // Create object from Serial class
 
// Create a session using your Temboo account application details
TembooSession session = new TembooSession("boril", "myFirstApp", "mljV10Z8EpQhRIpLb9Zfg46EIw5wbfDT");

void setup() {
  String portName = Serial.list()[2];
  myPort = new Serial(this, portName, 9600);
  
  runStatusesUpdateChoreo();
}
 
void runStatusesUpdateChoreo() {
  // Create the Choreo object using your Temboo session
  StatusesUpdate statusesUpdateChoreo = new StatusesUpdate(session);
 
  // Set credential to use for execution
  statusesUpdateChoreo.setCredential("Homework12");

 
  // Set inputs
  statusesUpdateChoreo.setAccessToken("2878889817-A1lJYK6T8V0i50Vp6KVDdl9JnduZMEHOp3ELC6S");
  statusesUpdateChoreo.setAccessTokenSecret("ZsxrnXixOUcmAHKH3SZKg7zrdncsoonYoXnnLty1yIHNM");
  statusesUpdateChoreo.setStatusUpdate("TESTING!!!!");
 
  // Execute Choreo
  StatusesUpdateResultSet statusesUpdateResults = statusesUpdateChoreo.run();

}

The Finger

So the final form of this project represents how I feel about this project Actually never mind, by the end of the project, due to a litany of technical difficulties and having to scrap what I thought I was coding and reinstall the entire arduino driver, this is actually pretty much how I felt about it:IMG_2329

In any case, the original conception of this project was that I wanted to make a hand. Just in general. Hands are expressive and they move in ways that seem pretty basic but aren’t. Initially I thought I was going to do something ridiculously complicated with like sixteen itty bitty gears that would replicate finger joints, just to prove that I could make a hand. Once I’d gotten that far it was too late to come up with a different concept, so I thought, “Okay, I’m making a hand. How can I make it interesting and/or amusing?”

And so this happened. Basically it’s a horribly lumpy little clay hand about the size of a ten-year-old’s, which gives the middle finger to its audience when you twist a potentiometer. There’s that saying, something like “it takes 4o something muscles to frown and only 4 to smile” and I don’t know how many it takes to flip someone the bird. I don’t know how many more muscles it is to turn a dial on a potentiometer, but I bet it’s more than just sticking up the middle finger yourself. Essentially, this is a machine that says that you’re putting some real effort into telling someone “fuck you.”

(Sketches are coming I promise)

Fritzing diagram:

potentiomiddle finger

Arduino code (borrowed under extenuating circumstances):

// Controlling a servo position using a potentiometer (variable resistor) 
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 
//code adopted under emergency circumstances

#include  
 
Servo myservo;  // create servo object to control a servo 
 
int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
}  
 
void loop() 
{ 
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023) 
  val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180) 
  myservo.write(val);                  // sets the servo position according to the scaled value 
  delay(15);                           // waits for the servo to get there 
}

A Button that Tweets

Full disclosure: I went for the minimal project so that I can dedicate more time to the final.

Screen Shot 2014-11-12 at 7.08.35 PMThis is my initial Temboo test, before the button was connected.

Screen Shot 2014-11-12 at 9.02.56 PMThis test has the button connection. Now we have a tweeting button!

circuittweetButton_bb

//Miranda Jacoby
//Electronic Media Studio Interactivity Section A
//majacoby@andrew@.cmu.edu
//Copyright Miranda Jacoby 2014
//Code created with help of Golan Levin
//With elements of the pushbutton example code 
   //created 2005
   //by DojoDave <http://www.0j0.org>
   //modified 30 Aug 2011
   //by Tom Igoe
   //http://www.arduino.cc/en/Tutorial/Button


// constants won't change. They're used here to 
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  Serial.begin(9600);  // initialize serial communications   
  
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead (buttonPin);

  // print if the pushbutton is pressed.
  // Serial.println (buttonState); writes the string "1" or "0"
  Serial.print (buttonState);  
  
  delay (10);   // wait some number of milliseconds

}
//Miranda Jacoby
//Electronic Media Studio Interactivity Section A
//majacoby@andrew@.cmu.edu
//Copyright Miranda Jacoby 2014
//Code created with help of Golan Levin and Temboo. 

import com.temboo.core.*;
import com.temboo.Library.Twitter.Tweets.*;
import processing.serial.*;

Serial myPort;  // Create object from Serial class
int currVal;      // Data received from the serial port
int prevVal;
int tweetTime;
int currentTime;

// Create a session using your Temboo account application details
TembooSession session = new TembooSession("pigeon", "pigeontwitter", "2289511ed75e4578a3b71a4b693fdb03");

void setup() {
  
  size(200, 200);
  String portName = Serial.list()[5];
  myPort = new Serial(this, portName, 9600);
  
   currentTime = millis();
}

void draw() {
  
  prevVal = currVal;  // swap
  if ( myPort.available() > 0) {  // If data is available,
    currVal = myPort.read();         // read it and store it in val
    myPort.clear();
  }
  background(255);             // Set background to white
  if (currVal == 48) {              // If the serial value is "0",
    fill(0);                   // set fill to black
  } else if (currVal == 49) {         // If the serial value is not 0,
    fill(240);                 // set fill to whiteish
  } else {
    fill(255, 0, 0);
  }
  rect(50, 50, 100, 100);

  if (currVal != prevVal) {
    if (currVal == 48) {
      sendTweet();
    } else if (currVal == 49) {
      // println ("Released!");
    }
  }
}

void sendTweet(){
  tweetTime = millis() - currentTime;
  println ("I was pressed at " + tweetTime);  
  if (tweetTime > 1000){
    println("Sucessful tweet");
    //send tweet by running the StatusesUpdate Choreo function
     runStatusesUpdateChoreo();
  } 
  else  {
    println("To soon to tweet!");
  }
  currentTime = millis();
}

void runStatusesUpdateChoreo() {
  // Create the Choreo object using your Temboo session
  StatusesUpdate statusesUpdateChoreo = new StatusesUpdate(session);

  // Set credential
  statusesUpdateChoreo.setCredential("TweetButton");

  // Set inputs
  statusesUpdateChoreo.setAccessToken("2769267476-rHudd8EwU7uLhkcruAwHxJtzA5AB7EH9lwPFD7s");
  statusesUpdateChoreo.setAccessTokenSecret("aIxNctSi3RXShSRn0iWfaDkE8NSN9OglhY4GgOU1gWRZy");
  statusesUpdateChoreo.setStatusUpdate("Testing, for the second time: A button that tweets when you press it.");

  // Run the Choreo and store the results
  StatusesUpdateResultSet statusesUpdateResults = statusesUpdateChoreo.run();
  
  // Print results
  println(statusesUpdateResults.getResponse());

}