public Move ( int srcPos, int destPos, int count ) : void | ||
srcPos | int | Source position. |
destPos | int | Destination position. |
count | int | Item count. |
return | void |
/// <summary> /// Get next logical name PDU. /// </summary> /// <param name="p">LN parameters.</param> /// <param name="reply">Generated message.</param> internal static void GetLNPdu(GXDLMSLNParameters p, GXByteBuffer reply) { bool ciphering = p.settings.Cipher != null && p.settings.Cipher.Security != Gurux.DLMS.Enums.Security.None; int len = 0; if (!ciphering && p.settings.InterfaceType == InterfaceType.HDLC) { AddLLCBytes(p.settings, reply); } if (p.command == Command.Aarq) { reply.Set(p.attributeDescriptor); } else { if (p.settings.LnSettings.GeneralBlockTransfer) { reply.SetUInt8((byte)Command.GeneralBlockTransfer); MultipleBlocks(p, reply, ciphering); // Is last block if (!p.lastBlock) { reply.SetUInt8(0); } else { reply.SetUInt8(0x80); } // Set block number sent. reply.SetUInt8(0); // Set block number acknowledged reply.SetUInt8((byte)p.blockIndex); ++p.blockIndex; // Add APU tag. reply.SetUInt8(0); // Add Addl fields reply.SetUInt8(0); } // Add command. reply.SetUInt8((byte)p.command); if (p.command == Command.DataNotification || p.command == Command.AccessRequest || p.command == Command.AccessResponse) { // Add Long-Invoke-Id-And-Priority reply.SetUInt32(GetLongInvokeIDPriority(p.settings)); // Add date time. if (p.time == null || p.time.Value.DateTime == DateTime.MinValue || p.time.Value.DateTime == DateTime.MaxValue || p.time.Value.LocalDateTime == DateTime.MinValue || p.time.Value.LocalDateTime == DateTime.MaxValue) { reply.SetUInt8(DataType.None); } else { // Data is send in octet string. Remove data type. int pos = reply.Size; GXCommon.SetData(p.settings, reply, DataType.OctetString, p.time); reply.Move(pos + 1, pos, reply.Size - pos - 1); } } else { //Get request size can be bigger than PDU size. if (p.command != Command.GetRequest && p.data != null && p.data.Size != 0) { MultipleBlocks(p, reply, ciphering); } //Change Request type if Set request and multiple blocks is needed. if (p.command == Command.SetRequest) { if (p.multipleBlocks) { if (p.requestType == 1) { p.requestType = 2; } else if (p.requestType == 2) { p.requestType = 3; } } } //Change request type If get response and multiple blocks is needed. if (p.command == Command.GetResponse) { if (p.multipleBlocks) { if (p.requestType == 1) { p.requestType = 2; } } } reply.SetUInt8(p.requestType); // Add Invoke Id And Priority. reply.SetUInt8(GetInvokeIDPriority(p.settings)); } //Add attribute descriptor. reply.Set(p.attributeDescriptor); if (p.command != Command.DataNotification && !p.settings.LnSettings.GeneralBlockTransfer) { //If multiple blocks. if (p.multipleBlocks) { // Is last block. if (p.lastBlock) { reply.SetUInt8(1); p.settings.Count = p.settings.Index = 0; } else { reply.SetUInt8(0); } // Block index. reply.SetUInt32(p.blockIndex); ++p.blockIndex; //Add status if reply. if (p.status != 0xFF) { if (p.status != 0 && p.command == Command.GetResponse) { reply.SetUInt8(1); } reply.SetUInt8(p.status); } //Block size. if (p.data != null) { len = p.data.Size - p.data.Position; } else { len = 0; } int totalLength = len + reply.Size; if (ciphering) { totalLength += CipheringHeaderSize; } if (totalLength > p.settings.MaxPduSize) { len = p.settings.MaxPduSize - reply.Size - p.data.Position; if (ciphering) { len -= CipheringHeaderSize; } len -= GXCommon.GetObjectCountSizeInBytes(len); } GXCommon.SetObjectCount(len, reply); reply.Set(p.data, len); } } //Add data that fits to one block. if (len == 0) { //Add status if reply. if (p.status != 0xFF) { if (p.status != 0 && p.command == Command.GetResponse) { reply.SetUInt8(1); } reply.SetUInt8(p.status); } if (p.data != null && p.data.Size != 0) { len = p.data.Size - p.data.Position; //Get request size can be bigger than PDU size. if (p.command != Command.GetRequest && len + reply.Size > p.settings.MaxPduSize) { len = p.settings.MaxPduSize - reply.Size; } reply.Set(p.data, len); } } if (ciphering) { byte[] tmp = p.settings.Cipher.Encrypt((byte)GetGloMessage(p.command), p.settings.Cipher.SystemTitle, reply.Array()); reply.Size = 0; if (p.settings.InterfaceType == InterfaceType.HDLC) { AddLLCBytes(p.settings, reply); } if (p.command == Command.DataNotification) { // Add command. reply.SetUInt8(tmp[0]); // Add system title. GXCommon.SetObjectCount( p.settings.Cipher.SystemTitle.Length, reply); reply.Set(p.settings.Cipher.SystemTitle); // Add data. reply.Set(tmp, 1, tmp.Length - 1); } else { reply.Set(tmp); } } } }
/// <summary> /// Get HDLC frame for data. /// </summary> /// <param name="settings">DLMS settings.</param> /// <param name="frame">Frame ID. If zero new is generated.</param> /// <param name="data">Data to add.</param> /// <returns>HDLC frames.</returns> internal static byte[] GetHdlcFrame(GXDLMSSettings settings, byte frame, GXByteBuffer data) { GXByteBuffer bb = new GXByteBuffer(); int frameSize, len = 0; byte[] primaryAddress, secondaryAddress; if (settings.IsServer) { primaryAddress = GetHdlcAddressBytes(settings.ClientAddress, 0); secondaryAddress = GetHdlcAddressBytes(settings.ServerAddress, settings.ServerAddressSize); } else { primaryAddress = GetHdlcAddressBytes(settings.ServerAddress, settings.ServerAddressSize); secondaryAddress = GetHdlcAddressBytes(settings.ClientAddress, 0); } // Add BOP bb.SetUInt8(GXCommon.HDLCFrameStartEnd); frameSize = Convert.ToInt32(settings.Limits.MaxInfoTX); // If no data if (data == null || data.Size == 0) { bb.SetUInt8(0xA0); } else if (data.Size - data.Position <= frameSize) { // Is last packet. bb.SetUInt8(0xA0); len = data.Size - data.Position; } else { // More data to left. bb.SetUInt8(0xA8); len = frameSize; } //Frame len. if (len == 0) { bb.SetUInt8((byte)(5 + primaryAddress.Length + secondaryAddress.Length + len)); } else { bb.SetUInt8((byte)(7 + primaryAddress.Length + secondaryAddress.Length + len)); } // Add primary address. bb.Set(primaryAddress); // Add secondary address. bb.Set(secondaryAddress); //Add frame ID. if (frame == 0) { frame = settings.NextSend(); } bb.SetUInt8(frame); // Add header CRC. UInt16 crc = GXFCS16.CountFCS16(bb.Data, 1, bb.Size - 1); bb.SetUInt16(crc); if (len != 0) { //Add data. bb.Set(data, len); // Add data CRC. crc = GXFCS16.CountFCS16(bb.Data, 1, bb.Size - 1); bb.SetUInt16(crc); } // Add EOP bb.SetUInt8(GXCommon.HDLCFrameStartEnd); if (data != null) { //Remove sent data in server side. if (settings.IsServer) { if (data.Size == data.Position) { data.Clear(); } else { data.Move(data.Position, 0, data.Size - data.Position); data.Position = 0; } } } return bb.Array(); }
public static bool GetData(GXDLMSSettings settings, GXByteBuffer reply, GXReplyData data) { byte frame = 0; // If DLMS frame is generated. if (settings.InterfaceType == InterfaceType.HDLC) { frame = GetHdlcData(settings.IsServer, settings, reply, data); data.FrameId = frame; } else if (settings.InterfaceType == InterfaceType.WRAPPER) { GetTcpData(settings, reply, data); } else if (settings.InterfaceType == InterfaceType.PDU) { data.PacketLength = reply.Size; data.IsComplete = true; } else { throw new ArgumentException("Invalid Interface type."); } // If all data is not read yet. if (!data.IsComplete) { return false; } GetDataFromFrame(reply, data); // If keepalive or get next frame request. if (data.Xml != null || (frame & 0x1) != 0) { if (settings.InterfaceType == InterfaceType.HDLC && data.Data.Size != 0) { reply.Position += 3; System.Diagnostics.Debug.Assert(reply.GetUInt8(reply.Position - 1) == 0x7e); } return true; } GetPdu(settings, data); if (data.Command == Command.DataNotification) { // Check is there more messages left. // This is Push message special case. if (reply.Position == reply.Size) { reply.Clear(); } else { int cnt = reply.Size - reply.Position; reply.Move(reply.Position, 0, cnt); reply.Position = 0; } } return true; }
/// <summary> /// Split DLMS PDU to wrapper frames. /// </summary> /// <param name="settings">DLMS settings.</param> /// <param name="data"> Wrapped data.</param> /// <returns>Wrapper frames</returns> internal static byte[] GetWrapperFrame(GXDLMSSettings settings, GXByteBuffer data) { GXByteBuffer bb = new GXByteBuffer(); // Add version. bb.SetUInt16(1); if (settings.IsServer) { bb.SetUInt16((UInt16)settings.ServerAddress); bb.SetUInt16((UInt16)settings.ClientAddress); } else { bb.SetUInt16((UInt16)settings.ClientAddress); bb.SetUInt16((UInt16)settings.ServerAddress); } if (data == null) { // Data length. bb.SetUInt16(0); } else { // Data length. bb.SetUInt16((UInt16)data.Size); // Data bb.Set(data); } //Remove sent data in server side. if (settings.IsServer) { if (data.Size == data.Position) { data.Clear(); } else { data.Move(data.Position, 0, data.Size - data.Position); data.Position = 0; } } return bb.Array(); }