The BCM/XCP Protocol

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.

General information

All data received from the UPS is in little endian (ie x86) byteorder.

Command format description:

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
01 1 byte long
34 the command
20 checksum

Result format description:

Byte 0: 0xAB packet start byte

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.

Checksum calculation:

Starting with 0, declared as an unsigned char, all bytes are subtracted from the last result.

Example:

for(c = 0, i = 0; i < len; i++)  c -= buf[i];
len is the length of the command/result buffer.

Status information

All byte positions here are relative to the beginning of the data block (Normally byte 4 of the received packet).

1 Byte commands

Status/information polling

Command
Byte

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 Line
0x60 On Bypass
0xF0 On Battery
Byte 1 - 3: Unknown
0x33 Current line status
(19 Bytes (PW5125))
Bytes 00 01: (unsigned char, hex)
50 xx On Line
50 C2 On Line
50 E2 On Line, just after LB->OL
60 xx On Bypass
F0 52 On Battery
F0 4A On Battery, LB imminent?
F0 6A Low Battery
10 60 Shutdown in progress?
Byte 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
0x02 discharging
0x03 floating
0x04 resting
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%
0xFA (250) == +/-5%
0x15E(350) == +/-7%
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.

Multi byte / extended mode commands

The commands are used to used to get extended information or program the UPS. It consists of two packets. The first one seems two switch the UPS into another state, the second does the job. Each packet has the same structure as described above. Starting with 0xAB, ending with checksum.
Use this with care.

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)

Remarks / Ideas