Original by Martin Schroeder, emes -at- geomer.de.
This is an unofficial decoding of the bcm/xcp protocol used by Powerware UPS's amongst others. There may be a lot of other commands that are not in these description. On the other hand I may have misinterpreted some of the data. So feel free to append new information and correct the mistakes I have made. Including typos, poor grammar, etc.
At this time all information is only evaluated on a Powerware 9120. As known other UPSes have different sets of commands and/or respond packets. One ore more of the packets seems to describe the format of data (the dialect used). See remarks at the end.
All data received from the UPS is in little endian (ie x86) byteorder.
Byte 0: 0xAB packet start byte
Byte 1: 0xn the command is n bytes long.
n Bytes: command
n + 1 Byte: checksum
Example: (all numbers in hex)
AB 01 34 20
AB start |
Byte 1: the low nibble of the command byte.
Byte 2: number of bytes in the result packet, starting from the 4th byte, excluding the checksum.
Byte 3: low nibble: chunk serial, high nibble: chunk complete.
4 - nBytes: data
n + 1 Byte: checksum
The data from one request may be split into chunks. The chunks are numbered from 1 to n (-> chunk serial. Byte 3). If the high nibble is non-zero the current chunk is the last one in the packet.
If the UPS doesn't understand a command the command byte minus 0x30/0x9 is returned in byte 1.
Example:
for(c = 0, i = 0; i < len; i++) c -= buf[i];len is the length of the command/result buffer.
Status/information polling |
||
Command |
Meaning |
|
0x31 | UPS capabilities (?) |
Most of the information is unknown. The firmware
revisions may be encoded here. Starting from byte 11 is the product name (null terminated string). |
0x33 |
Current line status (4 Bytes (PW9120)) |
Byte 0: (unsigned char)
0x50 On LineByte 1 - 3: Unknown |
0x33 |
Current line status (19 Bytes (PW5125)) |
Bytes 00 01: (unsigned char, hex)
50 xx On LineByte 2 - 18: Unknown |
0x34 |
Current measurements (52 Bytes) |
Byte 0: Output watt (integer) Byte 4: Output VA (integer) Byte 8: Output freq. (float) Byte 12: Input freq. (float) Byte 16: Batt. voltage (float) Byte 20: % Batt. charge (integer) Byte 24: Est. backup time in seconds (integer) Byte 28: Input voltage (integer) Byte 32: UPS temperature in °C (integer) Byte 36: Output current (float) Byte 40: unknown Byte 44: Maximum VA(?) (integer) Byte 48: Output voltage (integer) |
0x35 |
Alarms (?) (23 Bytes) |
unknown |
0x36 |
Hardware info (?) (80 Bytes) |
Byte 0: Date of assembly (time_t) Byte 4-25: unknown Byte 26: No. of external batteries (short) Byte 28-47: unknown Byte 48-63: Part no. (string) Byte 64-79: Serial no. (string) |
0x3B |
ABM status (?) (21 Bytes) |
Byte 0-19: unknown Byte 20: ABM status (unsigned char) 0x01 charging |
0x3C |
User settings (31 Bytes) |
Byte 0: Requested output voltage (unsigned short) Byte 2: Requested output freq. (unsigned short) Byte 4-7: unknown Byte 8: Freq. bypass threshold (unsigned short) 0x64 (100) == +/-2%Byte 10: Min. voltage bypass thresh. (unsigned short) Byte 12: Max. voltage bypass thresh. (unsigned short) Byte 14-30: unknown |
0x41 |
Startup delay (17 Bytes with a 2 phase ups) |
Byte 0-1: unknown Byte 2: Phase no. (char) Byte 3: unknown Byte 4: Phase start-up delay in seconds. (short) -1 == none Byte 6-7: unknown Byte 8: Phase no. (char) Byte 9: unknown Byte 10: Phase start-up delay in seconds. (short) (-1 == none) |
0x40 | Get command set (?) |
Returns legal commands of the UPS (?????). Just an early idea. |
0xCF69E8D5 | Init extended mode. | Enables subcommands/ Programming mode |
0x9702 S1 S2 | Set startup delay |
S1: byte – power segment number. S2: short - delay in seconds UPS must be in extended mode. |
0xB201 | Test Hardware | UPS must be in extended mode. |
0xA0 | Describe UPS |
????? The only thing known from this block is that it contains the internal product name. |
Example:
0xAB 04 CF69E8D5 5C AB 05 9702 01 1400 A2
|-----------------| |-------------------|
Init extended mode, subcommand: set startup delay (Segment 1. 20 seconds)