/// <summary> /// Constructor. /// </summary> /// <param name="ln">Logical name settings.</param> /// <param name="hdlc">HDLC settings.</param> public GXDLMSBase(GXDLMSAssociationLogicalName ln, GXDLMSHdlcSetup hdlc) : base(ln, hdlc) { MaxReceivePDUSize = 1024; //Default secret. ln.Secret = ASCIIEncoding.ASCII.GetBytes("Gurux"); }
/// <summary> /// Constructor. /// </summary> /// <param name="sn">Short name settings.</param> /// <param name="hdlc">HDLC settings.</param> public GXDLMSBase(GXDLMSAssociationShortName sn, GXDLMSHdlcSetup hdlc) : base(sn, hdlc, "GRX", 12345678) { MaxReceivePDUSize = 1024; //Default secret. sn.Secret = ASCIIEncoding.ASCII.GetBytes("Gurux"); }
///<summary> /// Constructor. ///</summary> ///<param name="sn">Short name settings. </param> ///<param name="hdlc"> /// Interface type. ///</param> ///<param name="flagID"> /// Three letters FLAG ID. ///</param> ///<param name="serialNumber"> /// Meter serial number. Size of serial number is 5 bytes. ///</param> public GXDLMSSecureServer(GXDLMSAssociationShortName sn, GXDLMSHdlcSetup hdlc, string flagID, UInt64 serialNumber) : base(sn, hdlc) { if (flagID == null || flagID.Length != 3) { throw new ArgumentOutOfRangeException("Invalid FLAG ID."); } if (flagID == null || flagID.Length != 3) { throw new ArgumentOutOfRangeException("Invalid FLAG ID."); } GXByteBuffer bb = new GXByteBuffer(); bb.Add(flagID); GXByteBuffer serial = new GXByteBuffer(); serial.SetUInt64(serialNumber); bb.Set(serial.Data, 3, 5); Ciphering = new GXCiphering(bb.Array()); Settings.Cipher = Ciphering; }
///<summary> /// Constructor. ///</summary> ///<param name="logicalNameReferencing"> /// Is logical name referencing used. ///</param> ///<param name="type"> /// Interface type. ///</param> public GXDLMSSecureServer(GXDLMSAssociationLogicalName ln, GXDLMSHdlcSetup hdlc) : base(ln, hdlc) { Ciphering = new GXCiphering(ASCIIEncoding.ASCII.GetBytes("ABCDEFGH")); Settings.Cipher = Ciphering; }
/// <summary> /// Initialize server. /// </summary> /// <remarks> /// This must call after server objects are set. /// </remarks> public void Initialize() { bool association = false; Initialized = true; for (int pos = 0; pos != Items.Count; ++pos) { GXDLMSObject it = Items[pos]; if (this.UseLogicalNameReferencing && (string.IsNullOrEmpty(it.LogicalName) || it.LogicalName.Split('.').Length != 6)) { throw new Exception("Invalid Logical Name."); } it.Start(this); if (it is GXDLMSProfileGeneric) { GXDLMSProfileGeneric pg = it as GXDLMSProfileGeneric; foreach (var obj in pg.CaptureObjects) { if (obj.Value.AttributeIndex < 1) { throw new Exception("Invalid attribute index. SelectedAttributeIndex is not set for " + obj.Key.Name); } } } else if (it is GXDLMSAssociationShortName && !this.UseLogicalNameReferencing) { if ((it as GXDLMSAssociationShortName).ObjectList.Count == 0) { (it as GXDLMSAssociationShortName).ObjectList.AddRange(this.Items); } association = true; } else if (it is GXDLMSAssociationLogicalName && this.UseLogicalNameReferencing) { if ((it as GXDLMSAssociationLogicalName).ObjectList.Count == 0) { (it as GXDLMSAssociationLogicalName).ObjectList.AddRange(this.Items); } association = true; } else if (it is GXDLMSHdlcSetup) { hdlcSetup = it as GXDLMSHdlcSetup; } else if (!(it is IGXDLMSBase))//Remove unsupported items. { Debug.WriteLine(it.ObjectType.ToString() + " not supported."); Items.RemoveAt(pos); --pos; } } if (!association) { if (UseLogicalNameReferencing) { GXDLMSAssociationLogicalName it = new GXDLMSAssociationLogicalName(); it.ObjectList = this.Items; Items.Add(it); } else { GXDLMSAssociationShortName it = new GXDLMSAssociationShortName(); it.ObjectList = this.Items; Items.Add(it); } } //Arrange items by Short Name. int sn = 0xA0; int offset, count; if (!this.UseLogicalNameReferencing) { foreach (GXDLMSObject it in Items) { //Generate Short Name if not given. if (it.ShortName == 0) { it.ShortName = (ushort)sn; //Add method index addresses. GXDLMS.GetActionInfo(it.ObjectType, out offset, out count); if (count != 0) { sn += offset + (8 * count); } else //If there are no methods. { //Add attribute index addresses. sn += 8 * (it as IGXDLMSBase).GetAttributeCount(); } } } } }
/// <summary> /// Initialize server. /// </summary> /// <remarks> /// This must call after server objects are set. /// <param name="manually">If true, server handle objects and all data are updated manually.</param> public void Initialize(bool manually) { Initialized = true; if (manually) { return; } bool association = false; for (int pos = 0; pos != Items.Count; ++pos) { GXDLMSObject it = Items[pos]; if (this.UseLogicalNameReferencing && (string.IsNullOrEmpty(it.LogicalName) || it.LogicalName.Split('.').Length != 6)) { throw new Exception("Invalid Logical Name."); } it.Start(this); if (it is GXDLMSProfileGeneric) { GXDLMSProfileGeneric pg = it as GXDLMSProfileGeneric; foreach (var obj in pg.CaptureObjects) { if (obj.Value.AttributeIndex < 1) { throw new Exception("Invalid attribute index. SelectedAttributeIndex is not set for " + obj.Key.Name); } } } else if (it is GXDLMSAssociationShortName && !this.UseLogicalNameReferencing) { if ((it as GXDLMSAssociationShortName).ObjectList.Count == 0) { (it as GXDLMSAssociationShortName).ObjectList.AddRange(this.Items); } association = true; } else if (it is GXDLMSAssociationLogicalName && this.UseLogicalNameReferencing) { if ((it as GXDLMSAssociationLogicalName).ObjectList.Count == 0) { (it as GXDLMSAssociationLogicalName).ObjectList.AddRange(this.Items); } association = true; } else if (it is GXDLMSHdlcSetup) { hdlcSetup = it as GXDLMSHdlcSetup; } else if (!(it is IGXDLMSBase))//Remove unsupported items. { Debug.WriteLine(it.ObjectType.ToString() + " not supported."); Items.RemoveAt(pos); --pos; } } if (!association) { if (UseLogicalNameReferencing) { GXDLMSAssociationLogicalName it = new GXDLMSAssociationLogicalName(); it.ObjectList = this.Items; Items.Add(it); } else { GXDLMSAssociationShortName it = new GXDLMSAssociationShortName(); it.ObjectList = this.Items; Items.Add(it); } } //Arrange items by Short Name. UpdateShortNames(false); }
/// <summary> /// Execute basic tests. /// </summary> /// <param name="settings">Settings.</param> /// <param name="output">Generated output.</param> public static bool Basic(GXSettings settings, GXOutput output) { Reader.GXDLMSReader reader = new Reader.GXDLMSReader(settings.client, settings.media, settings.trace, settings.iec); reader.WaitTime = settings.WaitTime; try { settings.media.Open(); } catch (System.Net.Sockets.SocketException e) { //If failed to make connection to the meter. output.Errors.Add("Failed to connect to the meter: " + e.Message); output.MakeReport(); return(false); } if (settings.trace > TraceLevel.Error) { Console.WriteLine("------------------------------------------------------------"); Console.WriteLine("Initialize connection."); } reader.InitializeConnection(); if (settings.trace > TraceLevel.Error) { Console.WriteLine("Get association view."); } reader.GetAssociationView(false); if (settings.client.UseLogicalNameReferencing) { output.PreInfo.Add("Testing using Logical Name referencing."); } else { output.PreInfo.Add("Testing using Short Name referencing."); } output.PreInfo.Add("Authentication level: " + settings.client.Authentication); output.PreInfo.Add("Total amount of objects: " + settings.client.Objects.Count.ToString()); if (settings.client.UseLogicalNameReferencing) { if (settings.trace > TraceLevel.Error) { Console.WriteLine("Finding Logical Device Name and SAP."); } GXDLMSObject ldn = settings.client.Objects.FindByLN(ObjectType.None, "0.0.42.0.0.255"); GXDLMSObjectCollection saps = settings.client.Objects.GetObjects(ObjectType.SapAssignment); if (ldn == null && saps.Count == 0) { output.Errors.Add("Logical Device Name or SAP is not implemented. Read more: GB: 4.1.8.4."); } if (settings.trace > TraceLevel.Error) { if (ldn != null) { reader.Read(ldn, 2); output.PreInfo.Add("Meter Logical Device Name is: " + (ldn as GXDLMSData).Value.ToString() + "."); } if (saps.Count != 0) { output.PreInfo.Add("SAP is not implemented."); } } } //Check OBIS codes. foreach (GXDLMSObject it in settings.client.Objects) { if (it.Description == "Invalid") { output.Errors.Add("Invalid OBIS code " + it.LogicalName + " for <a target=\"_blank\" href=http://www.gurux.fi/" + it.GetType().FullName + ">" + it.ObjectType + "</a>."); if (settings.trace > TraceLevel.Warning) { Console.WriteLine("------------------------------------------------------------"); Console.WriteLine(it.LogicalName + ": Invalid OBIS code."); } } } //Read structures of Cosem objects. List <KeyValuePair <string, List <GXDLMSXmlPdu> > > cosemTests = new List <KeyValuePair <string, List <GXDLMSXmlPdu> > >(); GXDLMSTranslator translator = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); foreach (string it in GetTests()) { using (Stream stream = typeof(Program).Assembly.GetManifestResourceStream(it)) using (StreamReader sr = new StreamReader(stream)) { XmlDocument doc = new XmlDocument(); doc.LoadXml(sr.ReadToEnd()); XmlNodeList list = doc.SelectNodes("/Messages/GetRequest/GetRequestNormal"); ObjectType ot = ObjectType.None; foreach (XmlNode node in list) { ot = (ObjectType)int.Parse(node.SelectNodes("AttributeDescriptor/ClassId")[0].Attributes["Value"].Value); //If this object type is skipped. if (settings.excludedObjects.Contains(ot)) { output.Info.Add("Skipping " + ot.ToString() + " object types."); break; } int index = int.Parse(node.SelectNodes("AttributeDescriptor/AttributeId")[0].Attributes["Value"].Value); //Update logical name. foreach (GXDLMSObject obj in settings.client.Objects.GetObjects(ot)) { if ((obj.GetAccess(index) & AccessMode.Read) != 0) { string tmp = GXCommon.ToHex(LogicalNameToBytes(obj.LogicalName), false); foreach (XmlNode n in list) { XmlAttribute ln = n.SelectNodes("AttributeDescriptor/InstanceId")[0].Attributes["Value"]; ln.Value = tmp; } cosemTests.Add(new KeyValuePair <string, List <GXDLMSXmlPdu> >(ot.ToString(), settings.client.LoadXml(doc.InnerXml))); } } break; } } } foreach (KeyValuePair <string, List <GXDLMSXmlPdu> > it in cosemTests) { try { Execute(settings, reader, it.Key, it.Value, output); } catch (Exception ex) { if (settings.trace > TraceLevel.Off) { Console.WriteLine("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); Console.WriteLine(ex.Message); } } } List <ObjectType> unknownDataTypes = new List <ObjectType>(); foreach (GXDLMSObject o in settings.client.Objects) { if (!unknownDataTypes.Contains(o.ObjectType)) { bool found = false; foreach (KeyValuePair <string, List <GXDLMSXmlPdu> > t in cosemTests) { if (o.ObjectType.ToString() == t.Key) { found = true; break; } } if (!found) { unknownDataTypes.Add(o.ObjectType); output.Warnings.Add("<a target=\"_blank\" href=http://www.gurux.fi/" + o.GetType().FullName + ">" + o.ObjectType + "</a> is not tested."); } } } //Check InactivityTimeout. bool fail = false; int rc = reader.RetryCount; int wt = reader.WaitTime; int inactivityTimeout; if (settings.client.InterfaceType == InterfaceType.HDLC) { GXDLMSHdlcSetup s = (GXDLMSHdlcSetup)settings.client.Objects.GetObjects(ObjectType.IecHdlcSetup)[0]; s.InactivityTimeout = 0; reader.Read(s, 8); inactivityTimeout = s.InactivityTimeout; output.PreInfo.Add("HdlcSetup default inactivity timeout value is " + inactivityTimeout + " seconds."); if ((s.GetAccess(8) & AccessMode.Write) != 0) { //Wait second. s.InactivityTimeout = 1; reader.Write(s, 8); Thread.Sleep(2000); try { reader.WaitTime = 1000; reader.RetryCount = 0; reader.Read(s, 8); } catch (Exception) { //This should fails. fail = true; } reader.InitializeConnection(); s.InactivityTimeout = inactivityTimeout; reader.Write(s, 8); if (!fail) { output.Errors.Add("HdlcSetup failed. InactivityTimeout don't work."); } } else { output.PreInfo.Add("HdlcSetup inactivity timeout is not tested."); } } else { GXDLMSTcpUdpSetup s = (GXDLMSTcpUdpSetup)settings.client.Objects.GetObjects(ObjectType.TcpUdpSetup)[0]; s.InactivityTimeout = 0; reader.Read(s, 6); inactivityTimeout = s.InactivityTimeout; output.PreInfo.Add("TcpUdpSetup default inactivity timeout value is " + inactivityTimeout + " seconds."); if ((s.GetAccess(6) & AccessMode.Write) != 0) { //Wait second. s.InactivityTimeout = 1; reader.Write(s, 6); Thread.Sleep(2000); try { reader.WaitTime = 1000; reader.RetryCount = 0; reader.Read(s, 6); } catch (Exception) { //This should fails. fail = true; } reader.InitializeConnection(); s.InactivityTimeout = inactivityTimeout; reader.Write(s, 6); if (!fail) { output.Errors.Add("TcpUdpSetup failed. InactivityTimeout don't work."); } } else { output.PreInfo.Add("TcpUdpSetup inactivity timeout is not tested."); } } reader.WaitTime = wt; reader.RetryCount = rc; output.MakeReport(); return(true); }