Playing with the Nest Rest API

I bought the Nest thermostat for fun. I purchased it couple months ago to go with the new furnace and air conditioner. I could have gone with a thermostat provided by the contractor, or any number of cheaper options, but I wanted something with which to play. Even though I don’t consider myself a “gadget person”, I wanted this gadget.  I wanted to play with it’s API and see what I could make it do.

With summer ending and school starting, there was a lot going on in the household.  Also, we went for about a month when neither air conditioning nor heating were required, so internal climate control was not often on my mind.  Now the heat is coming on for a few minutes in the morning and I’ve started playing with the Nest Rest API.

The Nest developer website has documentation that helped get me up and running.  As usual, the trickiest part in getting started is figuring out how to authenticate, but that actually went smoothly (I’m not sure whether I’m getting better at doing that sort of thing, or if the Nest process and/or instructions are better).  I was then able to read information about my Nest thermostat.  It was when I tried to write data that I ran into problems.

I had many failures in trying to perform a write.  At first I tried various incarnations of Java code to perform a REST PUT, but I had a variety of problems and errors.  I simplified things.  I tried a simpler use case.  I removed Java from the picture and just used curl.  Eventually I resorted to the instructions I found to change the target temperature on a thermostat:

curl
-X PUT
-H "Content-Type: application/json"
-H "Authorization: Bearer c.lPg4Z..."
-d "{"target_temperature_f": 72}"
'https://developer-api.nest.com/devices/thermostats/DEVICE_ID'

I plugged in my own authorization token and device ID, but still it wouldn’t work.  After a lot of kicking and swearing and reading various websites and forums, I came up with:

curl
-L 
-X PUT 
-H "Content-Type: application/json"
-H "Authorization: Bearer c.lPg4Z..." 
-d '72' 
https://developer-api.nest.com/devices/thermostats/DEVICE_ID/target_temperature_f

The key differences are:  1) The “-L” flag tells curl to follow the 307 redirect that is returned, 2) Passing just the desired value instead of a JSON snippet, and 3) Specifying the variable name as part of the URL.

When I plugged in my authorization token and device id, things worked–by the time I had taken the seven steps from my disheveled desk to the thermostat, the new value had taken affect and the Nest was turning on the heat.

Although there was some frustration along the way, I had fun playing with the Nest Rest API and am glad I was able to get some basic use cases to work.  Now that I know how to read and write data, I can make make something interesting.

Running a Java program every 15 minutes

I wrote a simple Java program that I wanted to run every 15 minutes.  I decided to wrap everything into a Docker image so that I would get the logging, restart capability, and portability goodness that one gets for free when running a Docker container.  It’s not a difficult thing to do, but it took me longer than it should since I made some incorrect assumptions.

Since I wanted the image to be small, I went with an “Alpine” version of the openjdk image.  My first incorrect assumption was that I could use cron and crontab like I do on Ubuntu or Red Hat systems–but Alpine doesn’t come with cron.  However, it’s actually easier than messing with crontab–I just had to put my script into the /etc/periodic/15min directory.

Once I had the script in place, I tried to run the container, but eventually discovered the the small Alpine image does not have the daemon enabled when the container starts up.  This was solved by running crond in the foreground.  Here’s a Dockerfile showing the important bits:

ROM openjdk:alpine
MAINTAINER Nathan Bak <dockerhub@yellowslicker.com>

# Create directory to store jars and copy jars there
RUN mkdir /jars
COPY jars/*.jar /jars/

# Copy bin directory of project to root directory
COPY bin/ /

# Copy runJavaApp script into correct location and modify permissions
COPY runJavaApp /etc/periodic/15min/
RUN chmod 755 /etc/periodic/15min/runJavaApp

# When the container starts, run crond in foreground and direct the output to stderr
CMD ["crond", "-f", "-d", "8"]

Here is the runJavaApp script:

#!/bin/sh
java -cp /:/jars/commons-codec-1.9.jar:/jars/commons-logging-1.2.jar:/jars/fluent-hc-4.5.2.jar:/jars/httpclient-4.5.2.jar:/jars/httpclient-cache-4.5.2.jar:/jars/httpclient-win-4.5.2.jar:/jars/httpcore-4.4.4.jar:/jars/httpmime-4.5.2.jar:/jars/jna-4.1.0.jar:/jars/jna-platform-4.1.0.jar com.yellowslicker.sample.Client

The “gotchas” I ran into with the script include:

  1. The script must begin with #!/bin/sh (out of habit I tried #!/bin/bash, but Alpine doesn’t come with bash)
  2. Each jar must be listed explicitly (I tried using /:/jars/*.jar for my path, but it didn’t work)

There are a lot of ways to schedule things, but this method was simple (once I figured it out) and I think it is robust.  In my case, it also fits well into the Docker microservice environment I’m running.

Sherlock Holmes: Predictable and Original

2016-10-09-18-12-22

Several years ago, my wife and I purchased a collection of Sherlock Holmes stories as a Christmas present for our niece and I mentioned that I had never read any Sherlock Holmes save an abbreviated version of Hound of the Baskervilles I encountered in fifth grade.  I believe my wife was appalled at this dearth in literary knowledge and as a remedy I soon received a nice version of the Sherlockian canon.  I like to consume literature in bulk–there was no intimidation at 2000-3000 pages, but rather a comfort of knowing there were many hours of reading material immediately available to me.  And so I began.

I really enjoy reading about the various adventures of Sherlock Holmes, but initially I was surprised at how well I could predict the outcome.  Not only did I out pace Watson, but sometimes even the great sleuth himself.  Initially I assumed I was just incredibly clever, but soon reality set in there was the realization that, though the details were different, the “twist” was something previously encountered.  I had read various mysteries including a binge with Agatha Christie while in college.  Before that I had ready Hardy Boys novels (also in mass quantities) and watched episodes of Scooby-Doo.  Sherlock Holmes was quite original when it was written, but it has since become the foundation upon which most modern Western mystery is built.

I think I enjoy the short stories more than the novels; that’s odd considering my general preference towards quantity.  The short stories come across as more tightly written and more focused on the mystery rather than a lot of back story.  Also, since I usually had a good idea where the story was headed, I think I missed out on a certain measure of suspense.

Even though most modern readers won’t be thoroughly astounded by the genius of Sherlock Holmes because of the predictability, it’s not due to lack of originally for it is the original.  Reading the text is a fun journey to the early days of the mystery genre.  If you haven’t yet experienced the world of Holmes and Watson, enjoy the originality and don’t fret the predictability.

The Parable of the Soccer Coach

A coach went to coach a soccer game and place his players on the field.

And as he coached, some players fell into pleasant conversation and failed to notice the game going on around.

And some players went running all over the field after the ball at a full sprint regardless of where the ball went.

And as the minutes passed they quickly tired and, because they had no stamina, whined for a sub.

And some failed to spread out and instead ended up in a clump of players resembling a rugby scrum; and the flailing feet and elbows caused bruised shins and sore ribs.

But others played their assigned positions applying practiced skills to the best of their individual abilities and together they had great plays: some scoring goals, some making assists, some playing a solid defense.