
Resume Projects ...... .... .. |
UPS Hacking
I recently bought an APC Back-UPS XS 1000. It has a USB interface, and software for windows,
but not for any other OS of course. My FreeBSD 5.2 machine, which does nightly backups, is the only one
I have that stays up 24/7. Naturally, I need it to intercept any signals that the UPS will send when the
power goes out. Unfortunately, I can find no documentation on how to do this with FreeBSD. There are
a few random hints scattered about the internet, but nothing is complete.
My FreeBSD machine detects the UPS correctly, here is the output from dmesg: uhid0: American Power Conversion Back-UPS RS 1000 FW:7.g8 .D USB FW:g8, rev 1.10/1.06, addr 2, iclass 3/0 I discovered that the device /dev/uhid0 can be opened and read from in perl. It appears to send a series of 3 messages, every 3 or 4 seconds. The messages are 15 bytes long. The first 4 bytes appear to be important, but the rest appear somewhat random. They are usually 0, but sometimes not. They may have importance that I cannot yet recognize. Here is a sampling: +0.00:00:00.07 06 00 00 08 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:00.28 0c 64 48 03 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:00.48 16 0c 00 00 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:04.16 06 00 00 08 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:04.36 0c 64 48 03 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:04.56 16 0c 00 00 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:08.24 06 00 00 08 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:08.45 0c 64 48 03 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:08.65 16 0c 00 00 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:12.34 06 00 00 08 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:12.54 0c 64 48 03 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:12.74 16 0c 00 00 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:16.42 06 00 00 08 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:16.63 0c 64 48 03 00 00 00 01 00 00 00 00 00 00 00 +0.00:00:16.83 16 0c 00 00 00 00 00 01 00 00 00 00 00 00 00
I was able to decipher the signals somewhat by switching the USB cable back and forth between my windows machine with the APC software installed, and my FreeBSD box. The first byte indicates the type of data to be contained in the next few bytes. I don't know what 0x06 is for, but 0x0c lines contain data representing the % charge and the estimated battery run-down time. The messages starting with 0x16 give the status of the UPS. 0x0c Using the example data, "0c 64 58 03" tells me that the UPS battery has a 100% charge, and that it estimates a 14 minute run-down time. The second byte is an integer representing the percent charge remaining on the battery, 0 to 100, or 0x00 to 0x64. The 3rd and 4th bytes indicate the estimated run-down time. Add the value of the 3rd byte to the value of the 4th byte multiplied by 256, and voila, the number of seconds remaining if the AC were to die: 0x48 = 72 0x03 = 3 72 + (3 * 256) = 840 seconds, or 14 minutes. 0x16 I have seen 3 variations of the second byte: 0x0a, 0x0c, and 0x0d. 0x0a seems to mean that there is no AC input. 0x0c means that the AC is on. 0x0d means that the AC is on, and that the UPS battery is charging. Therefore, "16 0c 00 00" means that the AC is on, and that the battery is fully charged. Other Messages I have seen several other messages from the UPS. Many of them only appear right after connecting the UPS. Others I have seen while using a USB sniffer on my windows machine, and are only there when prompted by a signal from the APC software. So far I have been unable to write to the UHID device. When attempting to write using the syswrite function in perl, $! is set to "Invalid argument". This may be a problem with the generic UHID driver for FreeBSD. Here are some of the other messages I have seen using a USB sniffer. They do not appear to conform to the 15 byte messages I get while hooked up to the FreeBSD machine. I think this one gives you the AC voltage. 0x74 is 116, which is what the APC software said the AC voltage was at the time. This message appears after the APC software sends "a1 01 31 03 00 00 06 00". This message appears after the APC software sends "a1 01 7a 03 00 00 60 00". This message appears after the APC software sends "a1 01 50 03 00 00 60 00". This message appears after the APC software sends "a1 01 22 03 00 00 60 00".
I have been working on a script that monitors the signals and reports status. It will also
shutdown the system if the battery charge gets too low. I have run into a potentially serious problem though.
After some amount of time, The signals no longer accurately represent the UPS status. For no apparent reason,
the UPS starts sending conflicting messages. It seems to switch back and forth between saying that there is 100%
charge, and that there is 146% charge. After it starts doing this, the signals are no longer useful. It will no longer
signal when the AC has been cut. I have not yet discovered why this occurs or how to rectify it.
UPDATE 2005-10-27: The problem is merely a bug in my program. Instead of reading each message as a whole, I was reading each byte individually, and it was confusing a data byte as a message start byte. Work on the program continutes. Original Document: 2005-10-25 | ||||||||||||||||