Last summer I found out about CubeSensors, which are small cubes packed full of sensors for monitoring your indoor environment. I loved the idea but they seemed a bit pricy and they were still taking preorders, having not shipped anything yet. After a couple weeks of thinking about it I went ahead and paid the deposit to reserve my spot in the second batch and lock in the price, which was fortunate because within a couple weeks the price had gone up (to cover adding adding more features I believe). Being a new company, there were naturally delays shipping the first batch, then they wanted to incorporate changes based on feedback from the first cubes in the wild, so I finally got my cubes this last June.

Not only did the box include my cubes and base station but it’s the perfect size for my cats to hide behind when playing:
Dash Stalking

The only trouble I had setting the cubes up was user-error: I tried to connect all the cubes at once and thought one of the connected ones was the last disconnected one. They glow red when you shake them and they don’t like your environment (so with low humidity and high temperatures the one that was connected would light up red when I shook it) and they flash red when you shake them and they’re trying to connect (the expected result when adding a new cube to the network). I didn’t recognize the difference so it took me a few days to think to have it tell me which cube was which by lighting them up from the webapp, at which point it became obvious what I was doing wrong.

Here’s loft-cube in action:
Loft Cube in action

While I appreciate the raw data from the cubes I’m not really a fan of how it’s presented:

First off, there’s no way to get raw data side-by-side. For example: the app doesn’t offer a plot of the temperatures of all rooms at the same time. You can click on the cube on the overview screen to see details for that room but the only way to see more than one at a time is by using multiple browsers.

Also, there’s no way to adjust the target values. I’m comfortable at a far wider range of temperatures (especially warmer) than the 73.4-78.8°F the app insists I should set my house to. That means that most of the time the overview page just tells me that it doesn’t approve of how I live, which often isn’t an indication that I should do anything about it.

Besides just the app I also have a gripes about the hardware itself: The charging circuit produces heat, so any time a cube is charging the temperature (and humidity) readings can’t be trusted. I’d hoped that leaving the cubes plugged in would result in it using the provided power to run and not needing to drain/charge the battery, but the actual result is that it drains the battery for a number of hours, then charges for a while, then drains the battery. That produces a plot with periodic temperature spikes and doesn’t really tell me about my indoor environment or provide useful data that I can mine.

None of those issues are dealbreakers so I still appreciate having the cubes and think they were worth what I paid for them, I just have to work within the limits of the cubes.

Fortunately, the app isn’t a limitation because there’s an alpha API available for use.

Of course an API doesn’t do me any good if I can’t access it, and I’d never used OAuth before. OAuth requires you to have an app key/secret pair (currently gotten by emailing the address on the API page), then do a handshake sequence that involves the user logging into the CubeSensors site to allow the app to use the account, then use the key the api provided to request data specific to the user. Searching online it was easy to find a Java library for OAuth, but it wasn’t so simple to get it to work for CubeSensors. I ended up playing with Scribe and a firefox plugin called Poster until I managed to get a signed query accepted, then I tweaked my Scribe settings until I got it working.

Once I had authentication working it was a fairly simple matter to wrap the JSON-based API in Java objects using Jackson, and at that point I went ahead and published my results on github for anyone else that wants to use Java to query CubeSensors data.

Someday (hopefully) soon I’ll be building a nicer interface for my cubes, which I’ll probably post about here as I get it working.

Mandelbrot Zoomer

Back in college I wrote a handful of applets that drew fractals. The last one I did was the mandelbrot set, but it didn’t have the performance I wanted and I didn’t work on it much.

A few days ago I got to thinking about it again, and figured I’d try optimizing it since I’ve been doing a lot of concurrent and parallel programming at work and I figured at worst I could just make it multi-threaded. There’s still room for improvement, but I got a basic interface down and a level based drawing pattern that does remarkably well with only two threads (one refreshing the image at ~60 fps and running the interface, the other doing the calculation):

Holding the left mouse button on a point in the applet zooms in, the right button zooms out, and the ‘r’ key resets the view.

Somewhat Productive Weekend

I got a few things done this weekend since my post on Friday, just not most of what I’d planned (and really need) to do.

First off, I wrote an interface and pair of streams to replace Externalizable and ObjectOutput/InputStream. I had a bug at work where I’d implemented Externalizable but not specified the serialVersionUID and the versionUID changed without my custom serialization changing so suddenly my old data logs couldn’t be read. Basically I hadn’t realized how much metadata (serialVersionUID, class name, and probably some other stuff) was written to the stream, and working on this at home was my reaction to how inefficient Externalizable is for what I’m using it for. Anyways, the library I wrote this weekend typically sends exactly 1 byte of stream header information, and only sends the class name when the class hasn’t been written to the stream recently. After the header it sends exactly what you specify. Once I’m convinced it’s tested enough I may release it somewhere, but not yet.

Unfortunately, I designed the library to prevent a problem I’ve already solved at work, and since I was more concerned with recovering the ~500 GB of data I’d already recorded than having extremely lightweight serialization I can’t apply this there. I don’t even have a project of my own that uses networking currently, which makes it hard to really test the library. I’ll probably use the lessons learned at some point, but the most obvious application of this is in another part that’s already finished, tested, and working.

What I’d planned to do this weekend (same thing I’ve intended to do for the last several weekends) was take my car in to the shop for an oil change and to swap the winter tires off, as well as have them look at one of the back wheels to try to figure out why it rumbles (I’m guessing bearings from talking to people at work). Instead I slept till noon, and that late on a Saturday I expect to have to wait a while, so I put it off again. The idea is to get there not too long after they open and have a book so I can just sit in the waiting room till they’re done.

I did at least manage to make it to an auto parts place to buy new windshield wipers since the rubber part had mostly fallen off mine. I also tried to twist one of the wiper arms back to where it should be (it’s twisted such that the blade doesn’t meet the windshield at a right angle), but that wasn’t happening with the little pair of pliers I have. Wish I hadn’t left so many of my tools at my parents house, but that will be partially resolved in a few weeks after I go home for vacation.

I also finished with (not “finished”) a couple books. The first I read all the way through. It wasn’t bad, but between a couple rather graphic scenes and the way the world building was done it wasn’t quite what I prefer reading. The other one I got over half way through and had to ask myself why I was still reading it (at which point I promptly stopped). It was very much not the type story I prefer, and the overly heavy usage of the main character’s magic in nearly every situation just got old. I need to make another trip to the library soon, possibly to just wander till something catches my eye.