/// <summary>
        /// Handle get request with list command.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void GetRequestWithList(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            ValueEventArgs e;
            GXByteBuffer   bb = new GXByteBuffer();
            int            pos;
            int            cnt = GXCommon.GetObjectCount(data);

            GXCommon.SetObjectCount(cnt, bb);
            List <ValueEventArgs> list = new List <ValueEventArgs>();

            if (xml != null)
            {
                xml.AppendStartTag(TranslatorTags.AttributeDescriptorList, "Qty", xml.IntegerToHex(cnt, 2));
            }
            try
            {
                for (pos = 0; pos != cnt; ++pos)
                {
                    ObjectType ci = (ObjectType)data.GetUInt16();
                    byte[]     ln = new byte[6];
                    data.Get(ln);
                    short attributeIndex = data.GetUInt8();
                    // AccessSelection
                    int    selection  = data.GetUInt8();
                    int    selector   = 0;
                    object parameters = null;
                    if (selection != 0)
                    {
                        selector = data.GetUInt8();
                        GXDataInfo info = new GXDataInfo();
                        parameters = GXCommon.GetData(settings, data, info);
                    }
                    if (xml != null)
                    {
                        xml.AppendStartTag(TranslatorTags.AttributeDescriptorWithSelection);
                        xml.AppendStartTag(TranslatorTags.AttributeDescriptor);
                        xml.AppendComment(ci.ToString());
                        xml.AppendLine(TranslatorTags.ClassId, "Value", xml.IntegerToHex((int)ci, 4));
                        xml.AppendComment(GXCommon.ToLogicalName(ln));
                        xml.AppendLine(TranslatorTags.InstanceId, "Value", GXCommon.ToHex(ln, false));
                        xml.AppendLine(TranslatorTags.AttributeId, "Value", xml.IntegerToHex(attributeIndex, 2));
                        xml.AppendEndTag(TranslatorTags.AttributeDescriptor);
                        xml.AppendEndTag(TranslatorTags.AttributeDescriptorWithSelection);
                    }
                    else
                    {
                        GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln));
                        if (obj == null)
                        {
                            obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln));
                        }
                        if (obj == null)
                        {
                            // "Access Error : Device reports a undefined object."
                            e       = new ValueEventArgs(server, obj, attributeIndex, 0, 0);
                            e.Error = ErrorCode.UndefinedObject;
                            list.Add(e);
                        }
                        else
                        {
                            ValueEventArgs arg = new ValueEventArgs(server, obj, attributeIndex, selector, parameters);
                            arg.InvokeId = invokeID;
                            if (server.NotifyGetAttributeAccess(arg) == AccessMode.NoAccess)
                            {
                                //Read Write denied.
                                arg.Error = ErrorCode.ReadWriteDenied;
                                list.Add(arg);
                            }
                            else
                            {
                                list.Add(arg);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (xml == null)
                {
                    throw ex;
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(TranslatorTags.AttributeDescriptorList);
                return;
            }

            server.NotifyRead(list.ToArray());
            object value;

            pos = 0;
            foreach (ValueEventArgs it in list)
            {
                try
                {
                    if (it.Handled)
                    {
                        value = it.Value;
                    }
                    else
                    {
                        value = (it.Target as IGXDLMSBase).GetValue(settings, it);
                    }
                    bb.SetUInt8(it.Error);
                    if (it.ByteArray)
                    {
                        bb.Set((byte[])value);
                    }
                    else
                    {
                        GXDLMS.AppendData(settings, it.Target, it.Index, bb, value);
                    }
                    invokeID = (byte)it.InvokeId;
                }
                catch (Exception)
                {
                    bb.SetUInt8((byte)ErrorCode.HardwareFault);
                }
                if (settings.Index != settings.Count)
                {
                    server.transaction = new GXDLMSLongTransaction(list.ToArray(), Command.GetRequest, null);
                }
                ++pos;
            }
            server.NotifyPostRead(list.ToArray());
            GXDLMSLNParameters p = new GXDLMSLNParameters(settings, invokeID, Command.GetResponse, 3, null, bb, 0xFF);

            GXDLMS.GetLNPdu(p, replyData);
        }
예제 #2
0
        /// <summary>
        /// Read DLMS Data from the device.
        /// </summary>
        /// <param name="data">Data to send.</param>
        /// <returns>Received data.</returns>
        public void ReadDLMSPacket(byte[] data, GXReplyData reply)
        {
            if (data == null && !reply.IsStreaming())
            {
                return;
            }
            GXReplyData notify = new GXReplyData();

            reply.Error = 0;
            object eop = (byte)0x7E;

            //In network connection terminator is not used.
            if (Client.InterfaceType == InterfaceType.WRAPPER && Media is GXNet)
            {
                eop = null;
            }
            int  pos       = 0;
            bool succeeded = false;
            ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>()
            {
                Eop      = eop,
                WaitTime = WaitTime,
            };

            if (eop == null)
            {
                p.Count = 8;
            }
            else
            {
                p.Count = 5;
            }
            GXByteBuffer rd = new GXByteBuffer();

            lock (Media.Synchronous)
            {
                while (!succeeded && pos != 3)
                {
                    if (!reply.IsStreaming())
                    {
                        WriteTrace("TX:\t" + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(data, true));
                        Media.Send(data, null);
                    }
                    succeeded = Media.Receive(p);
                    if (!succeeded)
                    {
                        if (++pos >= RetryCount)
                        {
                            throw new Exception("Failed to receive reply from the device in given time.");
                        }
                        //If Eop is not set read one byte at time.
                        if (p.Eop == null)
                        {
                            p.Count = 1;
                        }
                        //Try to read again...
                        System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3");
                    }
                }
                rd = new GXByteBuffer(p.Reply);
                try
                {
                    pos = 0;
                    //Loop until whole COSEM packet is received.
                    while (!Client.GetData(rd, reply, notify))
                    {
                        p.Reply = null;
                        if (notify.Data.Data != null)
                        {
                            //Handle notify.
                            if (!notify.IsMoreData)
                            {
                                //Show received push message as XML.
                                string           xml;
                                GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml);
                                t.DataToXml(notify.Data, out xml);
                                Console.WriteLine(xml);
                                notify.Clear();
                            }
                            continue;
                        }
                        else if (p.Eop == null)
                        {
                            p.Count = Client.GetFrameSize(rd);
                        }
                        while (!Media.Receive(p))
                        {
                            if (++pos >= RetryCount)
                            {
                                throw new Exception("Failed to receive reply from the device in given time.");
                            }
                            //If echo.
                            if (rd == null || rd.Size == data.Length)
                            {
                                Media.Send(data, null);
                            }
                            //Try to read again...
                            System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3");
                        }
                        rd.Set(p.Reply);
                    }
                }
                catch (Exception ex)
                {
                    WriteTrace("RX:\t" + DateTime.Now.ToLongTimeString() + "\t" + rd);
                    throw ex;
                }
            }
            WriteTrace("RX:\t" + DateTime.Now.ToLongTimeString() + "\t" + rd);
            if (reply.Error != 0)
            {
                if (reply.Error == (short)ErrorCode.Rejected)
                {
                    Thread.Sleep(1000);
                    ReadDLMSPacket(data, reply);
                }
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
 /// <summary>
 /// Read all objects from the meter.
 /// </summary>
 /// <remarks>
 /// It's not normal to read all data from the meter. This is just an example.
 /// </remarks>
 public void GetReadOut()
 {
     foreach (GXDLMSObject it in Client.Objects)
     {
         // Profile generics are read later because they are special cases.
         // (There might be so lots of data and we so not want waste time to read all the data.)
         if (it is GXDLMSProfileGeneric)
         {
             continue;
         }
         if (!(it is IGXDLMSBase))
         {
             //If interface is not implemented.
             //Example manufacturer spesific interface.
             if (Trace > TraceLevel.Error)
             {
                 Console.WriteLine("Unknown Interface: " + it.ObjectType.ToString());
             }
             continue;
         }
         if (Trace > TraceLevel.Warning)
         {
             Console.WriteLine("-------- Reading " + it.GetType().Name + " " + it.Name + " " + it.Description);
         }
         foreach (int pos in (it as IGXDLMSBase).GetAttributeIndexToRead(true))
         {
             try
             {
                 object val = Read(it, pos);
                 ShowValue(val, pos);
             }
             catch (Exception ex)
             {
                 Console.WriteLine("Error! Index: " + pos + " " + ex.Message);
             }
         }
     }
     //Find profile generics and read them.
     foreach (GXDLMSObject it in Client.Objects.GetObjects(ObjectType.ProfileGeneric))
     {
         //If trace is info.
         if (Trace > TraceLevel.Warning)
         {
             Console.WriteLine("-------- Reading " + it.GetType().Name + " " + it.Name + " " + it.Description);
         }
         long entriesInUse = Convert.ToInt64(Read(it, 7));
         long entries      = Convert.ToInt64(Read(it, 8));
         //If trace is info.
         if (Trace > TraceLevel.Warning)
         {
             Console.WriteLine("Entries: " + entriesInUse + "/" + entries);
         }
         //If there are no columns or rows.
         if (entriesInUse == 0 || (it as GXDLMSProfileGeneric).CaptureObjects.Count == 0)
         {
             continue;
         }
         //All meters are not supporting parameterized read.
         if ((Client.NegotiatedConformance & (Gurux.DLMS.Enums.Conformance.ParameterizedAccess | Gurux.DLMS.Enums.Conformance.SelectiveAccess)) != 0)
         {
             try
             {
                 //Read first row from Profile Generic.
                 object[] rows = ReadRowsByEntry(it as GXDLMSProfileGeneric, 1, 1);
                 //If trace is info.
                 if (Trace > TraceLevel.Warning)
                 {
                     StringBuilder sb = new StringBuilder();
                     foreach (object[] row in rows)
                     {
                         foreach (object cell in row)
                         {
                             if (cell is byte[])
                             {
                                 sb.Append(GXCommon.ToHex((byte[])cell, true));
                             }
                             else
                             {
                                 sb.Append(Convert.ToString(cell));
                             }
                             sb.Append(" | ");
                         }
                         sb.Append("\r\n");
                     }
                 }
             }
             catch (Exception ex)
             {
                 Console.WriteLine("Error! Failed to read first row: " + ex.Message);
                 //Continue reading.
             }
         }
         //All meters are not supporting parameterized read.
         if ((Client.NegotiatedConformance & (Gurux.DLMS.Enums.Conformance.ParameterizedAccess | Gurux.DLMS.Enums.Conformance.SelectiveAccess)) != 0)
         {
             try
             {
                 //Read last day from Profile Generic.
                 object[] rows = ReadRowsByRange(it as GXDLMSProfileGeneric, DateTime.Now.Date, DateTime.MaxValue);
                 //If trace is info.
                 if (Trace > TraceLevel.Warning)
                 {
                     StringBuilder sb = new StringBuilder();
                     foreach (object[] row in rows)
                     {
                         foreach (object cell in row)
                         {
                             if (cell is byte[])
                             {
                                 sb.Append(GXCommon.ToHex((byte[])cell, true));
                             }
                             else
                             {
                                 sb.Append(Convert.ToString(cell));
                             }
                             sb.Append(" | ");
                         }
                         sb.Append("\r\n");
                     }
                 }
             }
             catch (Exception ex)
             {
                 Console.WriteLine("Error! Failed to read last day: " + ex.Message);
                 //Continue reading.
             }
         }
     }
 }