Wednesday, February 19, 2014

A lamp that shimmers when your sweetheart mentions you in her tweet (Arduino Yun + Temboo)

I have talked out my Floor Lamp (Ikea Orgel Vreten Floor Lamp) and how I got a Jugaad Plug-in Dimmer made for it. I had an Arduino Yún lying around and had just read up on Temboo. That's when I realized I could use the Arduino to control the lamp from the internet very easily. I noticed that Temboo could fetch tweets and so I got an idea - I could program the Arduino to dim in and dim out the lamp whenever @ZeniaIrani mentioned me in her tweets. I call the project "The Zenomaniac's Lamp"

Here is how I got it done:
  1. Configured the Arduino Yún to connect to to my WiFi. Installed the latest version of Arduino IDE on my PC.
  2. Bought a 5V cell phone charger
  3. Brought the digital from Sunrom: http://www.sunrom.com/249
  4. Assembled the circuit and installed everything in a plastic lunch box. I used white three cored cable used for electric irons for the AC input and AC output - they are long lasting and look nice. Installed 2 pin socket and plugs on the ends of the wire for easily attaching/detaching of the circuit to the lamp.
  5. Read up on the instructions and code for fetching tweets here: https://www.temboo.com/arduino/read-a-tweet
  6. Got a Temboo account. The free account allows you to add only one application. I renamed my default application (My Account > Applications) to "Zenomania" and noted down the application key. The free plan will allow you only 1000 calls per month - meaning you can check your twitter feed only that many times in a given month window before the thing stops working - this is sad!
  7. Got a Twitter Dev account - visit this link, login with your usual twitter account and create an application. I named mine "Zenomania". The Temboo application running on Arduino Yún requires four things - Access token, Access token secret, API key, API Secret. The API Key and API secret are shown on the API keys tab under the Application Management page. For the Access token and Access token secret, I had to click on "Test OAuth" Button - twitter then asked me to sign in once again with my twitter credentials and then displayed the Access token and secret.
  8. I added the secrets and API keys to the Temboo read-a-tweet example and downloaded the code to Arduino over the network. The Temboo keys go into TembooAccount.h where as the Twitter keys go into the .ino file. Once I was able to get the example to working, I moved on to the next step.
  9. I modified the Temboo read-a-tweet code so that instead of fetching tweets from my timeline, it instead fetched tweets that mentioned me. I added a function to shimmer the lamp - cycle through the 16 levels (to and fro) of dimming supported by the sunrom's digital dimmer. From the code I would call the Temboo API to fetch the latest tweet that mentions me every 65 seconds (Twitter has throttling active on all apps - you can fetch data only 15 times in a 15 minutes window before you are blocked until the end of that window). I would then check if the tweet is new and if its by ZeniaIrani. If yes, I enable the lamp to shimmer for the next 65 seconds until I check for tweets again.
  10. So once ZeniaIrani mentions me in a tweets, it may take upto 65 seconds before the lamp starts blinking. As mentioned earlier, because of limitations imposed by twitter, we can't check the tweets more often otherwise we will start getting HTTP error codes. Similarly, once you run out of 1000 API calls per month, the lamp will stop working till the end of the 30 days period. Temboo might not be that great after all.
The Connection Diagram

16 Step dimmer modules from Sunrom.
There are also 256 Step ones available that can be
controlled using a single UART pin.

A lunch box to put everything in.
D'Cold for curing the stuffy nose syndrome.

The Arduino, dimmer and power supply for Arduino all connected.
White colored power supply was actually a phone charger.

Everything mounted neatly inside the lunchbox.
I had to break open the phone charger shell to decrease its size,
so that I could fit everything inside the box.
Used hot glue gun to stick everything inside.
For Arduino, I used screws and mounted it on the inside of the lid.

The Zenomaniac's lamp - All installed, online and working

The Shimmering Zenomaniac's Lamp

Zenomania.ino
(Assign your Twitter keys and key secrets to the four string constants declared in the beginning of the code. Modify the author name in line 123 to your own sweetheart's name)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
  ReadATweet
 
 Demonstrates retrieving the most recent Tweet from a user's home timeline 
 using the Temboo Arduino Yun SDK.
 
 This example code is in the public domain.
 */

#include <Bridge.h>
#include <Temboo.h>
#include "TembooAccount.h" // contains Temboo account information

/*** SUBSTITUTE YOUR VALUES BELOW: ***/

// Note that for additional security and reusability, you could
// use #define statements to specify these values in a .h file.
const String TWITTER_ACCESS_TOKEN = "5ghgfhgfhgfhgfhgfhgfhgfhgfhgfhgfhghfgJ";
const String TWITTER_ACCESS_TOKEN_SECRET = "9xSrXMhIhgjdfkjghdfgjdfkljgXrgumB24";
const String TWITTER_CONSUMER_KEY = "ECfgkjhdfkjgjdfhgkjdhfkrQ";
const String TWITTER_CONSUMER_SECRET = "Tt9lgfjdfklgjdfkljgfkGjU";

String last_author;
String last_tweet;

unsigned char dim_val = 0;
unsigned char dim_dir = 0;
unsigned char dim_state = 1;
unsigned int loop_ctr = 0;

void setup() {
  pinMode(2, OUTPUT);   
  pinMode(3, OUTPUT); 
  pinMode(4, OUTPUT); 
  pinMode(5, OUTPUT);

  Bridge.begin();
}
void loop()
{

  TembooChoreo HomeTimelineChoreo;
  if(loop_ctr == 650) { // wait 65 seconds between HomeTimeline calls
    loop_ctr = 0;
    // invoke the Temboo client.
    // NOTE that the client must be reinvoked, and repopulated with
    // appropriate arguments, each time its run() method is called.
    HomeTimelineChoreo.begin();

    // set Temboo account credentials
    HomeTimelineChoreo.setAccountName(TEMBOO_ACCOUNT);
    HomeTimelineChoreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
    HomeTimelineChoreo.setAppKey(TEMBOO_APP_KEY);

    // tell the Temboo client which Choreo to run (Twitter > Timelines > HomeTimeline)
    HomeTimelineChoreo.setChoreo("/Library/Twitter/Timelines/Mentions");

    // set the required choreo inputs
    // see https://www.temboo.com/library/Library/Twitter/Timelines/HomeTimeline/
    // for complete details about the inputs for this Choreo

      HomeTimelineChoreo.addInput("Count", "1"); // the max number of Tweets to return from each request
    HomeTimelineChoreo.addInput("AccessToken", TWITTER_ACCESS_TOKEN);
    HomeTimelineChoreo.addInput("AccessTokenSecret", TWITTER_ACCESS_TOKEN_SECRET);
    HomeTimelineChoreo.addInput("ConsumerKey", TWITTER_CONSUMER_KEY);    
    HomeTimelineChoreo.addInput("ConsumerSecret", TWITTER_CONSUMER_SECRET);

    // next, we'll define two output filters that let us specify the 
    // elements of the response from Twitter that we want to receive.
    // see the examples at http://www.temboo.com/arduino
    // for more on using output filters

    // we want the text of the tweet
    HomeTimelineChoreo.addOutputFilter("tweet", "/[1]/text", "Response");

    // and the name of the author
    HomeTimelineChoreo.addOutputFilter("author", "/[1]/user/screen_name", "Response");


    // tell the Process to run and wait for the results. The 
    // return code will tell us whether the Temboo client 
    // was able to send our request to the Temboo servers
    unsigned int returnCode = HomeTimelineChoreo.run();

    // a response code of 0 means success; print the API response
    if(returnCode == 0) {

      String author; // a String to hold the tweet author's name
      String tweet; // a String to hold the text of the tweet


        // choreo outputs are returned as key/value pairs, delimited with 
      // newlines and record/field terminator characters, for example:
      // Name1\n\x1F
      // Value1\n\x1E
      // Name2\n\x1F
      // Value2\n\x1E      

      // see the examples at http://www.temboo.com/arduino for more details
      // we can read this format into separate variables, as follows:
      while(HomeTimelineChoreo.available()) {
        // read the name of the output item
        String name = HomeTimelineChoreo.readStringUntil('\x1F');
        name.trim();

        // read the value of the output item
        String data = HomeTimelineChoreo.readStringUntil('\x1E');
        data.trim();

        // assign the value to the appropriate String
        if (name == "tweet") {
          tweet = data;
        } 
        else if (name == "author") {
          author = data;
        }
      }

      if((last_author == author) && (last_tweet == tweet) ) {
        //Nothing new
        dim_state = 0; //Turn off the lamp now
      } 
      else if(author == "ZeniaIrani") { //New Tweet from Zenia
        last_tweet=tweet;
        last_author=author;
        dim_state = 1;
      } 
      else { //New Tweet but not from Zenia
        last_tweet=tweet;
        last_author=author;
        dim_state = 0;
      }
    } 
    else {
      // there was an error
      dim_state = 0;
    }

    HomeTimelineChoreo.close();
  }

  if(dim_state == 1) { //Yes we must blink the lamp

    if(dim_dir == 0) {
      dim_val= dim_val+1;
    } 
    else {
      dim_val = dim_val-1;    
    }


    if(dim_val == 16){
      dim_dir = 1;
      dim_val = 15;
    } 
    else if(dim_val == 0){
      dim_dir = 0;
      dim_val = 1;
    }


    if((dim_val&0x01) == 0x01) {
      digitalWrite(2, HIGH);
    } 
    else {
      digitalWrite(2, LOW); 
    }

    if((dim_val&0x02) == 0x02) {
      digitalWrite(3, HIGH);
    } 
    else {
      digitalWrite(3, LOW); 
    }

    if((dim_val&0x04) == 0x04) {
      digitalWrite(4, HIGH);
    } 
    else {
      digitalWrite(4, LOW); 
    }

    if((dim_val&0x08) == 0x08) {
      digitalWrite(5, HIGH);
    } 
    else {
      digitalWrite(5, LOW); 
    }
  } 
  else if(dim_state == 0) { //Turn off the lamp
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
  }
  delay(100); 
  loop_ctr = loop_ctr+1;
}


TembooAccount.h
(Modify the 3 defines to match your own temboo login name, application name and application key. Place this file in the same folder as .ino file)

1
2
3
#define TEMBOO_ACCOUNT "lithiumhead"  // your Temboo account name 
#define TEMBOO_APP_KEY_NAME "Zenomania"  // your Temboo app key name
#define TEMBOO_APP_KEY  "fgdfsgdfgdfgdfgdffgdfgc"  // your Temboo app key


0 comments:

Post a Comment