internal static bool 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.MessageCode = cemi[0]; datagram.AditionalInfoLength = cemi[1]; if (datagram.AditionalInfoLength > 0) { datagram.AditionalInfo = new byte[datagram.AditionalInfoLength]; for (var i = 0; i < datagram.AditionalInfoLength; i++) { datagram.AditionalInfo[i] = cemi[2 + i]; } } datagram.ControlField1 = cemi[2 + datagram.AditionalInfoLength]; datagram.ControlField2 = cemi[3 + datagram.AditionalInfoLength]; datagram.SourceAddress = GetIndividualAddress(new[] { cemi[4 + datagram.AditionalInfoLength], cemi[5 + datagram.AditionalInfoLength] }); datagram.DestinationAddress = GetKnxDestinationAddressType(datagram.ControlField2).Equals(KnxDestinationAddressType.Individual) ? GetIndividualAddress(new[] { cemi[6 + datagram.AditionalInfoLength], cemi[7 + datagram.AditionalInfoLength] }) : GetGroupAddress(new[] { cemi[6 + datagram.AditionalInfoLength], cemi[7 + datagram.AditionalInfoLength] }, true); datagram.DataLength = cemi[8 + datagram.AditionalInfoLength]; datagram.Apdu = new byte[datagram.DataLength + 1]; for (var i = 0; i < datagram.Apdu.Length; i++) { datagram.Apdu[i] = cemi[9 + i + datagram.AditionalInfoLength]; } datagram.Data = new byte[datagram.Apdu.Length - 2]; Array.Copy(datagram.Apdu, 2, datagram.Data, 0, datagram.Apdu.Length - 2); if (datagram.Data.Length == 0) { datagram.Data = new byte[1]; datagram.Data[0] = (byte)(datagram.Apdu[1] & 0x01); } if (datagram.MessageCode != 0x29) { return(false); } var type = datagram.Apdu[1] >> 4; return(true); } catch (Exception e) { Logger.LogError(e, "Unkown error occured"); } return(false); }
public KnxDatgramEventArgs(KnxDatagram datagram) { Datagram = datagram; }