
PelcoDParser C++ library
v1.0.6
Table of contents
- Overview
- Versions
- Library files
- PelcoDParser class description
- Data structures
- Build and connect to your project
- Portability
- Test application
Overview
The PelcoDParser is a C++ library for encoding and decoding PelcoD responses and commands. The library includes basic methods for preparing commands (encoding) and interpreting the camera responses (decoding). It uses C++17 standard. The library provides simple interface and doesn’t have third party dependencies to be installed in OS. Also, the library provides test application to check communication with cameras via serial ports. Test application depends on SerialPort (provides methods to work with serial ports). The SerialPort repository must be located next to the PelcoDParser repository, see Build stand alone.
PelcoDParser is general-purpose software: it is not tied to any sector or application, and the developer of a program decides what the program does with it.
Versions
Table 1 - Library versions.
| Version | Release date | What’s new |
|---|---|---|
| 1.0.0 | 14.03.2025 | - First version. |
| 1.0.1 | 26.10.2025 | - SerialPort submodule update in test application. |
| 1.0.2 | 30.07.2026 | - Fixed limits for MAGNIFICATION_RESPONSE. - Fixed fall-through bug for SET_BAUDRATE. |
| 1.0.3 | 01.09.2026 | - Fixed the CMND 1 / CMND 2 bit map of standard commands: Up and Down were swapped, and so were Iris Open and Iris Close, in both getStandardCommand and decodeCommand. - Fixed SET_AUXILIARY, SET_INDICATOR, CLEAR_AUXILIARY and CLEAR_INDICATOR overwriting data1 before the command was recognised, which corrupted the command word returned with UNKNOWN_COMMAND. - Documented the standard command bit map and corrected the decodeCommand speed ranges. |
| 1.0.5 | 12.09.2026 | - Fixed command byte 0x73 with command extension 0x02 or 0x03 decoding to NONE. - decodeCommand now documents the difference between NONE and UNKNOWN_COMMAND. - Fixed documentation. |
| 1.0.6 | 16.10.2026 | - Removed the SerialPort sub-repository: the test application uses the SerialPort repository located next to the PelcoDParser repository. - getStandardCommand, getExtendedCommand and getResponse return FALSE for a nullptr buffer (the methods used to dereference it) and do not change the buffer if they return FALSE. getResponse sets responseSize to 0 if it returns FALSE. - getExtendedCommand and getResponse return FALSE for an argument that does not fit into its field of the message: a negative value or a value above 0xFF / 0xFFFF used to be encoded modulo 256 / 65536 (for example EVEREST_MACRO_SET_PAN_LIMIT with a negative limit type was encoded as another command). - EVEREST_MACRO_SET_ZOOM_LIMIT accepts the limit 0 - 65535 (0 - 35999 was accepted). - The encoded messages and the decoded values are not changed for valid arguments and valid messages. - Compiler warning options and exploit mitigation options added to the CMake files, the code is compiled without warnings with the strict warning set. - Added the option –self-test of the test application: tests which do not need a serial port. - Fixed the test application: the speed was read as a character, uninitialized values were printed, the application did not stop when the input was closed. - Fixed documentation: ranges of the arguments, the device type response, the output arguments of the decoding methods, the build instructions. |
Library files
The library is supplied only by source code. The user is given a set of files in the form of a CMake project (repository). The repository structure is shown below:
CMakeLists.txt ---------------- Main CMake file of the library.
static ------------------------ Folder with images used by this document.
src -------------------------- Folder with library source code.
CMakeLists.txt ------------ CMake file of the library.
PelcoDParser.h ------------ Main library header file.
PelcoDParserVersion.h ----- Header file with library version.
PelcoDParserVersion.h.in -- Service CMake file to generate version header.
PelcoDParser.cpp ---------- C++ implementation file.
test -------------------------- Folder for test application files.
CMakeLists.txt ------------ CMake file for test application.
main.cpp ------------------ Source C++ file of test application.
PelcoDParser class description
PelcoDParser class declaration
namespace rapidpixel
{
class PelcoDParser
{
public:
/// Get library version.
static std::string getVersion();
/// Encode standard command.
bool getStandardCommand(
uint8_t* message,
uint8_t addr,
bool sense,
bool autoScan,
bool cameraOn,
bool irisOpen,
bool irisClose,
bool focusNear,
bool focusFar,
bool zoomWide,
bool zoomTele,
bool up,
bool down,
bool left,
bool right,
uint8_t panSpeed = 0x00,
uint8_t tiltSpeed = 0x00);
/// Encode extended command.
bool getExtendedCommand(
uint8_t* message,
uint8_t addr,
PelcoDCommand id,
int data1,
int data2);
/// Encode response.
bool getResponse(
uint8_t* message,
uint8_t addr,
PelcoDResponse id,
uint8_t& responseSize,
int data1,
int data2);
/// Decode response.
PelcoDResponse decodeResponse(
uint8_t byte,
int& data1,
int& data2);
/// Decode standard and extended command.
PelcoDCommand decodeCommand(
uint8_t byte,
int& address,
int& data1,
int& data2,
bool& sense,
bool& autoScan,
bool& cameraOn,
bool& irisOpen,
bool& irisClose,
bool& focusNear,
bool& focusFar,
bool& zoomWide,
bool& zoomTele,
bool& up,
bool& down,
bool& left,
bool& right,
uint8_t& panSpeed,
uint8_t& tiltSpeed);
};
}
getVersion method
The getVersion() method returns a string of current PelcoDParser class version. Method declaration:
static std::string getVersion();
Method can be used without PelcoDParser class instance and can be called from any thread:
std::cout << "PelcoDParser version: " << rapidpixel::PelcoDParser::getVersion();
Console output:
PelcoDParser version: 1.0.6
getStandardCommand method
The getStandardCommand(…) method encodes (prepares data) standard control command. Method declaration:
bool getStandardCommand(
uint8_t* message,
uint8_t addr,
bool sense,
bool autoScan,
bool cameraOn,
bool irisOpen,
bool irisClose,
bool focusNear,
bool focusFar,
bool zoomWide,
bool zoomTele,
bool up,
bool down,
bool left,
bool right,
uint8_t panSpeed = 0x00,
uint8_t tiltSpeed = 0x00);
| Parameter | Value |
|---|---|
| message | Pointer to the buffer where the command will be encoded. Must not be nullptr. The buffer must be at least 7 bytes long: the library can not check the size of the buffer. |
| addr | Camera address (1-255). The value is not checked. |
| sense | Sense bit. If set to true the command will be sent with sense bit. |
| autoScan | Auto scan bit. If set to true the command will be sent with auto scan bit. |
| cameraOn | Camera on bit. If set to true the command will be sent with camera on bit. |
| irisOpen | Iris open bit. If set to true the command will be sent with iris open bit. |
| irisClose | Iris close bit. If set to true the command will be sent with iris close bit. |
| focusNear | Focus near bit. If set to true the command will be sent with focus near bit. |
| focusFar | Focus far bit. If set to true the command will be sent with focus far bit. |
| zoomWide | Zoom wide bit. If set to true the command will be sent with zoom wide bit. |
| zoomTele | Zoom tele bit. If set to true the command will be sent with zoom tele bit. |
| up | Up bit. If set to true the command will be sent with up bit. |
| down | Down bit. If set to true the command will be sent with down bit. |
| left | Left bit. If set to true the command will be sent with left bit. |
| right | Right bit. If set to true the command will be sent with right bit. |
| panSpeed | Pan speed. The value of the parameter is from 0x00 to 0x3F. |
| tiltSpeed | Tilt speed. The value of the parameter is from 0x00 to 0x3F |
Returns: TRUE if command was successfully encoded, otherwise FALSE. The method returns FALSE when message is nullptr, when two opposite bits are set at the same time (irisOpen with irisClose, focusNear with focusFar, zoomWide with zoomTele, up with down, left with right), or when panSpeed or tiltSpeed is above 0x3F. The buffer is not changed if the method returns FALSE. The method does not use the state of the object.
NOTE: the encoder deliberately restricts the speed bytes to the standard 0x00 - 0x3F range. A master that has to send a turbo speed above 0x3F must build that message itself; decodeCommand accepts and reports the full 0x00 - 0xFF range on the receiving side.
Standard command bit map
CMND 1 and CMND 2 carry one motion per bit. Both getStandardCommand and decodeCommand use exactly this mapping, which is the one defined by the PelcoD protocol specification of Pelco (revision 5.0.1).
Table 2 - Bits of CMND 1.
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|
| Sense | 0 | 0 | Auto scan | Camera on | Iris close | Iris open | Focus near |
Table 3 - Bits of CMND 2.
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|
| Focus far | Zoom wide | Zoom tele | Down | Up | Left | Right | Always 0 |
NOTE: bit 0 of CMND 2 is what separates the two kinds of message. It is always 0 in a standard command; an extended command always has an odd CMND 2, and that is how decodeCommand tells them apart.
getExtendedCommand method
The getExtendedCommand(…) method encodes (prepares data) extended control command for camera. Method declaration:
bool getExtendedCommand(
uint8_t* message,
uint8_t addr,
PelcoDCommand id,
int data1,
int data2);
| Parameter | Value | | ——— | ———————————————————– | | message | Pointer to the buffer where the command will be encoded. Must not be nullptr. The buffer must be at least 7 bytes long: the library can not check the size of the buffer. | | addr | Camera address (1-255). The value is not checked. | | id | Command ID (see PelcoDCommand enum). NONE, GENERAL_COMMAND and UNKNOWN_COMMAND are not encoded. | | data1 | Command argument 1. The value of argument depends on command ID (see PelcoDCommand enum). Some commands don’t have arguments: the argument is ignored. | | data2 | Command argument 2. The value of argument depends on command ID (see PelcoDCommand enum). Some commands don’t have arguments: the argument is ignored. |
Returns: TRUE if command was successfully encoded, otherwise FALSE. The method returns FALSE when message is nullptr, when the command ID is not encoded, or when an argument does not fit into its field of the message (a negative value, a value above 0xFF or 0xFFFF, a value outside of -0x7FFF - 0x7FFF for a signed 16 bit field) or is above the upper limit that the library checks for the command (see PelcoDCommand enum). The buffer is not changed if the method returns FALSE. The method does not use the state of the object.
getResponse method
The getResponse(…) method encodes (prepares data) response buffer. Method declaration:
bool getResponse(
uint8_t* message,
uint8_t addr,
PelcoDResponse id,
uint8_t& responseSize,
int data1,
int data2);
| Parameter | Value |
|---|---|
| message | Pointer to the buffer where the response will be encoded. Must not be nullptr. The buffer must be at least 7 bytes long: the library can not check the size of the buffer. |
| addr | Camera address (1-255). The value is not checked. |
| id | Response ID (see PelcoDResponse enum). NONE and STANDARD_EXTENDED are not encoded. |
| responseSize | Size of the response: 4 bytes for GEN and 7 bytes for the other responses. Set to 0 if the method returns FALSE. |
| data1 | Response argument 1. The value of argument depends on response ID (see PelcoDResponse enum). Some responses don’t have arguments: the argument is ignored. |
| data2 | Response argument 2. The value of argument depends on response ID (see PelcoDResponse enum). Some responses don’t have arguments: the argument is ignored. |
Returns: TRUE if response was successfully encoded, otherwise FALSE. The method returns FALSE when message is nullptr, when the response ID is not encoded, or when an argument does not fit into its field of the message (a negative value or a value above 0xFF or 0xFFFF) or is above the upper limit that the library checks for the response (see PelcoDResponse enum). The buffer is not changed if the method returns FALSE. The method does not use the state of the object.
decodeResponse method
The decodeResponse(…) method decodes (interprets) response buffer. Call the method for every byte received from the serial port. The object keeps the last 7 bytes: a response is detected when these bytes start with 0xFF and have a valid checksum, so the method returns NONE for most of the bytes. The 4 bytes General Reply (GEN) is not decoded. The method changes the state of the object: an object must not be used from several threads at the same time, use a separate object for every serial port. Method declaration:
PelcoDResponse decodeResponse(
uint8_t byte,
int& data1,
int& data2);
| Parameter | Value |
|---|---|
| byte | Next byte of response buffer. |
| data1 | Reference to a variable to store response argument 1. The value of argument depends on response ID (see PelcoDResponse enum). The variable is set only if the returned response has this argument, otherwise it is not changed. |
| data2 | Reference to a variable to store response argument 2. The value of argument depends on response ID (see PelcoDResponse enum). The variable is set only if the returned response has this argument, otherwise it is not changed. |
Returns: Response ID (see PelcoDResponse enum). If no response was detected, the method returns PelcoDResponse::NONE. The method never returns GEN and STANDARD_EXTENDED.
decodeCommand method
The decodeCommand(…) method decodes (interprets) command buffer. Call the method for every byte received from the serial port. The object keeps the last 7 bytes: a command is detected when these bytes start with 0xFF and have a valid checksum. The method changes the state of the object: an object must not be used from several threads at the same time, use a separate object for every serial port. Method declaration:
PelcoDCommand decodeCommand(
uint8_t byte,
int& address,
int& data1,
int& data2,
bool& sense,
bool& autoScan,
bool& cameraOn,
bool& irisOpen,
bool& irisClose,
bool& focusNear,
bool& focusFar,
bool& zoomWide,
bool& zoomTele,
bool& up,
bool& down,
bool& left,
bool& right,
uint8_t& panSpeed,
uint8_t& tiltSpeed);
| Parameter | Value |
|---|---|
| byte | Next byte from command buffer. |
| address | Reference to a variable to store camera address. |
| data1 | Reference to a variable to store command argument 1. The value of argument depends on command ID (see PelcoDCommand enum). Some commands don’t have arguments. |
| data2 | Reference to a variable to store command argument 2. The value of argument depends on command ID (see PelcoDCommand enum). Some commands don’t have arguments. |
| sense | Reference to a variable to store sense bit. |
| autoScan | Reference to a variable to store auto scan bit. |
| cameraOn | Reference to a variable to store camera on bit. |
| irisOpen | Reference to a variable to store iris open bit. |
| irisClose | Reference to a variable to store iris close bit. |
| focusNear | Reference to a variable to store focus near bit. |
| focusFar | Reference to a variable to store focus far bit. |
| zoomWide | Reference to a variable to store zoom wide bit. |
| zoomTele | Reference to a variable to store zoom tele bit. |
| up | Reference to a variable to store up bit. |
| down | Reference to a variable to store down bit. |
| left | Reference to a variable to store left bit. |
| right | Reference to a variable to store right bit. |
| panSpeed | Reference to a variable to store pan speed. The raw speed byte, 0x00 - 0xFF: the decoder does not restrict it the way getStandardCommand does, because a master may legitimately send a turbo speed above 0x3F. |
| tiltSpeed | Reference to a variable to store tilt speed. The raw speed byte, 0x00 - 0xFF, see panSpeed above. |
Returns: Command ID (see PelcoDCommand enum).
Output arguments: if NONE is returned no output argument is changed. If GENERAL_COMMAND is returned address, the bits and the speeds are set, data1 and data2 are not changed. For any other value address, data1 and data2 are set and the bits and the speeds are not changed. A command that has no arguments returns in data1 and data2 the raw command field data[2]*256 + data[3] and the raw data field data[4]*256 + data[5], as UNKNOWN_COMMAND does. The arguments of the commands are the values described in the PelcoDCommand enum with these exceptions: for SCREEN_MOVE_ABSOLUTE data1 and data2 are the raw bytes 0 - 255 (they are not converted to signed values as for SCREEN_MOVE_RELATIVE), for QUERY data1 is the raw command field data[2]*256 + data[3] (the query type is data1 » 8).
NOTE: NONE and UNKNOWN_COMMAND are not interchangeable, and a caller that confuses them will violate the protocol.
- NONE means no complete, valid packet yet: the seven byte window does not start with 0xFF, or its checksum does not match. The caller must send nothing and feed the next byte.
- UNKNOWN_COMMAND means a valid packet arrived whose command is not recognised. The PelcoD specification requires a reply to every received command, so the caller must answer with a NAC - never with silence.
Because the parser slides its window one byte at a time, NONE is the normal return for six out of every seven bytes of a valid message.
Data structures
PelcoDCommand enum
The command IDs are described in the PelcoDCommand enum in the PelcoDParser.h file. The definition of the enum is as follows:
namespace rapidpixel
{
/**
* @brief Pelco-D command IDs.
*
* The IDs from SET_PRESET to SCREEN_MOVE_RELATIVE are the commands which
* getExtendedCommand(...) encodes. The ranges of data1 and data2 given for
* the IDs are the ranges of the protocol. getExtendedCommand(...) returns
* FALSE if an argument cannot be encoded into its field of the message (a
* negative value, a value above 0xFF or 0xFFFF, a value outside of the
* range -0x7FFF - 0x7FFF for a signed 16 bit field) or if it is above the
* upper limit that the library checks for the command. A lower limit of a
* range which is not 0 (for example 0x01 for a month) is not checked.
* NONE, GENERAL_COMMAND and UNKNOWN_COMMAND are returned by decodeCommand(...)
* only.
*/
enum class PelcoDCommand
{
/**
* @brief Set preset. Command generates "General Reply".
* @arg data1 - PresetID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
SET_PRESET,
/**
* @brief Clear preset. Command generates "General Reply".
* @arg data1 - PresetID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
CLEAR_PRESET,
/**
* @brief Call preset. Command generates "General Reply".
* @arg data1 - PresetID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
CALL_PRESET,
/**
* @brief Set auxiliary. Command generates "General Reply".
* @arg data1 - AuxiliaryID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
SET_AUXILIARY,
/**
* @brief Set indicator. Command generates "General Reply".
* @arg data1 - AuxiliaryID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
SET_INDICATOR,
/**
* @brief Clear auxiliary. Command generates "General Reply".
* @arg data1 - AuxiliaryID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
CLEAR_AUXILIARY,
/**
* @brief Clear indicator. Command generates "General Reply".
* @arg data1 - AuxiliaryID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
CLEAR_INDICATOR,
/**
* @brief Originally an unused command.
* Command generates "General Reply".
* @arg data1 - Sub-device ID: 0x00 - 0xFF.
* @arg data2 - ON/OFF/TEMP: 0x00 - 0xFF.
*/
DUMMY,
/**
* @brief Reset camera. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
REMOTE_RESET,
/**
* @brief Set zone start. Command generates "General Reply".
* @arg data1 - ZoneID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
SET_ZONE_START,
/**
* @brief Set zone end. Command generates "General Reply".
* @arg data1 - ZoneID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
SET_ZONE_END,
/**
* @brief Write character to screen.
* Command generates "General Reply".
* @arg data1 - Screen column: 0x00 - 0x28.
* @arg data2 - ASCII char: 0x00 - 0xFF.
*/
WRITE_CHARACTER_TO_SCREEN,
/**
* @brief Clear screen. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
CLEAR_SCREEN,
/**
* @brief Alarm acknowledge. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
ALARM_ACKNOWLEDGE,
/**
* @brief Zone scan on. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
ZONE_SCAN_ON,
/**
* @brief Zone scan off. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
ZONE_SCAN_OFF,
/**
* @brief Pattern start. Command generates "General Reply".
* @arg data1 - PatternID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
RECORD_PATTERN_START,
/**
* @brief Pattern end. Command generates "General Reply".
* @arg data1 - PatternID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
RECORD_PATTERN_END,
/**
* @brief Run pattern. Command generates "General Reply".
* @arg data1 - PatternID: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
RUN_PATTERN,
/**
* @brief Set zoom speed. Command generates "General Reply".
* @arg data1 - Zoom speed: 0x00 - 0x03.
* @arg data2 - Not used.
*/
SET_ZOOM_SPEED,
/**
* @brief Set focus speed. Command generates "General Reply".
* @arg data1 - Focus speed: 0x00 - 0x03.
* @arg data2 - Not used.
*/
SET_FOCUS_SPEED,
/**
* @brief Reset camera to default.
* Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
RESET_CAMERA_TO_DEFAULT,
/**
* @brief Auto focus. Command generates "General Reply".
* @arg data1 - 0x00 - Automatic operation.
* 0x01 - Auto focus is off.
* @arg data2 - Not used.
*/
AUTO_FOCUS,
/**
* @brief Auto iris. Command generates "General Reply".
* @arg data1 - 0x00 - Automatic operation.
* 0x01 - Auto iris is off.
* @arg data2 - Not used.
*/
AUTO_IRIS,
/**
* @brief AGC. Command generates "General Reply".
* @arg data1 - 0x00 - Automatic operation.
* 0x01 - AGC is off.
* @arg data2 - Not used.
*/
AGC,
/**
* @brief Backlight compensation.
* Command generates "General Reply".
* @arg data1 - 0x00 - BLC is off "Spectra IV".
* 0x01 - BLC is off / BLC is on "Spectra IV".
* 0x02 - BLC is on.
* @arg data2 - Not used.
*/
BACKLIGHT_COMPENSATION,
/**
* @brief Auto white balance. Command generates "General Reply".
* @arg data1 - 0x00 - AWB is on "Spectra IV".
* 0x01 - AWB is on / AWB is off "Spectra IV".
* 0x02 - AWB is off.
* @arg data2 - Not used.
*/
AUTO_WHITE_BALANCE,
/**
* @brief Enable device phase delay mode.
* Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
ENABLE_DEVICE_PHASE_DELAY_MODE,
/**
* @brief Set shutter speed.
* Command generates "General Reply".
* @arg data1 - Shutter speed code: uint16_t value, depends on
* particular device.
* @arg data2 - Not used.
*/
SET_SHUTTER_SPEED,
/**
* @brief Set line lock phase delay.
* Command generates "General Reply".
* @arg data1 - uint16_t phase delay value 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
ADJUST_LINE_LOCK_PHASE_DELAY_ABSOLUTE,
/**
* @brief Adjust line lock phase delay relative.
* Command generates "General Reply".
* @arg data1 - int16_t phase delay change -0x7FFF - 0x7FFF.
* @arg data2 - Not used.
*/
ADJUST_LINE_LOCK_PHASE_DELAY_RELATIVE,
/**
* @brief Adjust white balance R/B.
* Command generates "General Reply".
* @arg data1 - R/B value: 0x0000 - 0xffff
* @arg data2 - Not used.
*/
ADJUST_WHITE_BALANCE_R_B_ABSOLUTE,
/**
* @brief Adjust white balance R/B relative.
* Command generates "General Reply".
* @arg data1 - R/B change: -0x7fff - 0x7fff.
* @arg data2 - Not used.
*/
ADJUST_WHITE_BALANCE_R_B_RELATIVE,
/**
* @brief Adjust white balance M/G.
* Command generates "General Reply".
* @arg data1 - M/G value: 0x0000 - 0xffff.
* @arg data2 - Not used.
*/
ADJUST_WHITE_BALANCE_M_G_ABSOLUTE,
/**
* @brief Adjust white balance M/G relative.
* Command generates "General Reply".
* @arg data1 - M/G change: -0x7fff - 0x7fff.
* @arg data2 - Not used.
*/
ADJUST_WHITE_BALANCE_M_G_RELATIVE,
/**
* @brief Adjust gain. Command generates "General Reply".
* @arg data1 - Gain value: 0x0000 - 0xffff.
* @arg data2 - Not used.
*/
ADJUST_GAIN_ABSOLUTE,
/**
* @brief Adjust gain relative.
* Command generates "General Reply".
* @arg data1 - Gain change: -0x7fff - +0x7fff.
* @arg data2 - Not used.
*/
ADJUST_GAIN_RELATIVE,
/**
* @brief Adjust auto iris level.
* Command generates "General Reply".
* @arg data1 - Iris level: 0x0000 - 0xffff.
* @arg data2 - Not used.
*/
ADJUST_AUTO_IRIS_LEVEL_ABSOLUTE,
/**
* @brief Adjust auto iris level relative.
* Command generates "General Reply".
* @arg data1 - Iris change: -0x7fff - 0x7fff.
* @arg data2 - Not used.
*/
ADJUST_AUTO_IRIS_LEVEL_RELATIVE,
/**
* @brief Adjust auto iris peak value.
* Command generates "General Reply".
* @arg data1 - Iris peak value 0x0000 - 0xffff.
* @arg data2 - Not used.
*/
ADJUST_AUTO_IRIS_PEAK_VALUE_ABSOLUTE,
/**
* @brief Adjust auto iris peak value relative.
* Command generates "General Reply".
* @arg data1 - Iris peak value change: -0x7fff - 0x7fff.
* @arg data2 - Not used.
*/
ADJUST_AUTO_IRIS_PEAK_VALUE_RELATIVE,
/**
* @brief Query. Command generates "Query Reply".
* @arg data1 - Query type: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
QUERY,
/**
* @brief Set preset scan. Visit every preset for a given delay.
* Command generates "General Reply".
* @arg data1 - Delay (s): 0x00 - 0xFF.
* @arg data2 - Not used.
*/
PRESET_SCAN,
/**
* @brief Set zero position. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
SET_ZERO_POSITION,
/**
* @brief Set pan position. Command generates "General Reply".
* @arg data1 - Pan position: 0 - 35999.
* @arg data2 - Not used.
*/
SET_PAN_POSITION,
/**
* @brief Set tilt position. Command generates "General Reply".
* @arg data1 - Tilt position: 0 - 35999.
* Zero position means horizontal. Ninety degrees indicates that the device
* is pointed straight down.
* @arg data2 - Not used.
*/
SET_TILT_POSITION,
/**
* @brief Set zoom position. Command generates "General Reply".
* @arg data1 - Zoom position: 0 - 65535.
* @arg data2 - Not used.
*/
SET_ZOOM_POSITION,
/**
* @brief Query pan position. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
QUERY_PAN_POSITION,
/**
* @brief Query tilt position. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
QUERY_TILT_POSITION,
/**
* @brief Query zoom position. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
QUERY_ZOOM_POSITION,
/**
* @brief Prepare for download. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
PREPARE_FOR_DOWNLOAD,
/**
* @brief Set magnification absolute.
* Command generates "General Reply".
* @arg data1 - Magnification value: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
SET_MAGNIFICATION_ABSOLUTE,
/**
* @brief Set magnification relative.
* Command generates "General Reply".
* @arg data1 - int16_t Magnification value change -0x7FFF - 0x7FFF.
* @arg data2 - Not used.
*/
SET_MAGNIFICATION_RELATIVE,
/**
* @brief Query magnification. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
QUERY_MAGNIFICATION,
/**
* @brief Activate echo mode. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
ACTIVATE_ECHO_MODE,
/**
* @brief Set remote baudrate. Command generates "General Reply".
* @arg data1 - 0x00 - 2400.
* 0x01 - 4800.
* 0x02 - 9600.
* 0x03 - 19200.
* 0x04 - 38400.
* 0x05 - 115200.
* @arg data2 - Not used.
*/
SET_BAUDRATE_REMOTE,
/**
* @brief Set local baudrate. Command generates "General Reply".
* @arg data1 - 0x00 - 2400.
* 0x01 - 4800.
* 0x02 - 9600.
* 0x03 - 19200.
* 0x04 - 38400.
* 0x05 - 115200.
* @arg data2 - Not used.
*/
SET_BAUDRATE_LOCAL,
/**
* @brief Start download. Command generates "General Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
START_DOWNLOAD,
/**
* @brief Query device type. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
QUERY_DEVICE_TYPE,
/**
* @brief Query diagnostic information.
* Command generates "Extended Reply" or "Super Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
QUERY_DIAGNOSTIC_INFORMATION,
/**
* @brief Version Information Macro Opcode. SW version.
* Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
VERSION_INFORMATION_MACRO_SW_VERSION,
/**
* @brief Version Information Macro Opcode. Build version.
* Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
VERSION_INFORMATION_MACRO_BUILD,
/**
* @brief Query pan offset. Command generates "Extended Reply".
* @arg data1 - not used.
* @arg data2 - Not used.
*/
EVEREST_MACRO_QUERY_PAN_OFFSET,
/**
* @brief Set zoom limit. Command generates "General Reply".
* @arg data1 - Zoom limit in hundredths: 0 - 65535.
* Example: 1600 means x16 zoom.
* @arg data2 - Not used.
*/
EVEREST_MACRO_SET_ZOOM_LIMIT,
/**
* @brief Query zoom limit. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
EVEREST_MACRO_QUERY_ZOOM_LIMIT,
/**
* @brief Query alarms. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
EVEREST_MACRO_QUERY_ALARMS,
/**
* @brief Delete pattern. Command generates "General Reply".
* @arg data1 - Pattern ID: 0x01 - 0xFF (0x00 is not checked).
* @arg data2 - Not used.
*/
EVEREST_MACRO_DELETE_PATTERN,
/**
* @brief Set pan limit. Command generates "General Reply".
* @arg data1 - Limit type: 0x00 - Manual pan left limit.
* 0x01 - Manual pan right limit.
* 0x02 - Scan pan left limit.
* 0x03 - Scan pan right limit.
* @arg data2 - Pan limit: 0 - 35999.
*/
EVEREST_MACRO_SET_PAN_LIMIT,
/**
* @brief Query manual pan right limit.
* Command generates "ExtendedReply".
* @arg data1 - Limit type: 0x00 - Manual pan left limit.
* 0x01 - Manual pan right limit.
* 0x02 - Scan pan left limit.
* 0x03 - Scan pan right limit.
* @arg data2 - Not used.
*/
EVEREST_MACRO_QUERY_PAN_LIMIT,
/**
* @brief Set Enable/Disable limits.
* Command generates "General Reply".
* @arg data1 - Limit type: 0x00 - Disable limits.
* 0x01 - Enable limits.
* @arg data2 - Not used.
*/
EVEREST_MACRO_ENABLE_LIMITS,
/**
* @brief Query defined presets.
* Command generates "Extended Reply".
* @arg data1 - Preset group: 0x00 - 0xFF. The protocol
* specification defines the groups 0x00 - 0x0F.
* @arg data2 - Not used.
*/
EVEREST_MACRO_QUERY_DEFINED_PRESETS,
/**
* @brief Query defined patterns.
* Command generates "Extended Reply".
* @arg data1 - Pattern group: 0x00 - 0xFF. The protocol
* specification defines the group 0x00 only.
* @arg data2 - Not used.
*/
EVEREST_MACRO_QUERY_DEFINED_PATTERNS,
/**
* @brief Set seconds and synchronize time.
* Command generates "General Reply".
* @arg data1 - Seconds: 0x00 - 0x3B.
* @arg data2 - Not used.
*/
TIMESET_MACRO_SET_SECONDS_AND_SYNC,
/**
* @brief Query seconds. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
TIMESET_MACRO_QUERY_SECONDS,
/**
* @brief Set hour and minute. Command generates "General Reply".
* @arg data1 - Hour: 0x00 - 0x17.
* @arg data2 - Minute: 0x00 - 0x3B.
*/
TIMESET_MACRO_SET_HOUR_AND_MINUTE,
/**
* @brief Query hour and minute.
* Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
TIMESET_MACRO_QUERY_HOUR_AND_MINUTE,
/**
* @brief Set month and day. Command generates "General Reply".
* @arg data1 - Month: 0x01 - 0x0C.
* @arg data2 - Day: 0x01 - 0x1F.
*/
TIMESET_MACRO_SET_MONTH_AND_DAY,
/**
* @brief Query month and day. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
TIMESET_MACRO_QUERY_MONTH_AND_DAY,
/**
* @brief Set year. Command generates "General Reply".
* @arg data1 - Year + 2000: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
TIMESET_MACRO_SET_YEAR,
/**
* @brief Query year. Command generates "Extended Reply".
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
TIMESET_MACRO_QUERY_YEAR,
/**
* @brief Screen move absolute. Pan/tilt positions are percentage
* of distance from center of screen to the corresponding edge.
* Command generates "General Reply".
* @arg data1 - Pan: -50 - 50. Negative values move left,
* positive right.
* @arg data2 - Tilt: -50 - 50. Negative values move down,
* positive up.
*/
SCREEN_MOVE_ABSOLUTE,
/**
* @brief Screen move relative. Pan/tilt positions are percentage
* of distance from center of screen to the corresponding edge.
* Command generates "General Reply".
* @arg data1 - Pan: -100 - 100. Negative values move left,
* positive right.
* @arg data2 - Tilt: -100 - 100. Negative values move down,
* positive up.
*/
SCREEN_MOVE_RELATIVE,
// The IDs below are returned by decodeCommand(...) only. If one of them is
// passed to getExtendedCommand(...) the method returns FALSE.
/**
* @brief "No command": a complete valid message was not received yet.
*/
NONE,
/**
* @brief Standard command. The bits of the command are returned in the
* output arguments of decodeCommand(...).
*/
GENERAL_COMMAND,
/**
* @brief Unknown command type: the message has a valid checksum but its
* command is not recognized (it can be a command of an extended command
* set of a particular device).
* @arg data1 - command field. data[2]*256 + data[3].
* @arg data2 - data field. data[4]*256 + data[5].
*/
UNKNOWN_COMMAND
};
}
PelcoDResponse enum
The response IDs are described in the PelcoDResponse enum in the PelcoDParser.h file. The definition of the enum is as follows:
namespace rapidpixel
{
/**
* @brief Pelco-D response IDs.
*
* getResponse(...) encodes all IDs except NONE and STANDARD_EXTENDED (it
* returns FALSE for them). decodeResponse(...) returns all IDs except GEN and
* STANDARD_EXTENDED. The ranges of data1 and data2 given for the IDs are the
* ranges of the protocol. getResponse(...) returns FALSE if an argument cannot
* be encoded into its field of the message (a negative value or a value above
* 0xFF or 0xFFFF) or if it is above the upper limit that the library checks
* for the response. A lower limit of a range which is not 0 is not checked.
*/
enum PelcoDResponse
{
/**
* @brief "No response": a complete valid message was not received yet.
* Returned by decodeResponse(...) only.
*/
NONE,
/**
* @brief "General Reply".
* This is a response to a command that does not have a specific response.
* Size of the message is 4 bytes: 0xFF, address, alarm code and the
* checksum (the lower 8 bits of data1 + data2). Encoded by
* getResponse(...) only: decodeResponse(...) never returns GEN.
* @arg data1 - Alarm code: bit 0 - Alarm 1, bit 1 - Alarm - 2, etc.
* @arg data2 - Checksum of the command that caused this reply.
*/
GEN,
/**
* @brief "Standard extended response": acknowledge.
* Size of the message is 7 bytes.
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
ACK,
/**
* @brief "Standard extended response": negative acknowledge.
* Size of the message is 7 bytes.
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
NAK,
/**
* @brief "Standard extended response". Reserved: it is not encoded by
* getResponse(...) and not returned by decodeResponse(...).
* @arg data1 - Not used.
* @arg data2 - Not used.
*/
STANDARD_EXTENDED,
/**
* @brief "Extended Reply" Pan position response.
* @arg data1 - Pan position: 0 - 35999.
* @arg data2 - Not used.
*/
PAN_POSITION_RESPONSE,
/**
* @brief "Extended Reply" Tilt position response.
* @arg data1 - Tilt position: 0 - 35999.
* Zero position means horizontal. Ninety degrees indicates that the device
* is pointed straight down.
* @arg data2 - Not used.
*/
TILT_POSITION_RESPONSE,
/**
* @brief "Extended Reply" Zoom position response.
* @arg data1 - Zoom position: 0 - 65535.
* @arg data2 - Not used.
*/
ZOOM_POSITION_RESPONSE,
/**
* @brief "Extended Reply" Magnification response.
* @arg data1 - Magnification value: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
MAGNIFICATION_RESPONSE,
/**
* @brief "Extended Reply" Device type response.
* @arg data1 - Device type: hard type in the high byte and soft type
* in the low byte. Value: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
DEVICE_TYPE_RESPONSE,
/**
* @brief "Extended Reply" Diagnostic information response.
* @arg data1 - Temp: 0x00 - 0xFF.
* @arg data2 - Sensor ID: 0x00 - 0xFF.
*/
DIAGNOSTIC_INFORMATION_RESPONSE,
/**
* @brief "Extended Reply" Version information response.
* @arg data1 - Version number: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
INFORMATION_MACRO_SW_VERSION_RESPONSE,
/**
* @brief "Extended Reply" Version information response.
* @arg data1 - Build number: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
INFORMATION_MACRO_BUILD_RESPONSE,
/**
* @brief "Extended Reply" Pan offset response.
* @arg data1 - Pan offset. Value: 0 - 35999.
* @arg data2 - Not used.
*/
EVEREST_MACRO_PAN_OFFSET_RESPONSE,
/**
* @brief "Extended Reply" Zoom limit response.
* @arg data1 - Zoom limit in hundredths. Value: 0 - 65535.
* Example: 1600 means x16 zoom.
* @arg data2 - Not used.
*/
EVEREST_MACRO_ZOOM_LIMIT_RESPONSE,
/**
* @brief "Extended Reply" Alarms.
* @arg data1 - Alarm bit mask: 0x00 - 0xFF.
* @arg data2 - Not used.
*/
EVEREST_MACRO_ALARMS_RESPONSE,
/**
* @brief "Extended Reply" Pan limit response.
* Limit type depends on LIMIT ID that is being responded to.
* @arg data1 - Pan limit. Value: 0 - 35999. The upper limit is not
* checked, the value is encoded as it is (0 - 65535).
* @arg data2 - Not used.
*/
EVEREST_MACRO_LIMITS_RESPONSE,
/**
* @brief "Extended Reply" Defined presets response.
* @arg data1 - BITMASK: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
EVEREST_MACRO_DEFINED_PRESETS_RESPONSE,
/**
* @brief "Extended Reply" Defined patterns response.
* @arg data1 - BITMASK: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
EVEREST_MACRO_DEFINED_PATTERNS_RESPONSE,
/**
* @brief "Extended Reply" Seconds response.
* @arg data1 - Seconds: 0x00 - 0x3C. The upper limit is not checked,
* the value is encoded as it is (0x00 - 0xFF).
* @arg data2 - Not used.
*/
TIMESET_MACRO_SECONDS_RESPONSE,
/**
* @brief "Extended Reply" Hour and minute response.
* @arg data1 - Hour: 0x00 - 0x17.
* @arg data2 - Minute: 0x00 - 0x3B.
*/
TIMESET_MACRO_HOUR_MINUTE_RESPONSE,
/**
* @brief "Extended Reply" Month and day response.
* @arg data1 - Month: 0x01 - 0x0C.
* @arg data2 - Day: 0x01 - 0x1F.
*/
TIMESET_MACRO_MONTH_DAY_RESPONSE,
/**
* @brief "Extended Reply" Year response.
* @arg data1 - Year + 2000: 0x0000 - 0xFFFF.
* @arg data2 - Not used.
*/
TIMESET_MACRO_YEAR_RESPONSE
};
}
Build and connect to your project
Build stand alone
The repository does not contain sub-repositories. The library does not depend on other repositories. The test application depends on the SerialPort library: its repository must be cloned into the same folder as PelcoDParser. The folder structure must be:
<work folder>
PelcoDParser
SerialPort
Typical commands to build the library and the test application (use the URLs of the repositories provided to you):
git clone <PelcoDParser repository URL>
git clone <SerialPort repository URL>
cd PelcoDParser
mkdir build
cd build
cmake ..
make
On Windows use cmake --build . --config Release instead of make. If PelcoDParser is the top-level CMake project, the main CMakeLists.txt file adds the folder ../SerialPort before the test application itself. If the folder does not exist CMake stops with an error. The folder is not needed if the test application is switched off (see CMake options).
CMake options
Table 4 - CMake options of the repository. In the options below ${PARENT} is the prefix defined by the top-level project (empty if PelcoDParser is the top-level project).
| Option | Default | Description |
|---|---|---|
| ${PARENT}_PELCO_D_PARSER | ON | Build the library. |
| ${PARENT}_PELCO_D_PARSER_TEST | ON (stand alone), OFF (included in other project) | Build the test application. |
| ${PARENT}_SUBMODULE_CACHE_OVERWRITE | ON | Forced rewriting of the options above in the CMake cache. The top-level project sets it to OFF when it includes PelcoDParser as a sub-repository. |
| CMAKE_BUILD_TYPE | Release (if not specified) | Build type. |
In a stand alone build ${PARENT} is empty, so the option names start with an underscore, and the options are rewritten in the CMake cache on every run. To build only the library (the SerialPort folder is not needed in this case) switch off the rewriting and the test application:
cmake -D_SUBMODULE_CACHE_OVERWRITE=OFF -D_PELCO_D_PARSER_TEST=OFF ..
Connect to your project
If you want to connect PelcoDParser library to your CMake project as source code you can make the following. The library does not have dependencies: no other repository is needed to include it into another project (the test application is not built in this case). For example, if your repository has structure:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
Create folder 3rdparty in your repository folder and copy PelcoDParser repository folder there. New structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
PelcoDParser
Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:
cmake_minimum_required(VERSION 3.13)
################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)
################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)
################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
add_subdirectory(PelcoDParser)
File 3rdparty/CMakeLists.txt adds folder PelcoDParser to your project and excludes test application from compiling (by default test application is excluded from compiling if PelcoDParser is included as sub-repository). The new structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
CMakeLists.txt
PelcoDParser
Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:
add_subdirectory(3rdparty)
Next you have to include PelcoDParser library in your src/CMakeLists.txt file:
target_link_libraries(${PROJECT_NAME} PelcoDParser)
Done!
Portability
The library does not depend on the byte order of the CPU: messages are encoded and decoded byte by byte. The library does not contain CPU specific code. The type int must have at least 32 bits (checked at compile time). The library is compiled with GCC for x86-64 and aarch64 (Linux) without warnings.
Test application
Folder PelcoDParser/test contains the test application files. The test application allows you to generate any command, send it to the camera over the serial port, receive and decode the response. The test application depends on the SerialPort library, see Build stand alone. Once started, the user must enter the serial port name (full name for Linux or just the port number for Windows), baud rate and camera address (1-255):
================================================
PelcoDParser tester v1.0.6
================================================
Set serial port name: /dev/ttyUSB0
Set baudrate: 9600
Enter the camera address (1-255): 1
After that, the user can choose command (enter command ID). IDs 1 to 9 always build a standard command from the menu below, whatever the PelcoDCommand enum assigns to those values. To reach an extended command, enter its ID from the enum: only 0 and 10 and above are passed to getExtendedCommand. The application then asks for the data1 and data2 values of that command before it sends the message:
-1 - exit
0 - sense
1 - auto scan
2 - camera on
3 - iris open/close
4 - focus near/far
5 - zoom wide/tele
6 - up/down
7 - left/right
8 - pan speed
9 - tilt speed
10 - Other commands (see PelcoDCommand enum for IDs)
The test application started with the option –self-test does not use a serial port: it checks the encoding and decoding methods with known answers, ranges of the arguments and damaged data, prints one block per test and returns 0 if all tests passed (a non-zero value otherwise):
PelcoDParserTest --self-test