Difference between revisions of "DCE Binary Communication Protocol"

From LinuxMCE
Jump to: navigation, search
(How to serialize a message)
(How to serialize a message)
Line 242: Line 242:
  
 
Example:
 
Example:
 +
  
 
Here is the pseudocode to send the "on" command to a light switch.
 
Here is the pseudocode to send the "on" command to a light switch.
 +
 
We'll assume that the your device has #id 250 and the light switch has device #id 100
 
We'll assume that the your device has #id 250 and the light switch has device #id 100
 +
 
   
 
   
 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
   
 
   
 
MyDevice.Connect(router_ip, 3450 /*port*/)
 
MyDevice.Connect(router_ip, 3450 /*port*/)
 +
 
MyDevice.SendData("EVENT 250\n")
 
MyDevice.SendData("EVENT 250\n")
 +
 
MyDevice.ReceiveData()  //until you'll get a '\n'
 
MyDevice.ReceiveData()  //until you'll get a '\n'
 +
 
                                     //you should receive: "OK 250 IP=<device_ip_address> '\n';
 
                                     //you should receive: "OK 250 IP=<device_ip_address> '\n';
 +
 
   
 
   
 
//next: creating a message
 
//next: creating a message
 +
 
//let's say MyData is an array of bytes
 
//let's say MyData is an array of bytes
 +
 
SerializeLong(MyData, 1234) //magic number
 
SerializeLong(MyData, 1234) //magic number
 +
 
SerializeLong(MyData, 250) //my id
 
SerializeLong(MyData, 250) //my id
 +
 
SerializeLong(MyData, 100) //the light switch
 
SerializeLong(MyData, 100) //the light switch
 +
 
SerializeLong(MyData, 0) //not used now
 
SerializeLong(MyData, 0) //not used now
 +
 
SerializeLong(MyData, 192) //message id of command 'on'
 
SerializeLong(MyData, 192) //message id of command 'on'
 +
 
SerializeLong(MyData, 1) //normal priority
 
SerializeLong(MyData, 1) //normal priority
 +
 
SerializeLong(MyData, 1) //message type : command
 
SerializeLong(MyData, 1) //message type : command
 +
 
SerializeLong(MyData, 0) //not used now
 
SerializeLong(MyData, 0) //not used now
 +
 
SerializeLong(MyData, 0) //not used now
 
SerializeLong(MyData, 0) //not used now
 +
 
SerializeUnsignedChar(MyData, 0) //not including children
 
SerializeUnsignedChar(MyData, 0) //not including children
 +
 
SerializeLong(MyData, 0) //broadcast level : none
 
SerializeLong(MyData, 0) //broadcast level : none
 +
 
SerializeLong(MyData, 0) //don't retry
 
SerializeLong(MyData, 0) //don't retry
 +
 
SerializeUnsignedChar(MyData, 0) //relative to sender false
 
SerializeUnsignedChar(MyData, 0) //relative to sender false
 +
 
SerializeLong(MyData, 3) //delivery confirmation
 
SerializeLong(MyData, 3) //delivery confirmation
 +
 
SerializeString(MyData, "") //device list to empty
 
SerializeString(MyData, "") //device list to empty
 +
 
SerializeUnsignedLong(MyData, 2) //2 parameters
 
SerializeUnsignedLong(MyData, 2) //2 parameters
 +
 
SerializeLong(MyData, 98) //parameter type #98
 
SerializeLong(MyData, 98) //parameter type #98
 +
 
SerializeString(MyData, "") //empty value
 
SerializeString(MyData, "") //empty value
 +
 
SerializeLong(MyData, 97) //parameter type #97
 
SerializeLong(MyData, 97) //parameter type #97
 +
 
SerializeString(MyData, "") //empty value
 
SerializeString(MyData, "") //empty value
 +
 
SerializeUnsignedLong(MyData, 0) //no binary parameters
 
SerializeUnsignedLong(MyData, 0) //no binary parameters
 +
 
SerializeUnsignedLong(MyData, 0) //no extra messages
 
SerializeUnsignedLong(MyData, 0) //no extra messages
 +
 
SerializeUnsignedLong(6789) //magic number
 
SerializeUnsignedLong(6789) //magic number
 +
 
   
 
   
 +
 
MyDevice.SendData("MESSAGE " + MyData.length() + '\n')
 
MyDevice.SendData("MESSAGE " + MyData.length() + '\n')
 +
 
MyDevice.SendData(MyData)
 
MyDevice.SendData(MyData)
 +
 
MyDevice.ReceiveData()  //until you'll get a '\n'
 
MyDevice.ReceiveData()  //until you'll get a '\n'
 +
 
                                     //you should receive: "OK" an error message
 
                                     //you should receive: "OK" an error message
 +
 
   
 
   
 
MyDevice.CloseConnection();
 
MyDevice.CloseConnection();

Revision as of 09:39, 21 May 2007

Introduction

A device can create a command connection and one or more event connections to the router.

  • The command connection is used as an incoming connection and device will use it to receive message from the router (commands).
  • An event connection is used by the device as an outgoing connection to notify the router about events or the deliver commands to other devices.

The DCERouter process is listening on 3450 port.

How to create an event connection

Here is how the handshake is made for an event connection:

>> Device sends:

EVENT <my_device_id> '\n'


<< To router will respond with :

OK <my_device_id> IP=<device_ip_address> '\n'


>> To send a message, the device will send :

MESSAGE <size_of_binary_message> '\n'

and then

<serialized_binary_message>

How to create a command connection

Here is how the handshake is made for an event connection:

>> Device sends:

COMMAND <my_device_id> '\n'


<< To router will respond with :

OK <my_device_id> IP=<device_ip_address> '\n'


>> The device will wait for messages from dcerouter; the router will send :

MESSAGE <size_of_binary_message> '\n'

and then

<serialized_binary_message>

How to serialize data

DCE uses SerializeClass to serialize/deserialize data.

The sources can be found here : src/SerializeClass/Serialize.h/cpp.

The deserialize the data, the deserializing module must know the way the data was serialized like this:

- 4 bytes, unsigned long

- 1 byte, unsigned char


Primitives:

- 8 bytes, unsigned int64

- 8 bytes, int64

- 4 bytes, unsigned long

- 4 bytes, unsigned short

- 1 byte, unsigned char

- 1 byte, char

- 1 byte, long

- 4 bytes, float

- 8 bytes, double

- 2 bytes, short


Complex types:


1. string

- 4 bytes, STR_LENGTH + 1

- STR_LENGTH bytes, the array with chars

- 1 bytes, '/0'


2. block of data

- BLOCK_LENGTH bytes, the array with bytes


3. vector of strings

- VECT_LENGTH bytes, the number of strings from vector

- string 0

- string 1

...

- string VECT_LENGTH - 1


Other complex types serialized (see SerializeClass.cpp for details) :

- map<int,string>

- map<u_int64_t,string>

- map<int,int>

- map<string,string>

- vector<int>

- vector< pair<int,int> >

- map<string, pair<int,int> >


SerializeClass also allowed you to serialize/deserialize custom objects. Examples:

- PlutoColor

- PlutoPoint

- PlutoSize

- PlutoRectangle

- PlutoDataBlock

How to serialize a message

The class used by DCE is Message class from src/DCE/Message.h/cpp unit.


This is how the raw data looks like into a binary message:


- long, value must be 1234 (magic number)

- long, <device_from_id>

- long, <device_to_id>

- long, <device_group_to_id>

- long, <message_id>

- long, <message_priority>

- long, <message_type>

- long, <device_category_to>

- long, <device_template_to>

- unsigned char, <include_children>

- long, <message_broadcast_level>

- long, <message_retry>

- unsigned char, <relative_to_sender>

- long, <expected_response>

- string, <device_list_to>

- unsigned long, <number_of_string_parameters>

  • foreach <string_parameter>
  • - long, <string_parameter_id>
  • - string, <string_parameter_value>
  • end_foreach

- unsigned long, <number_of_data_parameters>

  • foreach <data_parameter>
  • - long, <data_parameter_id>
  • - unsigned long, <data_parameter_length>
  • - array of bytes, <data_parameter_value>
  • end_foreach

- unsigned long, <number_of_extra_messages>

  • foreach <extra_message>
  • - unsigned long, <serialized_extra_message_length>
  • - array of bytes, <serialized_extra_message_value>
  • end_foreach

- unsigned long, must be 6789


Enums:

- enum eBroadcastLevel { BL_None=0, BL_DirectSiblings=1, BL_SameComputer=2, BL_SameRoom=3, BL_SameHouse=4, BL_AllHouses=5 };

- enum eRetry { MR_None=0, MR_Retry=1, MR_Persist=2 };

- enum eExpectedResponse { ER_None=0, ER_ReplyMessage, ER_ReplyString, ER_DeliveryConfirmation };

- message types: enum { MESSAGETYPE_COMMAND=1, MESSAGETYPE_EVENT=2, MESSAGETYPE_DATAPARM_CHANGE=3, MESSAGETYPE_REPLY=4, MESSAGETYPE_DATAPARM_REQUEST=5, MESSAGETYPE_LOG=6, MESSAGETYPE_SYSCOMMAND=7, MESSAGETYPE_REGISTER_INTERCEPTOR=8, MESSAGETYPE_MESSAGE_INTERCEPTED=9, MESSAGETYPE_EXEC_COMMAND_GROUP=10, MESSAGETYPE_START_PING=11, MESSAGETYPE_STOP_PING=12, MESSAGETYPE_PURGE_INTERCEPTORS=13, MESSAGETYPE_PENDING_TASKS=14 };

- message priority : enum { PRIORITY_LOW=0, PRIORITY_NORMAL=1, PRIORITY_HIGH=2, PRIORITY_URGENT=3 };



Example:


Here is the pseudocode to send the "on" command to a light switch.

We'll assume that the your device has #id 250 and the light switch has device #id 100


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

MyDevice.Connect(router_ip, 3450 /*port*/)

MyDevice.SendData("EVENT 250\n")

MyDevice.ReceiveData() //until you'll get a '\n'

                                    //you should receive: "OK 250 IP=<device_ip_address> '\n';


//next: creating a message

//let's say MyData is an array of bytes

SerializeLong(MyData, 1234) //magic number

SerializeLong(MyData, 250) //my id

SerializeLong(MyData, 100) //the light switch

SerializeLong(MyData, 0) //not used now

SerializeLong(MyData, 192) //message id of command 'on'

SerializeLong(MyData, 1) //normal priority

SerializeLong(MyData, 1) //message type : command

SerializeLong(MyData, 0) //not used now

SerializeLong(MyData, 0) //not used now

SerializeUnsignedChar(MyData, 0) //not including children

SerializeLong(MyData, 0) //broadcast level : none

SerializeLong(MyData, 0) //don't retry

SerializeUnsignedChar(MyData, 0) //relative to sender false

SerializeLong(MyData, 3) //delivery confirmation

SerializeString(MyData, "") //device list to empty

SerializeUnsignedLong(MyData, 2) //2 parameters

SerializeLong(MyData, 98) //parameter type #98

SerializeString(MyData, "") //empty value

SerializeLong(MyData, 97) //parameter type #97

SerializeString(MyData, "") //empty value

SerializeUnsignedLong(MyData, 0) //no binary parameters

SerializeUnsignedLong(MyData, 0) //no extra messages

SerializeUnsignedLong(6789) //magic number


MyDevice.SendData("MESSAGE " + MyData.length() + '\n')

MyDevice.SendData(MyData)

MyDevice.ReceiveData() //until you'll get a '\n'

                                    //you should receive: "OK" an error message


MyDevice.CloseConnection();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

How to serialize data-grids

(in work)


Complex objects:

1) DataGridCellSerializableData

- unsigned long, <sizeof(DataGridCellSerializableData)>

- unsigned long, <graphic_length>

- unsigned long, <message_length>

- unsigned long, <text_length>

- unsigned long, <value_length>

- unsigned long, <image_path_length>

- unsigned long, <number_of_attributes_length>

- unsigned long, <attributes_length>

- int, <alternate_color>

- unsigned long, <graphic_format>

- unsigned char, <selectable>

- int, <style_detail>

- int, <col_span>

- int, <row_span>

- unsigned char, <dont_fire_grid_event>


Enums:

- enum eGraphicFormat { GR_UNKNOWN=0, GR_JPG=1, GR_GIF=2, GR_TIF=3, GR_PNG=4, GR_MNG=5, GR_BMP=6, GR_OCG=7, GR_PFG=8 };



2) DataGridCell

- DataGridCellSerializableData, <datagrid_cell_serializable_data>

- array of chars, <text>

- array of chars, <value>

- array of bytes, <graphic_data>

- array of bytes, <message_data>

- array of chars, <image_path>

  • foreach <cell_attribute>
  • - array of chars ended with '\0' , <cell_attribute_name>
  • - array of chars ended with '\0', <cell_attribute_value>
  • end_foreach


3) DataGridTableSerializableData

- int, <total_number_of_columns>

- int, <total_number_of_rows>

- unsigned char, <keep_row_header>

- unsigned char, <keep_column_header>

- int, <column_count>

- int, <row_count>

- int, <starting_column>

- int, <starting_row>

- int, <cell_count>


4) DataGridTableCellIndex

- unsigned int, <column_row_type>

- unsigned int, <size>


5) DataGridTable

- unsigned long, <sizeof(DataGridTableSerializableData)>

- array of DataGridTableCellIndex, <col * row * sizeof(DataGridTableCellIndex)>

- array of DataGridCell, <col * row * serialized DataGridCell>

/*********************************************************************************/

Additional step: lzo compression/decompression

Note: can be disabled if compiled with DISABLE_LZO_DATAGRID

/*********************************************************************************/