Get a feel for the emotional climate of your Twitter feed without ever having to go on, so that you control your social media experience and it doesn't control you.
Created: February 19th, 2017
During the last political election, things got really heated up online. People on various social media platforms --- friends, family, the media, etc --- were throwing insults left and right. As a result, going online just sucked. Not only were people not getting reliable, useful information, but they were also being smothered with negativity.
So our goal with this project was to create an ambient device that would notify users about the current climate on their social media platform(s). Our hope was that ultimately we would give users more control over their social media experience (so that they could avoid going on or actively post a positive message to help change the mood).
When deciding what type of solution we wanted to create, we had two main things to consider. One was that we had to work within the ambient device space. And two, was that mobile computing was ubiquitous. People could (and often did) access their social media at any time and any place. So we had to make sure our solution was just as ubiquitous in order to be the most effective.
So we decided to create an ambient-device bracelet that would signal to users when the climate of their Twitter feed was positive or negative.
Components used: AAA batteries, battery holders, wood panels, surgical tubes, jumper wires, LED lights, tapes, Photon.
1. Cut wood panels to make a fixed station for the bracelet.
2. Built a circuit
3. Connected three AAA batteries and soldered them together.
4. Soldered LED lights to wires and put them into a surgical tube
5. Put the bracelet into the station to simulate a situation when the bracelet can be part of a clock.
The goal on the software side was to get the statuses of the people a specific user follows, determine whether those statuses were overall more positive or negative, and then send that information to the ambient device.
Iteration 1: In the first iteration, we tried to use IFTTT to create a recipe that would publish an event whenever a specific user tweeted. A link to the applet can be found here: https://ifttt.com/applets/49694825d-if-new-tweet-by-specific-user-moneyg67-then-publish-an-event. The main problem with IFTTT was that there was no option to publish an event when a set of users tweeted. For that, it seemed we would have to create a new applet for each user. That was not scalable. Another problem was that there was an arbitrary (and thus unpredictable) delay between a tweet being posted and an event being published. So we decided that IFTTT wasn't the best tool to use.
//Code from https://docs.particle.io/guide/tools-and-features/ifttt/#publish-an-event
// This version of code is to check if Twitter tweets from
// my handle (moneyg67) trigger the Photon to print the data
// to the device
int i = 0;
void twitterHandler(const char *event, const char *data)
{
i++;
Serial.print(i);
Serial.print(event);
Serial.print(", data: ");
if(data) {
Serial.println(data);
} else {
Serial.println("Null");
}
}
void setup()
{
Particle.subscribe("twitter", twitterHandler);
Serial.begin(9600);
}
Iteration 2: In the second iteration, we wrote a node.js applet. We decided to use Twitter's API to pull a user's followers and their current statuses every 30 minutes, and then we used a sentiment analysis API to rate each status as positive, neutral, or negative (link: http://text-processing.com/docs/sentiment.html). Then we determined which rating (positive, neutral, or negative) occurred the most and published an event with that information. The Photon then pulled that information, and if the statuses were mostly positive or neutral, it would turn on the LEDs in the bracelet; otherwise, it would turn off the LEDs in the bracelet.
// The initial code (which was then modified after line 35)
// came from:
// https://github.com/heroku/node-js-getting-started.git
var express = require('express');
var app = express();
var http = require('http');
var querystring = require('querystring');
var request = require('request');
var Particle = require('particle-api-js');
var particle = new Particle();
// Global Variables
var token;
var numPositive = 0;
var numNegative = 0;
var numNeutral = 0;
var total = 0;
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
// views is directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.get('/', function(request, response) {
response.render('pages/index');
});
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
var nconf = require('nconf');
var Twit = require('twit');
var _ = require('lodash');
// Make sure to have a separate file in the working
// directory called 'config.json' containing info
// about the Twitter consumer key, etc
nconf.file({ file: 'config.json' }).env();
var T = new Twit({
consumer_key: nconf.get('TWITTER_CONSUMER_KEY'),
consumer_secret: nconf.get('TWITTER_CONSUMER_SECRET'),
access_token: nconf.get('TWITTER_ACCESS_TOKEN'),
access_token_secret: nconf.get('TWITTER_ACCESS_TOKEN_SECRET')
});
// Every 30 minutes, pull statuses from the list of people
// a specific twitter handle follows, and then analyze
// sentiment of those statuses and calculate which type of
// status, positive, neutral, or negative, occurs the most
setInterval(function(){
var options = {
screen_name: <twitter handle>, // Can replace with any twitter handle
skip_status: false,
include_user_entities: false
};
T.get('friends/list', options, function(err, data) {
for (var i = 0; i < (data.users).length; i++) {
total = 0;
numPositive = 0;
numNegative = 0;
numNeutral = 0;
console.log(data.users[i].screen_name);
console.log(data.users[i].status.text);
request.post({url:'http://text-processing.com/api/sentiment/', form:{text:data.users[i].status.text}}, function(error, response, body) {
if (!error && response.statusCode == 200) {
total += 1;
console.log(body);
var json = JSON.parse(body);
console.log(json.label);
if((json.label).localeCompare('pos') == 0)
{
numPositive += 1;
}
if((json.label).localeCompare('neg') == 0)
{
numNegative += 1;
}
if((json.label).localeCompare('neutral') == 0)
{
numNeutral += 1;
}
console.log(total);
console.log(numPositive/total);
console.log(numNegative/total);
console.log(numNeutral/total);
}});
};
});
}, 1800000);
// Every 30 minutes publish an event to Particle cloud
setInterval(function(){
particle.login({username: <insert username and email here>, password: <insert password here> }).then(
function(data) {
token = data.body.access_token;
console.log('Logged in successfully\n');
var result;
if(numPositive > numNegative){
result = "pos";
} else {
if(numNegative > numPositive){
result = "neg";
} else {
result = "neut";
}
}
result = "neg";
var publishEventPr = particle.publishEvent({name: 'twitter', data:result, auth:token});
publishEventPr.then(
function(data) {
if(data.body.ok) {console.log('Event published successfull')}},
function(err) {
console.log('Failed to publish event: ' + err)
}
);
},
function (err) {
console.log('Could not log in.', err);
}
);
}, 1800000);
// This code pulls the analysis of Twitter climate and then
// if the climate is mostly positive or neutral, it turns the
// LEDs in the bracelet on. Otherwise, if the climate is mostly
// negative, it turns the LEDs in the bracelet off.
int i = 0;
int ledPin = D4;
void twitterHandler(const char *event, const char *data)
{
i++;
Serial.print(i);
Serial.print(event);
Serial.print(", data: ");
if(data) {
Serial.println(data);
if(strcmp(data, "pos")==0)
{
Serial.println("in Pos");
digitalWrite(ledPin, HIGH);
} else if (strcmp(data, "neg") == 0){
Serial.println("in Neg");
digitalWrite(ledPin, LOW);
} else {
Serial.println("in Neut");
digitalWrite(ledPin, HIGH);
}
} else {
Serial.println("Null");
}
}
void setup()
{
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Particle.subscribe("twitter", twitterHandler);
Serial.begin(9600);
}
We achieved our original goal of creating an ambient display that connects us with our families, friends, and celebrities on twitter. The bracelet will continuously show whether those people we follow are being negative or positive by text-processing their twitter messages.
When we interacted with our bracelet, it feels like a normal bracelet except we need to power it constantly. Since the led lights kept turning on and off, it was somewhat bothering. However, every time the bracelet told me that people collectively are being negative, it motivated me to see what was going on, especially with my friends and families, and to tweet something that is positive.
In terms of drawbacks, the bracelet is not small enough to be integrated into the background. We are thinking of expanding the LED display, such as simmering, flashing, turning on every half a hour, to make the bracelet a more friendly wearable display. We also thought about giving the bracelet different colored lights so it has more indication and is more visually satisfying.
Lastly, the wooden station built to fixate the bracelet was intended for people to take off this bracelet at home or at work. The station could be put on the desk, fridge, wall and so on. When it is fixated into the station, it serves as an aesthetic piece that reminds people about what is going on in the world regarding the people they care on twitter.
Monisha: I had never worked with an API before or written a node.js applet. So tackling both of those was a challenge and took up most of my time in this project. If I had more time, I would research more sentiment analysis APIs and I would write a better string-parsing program to handle Tweets with links, foreign languages, etc. In terms of designing an ambient device, the most interesting thing was picking a notification system for the bracelet. If a user associates the bracelet with Twitter, then would a notification from the bracelet compel them to use their phone? Because (and it would take a lot of research to confirm) in that case, the bracelet (with or without notifications) is itself more a distraction than not. Then a better solution would be to create a pop-up screen that gives the same information to users before they log onto Twitter. That way, users aren't compelled to use their phone more than they normally would.
Lizzy: I made the bracelet by wood that I had more experience with. I was trying to make a acrylic box to carry the photon and the batteries; however, due to lack-of-experience and time limit, I could not finish the box before the documentation deadline of this project. In order to make this bracelet prettier, I think I need to learn how to laser-cut and how to connect more led lights in a small area.
The design process and making process of the bracelet was really interesting I wanted to make this bracelet pretty, light, and interesting(with a lot of colors). However, in reality, there are so many things to tackle such as the connecting a lot of led lights or the material of the bracelet. When it came to making the station, ideally I would make a metal station that is minimal and attach a magnet to it so it can be fixated to different places. Therefore, I need to acquire more skills as a maker to actualize my original design.
Get a feel for the emotional climate of your Twitter feed without ever having to go on, so that you control your social media experience and it doesn't control you.