private void ReadMoreData(object sender, GXPacket packet)
		{
			GXMBusDevice dev = (GXMBusDevice)GetDeviceFromSender(sender);
			packet.AppendData((byte)0x5B);
			packet.AppendData(dev.DeviceAddress);
		}
		private void Readout(object sender, GXPacket packet)
		{			
			GXMBusDevice device = (GXMBusDevice)GetDeviceFromSender(sender);
			IGXMedia media = (IGXMedia)device.GXClient.Media;

			bool isSerial = device.GXClient.MediaType == "Serial";
			if (isSerial)
			{
				((Gurux.Serial.GXSerial)media).BaudRate = 2400;
				((Gurux.Serial.GXSerial)media).DataBits = 8;
				((Gurux.Serial.GXSerial)media).Parity = System.IO.Ports.Parity.Even;
				((Gurux.Serial.GXSerial)media).StopBits = System.IO.Ports.StopBits.One;
			}


			List<byte> buff = new List<byte>(new byte[] {0x10, 0x40, device.DeviceAddress});
			buff.Add(CountShortFrameChecksum(buff.ToArray()));
			buff.Add(0x16);

			ReceiveParameters<byte[]> recParams = new ReceiveParameters<byte[]>();			
			lock (media.Synchronous)
			{
				recParams.AllData = true;
				recParams.Count = 1;
				recParams.Peek = false;
				recParams.Eop = null;
				recParams.Reply = null;
				recParams.WaitTime = device.WaitTime;

				media.Send(buff.ToArray(), null);
				if (!media.Receive(recParams))
				{
					throw new Exception("Handshake timeout.");
				}
			}
			System.Threading.Thread.Sleep(2000);

			if (!(recParams.Reply.Length > 0 && recParams.Reply[0] == 0xE5))
			{
				throw new Exception("Invalid handshake response.");
			}

			packet.Bop = (byte)0x10;
			packet.Eop = (byte)0x16;
			packet.ChecksumSettings.Position = -2;
            packet.ChecksumSettings.Type = ChecksumType.Sum8Bit;
			packet.ChecksumSettings.Start = 1;
			packet.ChecksumSettings.Count = -2;
			packet.AppendData((byte)0x5B);
			packet.AppendData(device.DeviceAddress);

			m_PreviousFCB = -1;
		}
        private void Disconnect(object sender, GXPacket packet)
		{
			GXIEC62056Device dev = null;
			if (sender is GXIEC62056Device)
			{
				dev = sender as GXIEC62056Device;
			}
			else if (sender is GXProperty)
			{
				dev = (sender as GXProperty).Device as GXIEC62056Device;
			}
			else
			{
				throw new Exception("InitRead failed. Unknown sender: " + sender.ToString());
			}
			if (dev.Mode != Protocol.ModeA)
			{
                packet.ResendCount = -1;
                packet.Eop = null;
                packet.ChecksumSettings.Position = -3;
                packet.ChecksumSettings.Count = -3;
                packet.AppendData("B0");
                packet.AppendData((byte) 3);
			}
		}
		private void ReadTableData(object sender, GXPacket packet)
		{
            GXIEC62056Table table = sender as GXIEC62056Table;		            
			DateTime start, end;
            (sender as IGXPartialRead).GetStartEndTime(out start, out end);
            packet.AppendData(IEC62056Parser.GenerateReadTable(table.Data, start, end, table.Parameters, table.ReadMode, table.ReadCount));
		}
		private void ReadData(object sender, GXPacket packet)
		{
			if (!(sender is GXIEC62056Property))
			{
				return;
			}
            GXIEC62056Property prop = sender as GXIEC62056Property;
            packet.AppendData("R" + prop.ReadMode.ToString());
            packet.AppendData((byte)2);
            packet.AppendData(prop.Data + "(" + prop.Parameters + ")");
		}
		private void ReadTableDataNext(object sender, GXPacket packet)
		{
			packet.Bop = null;
			packet.Eop = null;
			packet.ChecksumSettings.Type = ChecksumType.None;
			packet.AppendData((byte)0x06);
		}
 public void ExecuteSendCommand(object sender, string command, GXPacket packet)
 {
     if (command != "ReadAARQNext" && command != "ReadNextInfo" && command != "ReadNext")
     {
         IsMoreDataAvailable = RequestTypes.None;
     }
     GXDLMSProperty prop = sender as GXDLMSProperty;
     if (command == "InitRead")
     {
         LastNotifiedTransactionProgress = 0;
         InitRead(sender, packet);                
     }
     else if (command == "ReadSNRMSend")
     {
         LastNotifiedTransactionProgress = 0;
         ReadSNRMSend(sender, packet);            
     }
     else if (command == "ReadAARQ")
     {
         LastNotifiedTransactionProgress = 0;
         ReadAARQ(sender, packet);
     }
     else if (command == "ReadAARQNext")
     {
         LastNotifiedTransactionProgress = 0;
         ReadAARQNext(sender, packet);
     }            
     else if (command == "ReadData")
     {
         LastNotifiedTransactionProgress = 0;
         ReadData(prop, packet);
     }
     else if (command == "ReadDataType")
     {
         LastNotifiedTransactionProgress = 0;
         ReadDataType(prop, packet);                
     }
     else if (command == "WriteData")
     {
         LastNotifiedTransactionProgress = 0;
         WriteData(prop, packet);                
     }
     else if (command == "KeepAliveRequest")
     {
         LastNotifiedTransactionProgress = 0;
         //Network connection don't need this.
         if (!SupportNetworkSpecificSettings)
         {
             packet.AppendData(parser.GetKeepAlive());
         }
     }
     else if (command == "DisconnectRequest")
     {
         LastNotifiedTransactionProgress = 0;
         //Network connection don't need this.
         if (!SupportNetworkSpecificSettings)
         {
             packet.AppendData(parser.DisconnectRequest());
         }
     }
     else if (command == "ReadTableInfo")
     {
         if (this.Extension != null)
         {
             ReceivedData = null;
             ExtraInfoPos = 0;
             ExtraInfo.Clear();
             List<GXObisCode> items = new List<GXObisCode>();
             this.Extension.ReadExtraInfo(items);
             if (items.Count != 0)
             {
                 foreach (GXObisCode it in items)
                 {
                     ExtraInfo.Add(it, null);
                 }
                 GXObisCode item = items[0];
                 packet.AppendData(parser.Read(item.LogicalName, item.ObjectType, item.AttributeIndex)[0]);
             }
         }
     }
     else if (command == "ReadCapturePeriod")
     {
         ReceivedData = null;                
         GXDLMSTable table = sender as GXDLMSTable;
         //Capture period is read only once.
         if (table.CapturePeriod == 0)
         {
             if (parser.UseLogicalNameReferencing)
             {
                 packet.AppendData(parser.Read(table.LogicalName, Gurux.DLMS.ObjectType.ProfileGeneric, 4)[0]);
             }
             else
             {
                 packet.AppendData(parser.Read(table.ShortName, Gurux.DLMS.ObjectType.ProfileGeneric, 4)[0]);
             }
         }
     }                
     else if (command == "ReadTableContent")
     {
         //Check start and end times.
         DateTime starttm, endtm;
         GXDLMSTable table = sender as GXDLMSTable;
         (table as IGXPartialRead).GetStartEndTime(out starttm, out endtm);
         LastNotifiedTransactionProgress = 0;                
         ReceivedData = null;
         TryParse = false;
         if (parser.UseLogicalNameReferencing)
         {
             packet.AppendData(parser.Read(table.LogicalName, Gurux.DLMS.ObjectType.ProfileGeneric, 3)[0]);
         }
         else
         {
             packet.AppendData(parser.Read(table.ShortName, Gurux.DLMS.ObjectType.ProfileGeneric, 3)[0]);
         }
     }
     else if (command == "ReadNextInfo") //Read next part of the data or next item.
     {
         //Read next extra info.
         if (IsMoreDataAvailable == Gurux.DLMS.RequestTypes.None)
         {                                        
             GXObisCode item = ExtraInfo.Keys.ElementAt(ExtraInfoPos);
             object data = parser.Read(item.LogicalName, item.ObjectType, item.AttributeIndex)[0];
             packet.AppendData(data);
         }
         else //Read next part of the data.
         {
             Gurux.DLMS.RequestTypes readItem = Gurux.DLMS.RequestTypes.Frame;
             if ((IsMoreDataAvailable & RequestTypes.Frame) == 0)
             {
                 readItem = Gurux.DLMS.RequestTypes.DataBlock;
             }
             packet.AppendData(parser.ReceiverReady(readItem));
         }
     }
     else if (command == "ReadNext") //Read next part of data.
     {
         Gurux.DLMS.RequestTypes readItem = Gurux.DLMS.RequestTypes.Frame;
         if ((IsMoreDataAvailable & RequestTypes.Frame) == 0)
         {
             readItem = Gurux.DLMS.RequestTypes.DataBlock;
         }
         packet.AppendData(parser.ReceiverReady(readItem));
     }
     else if (command == "ReadTableData") //Read next part of data.
     {
         pg = Gurux.DLMS.GXDLMSClient.CreateObject(ObjectType.ProfileGeneric) as Gurux.DLMS.Objects.GXDLMSProfileGeneric;
         GXDLMSTable table2 = sender as GXDLMSTable;
         pg.CapturePeriod = table2.CapturePeriod;
         foreach (GXDLMSProperty col in table2.Columns)
         {
             GXDLMSObject item = Gurux.DLMS.GXDLMSClient.CreateObject(col.ObjectType);
             item.SetDataType(col.AttributeOrdinal, col.DLMSType);
             item.SetUIDataType(col.AttributeOrdinal, col.ValueType);
             item.LogicalName = col.LogicalName;
             //Update scaler for register.
             if (col is GXDLMSRegister && col.AttributeOrdinal == 2)
             {
                 GXDLMSRegister r = col as GXDLMSRegister;
                 if (item.ObjectType == ObjectType.DemandRegister)
                 {
                     (item as Gurux.DLMS.Objects.GXDLMSDemandRegister).Scaler = r.Scaler;
                 }
                 else
                 {
                     (item as Gurux.DLMS.Objects.GXDLMSRegister).Scaler = r.Scaler;
                 }
             }
             pg.CaptureObjects.Add(new GXKeyValuePair<GXDLMSObject, GXDLMSCaptureObject>(item, new GXDLMSCaptureObject(col.AttributeOrdinal, 0)));
         }
         LastNotifiedTransactionProgress = 0;
         GXDLMSTable table = sender as GXDLMSTable;                
         ReceivedRows = 0;
         TryParse = true;
         ReceivedData = null;                
         IGXPartialRead partialRead = table as IGXPartialRead;
         object name, data;
         int EDISType = 0, Version = 0;
         if (parser.UseLogicalNameReferencing)
         {
             name = table.LogicalName;
         }
         else
         {
             name = table.ShortName;
         }
         string ClockLN = "0.0.1.0.0.255";
         if (partialRead.Type == PartialReadType.All)
         {
             data = parser.Read(name, ObjectType.ProfileGeneric, 2)[0];
         }
         else if (partialRead.Type == PartialReadType.Entry)
         {
             data = parser.ReadRowsByEntry(name, Convert.ToInt32((table as IGXPartialRead).Start), Convert.ToInt32((table as IGXPartialRead).End));
         }                
         else
         {                    
             DateTime starttm = DateTime.MinValue, endtm = DateTime.MaxValue;                                        
             if (table.Columns.Count != 0)
             {
                 GXDLMSProperty col = table.Columns[0] as GXDLMSProperty;
                 EDISType = col.AttributeOrdinal;
                 Version = col.Version;
             }
             (table as IGXPartialRead).GetStartEndTime(out starttm, out endtm);
             System.Diagnostics.Debug.WriteLine("Reading table between: " + starttm.ToString() + "" + endtm.ToString());
             data = parser.ReadRowsByRange(name, ClockLN, Gurux.DLMS.ObjectType.Clock, Version, starttm, endtm);                    
         }
         packet.AppendData(data);
     }
     else
     {
         throw new NotImplementedException();
     }
 }      
 private void KeepAlive(GXIEC62056Device device, GXPacket packet)
 {
     if (device.AliveMode == 0)
     {
         packet.AppendData("R2");
         packet.AppendData((byte)2);
         packet.AppendData("0.0.0()");
     }
     else
     {
         packet.AppendData("R" + device.AliveMode.ToString());
         packet.AppendData((byte)2);
         packet.AppendData(device.AliveData + "(" + device.AliveParameters + ")");
     }
 }
 void WriteData(Gurux.Device.GXProperty property, GXPacket pack)
 {
     GXDLMSProperty prop = property as GXDLMSProperty;
     int AttributeOrdinal = ((GXDLMSProperty)prop).AttributeOrdinal;
     if (AttributeOrdinal < 1)
     {
         throw new Exception("Attribute Ordinal is invalid.");
     }
     object data = prop.GetValue(false);
     //Write component.
     if (parser.UseLogicalNameReferencing)
     {
         foreach (object it in parser.Write(prop.LogicalName, data, ObjectDataType, prop.ObjectType, AttributeOrdinal))
         {
             pack.AppendData(it);
         }
     }
     else //Use Short Name
     {
         uint sn = prop.ShortName;
         //If Short name not found.
         if (sn == 0)
         {
             throw new Exception("Short name not found.");
         }
         foreach (object it in parser.Write(sn, data, ObjectDataType, 0, AttributeOrdinal))
         {
             pack.AppendData(it);
         }
     }
 }
 /// <summary>
 /// Generate read message for selected property.
 /// </summary>
 /// <param name="property"></param>
 /// <param name="pack"></param>
 void ReadData(Gurux.Device.GXProperty property, GXPacket pack)
 {
     GXDLMSProperty prop = property as GXDLMSProperty;
     int AttributeOrdinal = ((GXDLMSProperty) prop).AttributeOrdinal;
     if (AttributeOrdinal < 1)
     {
         throw new Exception("Attribute Ordinal is invalid.");
     }
     //Read component.
     if (parser.UseLogicalNameReferencing)
     {
         pack.AppendData(parser.Read(prop.LogicalName, prop.ObjectType, AttributeOrdinal)[0]);
     }
     else //Use Short Name
     {
         uint sn = prop.ShortName;
         //If Short name not found.
         if (sn == 0)
         {
             throw new Exception("Short name not found.");
         }
         pack.AppendData(parser.Read(sn, 0, AttributeOrdinal)[0]);
     }
 }
 void ReadAARQNext(object sender, GXPacket GXPacket)
 {
     GXPacket.AppendData(AARQRequest.GetValue(AARQRequestPos));
     ++AARQRequestPos;
 }
 void ReadAARQ(object sender, GXPacket GXPacket)
 {            
     AARQRequest = parser.AARQRequest(null);
     int cnt = AARQRequest.Length;
     GXPacket.AppendData(AARQRequest.GetValue(AARQRequestPos));
     ++AARQRequestPos;
 }
 //Set the secondary station in connected mode and reset its sequence number variables.
 void ReadSNRMSend(object sender, GXPacket GXPacket)
 {
     GXDLMSDevice Device = sender as GXDLMSDevice;
     AARQRequestPos = 0;
     //Is connection made using network.
     bool NetConnect = !Device.UseRemoteSerial && Device.SupportNetworkSpecificSettings && Device.GXClient.Media is GXNet;
     //TODO: GXProperty.Device.KeepAliveEnabled = false;
     parser.Authentication = Device.Authentication;
     if (!string.IsNullOrEmpty(Device.Password))
     {
         parser.Password = ASCIIEncoding.ASCII.GetBytes(Device.Password);
     }
     else
     {
         parser.Password = null;
     }
     //GXCom is counting BOP, EOP and CRC.
     parser.GenerateFrame = false;
     //If Serial Number is used.	
     HDLCAddressType addressing = Device.HDLCAddressing;
      //If network media is used check is manufacturer supporting IEC 62056-47
     if (NetConnect)
     {
         GXPacket.Bop = GXPacket.Eop = null;
         GXPacket.ChecksumSettings.Type = ChecksumType.None;
         parser.InterfaceType = Gurux.DLMS.InterfaceType.Net;
         parser.ClientID = Convert.ToUInt16(Device.ClientID);
         parser.ServerID = Convert.ToUInt16(Device.PhysicalAddress);
     }
     else
     {
         if (addressing == HDLCAddressType.Custom)
         {
             parser.ClientID = Device.ClientID;
         }
         else
         {
             parser.ClientID = (byte)(Convert.ToByte(Device.ClientID) << 1 | 0x1);
         }
         if (addressing == HDLCAddressType.SerialNumber)
         {
             parser.ServerID = GXManufacturer.CountServerAddress(addressing, Device.SNFormula, Convert.ToUInt32(Device.SerialNumber), Device.LogicalAddress);
         }
         else
         {
             parser.ServerID = GXManufacturer.CountServerAddress(addressing, Device.SNFormula, Device.PhysicalAddress, Device.LogicalAddress);
         }
         object clientid = 0;
         if (parser.Authentication == Gurux.DLMS.Authentication.None)
         {
             clientid = Device.ClientID;
         }
         else if (parser.Authentication == Gurux.DLMS.Authentication.Low)
         {
             clientid = Device.ClientIDLow;
         }
         else if (parser.Authentication == Gurux.DLMS.Authentication.High)
         {
             clientid = Device.ClientIDHigh;
         }
         if (addressing == HDLCAddressType.Custom)
         {
             parser.ClientID = clientid;
         }
         else
         {
             parser.ClientID = (byte)(Convert.ToByte(clientid) << 1 | 0x1);
         }
     }
     // If Network standard is used SNRM message is not send.
     if (SupportNetworkSpecificSettings)
     {
         GXPacket.ClearData();
     }
     else
     {
         GXPacket.AppendData(parser.SNRMRequest());
     }
 }