internal byte[] ReadDLMSPacket(GXDLMSClient cosem, Gurux.Common.IGXMedia media, byte[] data, int wt)
		{
			if (data == null)
			{
				return null;
			}
            ReceiveParameters<byte[]> args = new ReceiveParameters<byte[]>()
            {
                Eop = (byte)0x7E,
                Count = 5,
                WaitTime = wt
            };
            if (cosem.InterfaceType == InterfaceType.Net)
            {
                args.Eop = null;
                args.Count = 8;
                args.AllData = true;
            }
            int pos = 0;
            bool succeeded = false;
            lock (media.Synchronous)
            {
                media.Send(data, null);
                while (!succeeded && pos != 3)
                {
                    succeeded = media.Receive(args);
                    if (!succeeded)
                    {
                        //Try to read again...
                        if (++pos != 3)
                        {
                            System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3");
                            continue;
                        }
                        string err = "Failed to receive reply from the device in given time.";
                        GXLogWriter.WriteLog(err, (byte[])args.Reply);
                        throw new Exception(err);
                    }
                }                
                //Loop until whole m_Cosem packet is received.                
                while (!(succeeded = cosem.IsDLMSPacketComplete(args.Reply)))
                {
                    if (!media.Receive(args))
                    {
                        //Try to read again...
                        if (++pos != 3)
                        {
                            System.Diagnostics.Debug.WriteLine("Data receive failed. Try to resend " + pos.ToString() + "/3");
                            continue;
                        }
                        string err = "Failed to receive reply from the device in given time.";
                        GXLogWriter.WriteLog(err, (byte[])args.Reply);
                        throw new Exception(err);
                    }
                }                
            }
            object[,] errors = cosem.CheckReplyErrors(data, args.Reply);
            if (errors != null)
            {
                int error = (int)errors[0, 0];
                throw new GXDLMSException(error);
            }
            return args.Reply;
		}
        public override void ImportFromDevice(Control[] addinPages, GXDevice device, Gurux.Common.IGXMedia media)
        {            			
			media.Eop = device.GXClient.Eop;			
            GXDLT645Device dev = device as GXDLT645Device;
            dev.Parser.IgnoreFrame = false;
            Dictionary<ulong, object> items = GXDLT645Property.ReadDataID();
            GXCategory cat = device.Categories.Find("Default");
            if (cat == null)
            {
                cat = new GXCategory("Default");
                device.Categories.Add(cat);
            }
            media.Open();
            int count = 0;
            foreach (var it in items)
            {
                Progress(++count, items.Count);
                byte[] data = dev.Parser.ReadValue(it.Key);
                lock (media.Synchronous)
                {					
                    media.Send(data, null);
                    ReceiveParameters<byte[]> p = new ReceiveParameters<byte[]>()
                    {
                        Eop = media.Eop,
                        WaitTime = device.WaitTime
                    };
                    bool compleate = false;
                    try
                    {
                        while (!(compleate = dev.Parser.IsPacketComplete(it.Key, p.Reply)))
                        {
                            if (!media.Receive<byte[]>(p))
                            {
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Trace(ex.Message + Environment.NewLine);
                    }
                    // If data is not received or error has occurred.
                    if (!compleate || dev.Parser.IsError(p.Reply))
                    {
                        continue;
                    }
                    GXDLT645Data d = it.Value as GXDLT645Data;
                    if (d != null)
                    {
                        Trace(it.Key + " " + d.Name + Environment.NewLine);
                        cat.Properties.Add(new GXDLT645Property(it.Key, d.Name, d.Type, d.Access));
                    }
                    else
                    {
                        GXDLT645TableTemplate t = it.Value as GXDLT645TableTemplate;
                        Trace(it.Key + " " + t.Name + Environment.NewLine);
                        GXDLT645Table table = new GXDLT645Table();
                        table.Name = t.Name;
                        table.DataID = it.Key;
                        foreach (GXDLT645Data col in t.Columns)
                        {
                            table.Columns.Add(new GXDLT645Property(it.Key, col.Name, col.Type, col.Access));
                        }
                        device.Tables.Add(table);
                    }
                }
            }            
        }       
 /// <summary>
 /// Read table data from the meter.
 /// </summary>
 /// <remarks>
 /// With commmand R6 data can be read one row at the time and it is parsed on the fly.
 /// With other commands all data must first read before data can be parse.
 /// </remarks>
 /// <param name="media"></param>
 /// <param name="wt"></param>
 /// <param name="name"></param>
 /// <param name="start"></param>
 /// <param name="end"></param>
 /// <param name="level"></param>
 /// <returns></returns>
 public static object[][] ReadTable(Gurux.Common.IGXMedia media, int wt, string name, DateTime start, DateTime end, string parameters, int level, int count, out string[] columns)
 {
     columns = null;
     List<byte> reply = new List<byte>();
     string header, frame;
     //Read CRC.
     ReceiveParameters<byte[]> crc = new ReceiveParameters<byte[]>()
     {
         Count = 1,
         WaitTime = wt
     };
     List<byte> data = new List<byte>();
     data.Add(1);
     data.AddRange(GenerateReadTable(name, start, end, parameters, level, count));
     data.Add(3);
     data.Add(CalculateChecksum(data, 1, data.Count - 1));
     lock (media.Synchronous)
     {
         do
         {
             List<byte> tmp = new List<byte>(SendData(media, data == null ? null : data.ToArray(), '\0', wt, true, level == 6, false));
             data = null;
             if (level != 6 && tmp[tmp.Count - 1] == 0x3)
             {
                 crc.Count = 1;
                 if (!media.Receive(crc))
                 {
                     throw new Exception("Failed to receive reply from the device in given time.");
                 }
                 tmp.AddRange(crc.Reply);
             }
             else if (level == 6)
             {                        
                 if (GetPacket(tmp, true, out header, out frame) == null)
                 {
                     throw new Exception("Failed to receive reply from the device in given time.");
                 }
                 if (tmp[tmp.Count - 2] == 0x4)
                 {
                     //Send ACK if more data is left.
                     data = new List<byte>();
                     data.Add(6);
                     System.Threading.Thread.Sleep(200);
                 }
             }
             reply.AddRange(tmp);
         }
         while (reply[reply.Count - 2] != 0x3);
     }
     int status = 0;
     DateTime tm = DateTime.MinValue;
     int add = 0;
     return ParseTableData(reply.ToArray(), ref columns, ref status, ref tm, ref add, name);        
 }