Indexing my movie collection

#FirstWorldProblems – having so many DVDs that you forget what you already own and end up buying multiple copies of the same movie.  While 126 movies isn’t a massive collection, it’s enough for me to sometimes forget what I have when I’m pillaging the $5 bins at Best Buy and Target.
To solve for this, I created a Google Sheets list of my collection so I could check what I have from my phone.  After typing all the titles into the list, I realized it’d be very easy for me to use the code I wrote for my DirecTV project to scrape additional details for the movies and create a nice, simple UI….so I did:
v1

What it does

  1. Using The Movie DB API, I pull several pieces of information about the film and store it locally: title, image, release date, rating, budget, revenue, runtime, synopsis, genres, cast, etc.
  2. Storing it locally reduces repetitive, slow API calls and allows me to cleanly add additional attributes like whether it’s DVD, Blu-Ray, Google Movies, Amazon Video, etc.
  3. Adding new titles is easy – I just type in the name and the rest of the details populate immediately.

 
There are two views: one shown above for desktop and another, more compact view, when a tablet or mobile device is detected:
v2
I’m not sure what’s next for this but it was a quick and fun project that connected my inner home automation and movie geeks.

Home Automation and NFC Tags

NFC has proven to be a pretty useless technology for cell phones (unless you’re one of the people who use you Google Wallet/Apple Pay).  Nevertheless, I decided to buy some tags and play with them because they’re so damn cheap (just over a dollar each, depending on the type).
20161002_121409
One useful application of NFC tags is setting “scenes” using my existing home automation setup.  By setting a tag where I usually place my phone at night, I can trigger several events all at once.  When I play my phone on my nightstand, the following events are triggered:

  1. If it’s a weekday, set my alarm for 7:00 AM.
  2. If an alarm was set, the phone will adjust its volume and say “Alarm set to 7 AM”.
  3. Using the same text to speech, the phone will say “Goodnight, Kevin.”
  4. After pausing for a few seconds, it’ll POST to a simple script I wrote  and turn all the lights in the apartment off before setting it’s volume to mute for the remainder of the night.

Play
It’s a simple way of automating my night time routine and is likely the most practical use of NFC tags with home automation (and it’s not super practical, at that).  If you want to recreate, here’s how I did it…

NFC Tag and App

I decided to go with the WhizTags brand because they boast more writeable space (888 bytes of writeable memory vs the standard 144 bytes). For reading and writing the tag, I went with the NFC Tools app. There’s no real reason for using this app – it just looked to be the most stable after a quick search.

Creating the Task

One of the benefits of the NFC Tools app is that you can export import json tasks.  Here’s the json for the task I noted

[ {
    "tasks.profile.name":"bedtime post",
    "tasks.profile.date":"20161002T101631",
    "tasks.profile.length":11,
    "tasks.profile.size":226,
    "tasks.profile.data":[ {
        "tasks.profile.fields": {
            "field1": "5"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "53", "itemTask": "5", "itemDescription": "5", "itemHash": "16686621-29d1-46bf-80f0-2d8905abcfdb"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "0"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "819", "itemTask": "1", "itemHash": "b63e98a5-7385-4ae5-a71e-a76949092649", "itemDescription": "1 second"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field4": "true", "field1": "true", "field3": "true", "field8": "1", "field2": "true", "field5": "true", "field7": "false", "field6": "false"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "92", "itemTask": "f9", "itemDescription": "MON,TUE,WED,THU,FRI\nPerform the tasks below", "itemHash": "eb2223cb-c5a2-4d59-a1a8-961e1bb13dde"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field3": "0", "field1": "7am", "field2": "7"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "41", "itemTask": "7:0;7am", "itemDescription": "7am - 07:00", "itemHash": "ba40261a-84e3-437d-b1e4-b44dbc6e0b8f"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "Alarm set for seven am."
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "85", "itemTask": "Alarm set for seven am.", "itemHash": "02fc2b51-36ba-497a-adea-1620b5799d8c", "itemDescription": "Alarm set for seven am."
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "1"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "819", "itemTask": "2", "itemDescription": "2 seconds", "itemHash": "60c8cd67-00bb-4850-a5c2-cbe5883f3de4"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "1"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "90", "itemTask": "1", "itemHash": "78382993-811f-4692-b110-61ff20406731", "itemDescription": "Close your conditional block"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "Goodnight, Kevin."
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "85", "itemTask": "Goodnight, Kevin.", "itemDescription": "Goodnight, Kevin.", "itemHash": "acab1f45-d379-4af4-99f9-0ccb63db4ae3"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "2"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "819", "itemTask": "3", "itemDescription": "3 seconds", "itemHash": "37320287-c034-4742-a959-705ac3399800"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "0"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "false", "requestType": "53", "itemTask": "0", "itemHash": "d7a566bd-107b-4dae-aff4-f2ce832f06e6", "itemDescription": "0"
        }
    }
    ,
    {
        "tasks.profile.fields": {
            "field1": "http:\/\/hellokevin.com\/nfc\/goodnight.php", "field2": "status=false;"
        }
        ,
        "tasks.profile.config": {
            "itemUpdate": "true", "requestType": "110", "itemTask": "http:\/\/hellokevin.com\/nfc\/goodnight.php|status=false;", "itemHash": "e1e00d48-16fa-4942-9d9e-298b806a65c2", "itemDescription": "Request: http:\/\/hellokevin.com\/nfc\/goodnight.php\nPOST parameters :\nName: status \/ Value: false", "itemTaskExtra": null
        }
    }
    ]
}
]

The Script

The script used to turn the lights off is a modified version of this script, which I posted earlier.  Instead of controlling a single device, I simply added in all the lights in my home and added in the POST var.

Expanding the Home Dashboard

In the previous post, I outlined the Home Dashboard touchscreen for controlling lights, temperature/humidity, displaying Amazon Echo information, displaying who’s home (via bluetooth sniffing), and displaying what was being watched on DirecTv.  As this dashboard is intended to be a sudo remote control for my home, I thought it made sense to be able to actually control the TV with it.
Screenshot 2016-09-01 at 10.18.31 PMScreenshot 2016-09-01 at 10.18.09 PM
After a bit of tweaking and some UI work, the end result is a super-quick (HTTP response is ~30 milliseconds which feels nearly as quick as the standard DirecTv remote) interaction between device and DirecTv receiver.
From my home dashboard/touchscreen controller, I can select the title that’s currently playing to launch the remove control (pictured above).  You’ll notice that the touchscreen controller can do everything the standard remote can do, including guide browsing, DVR browsing, etc.

Home Dashboard using a Raspberry Pi

After creating a desktop home automation dashboard and, later, a live stream “digital picture frame”, I got the idea to combine the two into an always-on control panel that condenses everything I care about into a single kiosk which can sit on my end table or nightstand.

What it does

It’s essentially a condensed UI of the desktop version linked above which uses the same databases and processes.

  • Current indoor temperature and humidity (via DHT11 sensor)
  • If my Amazon Echo is playing music, it’ll display the artist, song, and album
  • If I’m watching TV, it’ll show the title, channel, and image/movie poster
  • Display unique icons for each person in the house (by sniffing for their phone’s bluetooth signal)
  • It’ll show the status of my lights (on/off) and update if that status changes (using the Wink API)
  • Through touch screen, allow me to control my lights in near real-time.

Play

Materials Used

How it works

Much of this (temperature, humidty, DirecTv and Wink control) is covered in “The Foundation” post.  Specific to collecting information from the Amazon Echo, I use IfTTT and the Maker channel.  Each time my Echo plays a song, I POST to a script similar to the one below which stores the song in a MySQL database.  I can then query that, determine if the song is still playing, and publish it to the UI.

<?php
$conn = mysqli_connect(<credentials>);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$song=$_REQUEST['song'];
$artist=$_REQUEST['artist'];
$album=$_REQUEST['album'];
$timestamp=$_REQUEST['timestamp'];
$sql = "INSERT INTO echo_history (artist, song, album, timestamp)
VALUES ('$artist', '$song', '$album', '$timestamp')";
if (mysqli_query($conn, $sql)) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . mysqli_error($conn);
}
mysqli_close($conn);
?>

My Maker recipe looks something like this: IF then to URL

recordmusic.php?artist= {{ArtistName}}&song={{SongName}} &album={{AlbumName}} &timestamp={{PlayDateTime}}

Method POST.
That’s about it for the controller – quite simple and is probably the most practical project I’ve done thus far.

Using a Pi to measure TV habits

As noted here, I’m using the the DirecTV SHEF API and a Raspberry Pi to poll my DirecTV receivers every minute and store what they’re doing into a MySQL database. After ~6 months of storing that data, I thought it’d be interesting to analyze some of it.  After all, do I really watch enough HBO and Starz to warrant paying for them every month?

Channel Preferences

  • 25,900 minutes of TV watched (~2.25 hours per day…eek; still less than the national average!).
  • 2,612 minutes of that was recorded (10%).
  • NBC is our favorite channel (3,869 minutes watched, 15%).
  • E! is our second favorite channel (1,911 minutes watched, 7.37%). Gotta keep up with those Kardashians.
  • Premium movie channels (HBO, Starz, Encore, Cinemax, etc) were watched 6,870 minutes (26.52%) – apparently worth the money.
  • Premium movie channels were recorded only 571 minutes (lots of ad hoc movie watching, I guess).
  • NBC is our most recorded channel (479 minutes) followed by HGTV (391 minutes) and ABC (330).

Time Habits

  • Sunday is the most watched day (no surprise here) with 7,157 minutes watched (28%)
  • Saturday is the second with 5,385 (21%)
  • Wednesday is the least watch with 1,144 (4.4%)
  • April was our biggest TV month with 6,413 minutes watched (24.76%)
  • June was our lowest month with 1,197 (4.62%) — July is around 10%.  The excitement of summer faded fast, apparently.
  • 8PM is our biggest TV hour with 1,312 minutes (15.14%).  This is followed by 7pm (13%) and 6pm (10%).
  • 6AM is our lowest TV hour with 68 minutes watched (0.26%).  This is followed by 5am (0.49%) and 4am (0.90%).

This is pointless data but it’s always interesting to assess your own habits.  And if you’re wondering, it took roughly 60 minutes (0.23%) to query and publish this post :).