Monday Nov 25, 2013

Internet of Things (IoT) Thanksgiving Special: Turkey Tweeter (Part 4)

Now, on to the next step which is to write the Java SE Embedded code to automatically send an Internet of Things (IoT) tweet from your Raspberry Pi attached to your cooking turkey to a Twitter account. For this part you'll need to create your own Twitter app for your IoT Turkey, which is easy to do. Just follow the steps: here

After you are done with the above steps to create your own Twitter app, make note of the following settings from your Twitter app:

 1. OAuth setting: Consumer Key
 2. OAuth setting: Consumer Secret
 3. Access token: Access token
 4. Access token: Access token secret

You will use your Twitter app values from above in your Java Embedded program. Just replace the above values into the following Java Embedded code:

    // Application Defined Settings
    static String consumerKey = "XXXXXXXXXXXXXXXXXXXXXX";
    static String consumerSecret = 
            "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    static String accessToken = 
            "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    static String accessTokenSecret = 
            "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; 
    
    static String requestURI = "https://api.twitter.com/1.1/statuses/update.json";

Next, here is the code to send the tweet:

    void tweetStatus(String statusStr) {

        boolean verboseFlag = true;
        String requestURIEnc = null;
        
        try {
            requestURIEnc = URLEncoder.encode(requestURI, "UTF-8");
        } catch (UnsupportedEncodingException uee) {
            uee.printStackTrace();
        }
        
        try {

            if (statusStr == null) {
              statusStr = "Tweet, tweet.  Hello world!";
            }

            // Construct encoded string, parameter encoded string, & data
            String statusEncStr = URLEncoder.encode(statusStr, "UTF-8");

            // Param encode status string twice: once for unsafe characters 
            //  String, once for escaping % for Signature base string
            String statusUnsafeEncStr = unsafeEncode(unsafeEncode(statusStr));

            String postData = "status="+statusEncStr;

            // First set the default cookie manager
            CookieHandler.setDefault(new CookieManager(null,
                    CookiePolicy.ACCEPT_ALL));

            // Send postData
            URL url = new URL("https://api.twitter.com/1.1/statuses/update.json");

            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");

            // Get current date time with Calendar()
            Calendar cal = Calendar.getInstance();
            String timeStr = String.
                    valueOf(cal.getTimeInMillis()).substring(0, 10);

            String basestring = "POST&" + requestURIEnc + 
                    "&oauth_consumer_key%3D" + consumerKey + 
                    "%26oauth_nonce%3D5bffa3b2711bbcdaa4f301" + timeStr + 
                    "%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D" 
                    + timeStr + "%26oauth_token%3D" + accessToken + 
                    "%26oauth_version%3D1.0" + "%26status%3D" + 
                    statusUnsafeEncStr;

            String secretsStr = consumerSecret+"&"+accessTokenSecret;
            SecretKeySpec keySpec = 
                    new SecretKeySpec(secretsStr.getBytes(),
                    "HmacSHA1");

            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(keySpec);
            byte[] result = mac.doFinal(basestring.getBytes());

            String signature = URLEncoder.encode(base64Encode(result), "UTF-8");

            String credentials = 
                    "oauth_consumer_key=\"" + consumerKey + "\"," +
                    "oauth_nonce=\"5bffa3b2711bbcdaa4f301" + timeStr + 
                    "\"," +
                    "oauth_signature=\"" + signature + "\"," +
                    "oauth_signature_method=\"HMAC-SHA1\"," +
                    "oauth_timestamp=\"" + timeStr + "\"," +
                    "oauth_token=\"" +
                    accessToken + "\"," +
                    "oauth_version=\"1.0\"";

            conn.addRequestProperty("Authorization", "OAuth " + credentials);

            String lenStr = String.valueOf(postData.length());
            conn.setRequestProperty("Content-Length", lenStr);
            conn.setRequestProperty("Content-Type", 
                    "application/x-www-form-urlencoded");

            // Do as if you're using Firefox 3.6.3
            conn.setRequestProperty("User-Agent", 
                    "Mozilla/5.0 (Windows; U; Windows NT 5.1; "+
                    "en-US; rv:1.9.2.3) Gecko/20100401"); 

            conn.connect();
            OutputStream output = conn.getOutputStream();

            output.write(postData.getBytes("UTF-8"));

            // Get the response
            InputStream response = conn.getInputStream();
            BufferedReader rd =
                    new BufferedReader(new InputStreamReader(response));
            String line;
            while ((line = rd.readLine()) != null) {
                if (verboseFlag) {
                    System.out.println(line);
                }
            }
            rd.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

And, here's some code for the supporting utility methods:

   public static String unsafeEncode(String input) {
        StringBuilder resultStr = new StringBuilder();
        for (char ch : input.toCharArray()) {
            if (isUnsafe(ch)) {
                resultStr.append('%');
                resultStr.append(toHex(ch / 16));
                resultStr.append(toHex(ch % 16));
            } else {
                resultStr.append(ch);
            }
        }
        return resultStr.toString();
    }

    private static char toHex(int ch) {
        return (char) (ch < 10 ? '0' + ch : 'A' + ch - 10);
    }

    private static boolean isUnsafe(char ch) {
        if (ch > 128 || ch < 0) {
            return true;
        }
        return "$&+,/:;=?@ \"<>#%{}|\\^~[]`'!_*".indexOf(ch) >= 0;
    }
    
    
    private final static char[] BASE64CHARS = 
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
            .toCharArray();

    private static int[]  intChars   = new int[128];
    
     /**
     * Translates the specified byte array into Base64 string.
     *
     * @param inputBuffer byte array (not null)
     * @return the translated Base64 string (not null)
     */
    public static String base64Encode(byte[] inputBuffer){
        
        // Check if intChars array needs to be init'd
        if (intChars.length == 0) {
            for(int index=0; index < BASE64CHARS.length; index++){
                intChars[BASE64CHARS[index]]= index;
            }
        }
        
        int bufferSize = inputBuffer.length;
        char[] charArray = new char[((bufferSize + 2) / 3) * 4];
        int charIndex = 0;
        int inputIndex = 0;
        while(inputIndex < bufferSize){
            byte byte0 = inputBuffer[inputIndex++];
            byte byte1 = (inputIndex < bufferSize) ? 
                    inputBuffer[inputIndex++] : 0;
            byte byte2 = (inputIndex < bufferSize) ? 
                    inputBuffer[inputIndex++] : 0;

            int mask = 0x3F;
            charArray[charIndex++] = BASE64CHARS[(byte0 >> 2) & mask];
            charArray[charIndex++] = BASE64CHARS[((byte0 << 4) | 
                    ((byte1 & 0xFF) >> 4)) & mask];
            charArray[charIndex++] = BASE64CHARS[((byte1 << 2) | 
                    ((byte2 & 0xFF) >> 6)) & mask];
            charArray[charIndex++] = BASE64CHARS[byte2 & mask];
        }
        
        switch(bufferSize % 3){
            case 1: charArray[--charIndex]  = '=';
            case 2: charArray[--charIndex]  = '=';
        }
        
        return new String(charArray);
    }

That's all you need to send tweets to your Twitter app using Java SE Embedded. Easy-peazy! Next, we'll put it all together, so that your Raspberry Pi takes the Vernier Go!Temp temperature readings from your roasting bird, and sends out tweet updates, plus a tweet to tell the Twitterverse when your turkey is done. That's something delicious! :-)

See the full series on the steps to this cool demo:
Internet of Things (IoT) Thanksgiving Special: Turkey Tweeter (Part 1)
Internet of Things (IoT) Thanksgiving Special: Turkey Tweeter (Part 2)
Internet of Things (IoT) Thanksgiving Special: Turkey Tweeter (Part 3)
Internet of Things (IoT) Thanksgiving Special: Turkey Tweeter (Part 4)
Internet of Things (IoT) Thanksgiving Special: Turkey Tweeter (Part 5)

About

Hinkmond Wong's blog on making Machine to Machine (M2M) and the Incredible Internet of Things (IoT) smarter with Java Embedded Technologies

Search

Archives
« November 2013 »
SunMonTueWedThuFriSat
     
1
2
3
4
5
7
8
9
10
11
12
13
14
15
16
17
19
20
22
23
24
26
28
29
30
       
Today