internal override byte[] CreateActionDatagram(string destination_address, byte[] data) { lock (this.KNXConnectionTunneling.SequenceNumberLock) { try { int data_length = KNXHelper.GetDataLength(data); // HEADER byte[] dgram = new byte[10]; dgram[00] = 0x06; dgram[01] = 0x10; dgram[02] = 0x04; dgram[03] = 0x20; byte[] total_length = BitConverter.GetBytes(data_length + 20); dgram[04] = total_length[1]; dgram[05] = total_length[0]; dgram[06] = 0x04; dgram[07] = this.KNXConnectionTunneling.ChannelId; dgram[08] = this.KNXConnectionTunneling.GenerateSequenceNumber(); dgram[09] = 0x00; return(base.CreateActionDatagramCommon(destination_address, data, dgram)); } catch (Exception) { this.KNXConnectionTunneling.RevertSingleSequenceNumber(); return(null); } } }
protected byte[] CreateRequestStatusDatagramCommon(string destination_address, byte[] dgram, int cemi_start_pos) { int i = 0; if (this._connection.ActionMessageCode != 0x00) { dgram[cemi_start_pos + i++] = this._connection.ActionMessageCode; } else { dgram[cemi_start_pos + i++] = 0x11; } dgram[cemi_start_pos + i++] = 0x00; dgram[cemi_start_pos + i++] = 0xAC; if (KNXHelper.IsAddressIndividual(destination_address)) { dgram[cemi_start_pos + i++] = 0x50; } else { dgram[cemi_start_pos + i++] = 0xF0; } dgram[cemi_start_pos + i++] = 0x00; dgram[cemi_start_pos + i++] = 0x00; byte[] dst_address = KNXHelper.GetAddress(destination_address); dgram[cemi_start_pos + i++] = dst_address[0]; dgram[cemi_start_pos + i++] = dst_address[1]; dgram[cemi_start_pos + i++] = 0x01; dgram[cemi_start_pos + i++] = 0x00; dgram[cemi_start_pos + i] = 0x00; return(dgram); }
internal override byte[] CreateActionDatagram(string destination_address, byte[] data) { int data_length = KNXHelper.GetDataLength(data); // HEADER byte[] dgram = new byte[6]; dgram[0] = 0x06; dgram[1] = 0x10; dgram[2] = 0x05; dgram[3] = 0x30; byte[] total_length = BitConverter.GetBytes(data_length + 16); dgram[4] = total_length[1]; dgram[5] = total_length[0]; return(base.CreateActionDatagramCommon(destination_address, data, dgram)); }
internal override void ProcessDatagram(byte[] dgram) { try { switch (KNXHelper.GetServiceType(dgram)) { case KNXHelper.SERVICE_TYPE.CONNECT_RESPONSE: ProcessConnectResponse(dgram); break; case KNXHelper.SERVICE_TYPE.CONNECTIONSTATE_RESPONSE: ProcessConnectionStateResponse(dgram); break; case KNXHelper.SERVICE_TYPE.TUNNELLING_ACK: ProcessTunnelingAck(dgram); break; case KNXHelper.SERVICE_TYPE.DISCONNECT_REQUEST: ProcessDisconnectRequest(dgram); break; case KNXHelper.SERVICE_TYPE.TUNNELLING_REQUEST: ProcessDatagramHeaders(dgram); break; } } catch (Exception e) { Console.Write(e.Message); Console.Write(e.ToString()); Console.Write(e.StackTrace); if (e.InnerException != null) { Console.Write(e.InnerException.Message); Console.Write(e.ToString()); Console.Write(e.InnerException.StackTrace); } // ignore, missing warning information } }
internal void ProcessCEMI(KNXDatagram datagram, byte[] cemi) { try { // CEMI // +--------+--------+--------+--------+----------------+----------------+--------+----------------+ // | Msg |Add.Info| Ctrl 1 | Ctrl 2 | Source Address | Dest. Address | Data | APDU | // | Code | Length | | | | | Length | | // +--------+--------+--------+--------+----------------+----------------+--------+----------------+ // 1 byte 1 byte 1 byte 1 byte 2 bytes 2 bytes 1 byte 2 bytes // // Message Code = 0x11 - a L_Data.req primitive // COMMON EMI MESSAGE CODES FOR DATA LINK LAYER PRIMITIVES // FROM NETWORK LAYER TO DATA LINK LAYER // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | Data Link Layer Primitive | Message Code | Data Link Layer Service | Service Description | Common EMI Frame | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | L_Raw.req | 0x10 | | | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | | | | Primitive used for | Sample Common | // | L_Data.req | 0x11 | Data Service | transmitting a data | EMI frame | // | | | | frame | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | L_Poll_Data.req | 0x13 | Poll Data Service | | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | L_Raw.req | 0x10 | | | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // FROM DATA LINK LAYER TO NETWORK LAYER // +---------------------------+--------------+-------------------------+---------------------+ // | Data Link Layer Primitive | Message Code | Data Link Layer Service | Service Description | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Poll_Data.con | 0x25 | Poll Data Service | | // +---------------------------+--------------+-------------------------+---------------------+ // | | | | Primitive used for | // | L_Data.ind | 0x29 | Data Service | receiving a data | // | | | | frame | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Busmon.ind | 0x2B | Bus Monitor Service | | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Raw.ind | 0x2D | | | // +---------------------------+--------------+-------------------------+---------------------+ // | | | | Primitive used for | // | | | | local confirmation | // | L_Data.con | 0x2E | Data Service | that a frame was | // | | | | sent (does not mean | // | | | | successful receive) | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Raw.con | 0x2F | | | // +---------------------------+--------------+-------------------------+---------------------+ // Add.Info Length = 0x00 - no additional info // Control Field 1 = see the bit structure above // Control Field 2 = see the bit structure above // Source Address = 0x0000 - filled in by router/gateway with its source address which is // part of the KNX subnet // Dest. Address = KNX group or individual address (2 byte) // Data Length = Number of bytes of data in the APDU excluding the TPCI/APCI bits // APDU = Application Protocol Data Unit - the actual payload including transport // protocol control information (TPCI), application protocol control // information (APCI) and data passed as an argument from higher layers of // the KNX communication stack // datagram.message_code = cemi[0]; datagram.aditional_info_length = (int)cemi[1]; if (datagram.aditional_info_length > 0) { datagram.aditional_info = new byte[datagram.aditional_info_length]; for (int i = 0; i < datagram.aditional_info_length; i++) { datagram.aditional_info[i] = cemi[2 + i]; } } datagram.control_field_1 = cemi[2 + datagram.aditional_info_length]; datagram.control_field_2 = cemi[3 + datagram.aditional_info_length]; datagram.source_address = KNXHelper.GetIndividualAddress(new byte[] { cemi[4 + datagram.aditional_info_length], cemi[5 + datagram.aditional_info_length] }); if (KNXHelper.GetKNXDestinationAddressType(datagram.control_field_2).Equals(KNXHelper.KNXDestinationAddressType.INDIVIDUAL)) { datagram.destination_address = KNXHelper.GetIndividualAddress(new byte[] { cemi[6 + datagram.aditional_info_length], cemi[7 + datagram.aditional_info_length] }); } else { datagram.destination_address = KNXHelper.GetGroupAddress(new byte[] { cemi[6 + datagram.aditional_info_length], cemi[7 + datagram.aditional_info_length] }, KNXConnection.ThreeLevelGroupAddressing); } datagram.data_length = (int)cemi[8 + datagram.aditional_info_length]; datagram.apdu = new byte[datagram.data_length + 1]; for (int i = 0; i < datagram.apdu.Length; i++) { datagram.apdu[i] = cemi[9 + i + datagram.aditional_info_length]; } datagram.data = KNXHelper.GetRawData(datagram.data_length, datagram.apdu); if (KNXConnection.Debug) { Console.WriteLine("-----------------------------------------------------------------------------------------------------"); Console.WriteLine(BitConverter.ToString(cemi)); Console.WriteLine("Event Header Length: " + datagram.header_length); Console.WriteLine("Event Protocol Version: " + datagram.protocol_version.ToString("x")); Console.WriteLine("Event Service Type: 0x" + BitConverter.ToString(datagram.service_type).Replace("-", string.Empty)); Console.WriteLine("Event Total Length: " + datagram.total_length); Console.WriteLine("Event Message Code: " + datagram.message_code.ToString("x")); Console.WriteLine("Event Aditional Info Length: " + datagram.aditional_info_length); if (datagram.aditional_info_length > 0) { Console.WriteLine("Event Aditional Info: 0x" + BitConverter.ToString(datagram.aditional_info).Replace("-", string.Empty)); } Console.WriteLine("Event Control Field 1: " + Convert.ToString(datagram.control_field_1, 2)); Console.WriteLine("Event Control Field 2: " + Convert.ToString(datagram.control_field_2, 2)); Console.WriteLine("Event Source Address: " + datagram.source_address); Console.WriteLine("Event Destination Address: " + datagram.destination_address); Console.WriteLine("Event Data Length: " + datagram.data_length); Console.WriteLine("Event APDU: 0x" + BitConverter.ToString(datagram.apdu).Replace("-", string.Empty)); Console.WriteLine("Event Data: " + datagram.data); Console.WriteLine("-----------------------------------------------------------------------------------------------------"); } if (datagram.message_code == 0x29) { int type = ((int)datagram.apdu[1]) >> 4; if (type == 8) { this.KNXConnection.Event(datagram.source_address, datagram.destination_address, datagram.data); } else if (type == 4 || type == 0) { this.KNXConnection.Status(datagram.source_address, datagram.destination_address, datagram.data); } } } catch (Exception) { // ignore, missing warning information } }
protected byte[] CreateActionDatagramCommon(string destination_address, byte[] data, byte[] header) { int i = 0; int data_length = KNXHelper.GetDataLength(data); // HEADER byte[] dgram = new byte[data_length + 10 + header.Length]; for (i = 0; i < header.Length; i++) { dgram[i] = header[i]; } // CEMI (start at position 6) // +--------+--------+--------+--------+----------------+----------------+--------+----------------+ // | Msg |Add.Info| Ctrl 1 | Ctrl 2 | Source Address | Dest. Address | Data | APDU | // | Code | Length | | | | | Length | | // +--------+--------+--------+--------+----------------+----------------+--------+----------------+ // 1 byte 1 byte 1 byte 1 byte 2 bytes 2 bytes 1 byte 2 bytes // // Message Code = 0x11 - a L_Data.req primitive // COMMON EMI MESSAGE CODES FOR DATA LINK LAYER PRIMITIVES // FROM NETWORK LAYER TO DATA LINK LAYER // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | Data Link Layer Primitive | Message Code | Data Link Layer Service | Service Description | Common EMI Frame | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | L_Raw.req | 0x10 | | | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | | | | Primitive used for | Sample Common | // | L_Data.req | 0x11 | Data Service | transmitting a data | EMI frame | // | | | | frame | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | L_Poll_Data.req | 0x13 | Poll Data Service | | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // | L_Raw.req | 0x10 | | | | // +---------------------------+--------------+-------------------------+---------------------+------------------+ // FROM DATA LINK LAYER TO NETWORK LAYER // +---------------------------+--------------+-------------------------+---------------------+ // | Data Link Layer Primitive | Message Code | Data Link Layer Service | Service Description | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Poll_Data.con | 0x25 | Poll Data Service | | // +---------------------------+--------------+-------------------------+---------------------+ // | | | | Primitive used for | // | L_Data.ind | 0x29 | Data Service | receiving a data | // | | | | frame | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Busmon.ind | 0x2B | Bus Monitor Service | | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Raw.ind | 0x2D | | | // +---------------------------+--------------+-------------------------+---------------------+ // | | | | Primitive used for | // | | | | local confirmation | // | L_Data.con | 0x2E | Data Service | that a frame was | // | | | | sent (does not mean | // | | | | successful receive) | // +---------------------------+--------------+-------------------------+---------------------+ // | L_Raw.con | 0x2F | | | // +---------------------------+--------------+-------------------------+---------------------+ // Add.Info Length = 0x00 - no additional info // Control Field 1 = see the bit structure above // Control Field 2 = see the bit structure above // Source Address = 0x0000 - filled in by router/gateway with its source address which is // part of the KNX subnet // Dest. Address = KNX group or individual address (2 byte) // Data Length = Number of bytes of data in the APDU excluding the TPCI/APCI bits // APDU = Application Protocol Data Unit - the actual payload including transport // protocol control information (TPCI), application protocol control // information (APCI) and data passed as an argument from higher layers of // the KNX communication stack // if (this._connection.ActionMessageCode != 0x00) { dgram[i++] = this._connection.ActionMessageCode; } else { dgram[i++] = 0x11; } dgram[i++] = 0x00; dgram[i++] = 0xAC; if (KNXHelper.IsAddressIndividual(destination_address)) { dgram[i++] = 0x50; } else { dgram[i++] = 0xF0; } dgram[i++] = 0x00; dgram[i++] = 0x00; byte[] dst_address = KNXHelper.GetAddress(destination_address); dgram[i++] = dst_address[0]; dgram[i++] = dst_address[1]; dgram[i++] = (byte)(data_length); dgram[i++] = 0x00; dgram[i] = 0x80; KNXHelper.WriteData(dgram, data, i); return(dgram); }