Sunday, March 17, 2013

Some times you have to do it yourself.

A Quest for Inexpensive Power Control


When I started working on designing a teaching lab for system administration I wanted to include as many of the remote control and monitoring elements as I could.  One of the elements I wanted was remote power control.  I was discouraged to find that commercial grade switched PDUs are hard to find for less than $500US.  I've used hobbyist home automation with powerline signalling and found it to be cumbersome and unreliable.  A lucky search query lead me to PowerUSB.  It seemed to be exactly what I wanted. It's relatively inexpensive, uses standard USB communications and the vendor provides software for Linux.

It is important to note that these are not commercial grade power control.  The three switched sockets cannot carry a full 15A at 120VAC.  One of them is rated at 6A, controlled with a relay and the other two at 4A with solid state power switch.  You can't use these to control high powered rack-mount machines.  They'll do find for ordinary desktop units and are ideal for the low-power ARM systems I'm working with.

I ordered two of the Basic units to try in my first PiLab pod.

Almost, But Not Quite


A few days later they arrived, packed in nicely designed boxes. It didn't take me long to find that things weren't as bright as they looked.

The software on the included CD is a GUI application for Windows.  I want to be able to control the strips from Linux.

There are downloads for Linux on the PowerUSB web site.  Cool.  But they are binaries and shared libraries for ix86 and x86_64 only.  The aren't packaged and require a number of manual steps (placing udev rules) requiring root access to make them work.

Tweaks?


Alright.  I write to the email address indicated on the site and several days later I get an email which includes access to zip files containing the Linux source files.

It turns out that the Linux code seems to be a bit of an afterthought, or possibly the folks producing it aren't versed in best practices for Linux.  It uses a publicly available USB HID library which is licensed to allow both open source and proprietary use (hidapi).  The code that actually communicates with the power strip is fairly clear and consistent, but the CLI command that wraps it doesn't take advantage of current CLI argument patterns.  The output isn't really designed for either humans or computers to use easily.

Fair enough.  It could be that headless Linux servers are not their target market and so they haven't devoted too much time to it. They were very nice to give me what they did.  I can ask for more, or I can do it myself.

I started by writing a set of Makefiles and RPM packaging boilerplate so that I could automatically generate software for both RPM and DEB based distributions. (I work at Red Hat and I run Raspbian on my RPis at the moment).  That was OK as far as it went.  I could package and re-produce what I'd been given.  I sent that back to the folks at PowerUSB so they can share and use it if they wish.

There was something unsatisfying in the result.  So I dug some more.

What do I REALLY Want?


What I really wanted was something that would work on any distribution without a lot of compilation dependencies.  I like Python so I looked at what was available.

I found PyUSB and PyUDEV.  libhid has Python bindings.  In the end I found it easiest to use PyUSB to port just enough of the original hidapi to Python to do what I need.

It's not finished, but it does enough now for my purposes. It only manages the Basic features.  I'll need to get one each of the IO, Watchdog and Smart units to finish development and testing.

Usage Sample

So here's what I want to be able to do:

powerusb
0:0, Basic    , FWVer: 3.1, Curr(mA)  10.0, Power(KWh): 3.92, off,  on,  on
0:1, Basic    , FWVer: 3.1, Curr(mA)  10.0, Power(KWh): 8.70,  on, off, off

powerusb --xml 0:1 status 

powerusb 0:1:2 on

powerusb --syslog 0:1:1

Eventually I'd like to add a couple more things, like labeling power strips and/or sockets so that you can call them out by name.  I'd also like to be able to extend the library and CLI program to be able to manage the IO, Watchdog and Smart units.

Revision Control and Project Planning

The source code (such as it is) is on Github at https://github.com/markllama/powerusb

I've made just the slightest stab at trying Agile project management even when it's just me. I have this project on a free project management site, Trello: Mine is the powerusb-cli project.  (I just set it public, let me know if you want to join the project).

Please note that this is ALPHA! ALPHA! ALPHA! software. It will be changing as I get time to add things.

Hardware Wish List

There are a couple of things I'd like to see in the power strips themselves to make managing them easier.

Unique USB identifier

USB devices are identified by a Vendor and Product ID.  The Vendor ID is acquired from the Universal Serial Bus Implementer's Forum (USB-IF).  Currently the PowerUSB devices identify themselves by the chip manufacturer and device which PowerUSB used.  I see some indications that PowerUSB is not the only device manufacturer who has used those chips without modifying the Vendor or Product ID.  This could lead to mis-identfication of those devices if someone connected a different one that used the same chip. 

Unique Serial Number


USB Devices also report a serial number when the are connected.  It appears that the serial number for the two devices I have are identical.  The only way currently to distinguish two devices is by the bus and port number to which they are connected.  Adding devices, removing them, switching ports or adding or changing a hub could result in a device appearing to move.  A unique serial number on each device could resolve any ambiguity.

Is it an HID really?


This one is a nit-pick on my part, I admit. 

PowerUSB took advantage of the simplicity of the HID (Human Interface Device) specification and the plug-and-play nature of the HID connection protocol to make connecting PowerUSB strips simpler for them.  But HID devices are supposed to be things that humans use to communicate with the computer: Keyboards, Mice, Tablets, Microphones, Cameras etc. With a little more work PowerUSB could have implemented this as a regular USB device.  I'm going to be looking to see if I can manage this as a pure USB device.  The fragment of the hidapi library which I ported essentially lays the HID interface over plain ol' USB.

Just One Part

I have to remind myself that this is just one part of the real goal: The Pi Lab.  I've got most of the parts of the first pod.  The other hitch I've hit is that I specified a router that's been discontinued.  I'd also specified CeroWRT (bufferbloat.org) which only runs (and is being developed) on that discontinued router.  I think I'll have to pick a new router and switch to the more generally available OpenWRT.  More on that search later.

References



  • hidapi - https://github.com/signal11/hidapi
  • PyUSB - http://sourceforge.net/apps/trac/pyusb/
  • PyUDEV - https://github.com/lunaryorn/pyudev
  • libhid - http://libhid.alioth.debian.org/