protected byte[] CreateRequestStatusDatagramCommon(string destinationAddress, byte[] datagram, int cemi_start_pos) { var i = 0; datagram[cemi_start_pos + i++] = ActionMessageCode != 0x00 ? ActionMessageCode : (byte)0x11; datagram[cemi_start_pos + i++] = 0x00; datagram[cemi_start_pos + i++] = 0xAC; datagram[cemi_start_pos + i++] = KnxHelper.IsAddressIndividual(destinationAddress) ? (byte)0x50 : (byte)0xF0; datagram[cemi_start_pos + i++] = myAddress[0]; datagram[cemi_start_pos + i++] = myAddress[1]; byte[] dst_address = KnxHelper.GetAddress(destinationAddress); datagram[cemi_start_pos + i++] = dst_address[0]; datagram[cemi_start_pos + i++] = dst_address[1]; datagram[cemi_start_pos + i++] = 0x01; datagram[cemi_start_pos + i++] = 0x00; datagram[cemi_start_pos + i] = 0x00; return(datagram); }
protected byte[] CreateActionDatagram(string destinationAddress, bool b_bit, byte[] data) { try { var dataLength = KnxHelper.GetDataLength(b_bit, data); // HEADER var datagram = new byte[10]; datagram[00] = 0x06; datagram[01] = 0x10; datagram[02] = 0x04; datagram[03] = 0x20; var totalLength = BitConverter.GetBytes(dataLength + 20); datagram[04] = totalLength[1]; datagram[05] = totalLength[0]; datagram[06] = 0x04; datagram[07] = ChannelId; datagram[08] = IncrementSequenceNumber(); datagram[09] = 0x00; return(CreateActionDatagramCommon(destinationAddress, b_bit, data, datagram)); } catch { DecrementSingleSequenceNumber(); return(null); } }
private void ProcessDatagram(byte[] datagram) { try { switch (KnxHelper.GetServiceType(datagram)) { case KnxHelper.SERVICE_TYPE.CONNECT_RESPONSE: ProcessConnectResponse(datagram); break; case KnxHelper.SERVICE_TYPE.CONNECTIONSTATE_RESPONSE: ProcessConnectionStateResponse(datagram); break; case KnxHelper.SERVICE_TYPE.DISCONNECT_REQUEST: ProcessDisconnectRequest(datagram); break; case KnxHelper.SERVICE_TYPE.TUNNELLING_REQUEST: ProcessDatagramHeaders(datagram); break; } } catch (Exception e) { Logger.Log("ProcessDatagram: Exception ({0})", e.Message); ErrorLog.Exception("ProcessDatagram:", e); } }
public int Connect(String address, int target_port, int src_port, string myAddress) { Logger.Log("Connect({0},{1},{2},{3})", address, target_port, src_port, myAddress); if (client != null) { if (client.ServerStatus == SocketStatus.SOCKET_STATUS_CONNECTED) { DisconnectRequest(); client.DisableUDPServer(); client = null; } } SocketErrorCodes error = SocketErrorCodes.SOCKET_INVALID_STATE; try { this.myAddress = KnxHelper.GetAddress(myAddress); remoteEndpoint = get_IPEndpoint(address, target_port); if (src_port <= 0) { src_port = target_port; } localEndpoint = get_IPEndpoint(getLocalIP(), src_port); client = new UDPServer(remoteEndpoint, src_port, buffersz, EthernetAdapterType.EthernetLANAdapter); InitialParametersClass.ReadInInitialParameters(1); error = client.EnableUDPServer(); if (error == SocketErrorCodes.SOCKET_OK) { // start recieveing //error = client.ReceiveDataAsync(udpReceiver); //if (error == SocketErrorCodes.SOCKET_OPERATION_PENDING) //{ error = ConnectRequest(); if (error != SocketErrorCodes.SOCKET_OK) { client.DisableUDPServer(); client = null; } else { udpReadTimer.Reset(); stateRequestTimer.Reset(stateRequestTimerInterval); } } } catch (System.Exception e) { Logger.Log("Connect: Exception ({0})", e.Message); return(-1); } Logger.Log("Connect: ({0})", error); return(Convert.ToInt32(error)); }
protected byte[] CreateActionDatagramCommon(string destinationAddress, bool b_bit, byte[] data, byte[] header) { int i; var dataLength = KnxHelper.GetDataLength(b_bit, data); // HEADER var datagram = new byte[dataLength + 10 + header.Length]; for (i = 0; i < header.Length; i++) { datagram[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 // datagram[i++] = ActionMessageCode != 0x00 ? ActionMessageCode : (byte)0x11; datagram[i++] = 0x00; datagram[i++] = 0xAC; datagram[i++] = KnxHelper.IsAddressIndividual(destinationAddress) ? (byte)0x50 : (byte)0xF0; datagram[i++] = myAddress[0]; // Source address datagram[i++] = myAddress[1]; var dst_address = KnxHelper.GetAddress(destinationAddress); datagram[i++] = dst_address[0]; datagram[i++] = dst_address[1]; datagram[i++] = (byte)dataLength; datagram[i++] = 0x00; datagram[i] = 0x80; KnxHelper.WriteData(datagram, b_bit, data, i); return(datagram); }
protected 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 = cemi[1]; if (datagram.aditional_info_length > 0) { datagram.aditional_info = new byte[datagram.aditional_info_length]; for (var 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[] { cemi[4 + datagram.aditional_info_length], cemi[5 + datagram.aditional_info_length] }); datagram.destination_address = KnxHelper.GetKnxDestinationAddressType(datagram.control_field_2).Equals(KnxHelper.KnxDestinationAddressType.INDIVIDUAL) ? KnxHelper.GetIndividualAddress(new[] { cemi[6 + datagram.aditional_info_length], cemi[7 + datagram.aditional_info_length] }) : KnxHelper.GetGroupAddress(new[] { cemi[6 + datagram.aditional_info_length], cemi[7 + datagram.aditional_info_length] }, true); datagram.data_length = cemi[8 + datagram.aditional_info_length]; datagram.apdu = new byte[datagram.data_length + 1]; for (var i = 0; i < datagram.apdu.Length; i++) { datagram.apdu[i] = cemi[9 + i + datagram.aditional_info_length]; } datagram.data = KnxHelper.GetData(datagram.data_length, datagram.apdu); Logger.Log("-----------------------------------------------------------------------------------------------------"); Logger.Log(BitConverter.ToString(cemi)); Logger.Log("Event Header Length: " + datagram.header_length); Logger.Log("Event Protocol Version: " + datagram.protocol_version.ToString("x")); Logger.Log("Event Service Type: 0x" + BitConverter.ToString(datagram.service_type).Replace("-", string.Empty)); Logger.Log("Event Total Length: " + datagram.total_length); Logger.Log("Event Message Code: " + datagram.message_code.ToString("x")); Logger.Log("Event Aditional Info Length: " + datagram.aditional_info_length); if (datagram.aditional_info_length > 0) { Logger.Log("Event Aditional Info: 0x" + BitConverter.ToString(datagram.aditional_info).Replace("-", string.Empty)); } Logger.Log("Event Control Field 1: " + Convert.ToString(datagram.control_field_1, 2)); Logger.Log("Event Control Field 2: " + Convert.ToString(datagram.control_field_2, 2)); Logger.Log("Event Source Address: " + datagram.source_address); Logger.Log("Event Destination Address: " + datagram.destination_address); Logger.Log("Event Data Length: " + datagram.data_length); Logger.Log("Event APDU: 0x" + BitConverter.ToString(datagram.apdu).Replace("-", string.Empty)); Logger.Log("-----------------------------------------------------------------------------------------------------"); if (datagram.message_code != 0x29) { return; } var type = datagram.apdu[1] >> 4; switch (type) { case 8: BuildAndExecuteKnxRx(datagram); Logger.Log("{0}", datagram.source_address); break; case 4: BuildAndExecuteKnxRx(datagram); Logger.Log("Device {0} status {1}", datagram.source_address, datagram.destination_address); break; } } catch (Exception e) { Logger.Log("ProcessCEMI: {0}", e.Message); } }