Thursday, March 8, 2012

Pelco P and D protocol implementation in C#

PTZ camera have many type of protocol such as Samsumg-T, Pelco-P, Pelco-D, Bosch, Honeywell, Vicon, Ad, Samsung-E, Panasonic to supports commands. This is a full C# classes to control a PTZ cameras via RS422/485 Pelco 'P' and 'D' protocol.

Pelco-P
/*-------------------------------------------------------------------------------
* Author: Tamir Khason, 2004
* Email: tamir@khason.biz
* Web: http://www.dotnet.us/
*
* Freeware: Please do not remove this header
*
* File: P.cs
*
* Description: PELCO P Protocol Implementation dot.NET Way
* This is GPL software. Do with it as you want, but feed us back any improvements.
*
* This is a simple class to control a PELCO PTZ camera via RS422/485
* 'P' protocol. It supports all of the commands including UP, DOWN, IN, OUT, LEFT,
* RIGHT, NEAR, FAR, as well as all other extended commands.
*
* To use this, you need to put a RS232->RS422 adapter on the output
* of your desired serial port.
*
* The Pelco doesn't return ANY usefull info back, so you only really need 2-wire support
* (one way) communications out.
*
*
* Version: 1.4
* ------------------------------------------------------------------------------*/
using System;
using System.Collections;

//namespace Pelco
//{
///
/// dot.NET Implementation of Pelco P Protocol
///

public class P //: Pelco
{
private const byte STX = 0xA0;
private const byte ETX = 0xAF;

#region Pan and Tilt Commands
#region Data1
private const byte FocusFar = 0x01;
private const byte FocusNear = 0x02;
private const byte IrisOpen = 0x04;
private const byte IrisClose = 0x08;
private const byte CameraOnOff = 0x10;
private const byte AutoscanOn = 0x20;
private const byte CameraOn = 0x40;
#endregion

#region Data2
private const byte PanRight = 0x02;
private const byte PanLeft = 0x04;
private const byte TiltUp = 0x08;
private const byte TiltDown = 0x10;
private const byte ZoomTele = 0x20;
private const byte ZoomWide = 0x40;
#endregion

#region Data3
private const byte PanSpeedMin = 0x00;
private const byte PanSpeedMax = 0x40;
#endregion

#region Data4
private const byte TiltSpeedMin = 0x00;
private const byte TiltSpeedMax = 0x3F;
#endregion
#endregion

#region Enums
public enum PresetAction {Set,Clear,Goto}
public enum PatternAction {Start,Stop,Run}
public enum Action {Start,Stop}
public enum LensSpeed {Low=0x00,Medium=0x01,High=0x02,Turbo=0x03}
public enum Pan {Left = PanLeft,Right = PanRight}
public enum Tilt {Up = TiltUp,Down = TiltDown}
public enum Iris {Open = IrisOpen,Close = IrisClose}
public enum Zoom {Wide = ZoomWide,Tele = ZoomTele}
public enum Switch {On,Off}
public enum Focus {Near = FocusNear,Far = FocusFar}
#endregion

#region Extended Command Set
public byte[] Preset(uint deviceAddress, byte preset, PresetAction action)
{
byte m_action;
switch (action)
{
case PresetAction.Set:
m_action = 0x03;
break;
case PresetAction.Clear:
m_action = 0x05;
break;
case PresetAction.Goto:
m_action = 0x07;
break;
default:
m_action = 0x03;
break;
}
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,preset);
}

public byte[] Flip(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x07,0x00,0x21);
}

public byte[] ZeroPanPosition(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x07,0x00,0x22);
}

public byte[] AutoScan(uint deviceAddress, Action action)
{
byte m_action;
if(action == Action.Start)
m_action = 0x09;
else
m_action = 0x0B;
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,0x00);
}

public byte[] RemoteReset(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x0F,0x00,0x00);
}

public byte[] Zone(uint deviceAddress,byte zone, Action action)
{
if(zone<0x01 & zone>0x08)
throw new Exception("Zone value should be between 0x01 and 0x08 include");
byte m_action;
if(action == Action.Start)
m_action = 0x11;
else
m_action = 0x13;

return Message.GetMessage(deviceAddress,0x00,m_action,0x00,zone);
}



public byte[] WriteToScreen(uint deviceAddress,string text)
{
if(text.Length > 40)
text = text.Remove(40,text.Length-40);
System.Text.Encoding encoding = System.Text.Encoding.ASCII;
byte[] m_bytes = new byte[encoding.GetByteCount(text)*8];
int i = 0;
byte m_scrPosition;
byte m_ASCIIchr;

foreach(char ch in text)
{
m_scrPosition = Convert.ToByte(i/8);
m_ASCIIchr = Convert.ToByte(ch);
Array.Copy(Message.GetMessage(deviceAddress,0x00,0x15,m_scrPosition,m_ASCIIchr),0,m_bytes,i,8);
i = i + 8;
}

return m_bytes;
}

public byte[] ClearScreen(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x17,0x00,0x00);
}

public byte[] AlarmAcknowledge(uint deviceAddress, uint alarmID)
{
if(alarmID < 1 & alarmID>8)
throw new Exception("Only 8 alarms allowed for Pelco P implementation");
return Message.GetMessage(deviceAddress,0x00,0x19,0x00,Convert.ToByte(alarmID));
}

public byte[] ZoneScan(uint deviceAddress,Action action)
{
byte m_action;
if(action == Action.Start)
m_action = 0x1B;
else
m_action = 0x1D;
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,0x00);
}

public byte[] Pattern(uint deviceAddress,PatternAction action)
{
byte m_action;
switch (action)
{
case PatternAction.Start:
m_action = 0x1F;
break;
case PatternAction.Stop:
m_action = 0x21;
break;
case PatternAction.Run:
m_action = 0x23;
break;
default:
m_action = 0x23;
break;
}
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,0x00);
}

public byte[] SetZoomLensSpeed(uint deviceAddress, LensSpeed speed)
{
return Message.GetMessage(deviceAddress,0x00,0x25,0x00,(byte)speed);
}

public byte[] SetFocusLensSpeed(uint deviceAddress, LensSpeed speed)
{
return Message.GetMessage(deviceAddress,0x00,0x27,0x00,(byte)speed);
}

#endregion

#region Base Command Set

public byte[] CameraSwitch(uint deviceAddress,Switch action)
{
byte m_action = CameraOnOff;
if(action == Switch.On)
m_action += CameraOnOff; //Maybe wrong !!!
return Message.GetMessage(deviceAddress,m_action,0x00,0x00,0x00);

}

public byte[] CameraIrisSwitch(uint deviceAddress,Iris action)
{
return Message.GetMessage(deviceAddress,(byte)action,0x00,0x00,0x00);
}

public byte[] CameraFocus(uint deviceAddress,Focus action)
{
return Message.GetMessage(deviceAddress,(byte)action,0x00,0x00,0x00);
}

public byte[] CameraZoom(uint deviceAddress,Zoom action)
{
return Message.GetMessage(deviceAddress,0x00,(byte)action,0x00,0x00);
}

public byte[] CameraTilt(uint deviceAddress,Tilt action, uint speed)
{
if(speed32)
throw new Exception("Protocol Pelco P support 32 devices only");

Address = Byte.Parse((address-1).ToString());
Data1 = data1;
Data2 = data2;
Data3 = data3;
Data4 = data4;

CheckSum = (byte)(STX ^ Address ^ Data1 ^ Data2 ^ Data3 ^ Data4 ^ ETX);

return new byte[]{STX,Address,Data1,Data2,Data3,Data4,ETX,CheckSum};
}

}
}


//}











Pelco-D (I did some update from author source code for bugs)
/*-------------------------------------------------------------------------------
* Author: Tamir Khason, 2004
* Email: tamir@khason.biz
* Web: http://www.dotnet.us/
*
* Freeware: Please do not remove this header
*
* File: P.cs
*
* Description: PELCO P Protocol Implementation dot.NET Way
* This is GPL software. Do with it as you want, but feed us back any improvements.
*
* This is a simple class to control a PELCO PTZ camera via RS422/485
* 'P' protocol. It supports all of the commands including UP, DOWN, IN, OUT, LEFT,
* RIGHT, NEAR, FAR, as well as all other extended commands.
*
* To use this, you need to put a RS232->RS422 adapter on the output
* of your desired serial port.
*
* The Pelco doesn't return ANY usefull info back, so you only really need 2-wire support
* (one way) communications out.
*
*
* Version: 1.4
* ------------------------------------------------------------------------------*/
using System;
using System.Collections;

//namespace Pelco
//{
///
/// dot.NET Implementation of Pelco P Protocol
///

public class P //: Pelco
{
private const byte STX = 0xA0;
private const byte ETX = 0xAF;

#region Pan and Tilt Commands
#region Data1
private const byte FocusFar = 0x01;
private const byte FocusNear = 0x02;
private const byte IrisOpen = 0x04;
private const byte IrisClose = 0x08;
private const byte CameraOnOff = 0x10;
private const byte AutoscanOn = 0x20;
private const byte CameraOn = 0x40;
#endregion

#region Data2
private const byte PanRight = 0x02;
private const byte PanLeft = 0x04;
private const byte TiltUp = 0x08;
private const byte TiltDown = 0x10;
private const byte ZoomTele = 0x20;
private const byte ZoomWide = 0x40;
#endregion

#region Data3
private const byte PanSpeedMin = 0x00;
private const byte PanSpeedMax = 0x40;
#endregion

#region Data4
private const byte TiltSpeedMin = 0x00;
private const byte TiltSpeedMax = 0x3F;
#endregion
#endregion

#region Enums
public enum PresetAction {Set,Clear,Goto}
public enum PatternAction {Start,Stop,Run}
public enum Action {Start,Stop}
public enum LensSpeed {Low=0x00,Medium=0x01,High=0x02,Turbo=0x03}
public enum Pan {Left = PanLeft,Right = PanRight}
public enum Tilt {Up = TiltUp,Down = TiltDown}
public enum Iris {Open = IrisOpen,Close = IrisClose}
public enum Zoom {Wide = ZoomWide,Tele = ZoomTele}
public enum Switch {On,Off}
public enum Focus {Near = FocusNear,Far = FocusFar}
#endregion

#region Extended Command Set
public byte[] Preset(uint deviceAddress, byte preset, PresetAction action)
{
byte m_action;
switch (action)
{
case PresetAction.Set:
m_action = 0x03;
break;
case PresetAction.Clear:
m_action = 0x05;
break;
case PresetAction.Goto:
m_action = 0x07;
break;
default:
m_action = 0x03;
break;
}
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,preset);
}

public byte[] Flip(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x07,0x00,0x21);
}

public byte[] ZeroPanPosition(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x07,0x00,0x22);
}

public byte[] AutoScan(uint deviceAddress, Action action)
{
byte m_action;
if(action == Action.Start)
m_action = 0x09;
else
m_action = 0x0B;
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,0x00);
}

public byte[] RemoteReset(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x0F,0x00,0x00);
}

public byte[] Zone(uint deviceAddress,byte zone, Action action)
{
if(zone<0x01 & zone>0x08)
throw new Exception("Zone value should be between 0x01 and 0x08 include");
byte m_action;
if(action == Action.Start)
m_action = 0x11;
else
m_action = 0x13;

return Message.GetMessage(deviceAddress,0x00,m_action,0x00,zone);
}



public byte[] WriteToScreen(uint deviceAddress,string text)
{
if(text.Length > 40)
text = text.Remove(40,text.Length-40);
System.Text.Encoding encoding = System.Text.Encoding.ASCII;
byte[] m_bytes = new byte[encoding.GetByteCount(text)*8];
int i = 0;
byte m_scrPosition;
byte m_ASCIIchr;

foreach(char ch in text)
{
m_scrPosition = Convert.ToByte(i/8);
m_ASCIIchr = Convert.ToByte(ch);
Array.Copy(Message.GetMessage(deviceAddress,0x00,0x15,m_scrPosition,m_ASCIIchr),0,m_bytes,i,8);
i = i + 8;
}

return m_bytes;
}

public byte[] ClearScreen(uint deviceAddress)
{
return Message.GetMessage(deviceAddress,0x00,0x17,0x00,0x00);
}

public byte[] AlarmAcknowledge(uint deviceAddress, uint alarmID)
{
if(alarmID < 1 & alarmID>8)
throw new Exception("Only 8 alarms allowed for Pelco P implementation");
return Message.GetMessage(deviceAddress,0x00,0x19,0x00,Convert.ToByte(alarmID));
}

public byte[] ZoneScan(uint deviceAddress,Action action)
{
byte m_action;
if(action == Action.Start)
m_action = 0x1B;
else
m_action = 0x1D;
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,0x00);
}

public byte[] Pattern(uint deviceAddress,PatternAction action)
{
byte m_action;
switch (action)
{
case PatternAction.Start:
m_action = 0x1F;
break;
case PatternAction.Stop:
m_action = 0x21;
break;
case PatternAction.Run:
m_action = 0x23;
break;
default:
m_action = 0x23;
break;
}
return Message.GetMessage(deviceAddress,0x00,m_action,0x00,0x00);
}

public byte[] SetZoomLensSpeed(uint deviceAddress, LensSpeed speed)
{
return Message.GetMessage(deviceAddress,0x00,0x25,0x00,(byte)speed);
}

public byte[] SetFocusLensSpeed(uint deviceAddress, LensSpeed speed)
{
return Message.GetMessage(deviceAddress,0x00,0x27,0x00,(byte)speed);
}

#endregion

#region Base Command Set

public byte[] CameraSwitch(uint deviceAddress,Switch action)
{
byte m_action = CameraOnOff;
if(action == Switch.On)
m_action += CameraOnOff; //Maybe wrong !!!
return Message.GetMessage(deviceAddress,m_action,0x00,0x00,0x00);

}

public byte[] CameraIrisSwitch(uint deviceAddress,Iris action)
{
return Message.GetMessage(deviceAddress,(byte)action,0x00,0x00,0x00);
}

public byte[] CameraFocus(uint deviceAddress,Focus action)
{
return Message.GetMessage(deviceAddress,(byte)action,0x00,0x00,0x00);
}

public byte[] CameraZoom(uint deviceAddress,Zoom action)
{
return Message.GetMessage(deviceAddress,0x00,(byte)action,0x00,0x00);
}

public byte[] CameraTilt(uint deviceAddress,Tilt action, uint speed)
{
if(speed32)
throw new Exception("Protocol Pelco P support 32 devices only");

Address = Byte.Parse((address-1).ToString());
Data1 = data1;
Data2 = data2;
Data3 = data3;
Data4 = data4;

CheckSum = (byte)(STX ^ Address ^ Data1 ^ Data2 ^ Data3 ^ Data4 ^ ETX);

return new byte[]{STX,Address,Data1,Data2,Data3,Data4,ETX,CheckSum};
}

}
}


//}