Tuesday, August 14, 2012

Twittering shark laser intrusion detection system, in honor of Shark Week

Thanks again @bbenchoff for the post about the DIY perpetually-powered wireless outpost on @hackaday! A lot of good discussion on natural/perpetual power sources :)

I got an email from Dan earlier this week about making a fish tracking aquarium. Being that we’re right in the middle of Shark Week, I respectfully obliged…

image

This may or may not have implications for real-life shark tracking, but I’ll take an excuse to have my shark tweet me when he (or she, I’m no marine biologist) breaches the perimeter over to the sunny side of the tank.

Of course, I’m doing this with my toy shark-on-a-stick and only a laser level and a light sensor, but it’s possible to make this much more accurate and granular just by adding more strategically placed sensors/light sources into the mix.

Disclaimer: This project was designed purely with fun and proof-of-concept in mind, and in no way is designed to replace the $100 million airport intrusion detection system at JFK. The jet ski was too big and too fast for my 10 gallon fishtank…

I couldn’t find a picture of Tom Cruise doing this 
because the lasers in Mission Impossible weren’t visible…

Concept

Most laser security systems rely on infrared sensors that detect changes in heat, based on a beam of light hitting the sensor. If that beam is interrupted, it’s interpreted as a change in the thermal profile on the sensor, and an alarm goes off. Usually the beams are invisible too, so that picture above is mildly inaccurate. Here’s the basic idea of how the project went:

image

image

I took a little field trip to Petco and Toys R Us to get a fish tank simulation setup. For the laser pointer, a laser light level I had in the shop worked really nicely, but any standard laser pointer will do.

Tank Setup

Building the light sensor/laser setup

I ended up using a real, visible laser for two reasons: first, it’s easy to line up against my light sensor, and second, because I’m shooting the beam through water and 2 glass panels (on either side of my tank), which might otherwise diffuse the beam’s heat profile. Dry museums have it so easy…

Tank Setup Closeup

On the other side of the tank, I have an Arduino with a light sensor elegantly taped to the glass.

Light Sensor Closeup

I cut a hole in the wallpaper – on the left side, the laser is hitting the sensor directly. On the right, I moved the laser away, so you can see it the light sensor more clearly.

image  image

Chris and I just have some basic code running on the Arduino to get analog readings out from the AMBI light sensor. (The dead simple up-and-running post from way back when, as well as the wiki here). I uploaded the code to the Arduino, checked the output from serial, it seems like I’m good to go!

Connecting the sensor setup to a web-connected Android/BeagleBoard system

I connected the Arduino + Light Sensor to the BeagleBoard/BeagleTouch/Android stack sitting in my freshly dug up Mystery Box.

Mystery Box Setup

For a recap on how to connect the Arduino and sensor outputs over serial to output to the BeagleBoard over Android, here’s a link to the Antipasto wiki post. (This can still be tricky even with the Android Ambrosia SD card, so email me justin@liquidware.com, or comment below if you get stuck.)
Once I was able to get readings from the light sensor/Arduino in Android, I wrote a quick little Android APK to do two things:
1) Flash a Red Alert on BeagleTouch screen
2) Trigger a tweet to be sent
Why Twitter? It’s excellent for posting event alerts in an easy to subscribe fashion, and it’s also really easy to have these alerts forwarded to SMS, email, and Facebook. And they have a pretty excellent API, which I’ll get to in the next section.

If nothing is obstructing the the light sensor, the laser drives a light value of about 700-800.

IMG_0255

BeagleTouch Android App Off

As soon as the laser is obstructed by Bruce the shark himself, that light value drops. Once it’s below 400, the Android program issues a Red Alert warning that the sensor has been tripped, and sends a tweet.

IMG_0256

BeagleTouch Android App On

This serial app, which Chris originally wrote for the Liquidware Amber, simply takes the values being sent from the Arduino/light sensor, then funnels it through the following logic:

A ratchet digital filter that detects when the sensor has been obstructed (and resets)
if ( (sensorVal < NIGHT_TRIP_POINT) && (ratchetCounter > ratchetMin))
    ratchetCounter--;

if (ratchetCounter == ratchetMin)
    time = NIGHT;

if ((sensorVal > DAY_TRIP_POINT) && (ratchetCounter < ratchetMax))
    ratchetCounter++;

if (ratchetCounter == ratchetMax)
    time = DAY;
Then here are a few of Bruce’s tweet alerts, stored in a String array:
String [] mTweets = {
        "Yum.",
        "Fish are friends, not food!",
        "I am a nice shark, not a mindless eating machine.",
        "Anchor! Chum!",
        "So, what's a couple of bites like you doing out so late?"
        };
Finally, bringing these two pieces together…

if ((time == NIGHT) && (prevTime == DAY)) {
    mAlertDlg.setVisibility(View.V
ISIBLE);

    mTweetIndex++;
    if (mTweetIndex >= mTweets.length)
        mTweetIndex = 0;

    Tweet tweet = new Tweet(mContext,
             mTweets[mTweetIndex]);
}
I posted the full source code to the Android serial reading application on Github, if you’re interested. Big thanks to the folks who developed the twitter4j Android library!

Twitter Alerts from Bruce the Shark

Two of the world’s most famous sharks have been named Bruce (see hints below):



So I figured @BruceSharkAlert would be a fitting Twitter handle. In order to make Tweets actually happen, the code above needs to be linked to an authenticated Twitter developer account. Logging in as BruceSharkAlert on dev.twitter.com, this is what I’ve got:

I created this application…

image

Filled out the forms and got authentication keys…

image

image

(which I neatly chopped out :) They’re required in my Tweet.java file, which requires an authenticated account to automate tweet posts:
package com.liquidware.
networkedserial.app;

import android.os.AsyncTask;
import android.util.Log;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;

public class Tweet {
    private static final String TAG = "Tweet";

    /** Name to store the users access token */
    private static final String PREF_ACCESS_TOKEN ="[***your key here***]";
    /** Name to store the users access token secret */
    private static final String PREF_ACCESS_TOKEN_SECRET =" [***your key here***] ";
    /** Consumer Key generated when you registered your app athttps://dev.twitter.com/apps/ */
    private static final String CONSUMER_KEY =" [***your key here***] ";
    /** Consumer Secret generated when you registered your app athttps://dev.twitter.com/apps/  */
    private static final String CONSUMER_SECRET = " [***your key here***] "//XXX Encode in your app
    /** Twitter4j object */
    private final Twitter mTwitter;

    /** Called when the activity is first created. */
    public Tweet(String message) {
            Log.i(TAG"Loading TweetToTwitterActivity");

            // Load the twitter4j helper
            mTwitter = new TwitterFactory().getInstance();
            Log.i(TAG"Got Twitter4j");

            // Tell twitter4j that we want to use it with our app
            mTwitter.setOAuthConsumer(CONSUMER_KEY,CONSUMER_SECRET);
            Log.i(TAG"Inflated Twitter4j");

            //tweet
            new postMessage().execute(message);
    }

    /**
     * Login and tweet
     */
    public class postMessage extends AsyncTask {
        @Override
        protected Void doInBackground(String... message) {
            loginAuthorisedUser();
            tweetMessage(message[0]);
            return null;
        }
    }

    /**
     * The user had previously given our app permission to use Twitter
     * Therefore we retrieve these credentials and fill out the Twitter4j helper
     */
    private void loginAuthorisedUser() {
            String token = PREF_ACCESS_TOKEN;
            String secret = PREF_ACCESS_TOKEN_SECRET;

            // Create the twitter access token from the credentials we got previously
            AccessToken at = new AccessToken(token, secret);

            mTwitter.setOAuthAccessToken(at);

            Log.d(TAG"Welcome back user.");
    }

    /**
     * Send a tweet on your timeline, with a //Toast msg for success or failure
     */
    private void tweetMessage(String message) {
            try {
                    mTwitter.updateStatus(message);
                    Log.d(TAG"Tweet successful!");
            } catch (TwitterException e) {
                e.printStackTrace();
            }
    }
}

Now Bruce is tweeting one of the above pre-programmed lines (borrowed from Finding Nemo)

sshot-149

Phone Perimeter Breach Alerts

From there, I just followed @BruceSharkAlert, and since I have Twitter via SMS already set up, all I had to do was text 40404 (my Twitter “short code”) the command ON BruceSharkAlert. Now Bruce’s Tweets show up on my phone every time he breaks the laser line:

image

Mike gives us a little video walkthrough here:


When my phone goes off, I like to tell people that my shark tweeted me. Anyway, that’s my tribute to Shark Week, but if I had more time, laser pointers, and light sensors, I’d probably set up a crazy grid defense system. Till next time…

IMG_0253

What else could I use this for? Let me know in the comments, over email at justin@liquidware.com or tweet me @liquidware

5 comments:

Justin said...

Bonus points if you can guess what the bracketed numbers are for at the end of each Tweet :)

Scott Janousek said...

I'm going to guess they are timestamps ... or possibly IDs.

Justin said...

Close! The Twitter API blocks you from sending too many identical tweets in a short time span because it thinks you've sent them by accident.

The unique ID allows us to keep sending alerts and avoid having them blocked.

Scott Janousek said...

By accident ... or perhaps on purpose, like a spambot. :-]

indiafootball said...

Do you have wrist pulse rate sensors?