/// <summary>
 /// Default constructor
 /// </summary>
 public GXCategoryEventArgs(GXCategory category, CategoryStates status)
     : base(category)
 {
     Status = status;
 }
        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>
		/// Creates a new instance of all protocol addin GXCategory Types.
		/// </summary>
        public GXCategory[] GetCategories(object parent)
        {
			Type[] types = this.GetCategoryTypes(parent);
            GXCategory[] categories = new GXCategory[types.Length];
            for (int pos = 0; pos != types.Length; ++pos)
            {
                categories[pos] = Activator.CreateInstance(types[pos]) as GXCategory;
            }
            return categories;
        }
 /// <summary>
 /// Update categories data.
 /// </summary>
 /// <param name="trace"></param>
 /// <param name="progressbar"></param>
 /// <param name="media"></param>
 /// <param name="Device"></param>
 /// <param name="wt"></param>
 /// <param name="cosem"></param>
 /// <param name="man"></param>
 /// <param name="objs"></param>
 /// <param name="dataItems"></param>
 /// <param name="registers"></param>
 private object UpdateData(Gurux.Common.IGXMedia media, GXDLMSDevice Device, int wt, GXDLMSClient cosem, GXManufacturer man, GXDLMSObject it, GXCategory dataItems, GXCategory registers)
 {
     GXObisCode code = man.ObisCodes.FindByLN(it.ObjectType, it.LogicalName, null);            
     if (it.ObjectType == ObjectType.Register)
     {
         GXDLMSRegister prop = new GXDLMSRegister();
         UpdateObject(it, prop, 2);
         registers.Properties.Add(prop);
         return prop;
     }
     else if (it.ObjectType == Gurux.DLMS.ObjectType.Data)
     {
         GXDLMSProperty prop = new GXDLMSProperty();
         prop.ObjectType = ObjectType.Data;
         UpdateObject(it, prop, 2);
         dataItems.Properties.Add(prop);
         return prop;
     }
     else if (it.ObjectType == Gurux.DLMS.ObjectType.ProfileGeneric)
     {
         GXDLMSProfileGeneric pg = it as GXDLMSProfileGeneric;
         GXDLMSTable table = new GXDLMSTable();
         table.Name = it.LogicalName + " " + it.Description;
         table.ShortName = it.ShortName;
         table.LogicalName = it.LogicalName;
         table.AccessMode = Gurux.Device.AccessMode.Read;
         foreach(var it2 in pg.CaptureObjects)
         {
             GXDLMSProperty prop;
             if (it2.Key is Gurux.DLMS.Objects.GXDLMSRegister)
             {
                 Gurux.DLMS.Objects.GXDLMSRegister tmp = it2.Key as Gurux.DLMS.Objects.GXDLMSRegister;
                 GXDLMSRegister r = new GXDLMSRegister();
                 prop = r;
                 r.Scaler = tmp.Scaler;
                 r.Unit = tmp.Unit.ToString();                    
             }
             else
             {
                 prop = new GXDLMSProperty();
             }
             int index = it2.Value.AttributeIndex;
             prop.Name = it2.Key.LogicalName + " " + it2.Key.Description;
             prop.ObjectType = it2.Key.ObjectType;
             prop.AttributeOrdinal = index;
             prop.LogicalName = it2.Key.LogicalName;
             table.Columns.Add(prop);
             prop.DLMSType = it.GetDataType(index);                    
             prop.ValueType = it2.Key.GetUIDataType(index);
         }
         Device.Tables.Add(table);
         return table; 
     }
     GXDLMSCategory cat = new GXDLMSCategory();
     cat.ObjectType = it.ObjectType;
     UpdateObject(it, cat);
     Device.Categories.Add(cat);
     return cat;            
 }
 internal void CreateColumns(Gurux.Common.IGXMedia media, GXDLMSDevice Device, GXManufacturer man, int wt, GXDLMSClient cosem, IGXManufacturerExtension Extension, GXCategory dataItems, GXCategory registers, GXDLMSObject it, GXDLMSTable table)
 {            
 }
		/// <summary>
		/// Import properties from the device.
		/// </summary>
        /// <param name="addinPages">Addin pages.</param>
        /// <param name="device">The target GXDevice to put imported items.</param>
		/// <param name="media">A media connection to the device.</param>
		/// <returns>True if there were no errors, otherwise false.</returns>
        public override void ImportFromDevice(Control[] addinPages, GXDevice device, IGXMedia media)
		{
            media.Open();
			GXDLMSDevice Device = (GXDLMSDevice)device;            
			int wt = Device.WaitTime;
			GXDLMSClient cosem = null;
            byte[] data, reply = null;            
            IGXManufacturerExtension Extension = null;
			try
			{                
				//Initialize connection.
                cosem = new GXDLMSClient();
                cosem.UseLogicalNameReferencing = Device.UseLogicalNameReferencing;				
                if (Device.Manufacturers == null)
                {
                    Device.Manufacturers = new GXManufacturerCollection();
                    GXManufacturerCollection.ReadManufacturerSettings(Device.Manufacturers);
                }
                GXManufacturer man = Device.Manufacturers.FindByIdentification(Device.Identification);
                if (!string.IsNullOrEmpty(man.Extension))
                {
                    Type t = Type.GetType(man.Extension);
                    Extension = Activator.CreateInstance(t) as IGXManufacturerExtension;
                }

                if (!Device.UseRemoteSerial && media is GXNet) //If media is network.
				{
                    if (Device.SupportNetworkSpecificSettings)
                    {
                        cosem.InterfaceType = Gurux.DLMS.InterfaceType.Net;
                    }
				}
				else if (media is GXSerial) //If media is serial.
				{
                    byte terminator = 0xA;
                    if (Device.StartProtocol == StartProtocolType.IEC)
                    {
                        GXSerial serial = media as GXSerial;
                        serial.Eop = terminator;
                        serial.Eop = terminator;
                        //Init IEC connection. This must done first with serial connections.
                        string str = "/?" + Device.SerialNumber + "!\r\n";
                        ReceiveParameters<string> args = new ReceiveParameters<string>()
                        {
                            Eop = terminator,
                            WaitTime = wt
                        };
                        lock (media.Synchronous)
                        {
                            media.Send(str, null);
                            do
                            {
                                args.Reply = null;                                
                                if (!media.Receive(args))
                                {
                                    throw new Exception("Failed to receive reply from the device in given time.");
                                }
                            }
                            while (str == args.Reply);//Remove echo
                        }
                        string answer = args.Reply.ToString();                        
                        if (answer[0] != '/')
                        {
                            throw new Exception("Invalid responce.");
                        }
                        string manufactureID = answer.Substring(1, 3);
                        char baudrate = answer[4];
                        if (baudrate == ' ')
                        {
                            baudrate = '5';
                        }
                        int baudRate = 0;
                        switch (baudrate)
                        {
                            case '0':
                                baudRate = 300;
                                break;
                            case '1':
                                baudRate = 600;
                                break;
                            case '2':
                                baudRate = 1200;
                                break;
                            case '3':
                                baudRate = 2400;
                                break;
                            case '4':
                                baudRate = 4800;
                                break;
                            case '5':                            
                                baudRate = 9600;
                                break;
                            case '6':
                                baudRate = 19200;
                                break;
                            default:
                                throw new Exception("Unknown baud rate.");
                        }                        
                        //Send ACK
                        //Send Protocol control character
                        byte controlCharacter = (byte)'2';// "2" HDLC protocol procedure (Mode E)
                        //Send Baudrate character
                        //Mode control character 
                        byte ModeControlCharacter = (byte)'2';//"2" //(HDLC protocol procedure) (Binary mode)
                        //We are not receive anything.
                        data = new byte[] { 0x06, controlCharacter, (byte)baudrate, ModeControlCharacter, 0x0D, 0x0A };                        
                        lock (media.Synchronous)
                        {
                            args.Reply = null;                            
                            media.Send(data, null);                                                       
                            //This is in standard. Do not remove sleep.
                            //Some meters work without it, but some do not.
                            System.Threading.Thread.Sleep(500);
                            serial.BaudRate = baudRate;
                            ReceiveParameters<byte[]> args2 = new ReceiveParameters<byte[]>()
                            {
                                Eop = terminator,
                                WaitTime = 100
                            };
                            //If this fails, just read all data.
                            if (!media.Receive(args2))
                            {
                                //Read buffer.
                                args2.AllData = true;
                                args2.WaitTime = 1;
                                media.Receive(args2);
                            }
                            serial.DataBits = 8;
                            serial.Parity = Parity.None;
                            serial.StopBits = StopBits.One;
                            serial.DiscardInBuffer();
                            serial.DiscardOutBuffer();
                            serial.ResetSynchronousBuffer();
                        }                        
                    }
				}
                media.Eop = (byte) 0x7E;
                cosem.Authentication = (Gurux.DLMS.Authentication)Device.Authentication;
                object clientAdd = null;
                if (cosem.Authentication == Authentication.None)
                {
                    clientAdd = Device.ClientID;
                }
                else if (cosem.Authentication == Authentication.Low)
                {
                    clientAdd = Device.ClientIDLow;
                }
                else if (cosem.Authentication == Authentication.High)
                {
                    clientAdd = Device.ClientIDHigh;
                }
                if (!string.IsNullOrEmpty(Device.Password))
                {
                    cosem.Password = ASCIIEncoding.ASCII.GetBytes(Device.Password);
                }
                else
                {
                    cosem.Password = null;
                }
                //If network media is used check is manufacturer supporting IEC 62056-47
                if (!Device.UseRemoteSerial && media is GXNet && Device.SupportNetworkSpecificSettings)
                {
                    cosem.InterfaceType = InterfaceType.Net;
                    media.Eop = null;
                    cosem.ClientID = Convert.ToUInt16(clientAdd);
                    cosem.ServerID = Convert.ToUInt16(Device.PhysicalAddress);
                }
                else
                {
                    if (Device.HDLCAddressing == HDLCAddressType.Custom)
                    {
                        cosem.ClientID = clientAdd;
                    }
                    else
                    {
                        cosem.ClientID = (byte)(Convert.ToByte(clientAdd) << 1 | 0x1);
                    }
                    if (Device.HDLCAddressing == HDLCAddressType.SerialNumber)
                    {
                        cosem.ServerID = GXManufacturer.CountServerAddress(Device.HDLCAddressing, Device.SNFormula, Convert.ToUInt32(Device.SerialNumber), Device.LogicalAddress);
                    }
                    else
                    {
                        cosem.ServerID = GXManufacturer.CountServerAddress(Device.HDLCAddressing, Device.SNFormula, Device.PhysicalAddress, Device.LogicalAddress);
                    }                    
                }
                byte[] allData = null;
                data = cosem.SNRMRequest();
				//General Network connection don't need SNRMRequest.
				if (data != null)
				{
					Trace("--- Initialize DLMS connection\r\n");
					try
					{
						reply = ReadDLMSPacket(cosem, media, data, wt);
					}
					catch (Exception Ex)
					{
						throw new Exception("DLMS Initialize failed. " + Ex.Message);
					}
					//Has server accepted client.
					cosem.ParseUAResponse(reply);
				}
				Trace("Connecting\r\n");
                media.ResetSynchronousBuffer();
				try
				{                    
                    foreach (byte[] it in cosem.AARQRequest(null))
                    {                        
                        reply = ReadDLMSPacket(cosem, media, it, wt);
                    }
				}
				catch (Exception Ex)
				{
					throw new Exception("DLMS AARQRequest failed. " + Ex.Message);
				}
                cosem.ParseAAREResponse(reply);
                //Now 1/5 or actions is done.
                Progress(1, 5);
                Trace("Read Objects\r\n");
                try
				{
                    allData = ReadDataBlock(cosem, media, cosem.GetObjectsRequest(), wt, 1);
				}
				catch (Exception Ex)
				{
					throw new Exception("DLMS AARQRequest failed. " + Ex.Message);
				}
                Trace("--- Parse Objects ---\r\n");
                GXDLMSObjectCollection objs = cosem.ParseObjects((byte[])allData, true);

			    allData = null;
				//Now we know exact number of read registers. Update progress bar again.
                int max = objs.Count;				                
				Trace("--- Read scalars ---\r\n");
				//Now 2/5 or actions is done.
                Progress(2 * max, 5 * max);
                GXCategory dataItems = new GXCategory();
                dataItems.Name = "Data Items";
                GXCategory registers = new GXCategory();
                registers.Name = "Registers";
                Device.Categories.Add(dataItems);
                Device.Categories.Add(registers);
                int pos = 0;
                foreach (GXDLMSObject it in objs)
                {
                    ++pos;
                    //Skip association views.
                    if (it.ObjectType == ObjectType.AssociationLogicalName ||
                        it.ObjectType == ObjectType.AssociationShortName)
                    {
                        continue;
                    }
                    if (it.ObjectType != ObjectType.ProfileGeneric)
                    {
                        object prop = UpdateData(media, Device, wt, cosem, man, it, dataItems, registers);
                        //Read scaler and unit
                        if (it.ObjectType == ObjectType.Register)
                        {
                            try
                            {
                                data = cosem.Read(it.Name, it.ObjectType, 3)[0];
                                allData = ReadDataBlock(cosem, media, data, wt, 2);
                                cosem.UpdateValue(allData, it, 3);
                                Gurux.DLMS.Objects.GXDLMSRegister item = it as Gurux.DLMS.Objects.GXDLMSRegister;
                                GXDLMSRegister r = prop as GXDLMSRegister;
                                r.Scaler = item.Scaler;
                                r.Unit = item.Unit.ToString();
                            }
                            //Ignore HW error and read next.
                            catch (GXDLMSException)
                            {
                                continue;
                            }
                            catch (Exception Ex)
                            {
                                throw new Exception("DLMS Register Scaler and Unit read failed. " + Ex.Message);
                            }
                        }
                        //Read scaler and unit
                        else if (it.ObjectType == ObjectType.ExtendedRegister)
                        {
                            try
                            {
                                data = cosem.Read(it.Name, it.ObjectType, 3)[0];
                                allData = ReadDataBlock(cosem, media, data, wt, 2);
                                cosem.UpdateValue(allData, it, 3);
                                Gurux.DLMS.Objects.GXDLMSExtendedRegister item = it as Gurux.DLMS.Objects.GXDLMSExtendedRegister;
                                GXDLMSCategory cat = prop as GXDLMSCategory;
                                GXDLMSRegister r = cat.Properties[0] as GXDLMSRegister;
                                r.Scaler = item.Scaler;
                                r.Unit = item.Unit.ToString();
                                cat.Properties[1].SetValue(item.Scaler.ToString() + ", " + item.Unit.ToString(), true, PropertyStates.None);
                            }
                            //Ignore HW error and read next.
                            catch (GXDLMSException)
                            {
                                continue;
                            }
                            catch (Exception Ex)
                            {
                                throw new Exception("DLMS Register Scaler and Unit read failed. " + Ex.Message);
                            }
                        }
                        //Read scaler and unit
                        else if (it.ObjectType == ObjectType.DemandRegister)
                        {
                            try
                            {
                                data = cosem.Read(it.Name, it.ObjectType, 3)[0];
                                allData = ReadDataBlock(cosem, media, data, wt, 2);
                                cosem.UpdateValue(allData, it, 3);
                                Gurux.DLMS.Objects.GXDLMSDemandRegister item = it as Gurux.DLMS.Objects.GXDLMSDemandRegister;
                                GXDLMSCategory cat = prop as GXDLMSCategory;
                                cat.Properties[2].SetValue(item.Scaler.ToString() + ", " + item.Unit.ToString(), true, PropertyStates.None);

                                GXDLMSRegister r = cat.Properties[0] as GXDLMSRegister;
                                r.Scaler = item.Scaler;
                                r.Unit = item.Unit.ToString();
                                r = cat.Properties[1] as GXDLMSRegister;
                                r.Scaler = item.Scaler;
                                r.Unit = item.Unit.ToString();
                            }
                            //Ignore HW error and read next.
                            catch (GXDLMSException)
                            {
                                continue;
                            }
                            catch (Exception Ex)
                            {
                                throw new Exception("DLMS Register Scaler and Unit read failed. " + Ex.Message);
                            }
                        }                        
                    }
                    //Now 3/5 actions is done.
                    double tmp = pos * max; 
                    tmp /= max;
                    tmp += 2 * max;
                    Progress((int) tmp , 5 * max);
                }
                //Now 3/5 actions is done.
                Progress(3 * max, 5 * max);
                Trace("--- Read Generic profiles ---\r\n");
                GXDLMSObjectCollection pg = objs.GetObjects(ObjectType.ProfileGeneric);
                foreach (GXDLMSProfileGeneric it in pg)
                {
                    try
                    {
                        allData = ReadDataBlock(cosem, media, cosem.Read(it.Name, it.ObjectType, 3)[0], wt, 3);
                        cosem.UpdateValue(allData, it, 3);
                        UpdateData(media, Device, wt, cosem, man, it, dataItems, registers);
                    }
                    //Ignore HW error and read next.
                    catch (GXDLMSException)
                    {
                        continue;
                    }
                    catch (Exception Ex)
                    {
                        Trace("DLMS Generic Profile read failed. " + Ex.Message + Environment.NewLine);
                    }
                }
                //Now 4/5 actions is done.
                Progress(4 * max, 5 * max);            

                //Update IEC HDLC interval if found. 
                GXDLMSObjectCollection objects = objs.GetObjects(ObjectType.IecHdlcSetup);
                if (objects.Count != 0)
                {
                    allData = ReadDataBlock(cosem, media, cosem.Read(objects[0].Name, objects[0].ObjectType, 8)[0], wt, 5);
                    //Minus 10 second.
                    Device.Keepalive.Interval = (Convert.ToInt32(cosem.GetValue(allData)) - 10) * 1000;
                }

                //Now all actions are done.
                Progress(max, max);
                Trace("--- Succeeded ---\r\n");
			}
			finally
			{                
                if (cosem != null && media != null)
				{
					Trace("--- Disconnecting ---\r\n");
                    byte[] allData = null;
					if (cosem != null)
					{
						//Network standard don't need this.					
                        if (!(media is GXNet && Device.SupportNetworkSpecificSettings))
						{
							try
							{
								reply = ReadDLMSPacket(cosem, media, cosem.DisconnectRequest(), wt);
								cosem.GetDataFromPacket(reply, ref allData);
							}
							catch (Exception Ex)
							{
								Trace("DisconnectRequest failed. " + Ex.Message);
							}
						}
					}
					if (media != null)
					{
						media.Close();
						media = null;
					}
					Trace("--- Disconnected ---\r\n--- Done---\r\n");					
				}
			}			
		}
        private void ShowAvailableCategory(GXCategory cat, TreeNode root)
        {
#if DEBUG
            m_ObjectIDs.Add(cat.ID, cat);
#endif //DEBUG
            System.Diagnostics.Debug.Assert(DeviceToTreeNode[cat] == null);
            TreeNode node = root.Nodes.Add(cat.DisplayName);
            node.Tag = cat;
            //If device ID is nill.
            ulong id = cat.ID;
            System.Diagnostics.Debug.Assert((id >> 16) != 0);
            //If category ID is nill.
            System.Diagnostics.Debug.Assert((id & 0xFFFF) != 0);
            node.SelectedImageIndex = node.ImageIndex = (int)DeviceImageType.DeviceCategory;
            DeviceToTreeNode[cat] = node;
            ShowAvailableProperties(cat.Properties, node);
        }
 public void UpdateColumns(GXDLMSDevice Device, 
             GXManufacturer man, GXDLMSClient cosem,
             Gurux.Common.IGXMedia media, int wt, Gurux.DLMS.Objects.GXDLMSObject it,
             GXDLMSTable table, GXDLMSAddIn parent, GXCategory dataItems, GXCategory registers)
 {
     //Reading data.                
     //If Load profile1
     if (it.LogicalName == "0.0.99.1.2.255")
     {
         //Read Load Profile 1 information
         byte[] allData = parent.ReadDataBlock(cosem, media, cosem.Read("0.0.99.128.1.255", ObjectType.ProfileGeneric, 2)[0], wt, 0);
         object[] items = (object[])((object[])cosem.GetValue(allData)).GetValue(0);
         int pos = 0;
         AddColumn(cosem, man, table, null, null, 0, "DateTime");
         AddColumn(cosem, man, table, null, null, 1, "Status");
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 2, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 3, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 4, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 5, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 6, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 7, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 8, null);
         pos += 2;
         AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 9, null);                
         return;
     }           
     parent.CreateColumns(media, Device, man, wt, cosem, this, dataItems, registers, it, table);                    
 }