/// <summary>
        /// Creates the set request file for edl40 mode.
        /// </summary>
        /// <param name="portId">The port id.</param>
        /// <param name="operationMode">The operation mode.</param>
        /// <returns></returns>
        public static SmlFile CreateSetRequestFileForOperationMode(string portId, BooleanParam operationMode)
        {
            var handler = new SmlHandler(portId);
            var smlFile = new SmlFile();
            handler.AddOpenRequest(smlFile);

            handler.AddSetBooleanParamRequest(
               smlFile, operationMode);

            handler.AddCloseRequest(smlFile);

            return smlFile;
        }
        /// <summary>
        /// Creates the get request file.
        /// </summary>
        /// <param name="portId">The port id.</param>
        /// <param name="obisCode">The obis code.</param>
        /// <returns></returns>
        public static SmlFile CreateGetRequestFile(string portId, long obisCode)
        {
            var handler = new SmlHandler(portId);
            var smlFile = new SmlFile();
            handler.AddOpenRequest(smlFile);
            if (obisCode == (long)ObisId.EdlEventLog)
            {
                handler.AddGetProfileRequest(smlFile, (ObisId)obisCode);
            }
            else
            {
                handler.AddGetParamRequest(smlFile, (ObisId)obisCode);
            }

            handler.AddCloseRequest(smlFile);

            return smlFile;
        }
 /// <summary>
 /// Adds the close request.
 /// </summary>
 /// <param name="reqFile">The req file.</param>
 private void AddCloseRequest(SmlFile reqFile)
 {
     var msg = new Core.Sml.Messages.Message()
     {
         TransactionId = new[] { (byte)(reqFile.Count + 1) },
         GroupNo = 0x00,
         CloseRequest = new Core.Sml.Messages.CloseRequest()
     };
     //var msg = SmlMessageFactory.CloseReq();
     //var transactionId = new byte[] { (byte)(reqFile.Count + 1) };
     //msg.TransactionId = new SmlOctetstring(transactionId);
     //msg.GroupNo = 0x00;
     reqFile.Add(msg);
 }
        /// <summary>
        /// Adds the set date time param request.
        /// </summary>
        /// <param name="reqFile">The req file.</param>
        /// <param name="param">The param.</param>
        private void AddSetDateTimeParamRequest(SmlFile reqFile, DateTimeParam param)
        {
            var timeToSet = param.Data.Value;
            var localOffset = (short)TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes;
            var seasonTimeOffset = timeToSet.IsDaylightSavingTime() ? (short)60 : (short)0;

            var msg = new Core.Sml.Messages.Message()
            {
                TransactionId = new[] { (byte)(reqFile.Count + 1) },
                GroupNo = 0x00,
                SetProcParameterRequest = new Core.Sml.Messages.SetProcParameterRequest()
                {
                    TreePath = new List<Core.Obis.ObisId>()
                    {
                        new Core.Obis.ObisId((ulong)param.ObisCode)
                    },
                    Tree = new Tree(new Core.Obis.ObisId((ulong)param.ObisCode), new Time(timeToSet.ToUniversalTime())
                    {
                        Type = TimeType.LocalTimestamp,
                        LocalOffset = localOffset,
                        SeasonTimeOffset = seasonTimeOffset
                    })
                }
            };
            //var obisId = (ObisId)param.ObisCode;
            //var paramTreePath = new SmlTreePath(obisId);
            //var tree = new SmlTree { ParameterName = new SmlOctetstring(ObisUtil.GetBytes(obisId)) };
            //if (param.Data.HasValue == false)
            //{
            //    throw new ArgumentNullException("param");
            //}

            //var smlTime = new SmlTime { Type = SmlTime.Choice.LocalTimestamp, UtcTime = param.Data.Value };
            //tree.ParameterValue = new SmlProcParValue(smlTime);
            //var msg = SmlMessageFactory.SetProcParamReq(paramTreePath, tree);

            //var transactionId = new byte[] { (byte)(reqFile.Count + 1) };
            //msg.TransactionId = new SmlOctetstring(transactionId);
            //msg.GroupNo = 0x00;
            reqFile.Add(msg);
        }
        /// <summary>
        /// Adds the set unsigned param request.
        /// </summary>
        /// <param name="reqFile">The req file.</param>
        /// <param name="param">The param.</param>
        private void AddSetUnsignedParamRequest(SmlFile reqFile, UnsignedParam param)
        {
            var msg = new Core.Sml.Messages.Message()
            {
                TransactionId = new[] { (byte)(reqFile.Count + 1) },
                GroupNo = 0x00,
                SetProcParameterRequest = new Core.Sml.Messages.SetProcParameterRequest()
                {
                    TreePath = new List<Core.Obis.ObisId>()
                    {
                        new Core.Obis.ObisId((ulong)param.ObisCode)
                    },
                    Tree = new Tree(new Core.Obis.ObisId((ulong)param.ObisCode), param.Data.Value)
                }
            };
            //var obisId = (ObisId)param.ObisCode;
            //var paramTreePath = new SmlTreePath(obisId);
            //var tree = new SmlTree { ParameterName = new SmlOctetstring(ObisUtil.GetBytes(obisId)) };
            //if (param.Data.HasValue == false)
            //{
            //    throw new ArgumentNullException("param");
            //}

            //// TODO: check if casting is obsolete
            //if (obisId == ObisId.EdlActiveTariffAplus || obisId == ObisId.EdlActiveTariffAminus)
            //{
            //    tree.ParameterValue = new SmlProcParValue(new SmlUnsigned8((byte)param.Data.Value));
            //}
            //else
            //{
            //    tree.ParameterValue = new SmlProcParValue(new SmlUnsigned64(param.Data.Value));
            //}

            //var msg = SmlMessageFactory.SetProcParamReq(paramTreePath, tree);

            //var transactionId = new byte[] { (byte)(reqFile.Count + 1) };
            //msg.TransactionId = new SmlOctetstring(transactionId);
            //msg.GroupNo = 0x00;
            reqFile.Add(msg);
        }
        /// <summary>
        /// Adds the set integer param request.
        /// </summary>
        /// <param name="reqFile">The req file.</param>
        /// <param name="param">The param.</param>
        private void AddSetIntegerParamRequest(SmlFile reqFile, IntegerParam param)
        {
            var msg = new Core.Sml.Messages.Message()
            {
                TransactionId = new[] { (byte)(reqFile.Count + 1) },
                GroupNo = 0x00,
                SetProcParameterRequest = new Core.Sml.Messages.SetProcParameterRequest()
                {
                    TreePath = new List<Core.Obis.ObisId>()
                    {
                        new Core.Obis.ObisId((ulong)param.ObisCode)
                    },
                    Tree = new Tree(new Core.Obis.ObisId((ulong)param.ObisCode), param.Data.Value)

                }
            };

            //var obisId = (ObisId)param.ObisCode;
            //var paramTreePath = new SmlTreePath(obisId);
            //var tree = new SmlTree { ParameterName = new SmlOctetstring(ObisUtil.GetBytes(obisId)) };
            //if (param.Data.HasValue == false)
            //{
            //    throw new ArgumentNullException("param");
            //}

            //tree.ParameterValue = new SmlProcParValue(new SmlInteger64(param.Data.Value));
            //var msg = SmlMessageFactory.SetProcParamReq(paramTreePath, tree);

            //var transactionId = new byte[] { (byte)(reqFile.Count + 1) };
            //msg.TransactionId = new SmlOctetstring(transactionId);
            //msg.GroupNo = 0x00;
            reqFile.Add(msg);
        }
        /// <summary>
        /// Adds the get profile request.
        /// </summary>
        /// <param name="reqFile">The req file.</param>
        /// <param name="obisId">The obis id.</param>
        private void AddGetProfileRequest(SmlFile reqFile, ObisId obisId)
        {
            var msg = new Core.Sml.Messages.Message()
            {
                TransactionId = new[] { (byte)(reqFile.Count + 1) },
                GroupNo = 0x00,
                GetProfileListRequest = new Core.Sml.Messages.GetProfileListRequest()
                {
                    TreePath = new List<Core.Obis.ObisId>()
                    {
                        Core.Obis.ObisId.Parse(ObisUtil.GetBytes(obisId))
                    }
                }
            };

            //var paramTreePath = new SmlTreePath(obisId);
            //var msg = SmlMessageFactory.GetProfileListReq(paramTreePath);

            //var transactionId = new byte[] { (byte)(reqFile.Count + 1) };
            //msg.TransactionId = new SmlOctetstring(transactionId);
            //msg.GroupNo = 0x00;
            reqFile.Add(msg);
        }
        /// <summary>
        /// Sends the file.
        /// </summary>
        /// <param name="requestFile">The SML file.</param>
        /// <param name="isManufacturerMode">if set to <c>true</c> [is manufacturer mode].</param>
        /// <returns>
        /// True if file could be written down the serial interface.
        /// </returns>
        private async Task<object> SendFile(SmlFile requestFile, bool isManufacturerMode = false)
        {
            if (requestFile == null)
            {
                throw new ArgumentNullException(nameof(requestFile));
            }

            Core.Obis.ObisId reqObis;
            if (requestFile[1].GetProcParameterRequest != null)
            {
                reqObis = requestFile[1].GetProcParameterRequest.TreePath.First();
                logger.Warn("READ OBIS: {0}", reqObis.ToHexString());
            }
            else if (requestFile[1].SetProcParameterRequest != null)
            {
                reqObis = requestFile[1].SetProcParameterRequest.TreePath.First();
                logger.Warn("WRITE OBIS: {0}", reqObis.ToHexString());
            }
            else
            {
                throw new InvalidOperationException();
            }

            var sendBuff = new List<byte>();
            requestFile.Serialize(sendBuff);

            this.logger.Debug("Sending SML file of size {0}.", sendBuff.Count);

            using (await this.asyncLock.LockAsync())
            {
                // try to read response from meter
                try
                {
                    this.EnsureConnected();

                    // WriteAsync does not work with Advantech boxes
                    //await 
                    this.tcpPort.GetStream().Write(sendBuff.ToArray(), 0, sendBuff.Count);
                    //.WriteAsync(sendBuff.ToArray(), 0, sendBuff.Count, token.Token);

                    this.logger.Trace("TX: {0}", BitConverter.ToString(sendBuff.ToArray()));
                    this.logger.Debug("File sent, waiting for response from meter.");

                    var receivedFile = await this.ReceiveSmlFile(TimeSpan.FromSeconds(8));

                    // process received file
                    var result = this.GetMeterResponse(requestFile, receivedFile);
                    return result;
                }
                catch (Exception ex)
                {
                    this.logger.ErrorException("ReceiveSmlFile failed: " + ex.StackTrace, ex);
                    this.tcpPort.Close();
                    throw;
                }
            }
        }
        /// <summary>
        /// Creates the set request file.
        /// </summary>
        /// <param name="portId">The port id.</param>
        /// <param name="param">The param.</param>
        /// <returns></returns>
        public static SmlFile CreateSetRequestFile(string portId, DateTimeParam param)
        {
            var handler = new SmlHandler(portId);
            var smlFile = new SmlFile();
            handler.AddOpenRequest(smlFile);
            handler.AddSetDateTimeParamRequest(smlFile, param);
            handler.AddCloseRequest(smlFile);

            return smlFile;
        }
        /// <summary>
        /// Sends the request file.
        /// </summary>
        /// <param name="requestFile">The request file.</param>
        /// <param name="enableManufacturerMode">if set to <c>true</c> [enable manufacturer mode].</param>
        private async Task SendRequestFile(SmlFile requestFile, bool enableManufacturerMode)
        {
            logger.Info("Sending request file");
            var response = await SendFile(requestFile, enableManufacturerMode).ConfigureAwait(false);
            var attentionRes = response as AttentionResponse;
            if (attentionRes == null)
            {
                logger.Error("No response received.");
                throw new DataException("No response received.");
            }

            if (attentionRes.AttentionNo != (ulong)AttentionCode.Ok)
            {
                logger.Error("Device returned an error: {0}.", attentionRes.AttentionNo);
                throw new DataException(string.Format("Device returned an error: {0}.", attentionRes.AttentionNo));
            }
        }
        /// <summary>
        /// Processes the periodic response.
        /// </summary>
        /// <param name="periodicFile">The periodic file.</param>
        /// <param name="response">The response.</param>
        private void ProcessPeriodicResponse(SmlFile periodicFile, object response)
        {
            Trace.WriteLine("Processing periodic response for com port {0}.", portName);
            try
            {
                if (periodicFile.Count < 2)
                {
                    return;
                }

                for (int i = 0; i < periodicFile.Count; i++)
                {
                    var getParamReq = periodicFile[i].GetProcParameterRequest;
                    if (getParamReq == null)
                    {
                        continue;
                    }

                    if (getParamReq.TreePath.Count < 1)
                    {
                        continue;
                    }

                    var requestedObis = getParamReq.TreePath[0];

                    switch (requestedObis)
                    {
                        case (long)ObisId.EdlDzgNumberOfTariffs:
                            var numberOfTariffs = Convert.ToInt32(response);

                            SmlComService.GetConfiguredPort(portName).EdlMeterDevice.TariffCount = numberOfTariffs;
                            Trace.WriteLine(string.Format("{0} Response for tariff count received", portName));
                            logger.Info("Response for read tariff count: {0}.", SmlComService.GetConfiguredPort(portName).EdlMeterDevice.TariffCount);
                            TariffCountReadAt = DateTime.Now;

                            break;
                        case (long)ObisId.DeviceIdentificationParams:
                            if (response is Tree)
                            {
                                Trace.WriteLine(string.Format("{0} Response for device id received", portName));
                                var di = CreateEdlDeviceIdentification((Tree)response);
                                var md = SmlComService.GetConfiguredPort(portName).EdlMeterDevice;
                                if (md == null)
                                {
                                    throw new ApplicationException(string.Format("Meter device for port {0} is null.",
                                        portName));
                                }

                                SmlComService.GetConfiguredPort(portName).EdlMeterDevice.PublicKey = di.PublicKey.Data;
                                SmlComService.GetConfiguredPort(portName).EdlMeterDevice.ServerId = di.ServerId.Data;

                                try
                                {
                                    SmlComService.GetConfiguredPort(portName).EdlMeterDevice.FirmwareVersion =
                                        di.FirmwareVersion.Data;
                                }
                                catch (Exception ex)
                                {
                                    logger.ErrorException(
                                        string.Format("Firmware parsing error at port {0}.", portName), ex);
                                }

                                try
                                {
                                    logger.Info(
                                        "Response for device identification. ServerId {0}, Public Key {1}, Firmware Version {2}.",
                                        BitConverter.ToString(di.ServerId.Data),
                                        BitConverter.ToString(di.PublicKey.Data),
                                        di.FirmwareVersion.Data);
                                }
                                catch (Exception ex)
                                {
                                    logger.WarnException("Logging error at port " + portName, ex);
                                }

                                DeviceIdentificationReadAt = DateTime.Now;
                            }

                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                logger.ErrorException(string.Format("Error at processing periodic response for {0}.", portName), ex);
            }

        }
        /// <summary>
        /// Gets the meter response.
        /// </summary>
        /// <param name="requestFile">The request File.</param>
        /// <param name="responseFile">The response File.</param>
        /// <returns>
        /// The response value for a request message.
        /// </returns>
        private object GetMeterResponse(SmlFile requestFile, SmlFile responseFile)
        {
            if (responseFile == null)
            {
                Trace.WriteLine(string.Format("{0} no response file from meter.", portName));
                logger.Error("No response file received.");
                throw new FaultException("No response sml file.");
            }

            if (requestFile == null)
            {
                Trace.WriteLine(string.Format("{0} !!! no request file available !!!", portName));
                logger.Error("No request file available.");
                throw new FaultException("No request sml file.");
            }

            foreach (var msg in requestFile)
            {
                if (msg.OpenRequest != null || msg.CloseRequest != null)
                {
                    continue;
                }

                // find request transactionId
                var reqTransacationId = msg.TransactionId;

                // search result message with matching transactionId
                var resMsg =
                   responseFile.FirstOrDefault(m => m.TransactionId.SequenceEqual(reqTransacationId));

                if (resMsg == null)
                {
                    Trace.WriteLine(string.Format("{0} no response message for request found.", portName));
                    logger.Error("No response for request found.");
                    throw new FaultException("No response message for request found.");
                }

                // check result message for attentionResponse
                if (resMsg.AttentionResponse != null)
                {
                    Trace.WriteLine(string.Format("{0} Attention response for request found.", portName));

                    // AttentionCode.Ok returned
                    return resMsg.AttentionResponse;
                }

                // check for event log readout
                if (msg.GetProfileListRequest != null)
                {
                    if (msg.GetProfileListRequest.TreePath[0] == (long)ObisId.EdlEventLog)
                    {
                        //var listResponses = new SmlListOfType<SmlGetProfileListRes>();
                        var listResponses = new SmlList();
                        foreach (var m in responseFile)
                        {
                            if (m.GetProfileListResponse == null)
                            {
                                continue;
                            }

                            if (m.GetProfileListResponse.TreePath[0] == (long)ObisId.EdlEventLog)
                            {
                                listResponses.Add(m.GetProfileListResponse);
                            }
                        }

                        return listResponses;
                    }
                }

                // extract value response from result message 
                if (resMsg.GetProcParameterResponse != null)
                {
                    Trace.WriteLine(string.Format("{0} response message for GetProcParam found.", portName));
                    var procParamRes = resMsg.GetProcParameterResponse;
                    if (procParamRes.Tree.Childs != null && procParamRes.Tree.Childs.Count > 0)
                    {
                        // return tree e.g. in case of deviceId response
                        return procParamRes.Tree;
                    }

                    // return single value
                    return procParamRes.Tree.Value;
                }

                // return message body
                if (resMsg.GetListResponse != null)
                {
                    return resMsg.GetListResponse;
                }

                logger.Error("No response message for request found.");
                throw new DataException("No response message for request found.");
            }

            return null;
        }
        /// <summary>
        /// Sends the file.
        /// </summary>
        /// <param name="requestFile">The SML file.</param>
        /// <param name="isManufacturerMode">if set to <c>true</c> [is manufacturer mode].</param>
        /// <returns>
        /// True if file could be written down the serial interface.
        /// </returns>
        private async Task<object> SendFile(SmlFile requestFile, bool isManufacturerMode = false)
        {
            if (requestFile == null)
            {
                throw new ArgumentNullException("requestFile");
            }

            if (SerialPort.GetPortNames().Contains(portName) == false)
            {
                logger.Error("Port {0} is not existing.", portName);
                throw new ArgumentException("Port " + portName + " is not existing");
            }

            Core.Obis.ObisId reqObis;
            if (requestFile[1].GetProcParameterRequest != null)
            {
                reqObis = requestFile[1].GetProcParameterRequest.TreePath.First();
                logger.Warn("READ OBIS: {0}", reqObis.ToHexString());
            }
            else if (requestFile[1].SetProcParameterRequest != null)
            {
                reqObis = requestFile[1].SetProcParameterRequest.TreePath.First();
                logger.Warn("WRITE OBIS: {0}", reqObis.ToHexString());
            }
            else
            {
                throw new InvalidOperationException();
            }

            var sendBuff = new List<byte>();
            requestFile.Serialize(sendBuff);

            logger.Debug("Sending SML file of size {0}.", sendBuff.Count);

            using (await asyncLock.LockAsync().ConfigureAwait(false))
            //using (var token = new CancellationTokenSource(1000))
            {
                // try to read response from meter
                try
                {
                    // WriteAsync does not work with Advantech boxes
                    //await 
                    serialPort.Write(sendBuff.ToArray(), 0, sendBuff.Count);
                    //.WriteAsync(sendBuff.ToArray(), 0, sendBuff.Count, token.Token).ConfigureAwait(false);

                    logger.Trace("TX: {0}", BitConverter.ToString(sendBuff.ToArray()));
                    logger.Debug("File sent, waiting for response from meter.");

                    var receivedFile = await ReceiveSmlFile(TimeSpan.FromSeconds(8))
                                        .ConfigureAwait(false);

                    // process received file
                    var result = GetMeterResponse(requestFile, receivedFile);
                    return result;
                }
                catch (Exception ex)
                {
                    logger.ErrorException("ReceiveSmlFile failed: " + ex.StackTrace, ex);
                    throw;
                }
            }
        }
        /// <summary>
        /// Sends the request file.
        /// </summary>
        /// <param name="requestFile">The request file.</param>
        /// <param name="enableManufacturerMode">if set to <c>true</c> [enable manufacturer mode].</param>
        private async Task SendRequestFile(SmlFile requestFile, bool enableManufacturerMode)
        {
            this.logger.Info("Sending request file");
            var response = await this.SendFile(requestFile, enableManufacturerMode);
            var attentionRes = response as Core.Sml.Messages.AttentionResponse;
            if (attentionRes == null)
            {
                this.logger.Error("No response received.");
                throw new DataException("No response received.");
            }

            if (attentionRes.AttentionNo != (ulong)Sml.AttentionCode.Ok)
            {
                this.logger.Error("Device returned an error: {0}.", attentionRes.AttentionNo);
                throw new DataException($"Device returned an error: {attentionRes.AttentionNo}.");
            }
        }
        /// <summary>
        /// Adds the open request.
        /// </summary>
        /// <param name="reqFile">The req file.</param>
        private void AddOpenRequest(SmlFile reqFile)
        {
            var msg = new Core.Sml.Messages.Message
            {
                TransactionId = new byte[] { (byte)(reqFile.Count + 1) },
                GroupNo = 0x00,
                OpenRequest = new Core.Sml.Messages.OpenRequest()
                {
                    ClientId = this.clientId,
                    ReqFileId = new byte[] { this.requestIndex++ },
                }
            };
            //var msg = Sml.SmlMessageFactory.OpenReq(this.clientId, new byte[] { this.requestIndex++ });
            //var transactionId = new byte[] { (byte)(reqFile.Count + 1) };
            //msg.TransactionId = new SmlOctetstring(transactionId);
            //msg.GroupNo = 0x00;
            reqFile.Add(msg);

            if (this.requestIndex > 200)
            {
                this.requestIndex = 0;
            }
        }
        /// <summary>
        /// Creates the set request file for tariff.
        /// </summary>
        /// <param name="portId">The port id.</param>
        /// <param name="bitMask">The bit mask.</param>
        /// <param name="tariffAplus">The tariff aplus.</param>
        /// <param name="tarrifAminus">The tarrif aminus.</param>
        /// <returns>The request file to set the tariffs and bitmask.</returns>
        public static SmlFile CreateSetRequestFileForTariff(
           string portId, UnsignedParam bitMask, UnsignedParam tariffAplus, UnsignedParam tarrifAminus)
        {
            var handler = new SmlHandler(portId);
            var smlFile = new SmlFile();
            handler.AddOpenRequest(smlFile);

            handler.AddSetBooleanParamRequest(
               smlFile, new BooleanParam() { ObisCode = (long)ObisId.EdlOperationModeEdl40, Data = false });
            handler.AddSetUnsignedParamRequest(smlFile, bitMask);

            if (tariffAplus != null)
            {
                handler.AddSetUnsignedParamRequest(smlFile, tariffAplus);
            }

            if (tarrifAminus != null)
            {
                handler.AddSetUnsignedParamRequest(smlFile, tarrifAminus);
            }

            handler.AddCloseRequest(smlFile);

            return smlFile;
        }
      private static SmlFile ReceiveSmlFile(SerialPort sp, TimeSpan timeOut)
      {
         var sw = new Stopwatch();
         var resetEvent = new AutoResetEvent(false);
         var rcvBuff = new List<byte>();
         var buff = new byte[1024];
         var escEoF = new byte[] { 0x1b, 0x1b, 0x1b, 0x1b, 0x1a };
         var escBoF = new byte[] { 0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01 };
         var smlFile = new SmlFile();
         sw.Start();
         while (sw.Elapsed < timeOut)
         {
            resetEvent.WaitOne(100);

            if (sp.BytesToRead < 1 && rcvBuff.Count <= 30)
            {
               resetEvent.WaitOne(10);
               continue;
            }

            if (sp.BytesToRead > 0)
            {
               int bytesRead = sp.Read(buff, 0, buff.Count());
               for (int i = 0; i < bytesRead; i++)
               {
                  rcvBuff.Add(buff[i]);
               }

               //this.logger.Trace("RX: {0}", BitConverter.ToString(buff, 0, bytesRead));
            }

            // check begin of file
            if (rcvBuff.Count < 8)
            {
               continue;
            }

            var fileHeader = rcvBuff.GetRange(0, 8);
            if (fileHeader.SequenceEqual(escBoF) == false)
            {
               rcvBuff.RemoveAt(0);
               continue;
            }

            // check end of file
            var fileTrailer = rcvBuff.GetRange(rcvBuff.Count - 8, 5);
            if (fileTrailer.SequenceEqual(escEoF) == false)
            {
               continue;
            }

            try
            {
               smlFile.Parse(rcvBuff);
               //this.logger.Debug("SML file of size {0} received.", rcvBuff.Count);
               return smlFile;
            }
            catch (SmlParseFailedException ex)
            {
               //this.logger.ErrorException("Parsing incoming file failed.", ex);
               Trace.WriteLine(string.Format("Port {0}. Parsing incoming file failed: {0}.", portName), ex.Message);

               // return file if there's a message inside.
               //if (smlFile.Count > 0)
               //{
               //   this.FileReceived = smlFile;
               //   return smlFile;
               //}

               continue;
            }
         }

         return smlFile;
      }