public Task SendAsync(IKnxAddress receivingAddress, IKnxData data) { if (!IsConnected) { throw new NotConnectedException(); } _sendMessages.Add(new TunnelRequestBuilder().Build(_communicationChannel, _sequenceCounter++, receivingAddress, data)); return(Task.CompletedTask); }
public byte[] Build(byte communicationChannelId, byte sequenceCounter, IKnxAddress receivingAddress, IKnxData data) { var dataBytes = data.GetBytes(); var length = GetLength(dataBytes); const byte headerLength = 0x06; const byte protocolVersion = 0x10; byte[] serviceTypeTunnelingRequest = { 0x04, 0x20 }; var sendingBytes = new List <byte> { headerLength, protocolVersion }; sendingBytes.AddRange(serviceTypeTunnelingRequest); const byte bodyStructureLength = 0x04; sendingBytes.Add(bodyStructureLength); sendingBytes.Add(communicationChannelId); sendingBytes.Add(sequenceCounter); sendingBytes.Add(0x00); sendingBytes.Add(0x11); sendingBytes.Add(0x00); sendingBytes.Add(0xAC); sendingBytes.Add(receivingAddress is MultiCastAddress ? (byte)0xF0 : (byte)0x50); sendingBytes.Add(0x00); sendingBytes.Add(0x00); sendingBytes.AddRange(receivingAddress.GetBytes()); sendingBytes.Add((byte)length); sendingBytes.Add(0x00); sendingBytes.Add(0x80); AddSendingData(sendingBytes, dataBytes); sendingBytes.InsertRange(4, BitConverter.GetBytes((ushort)(sendingBytes.Count + 2)).Reverse()); return(sendingBytes.ToArray()); }
public TunnelResponse(byte headerLength, byte protocolVersion, ushort totalLength, byte structureLength, byte communicationChannel, byte sequenceCounter, byte messageCode, byte addInformationLength, bool isRequest, bool ackWanted, byte controlField, byte controlField2, UnicastAddress sourceAddress, IKnxAddress destinationAddress, ApciTypes apci, int seqNumb, byte[] data) { HeaderLength = headerLength; ProtocolVersion = protocolVersion; TotalLength = totalLength; StructureLength = structureLength; CommunicationChannel = communicationChannel; SequenceCounter = sequenceCounter; MessageCode = messageCode; AddInformationLength = addInformationLength; AckWanted = ackWanted; ControlField = controlField; ControlField2 = controlField2; SourceAddress = sourceAddress; DestinationAddress = destinationAddress; APCI = apci; SequenceNumber = seqNumb; Data = data; IsRequest = IsRequest; }
//TODO sequenz obsolet machen!! public void Build(IKnxAddress sourceAddress, IKnxAddress destinationAddress, ApciTypes apciType, int sCounter = 255, byte[] data = null) { bytes.Add(0x11); //Message Code bytes.Add(0x00); //Manufacturer Code bytes.Add(bitToByte(ctrlByte)); // Control Byte drlByte.Set(7, destinationAddress is MulticastAddress); bytes.Add(bitToByte(drlByte)); // DRL Byte bytes.AddRange(new byte[] { 0x00, 0x00 }); // Source Address Unused bytes.AddRange(destinationAddress.GetBytes()); // Destination Address byte lengthData = 0x01; //TODO when apci first 4 bites is lower than 1111 thenlength++ or shift data to left in npdu byte if (data != null) { lengthData = BitConverter.GetBytes((ushort)(data.Count() + 1))[0]; List <ApciTypes> length0Apci = new List <ApciTypes>() { ApciTypes.MemoryRead, ApciTypes.MemoryWrite, ApciTypes.GroupValueWrite, ApciTypes.ADCRead, ApciTypes.Disconnect }; if (apciType == ApciTypes.MemoryRead || apciType == ApciTypes.MemoryWrite || apciType == ApciTypes.GroupValueWrite || apciType == ApciTypes.ADCRead) { lengthData--; } } else { switch (apciType) { case ApciTypes.ADCRead: case ApciTypes.ADCResponse: case ApciTypes.GroupValueResponse: case ApciTypes.GroupValueWrite: case ApciTypes.Ack: case ApciTypes.Connect: case ApciTypes.Disconnect: lengthData = 0x0; break; } } bytes.Add(lengthData); List <ApciTypes> datatypes = new List <ApciTypes>() { ApciTypes.Restart, ApciTypes.IndividualAddressRead, ApciTypes.DeviceDescriptorRead, ApciTypes.GroupValueRead, ApciTypes.GroupValueResponse, ApciTypes.GroupValueWrite, ApciTypes.ADCRead, ApciTypes.ADCResponse, ApciTypes.MemoryRead, ApciTypes.MemoryResponse, ApciTypes.MemoryWrite }; int _apci = (int)apciType; if (apciType == ApciTypes.Ack) { _apci--; } _apci = _apci | ((sCounter == 255 ? 0 : sCounter) << 10); _apci = _apci | ((sCounter == 255 ? 0 : 1) << 14); _apci = _apci | (((data == null && !datatypes.Contains(apciType)) ? 1 : 0) << 15); switch (apciType) { case ApciTypes.MemoryWrite: case ApciTypes.MemoryRead: int number = BitConverter.ToInt16(new byte[] { data[0], 0, 0, 0 }, 0); if (number > 63) { number = 63; } _apci = _apci | number; byte[] data_temp = new byte[data.Length - 1]; for (int i = 1; i < data.Length; i++) { data_temp[i - 1] = data[i]; } data = data_temp; break; } byte[] _apci2 = BitConverter.GetBytes(Convert.ToUInt16(_apci)); switch (apciType) { case ApciTypes.GroupValueResponse: case ApciTypes.GroupValueWrite: case ApciTypes.ADCRead: case ApciTypes.ADCResponse: case ApciTypes.Ack: case ApciTypes.Connect: case ApciTypes.Disconnect: bytes.Add(_apci2[1]); break; default: bytes.Add(_apci2[1]); bytes.Add(_apci2[0]); break; } if (data != null) { bytes.AddRange(data); } }
public Builders.TunnelResponse Build(byte headerLength, byte protocolVersion, ushort totalLength, byte[] responseBytes) { var structureLength = responseBytes[0]; var communicationChannel = responseBytes[1]; var sequenceCounter = responseBytes[2]; var messageCode = responseBytes[4]; var addInformationLength = responseBytes[5]; var controlField = responseBytes[6]; var controlField2 = responseBytes[7]; var npduLength = responseBytes[12]; byte[] npdu; if (npduLength != 0) { npdu = new byte[] { responseBytes[13], responseBytes[14] }; } else { npdu = new byte[] { responseBytes[13] }; } byte[] data = null; int seqNumb = 0x0; ApciTypes type = ApciTypes.Undefined; if (npduLength != 0) { BitArray bitsNpdu = new BitArray(npdu); if (bitsNpdu.Get(6)) { seqNumb = npdu[0] >> 2; seqNumb = seqNumb & 0xF; } int apci1 = ((npdu[0] & 3) << 2) | (npdu[1] >> 6); switch (apci1) { case 0: type = ApciTypes.GroupValueRead; break; case 1: type = ApciTypes.GroupValueResponse; int datai2 = npdu[1] & 63; data = new byte[responseBytes.Length - 15 + 1]; data[0] = Convert.ToByte(datai2); for (int i = 1; i < responseBytes.Length - 15 + 1; i++) { data[i] = responseBytes[i]; } break; case 2: type = ApciTypes.GroupValueWrite; int datai = npdu[1] & 63; data = new byte[responseBytes.Length - 15 + 1]; data[0] = Convert.ToByte(datai); for (int i = 1; i < responseBytes.Length - 15 + 1; i++) { data[i] = responseBytes[i]; } break; case 3: type = ApciTypes.IndividualAddressWrite; break; case 4: type = ApciTypes.IndividualAddressRead; break; case 5: type = ApciTypes.IndividualAddressResponse; break; case 6: type = ApciTypes.ADCRead; break; case 7: if (npdu[1] == 0) { type = ApciTypes.ADCResponse; } break; case 8: type = ApciTypes.MemoryRead; break; case 9: type = ApciTypes.MemoryResponse; break; case 10: type = ApciTypes.MemoryWrite; break; default: apci1 = ((npdu[0] & 3) << 8) | npdu[1]; type = (ApciTypes)apci1; break; } if (data == null) { data = new byte[responseBytes.Length - 15]; int c = 0; for (int i = 15; i < responseBytes.Length; i++) { data[c] = responseBytes[i]; c++; } } } else { data = new byte[0]; int apci3 = npdu[0] & 3; BitArray bitsNpdu = new BitArray(npdu); if (bitsNpdu.Get(6)) { seqNumb = npdu[0] >> 2; seqNumb = seqNumb & 0xF; } switch (apci3) { case 0: type = ApciTypes.Connect; break; case 1: type = ApciTypes.Disconnect; break; case 2: type = ApciTypes.Ack; break; case 3: type = ApciTypes.NAK; break; default: Debug.WriteLine("Unbekantes NPDU: " + apci3); break; } } BitArray bitsCtrl1 = new BitArray(new[] { responseBytes[6] }); BitArray bitsCtrl2 = new BitArray(new[] { responseBytes[7] }); IKnxAddress destAddr = null; if (bitsCtrl2.Get(7)) { destAddr = MulticastAddress.FromByteArray(new[] { responseBytes[10], responseBytes[11] }); } else { destAddr = UnicastAddress.FromByteArray(new[] { responseBytes[10], responseBytes[11] }); } bool ackWanted = bitsCtrl1.Get(2); bool isRequest = ReqMC.Contains(responseBytes[4]); switch (type) { case ApciTypes.MemoryWrite: case ApciTypes.MemoryRead: byte[] data_temp = new byte[data.Length + 1]; int restData = npdu[1] & 127; data_temp[0] = BitConverter.GetBytes(restData)[0]; for (int i = 0; i < data.Length; i++) { data_temp[i + 1] = data[i]; } data = data_temp; break; } return(new Builders.TunnelResponse(headerLength, protocolVersion, totalLength, structureLength, communicationChannel, sequenceCounter, messageCode, addInformationLength, isRequest, ackWanted, controlField, controlField2, UnicastAddress.FromByteArray(new[] { responseBytes[8], responseBytes[9] }), destAddr, type, seqNumb, data)); }
//TODO sequenz obsolet machen!! public void Build(IKnxAddress sourceAddress, IKnxAddress destinationAddress, ApciTypes apciType, int sCounter = 255, byte[] data = null) { bytes.Add(0x11); //Message Code bytes.Add(0x00); //Manufacturer Code bytes.Add(bitToByte(ctrlByte)); // Control Byte drlByte.Set(7, destinationAddress is MulticastAddress); bytes.Add(bitToByte(drlByte)); // DRL Byte bytes.AddRange(sourceAddress.GetBytes()); // Source Address bytes.AddRange(destinationAddress.GetBytes()); // Destination Address byte lengthData = Convert.ToByte(data?.Length ?? 0); List <ApciTypes> datatypes = new List <ApciTypes>() { ApciTypes.Restart, ApciTypes.IndividualAddressRead, ApciTypes.DeviceDescriptorRead, ApciTypes.GroupValueRead, ApciTypes.GroupValueResponse, ApciTypes.GroupValueWrite, ApciTypes.ADCRead, ApciTypes.ADCResponse, ApciTypes.MemoryRead, ApciTypes.MemoryResponse, ApciTypes.MemoryWrite }; int _apci = (int)apciType; if (apciType == ApciTypes.Ack) { _apci--; } _apci = _apci | ((sCounter == 255 ? 0 : sCounter) << 10); _apci = _apci | ((sCounter == 255 ? 0 : 1) << 14); _apci = _apci | (((data == null && !datatypes.Contains(apciType)) ? 1 : 0) << 15); List <ApciTypes> withData = new List <ApciTypes>() { ApciTypes.GroupValueRead, ApciTypes.GroupValueResponse, ApciTypes.GroupValueWrite, ApciTypes.ADCRead, ApciTypes.ADCResponse, ApciTypes.MemoryRead, ApciTypes.MemoryResponse, ApciTypes.MemoryWrite, ApciTypes.DeviceDescriptorRead, ApciTypes.DeviceDescriptorResponse, ApciTypes.Restart }; if (withData.Contains(apciType) && data != null) { byte first = data[0]; if (first < 64) { first &= 0b00111111; _apci |= first; data = data.Skip(1).ToArray(); lengthData--; } } byte[] _apci2 = BitConverter.GetBytes(Convert.ToUInt16(_apci)); switch (apciType) { case ApciTypes.ADCRead: case ApciTypes.ADCResponse: case ApciTypes.Ack: case ApciTypes.Connect: case ApciTypes.Disconnect: bytes.Add(lengthData); bytes.Add(_apci2[1]); break; default: bytes.Add(++lengthData); bytes.Add(_apci2[1]); bytes.Add(_apci2[0]); break; } if (data != null) { bytes.AddRange(data); } }