Products Security Virtualization

Unifi Video on CentOS Via Docker

Published by:

I recently got a UniFi Video Camera Dome to evaluate. It can be used standalone, but to get the most out of the camera it’s a good idea to run the UniFi Video server. This software provides management for the cameras and recordings. Unfortunately, my home NAS is EL based (CentOS 6), and they only provide Debian and Ubuntu .deb packages. I found some instructions online involving alien to convert .deb to .rpm, and others involving extracting the .deb, installing the java files, rewriting the init script, etc. Instead, I decided to use Docker to create an image that had the necessary Ubuntu dependencies. This is simpler than building a VM, and provides direct access for the Docker container to my NAS filesystem.


  • Any OS with Docker daemon. Setting up your system for Docker is outside of the scope of this post, but there are plenty of easy to find instructions for a wide array of operating systems. Oh, one other thing. It needs to support SO_REUSEADDR, due to a dependency that the UniFi software has. For linux this means kernel 3.9+, which you’ll probably already have if you’re running Docker. For CentOS 6, see If you need a kernel, El Repo is always a good source.
  • A filesystem capable of holding at least a few tens of gigs for videos. For my example I use a fictitious path “/local/video/data”.
  • The URL to the UniFi Video .deb package for Ubuntu 14.04. This can be found on the support site.

First, we pull the prerequisite Ubuntu image, download the .deb to the video path so we’ll have it in the container, and launch the Ubuntu container. When we launch the container we’re going to do so in interactive mode, linking the host’s network to the container, and mapping the host’s selected video filesystem to the container’s unifi-video path:

docker pull ubuntu:14.04

wget -O /local/video/data/unifi-video.deb

docker run -t -i --net=host -v /local/video/data:/var/lib/unifi-video/videos ubuntu:14.04


At this point we should be in a prompt within the container. We’re simply going to install the .deb and its dependencies:


apt-get update

dpkg -i /var/lib/unifi-video/videos/unifi-video.deb #errors are ok

apt-get install -f #(to fix/install dependencies)


Now we should be out of the container. We’re going to commit our changes, making a new container image, and then run an instance of that container, starting the unifi software and then tailing /dev/null to keep the container running.


docker ps -a # find container id

docker commit <container id> unifi-video:1

docker run -d --privileged=true --net=host -v /local/video/data:/var/lib/unifi-video/videos unifi-video:1 /bin/bash -c "/etc/init.d/unifi-video start; tail -f /dev/null"


That’s it. At this point you should be able to go to http://<server ip>:7080 or 7443 and see the UniFi software.

While this is fairly easy and straightforward, it’s also a fairly naive way to deploy software in a container.  Normally you’d want to just have the necessary Java components and launch the java process itself, rather than using a whole pseudo OS, but it gets the job done quickly.


Don’t Throw Out Those QC2.0 Chargers Just Yet!

Published by:

Nexus 5X and 6P are out, and there’s a fair amount of noise about lack of QC2.0 support, despite having Qualcomm chipsets. When I got my Nexus 5X, one of the first things I did was try to charge it with my QC2.0 charger. Lo and behold, the marshmallow lock screen declared “charging rapidly”. I then did an unscientific test, letting it charge from about 50% to 55% with the QC2.0 charger, then switching to the stock charger, and looking at the charging graph. There was no discernible change in the slope of the charging curve on the battery graph in settings. Great!

However, not all was well. The next day I plugged in at work, with the same model of charger but a different, longer cable of another brand. No “charging rapidly”. I assume there’s a degree of variance in the cables (both marketed as USB 3.1 compliant), but I need to try the original cable with the other charger to be sure.

Later, I began looking around online and found many reports that these phones are not QC2.0 compatible, and to expect slow charging from the adapters. So I plugged in my original charger/cable, and took some pictures with a kill-a-watt. Still not exactly scientific, but you can clearly see that I’m getting pretty good charging out of it (~13W), in fact slightly better than I was getting from stock (~11W). I let it charge on each one for about 5 minutes, taking a snapshot of what seemed like the rough average, and swapped back and forth between the two twice, with the same results.

The charger is an Aukey QC2.0 and the cable is a ‘cable matters’ 3ft type A to type C cable, both acquired from Amazon. These pictures are bad, I didn’t want to use the Nexus 5X to take the photos so I resorted to a Nexus 7 that was lying around. The kill-a-watt is set to measure watts.






QC2.0 on Nexus 5X


Arduino BeagleBone Neutrino

Neutrino Lives!

Published by:

I’ve had a lot going on over the last few months, and among the bustle Neutrino has gone through several iterations. The baseboard is currently at version 3.2, and the sensor at 4.1.2. Some of the key changes include building the radio onboard both devices, pcb antenna on the sensor, changing to a better battery clip, adding pads to support the BME280 (when it becomes available, it can replace both the SI7021 and BMP180. It can save money if it costs less, and possibly power with one less device). The base now has a microcontroller onboard, which handles the relays and LEDs. This allows it to be functional standalone as a relay board, though the radio is not integrated into the microcontroller portion. The base still interfaces with either beaglebone black or raspberry pi, and the microcontroller is reachable via serial and programmable via avrdude gpio programming. The microcontroller is powered off of 5v, and as such level shifters have been added to interface with the beaglebone. I initially was able to run it off of 3.3v, but the microcontroller is essentially overclocked in this mode, and I wanted it to be reliable.

In the past two months I’ve changed jobs and moved to another state.  This home has two floors with a two zone heating system.  It’s winter, and we found that the kids’ rooms were very cold. Neutrino to the rescue!  I installed a sensor in all three rooms, and the following immediately became apparent:  1) The master was usually ~3 degrees warmer than the other bedrooms. 2)When the downstairs and upstairs were both calling for heat, the upstairs rooms heated evenly due to the CFM being spread out among the whole house. In this mode the upstairs rooms eventually equalized 3) When only the upstairs called for heat, the master got heated much more quickly than the other rooms. This was a problem because the master has the upstairs thermostat, and we want to turn the heat down in downstairs zone at night. In doing that, the other rooms would slowly drift to being ~5 degrees colder throughout the night.

On the first night it was installed as a controller (instead of just passively collecting data), we drove the upstairs heat off of the average temperature of all three rooms. This was a marked improvement. It maintained the ~3 degree difference between rooms, but put a floor on how cold it got in the kids’ rooms. It also meant a little extra heat for the master, but no big deal, we essentially split the difference between the rooms. After the data from that night was collected, we closed the vents in the master half way, and that seems to have helped significantly.  The heating is now a bit more even, regardless of which zones call for heat.

I’ve learned a few things in this new home. The first is that zoned systems seem to need Neutrino MORE than non-zoned. I had initially built the thing as sort of a poor man’s alternative to zoning, but a multi-zoned system has interesting dynamics going on, and an increased complexity in how the home heat is distributed when running in various modes. As such, one needs a way to see that information in order to tune the system, or bad things can happen. It could probably be remedied with trial and error, but having the data helps a lot. For example, my wife noticed that having the downstairs heat on made the bedrooms more evenly warm, so suggested we try leaving the downstairs heat on. I, on the other hand, surmised that the heat from the first floor was rising into the master (with our door being open and the thermostat nearby) and artificially raising the master’s temperature, thus we should turn the heat off downstairs at night. It wasn’t until we had the data that we realized that the downstairs vents being on reduced the CFM in the master to the point that the bedrooms would heat evenly if both zones were running.

I’ve ordered manufactured prototypes, 10 bases and 10 sensors.  I feel that the software needs a bit more polish, but eventually I’d like to start offering the boards as dev kits. I want to have software that will run, but I also think it would be far better if others could pitch in. I can do it all myself, but I know there are people better than me at the various aspects, particularly UI.


You’ll notice here the sawtooth, it’s due to only being able to turn the furnace on or off. We’d need variable fan speed and a furnace capable of efficiently producing lower temperatures to even that out.  Neutrino actually has a ‘hysteresis’ setting to decide how big the sawtooth will be, here it heats to 1.5 degrees above the low setting before kicking off. I could set it lower for a smaller sawtooth, at the expense of the furnace kicking on and off more often, but it’s surprisingly comfortable as-is, and more consistent than the stock thermostat.


Screen Shot 2014-12-28 at 8.58.00 AM

Arduino BeagleBone Engineering Neutrino Raspberry Pi

Neutrino Platform Update

Published by:

Screen Shot 2014-07-11 at 12.37.11 AM

The Neutrino temperature, humidity, and pressure sensor has had some heavy modifications over the last few weeks. Most notably, I’ve given it the option of installing an nRF24L01+ module onboard while still providing the header for an external board. We’ve also got jumpers to select the channel, address, and encryption. It has also grown a reed switch, for use as a door/window open sensor. The Arduino library for the SI7021 pressure and humidity module has been written, and hosted on github here.

Work has commenced on the web UI, and while there’s work to do yet, this has allowed me to also flesh out the API and database. Here is a screenshot of the per-sensor and sensor group views.

Screen Shot 2014-07-11 at 12.45.57 AMScreen Shot 2014-07-11 at 12.46.23 AM


How to tell Raspberry Pi from BeagleBone Black in C

Published by:

If you’ve got a cross-platform C or C++ program and want to compile it correctly for BeagleBone Black or Raspberry Pi, you can just use the C macro that corresponds with the ARM version. For example:

#include <stdio.h>

int main(int argc,char **argv)
#if defined __ARM_ARCH_6__
printf("Hello from RPI\n");
#elif defined __ARM_ARCH_7A__
printf("Hello from BBB\n");
return 0;