NotifyRead() private method

Read selected item.
private NotifyRead ( ValueEventArgs args ) : void
args ValueEventArgs Handled read requests.
return void
Beispiel #1
0
        /// <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(null, settings, invokeID, Command.GetResponse, 3, null, bb, 0xFF);

            GXDLMS.GetLNPdu(p, replyData);
        }
Beispiel #2
0
        /// <summary>
        /// Handle get request normal command.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void GetRequestNormal(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            ValueEventArgs e  = null;
            GXByteBuffer   bb = new GXByteBuffer();
            // Get type.
            ErrorCode status = ErrorCode.Ok;

            settings.Count = settings.Index = 0;
            settings.ResetBlockIndex();
            // CI
            ObjectType ci = (ObjectType)data.GetUInt16();

            byte[] ln = new byte[6];
            data.Get(ln);
            // Attribute Id
            byte attributeIndex = data.GetUInt8();

            // AccessSelection
            byte       selection  = data.GetUInt8();
            byte       selector   = 0;
            object     parameters = null;
            GXDataInfo info       = new GXDataInfo();

            if (selection != 0)
            {
                selector = data.GetUInt8();
            }
            if (xml != null)
            {
                AppendAttributeDescriptor(xml, (int)ci, ln, attributeIndex);
                if (selection != 0)
                {
                    info.xml = xml;
                    xml.AppendStartTag(TranslatorTags.AccessSelection);
                    xml.AppendLine(TranslatorTags.AccessSelector, "Value", xml.IntegerToHex(selector, 2));
                    xml.AppendStartTag(TranslatorTags.AccessParameters);
                    GXCommon.GetData(settings, data, info);
                    xml.AppendEndTag(TranslatorTags.AccessParameters);
                    xml.AppendEndTag(TranslatorTags.AccessSelection);
                }
                return;
            }
            if (selection != 0)
            {
                parameters = GXCommon.GetData(settings, data, info);
            }

            GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln));

            if (obj == null)
            {
                obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln));
            }
            e          = new ValueEventArgs(server, obj, attributeIndex, selector, parameters);
            e.InvokeId = invokeID;
            if (obj == null)
            {
                // "Access Error : Device reports a undefined object."
                status = ErrorCode.UndefinedObject;
            }
            else
            {
                if (server.NotifyGetAttributeAccess(e) == AccessMode.NoAccess)
                {
                    //Read Write denied.
                    status = ErrorCode.ReadWriteDenied;
                }
                else
                {
                    if (e.Target is GXDLMSProfileGeneric && attributeIndex == 2)
                    {
                        e.RowToPdu = GXDLMS.RowsToPdu(settings, (GXDLMSProfileGeneric)e.Target);
                    }
                    object value;
                    server.NotifyRead(new ValueEventArgs[] { e });
                    if (e.Handled)
                    {
                        value = e.Value;
                    }
                    else
                    {
                        settings.Count = e.RowEndIndex - e.RowBeginIndex;
                        value          = (obj as IGXDLMSBase).GetValue(settings, e);
                    }
                    if (e.ByteArray)
                    {
                        bb.Set((byte[])value);
                    }
                    else
                    {
                        GXDLMS.AppendData(settings, obj, attributeIndex, bb, value);
                    }
                    server.NotifyPostRead(new ValueEventArgs[] { e });
                    status = e.Error;
                }
            }
            GXDLMSLNParameters p = new GXDLMSLNParameters(null, settings, e.InvokeId, Command.GetResponse, 1, null, bb, (byte)status);

            GXDLMS.GetLNPdu(p, replyData);
            if (settings.Count != settings.Index || bb.Size != bb.Position)
            {
                server.transaction = new GXDLMSLongTransaction(new ValueEventArgs[] { e }, Command.GetRequest, bb);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Handle get request next data block command.
        /// </summary>
        /// <param name="data">Received data.</param>
        internal static void GetRequestNextDataBlock(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml, bool streaming)
        {
            GXByteBuffer bb = new GXByteBuffer();

            if (!streaming)
            {
                UInt32 index;
                // Get block index.
                index = data.GetUInt32();
                if (xml != null)
                {
                    xml.AppendLine(TranslatorTags.BlockNumber, null, xml.IntegerToHex(index, 8));
                    return;
                }
                if (index != settings.BlockIndex)
                {
                    Debug.WriteLine("handleGetRequest failed. Invalid block number. " + settings.BlockIndex + "/" + index);
                    GXDLMS.GetLNPdu(new GXDLMSLNParameters(null, settings, 0, Command.GetResponse, 2, null, bb, (byte)ErrorCode.DataBlockNumberInvalid), replyData);
                    return;
                }
            }
            settings.IncreaseBlockIndex();
            GXDLMSLNParameters p = new GXDLMSLNParameters(null, settings, invokeID, streaming ? Command.GeneralBlockTransfer : Command.GetResponse, 2, null, bb, (byte)ErrorCode.Ok);

            p.Streaming  = streaming;
            p.WindowSize = settings.WindowSize;
            //If transaction is not in progress.
            if (server.transaction == null)
            {
                p.status = (byte)ErrorCode.NoLongGetOrReadInProgress;
            }
            else
            {
                bb.Set(server.transaction.data);
                bool moreData = settings.Index != settings.Count;
                if (moreData)
                {
                    //If there is multiple blocks on the buffer.
                    //This might happen when Max PDU size is very small.
                    if (bb.Size < settings.MaxPduSize)
                    {
                        foreach (ValueEventArgs arg in server.transaction.targets)
                        {
                            object value;
                            server.NotifyRead(new ValueEventArgs[] { arg });
                            if (arg.Handled)
                            {
                                value = arg.Value;
                            }
                            else
                            {
                                value = (arg.Target as IGXDLMSBase).GetValue(settings, arg);
                            }
                            //Add data.
                            if (arg.ByteArray)
                            {
                                bb.Set((byte[])value);
                            }
                            else
                            {
                                GXDLMS.AppendData(settings, arg.Target, arg.Index, bb, value);
                            }
                        }
                        moreData = settings.Index != settings.Count;
                    }
                }
                p.multipleBlocks = true;
                GXDLMS.GetLNPdu(p, replyData);
                if (moreData || bb.Size - bb.Position != 0)
                {
                    server.transaction.data = bb;
                }
                else
                {
                    server.transaction = null;
                    settings.ResetBlockIndex();
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Handle read Block in blocks.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void HandleReadBlockNumberAccess(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            UInt16 blockNumber = data.GetUInt16();

            if (xml != null)
            {
                xml.AppendStartTag(Command.ReadRequest, VariableAccessSpecification.BlockNumberAccess);
                xml.AppendLine("<BlockNumber Value=\"" + xml.IntegerToHex(blockNumber, 4) + "\" />");
                xml.AppendEndTag(Command.ReadRequest, VariableAccessSpecification.BlockNumberAccess);
                return;
            }

            if (blockNumber != settings.BlockIndex)
            {
                GXByteBuffer bb = new GXByteBuffer();
                Debug.WriteLine("handleReadRequest failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber);
                bb.SetUInt8(ErrorCode.DataBlockNumberInvalid);
                GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, Command.ReadResponse, 1, (byte)SingleReadResponse.DataAccessError, bb, null), replyData);
                settings.ResetBlockIndex();
                return;
            }
            if (settings.Index != settings.Count && server.transaction.data.Size < settings.MaxPduSize)
            {
                List <ValueEventArgs> reads   = new List <ValueEventArgs>();
                List <ValueEventArgs> actions = new List <ValueEventArgs>();
                foreach (ValueEventArgs it in server.transaction.targets)
                {
                    if (it.action)
                    {
                        actions.Add(it);
                    }
                    else
                    {
                        reads.Add(it);
                    }
                }
                if (reads.Count != 0)
                {
                    server.NotifyRead(reads.ToArray());
                }

                if (actions.Count != 0)
                {
                    server.NotifyAction(actions.ToArray());
                }
                GetReadData(settings, server.transaction.targets, server.transaction.data);
                if (reads.Count != 0)
                {
                    server.NotifyPostRead(reads.ToArray());
                }

                if (actions.Count != 0)
                {
                    server.NotifyPostAction(actions.ToArray());
                }
            }
            settings.IncreaseBlockIndex();
            GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.ReadResponse, 1,
                                                          (byte)SingleReadResponse.DataBlockResult, null, server.transaction.data);

            p.multipleBlocks = true;
            GXDLMS.GetSNPdu(p, replyData);
            //If all data is sent.
            if (server.transaction.data.Size == server.transaction.data.Position)
            {
                server.transaction = null;
                settings.ResetBlockIndex();
            }
            else
            {
                server.transaction.data.Trim();
            }
        }
Beispiel #5
0
        /// <summary>
        /// Handle read request.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="server">DLMS server.</param>
        /// <param name="data">Received data.</param>
        public static void HandleReadRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            GXByteBuffer          bb      = new GXByteBuffer();
            int                   cnt     = 0xFF;
            byte                  type    = 0;
            List <ValueEventArgs> list    = new List <ValueEventArgs>();
            List <ValueEventArgs> reads   = new List <ValueEventArgs>();
            List <ValueEventArgs> actions = new List <ValueEventArgs>();

            //If get next frame.
            if (xml == null && data.Size == 0)
            {
                if (server.transaction != null)
                {
                    return;
                }
                bb.Set(replyData);
                replyData.Clear();
                foreach (ValueEventArgs it in server.transaction.targets)
                {
                    list.Add(it);
                }
            }
            else
            {
                cnt = GXCommon.GetObjectCount(data);
                if (xml != null)
                {
                    xml.AppendStartTag(Command.ReadRequest, "Qty", xml.IntegerToHex(cnt, 2));
                }

                for (int pos = 0; pos != cnt; ++pos)
                {
                    type = data.GetUInt8();
                    if (type == (byte)VariableAccessSpecification.VariableName ||
                        type == (byte)VariableAccessSpecification.ParameterisedAccess)
                    {
                        HandleRead(settings, server, type, data, list, reads, actions, replyData, xml);
                    }
                    else if (type == (byte)VariableAccessSpecification.BlockNumberAccess)
                    {
                        HandleReadBlockNumberAccess(settings, server, data, replyData, xml);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                    else if (type == (byte)VariableAccessSpecification.ReadDataBlockAccess)
                    {
                        HandleReadDataBlockAccess(settings, server, Command.ReadResponse, data, cnt, replyData, xml);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                    else
                    {
                        ReturnSNError(settings, server, Command.ReadResponse, ErrorCode.ReadWriteDenied, replyData);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                }
                if (reads.Count != 0)
                {
                    server.NotifyRead(reads.ToArray());
                }

                if (actions.Count != 0)
                {
                    server.NotifyAction(actions.ToArray());
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(Command.ReadRequest);
                return;
            }

            byte requestType = (byte)GetReadData(settings, list.ToArray(), bb);

            if (reads.Count != 0)
            {
                server.NotifyPostRead(reads.ToArray());
            }

            if (actions.Count != 0)
            {
                server.NotifyPostAction(actions.ToArray());
            }

            GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.ReadResponse, list.Count, requestType, null, bb);

            GXDLMS.GetSNPdu(p, replyData);
            if (server.transaction == null && (bb.Size != bb.Position || settings.Count != settings.Index))
            {
                reads = new List <ValueEventArgs>();
                foreach (var it in list)
                {
                    reads.Add(it);
                }
                server.transaction = new GXDLMSLongTransaction(reads.ToArray(), Command.ReadRequest, bb);
            }
            else if (server.transaction != null)
            {
                replyData.Set(bb);
                return;
            }
        }
        /// <summary>
        /// Handle get request with list command.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void GetRequestWithList(GXDLMSSettings settings, 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.AppendLine(TranslatorTags.ClassId, "Value", xml.IntegerToHex((int)ci, 4));
                        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, GXDLMSObject.ToLogicalName(ln));
                        if (obj == null)
                        {
                            obj = server.NotifyFindObject(ci, 0, GXDLMSObject.ToLogicalName(ln));
                        }
                        if (obj == null)
                        {
                            // "Access Error : Device reports a undefined object."
                            e = new ValueEventArgs(settings, obj, attributeIndex, 0, 0);
                            e.Error = ErrorCode.UndefinedObject;
                            list.Add(e);
                        }
                        else
                        {
                            if (obj.GetAccess(attributeIndex) == AccessMode.NoAccess)
                            {
                                //Read Write denied.
                                ValueEventArgs arg = new ValueEventArgs(settings, obj, attributeIndex, 0, null);
                                arg.Error = ErrorCode.ReadWriteDenied;
                                list.Add(arg);
                            }
                            else
                            {
                                ValueEventArgs arg = new ValueEventArgs(settings, obj, attributeIndex, selector, parameters);
                                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);
                    GXDLMS.AppendData(settings, it.Target, it.Index, bb, value);
                }
                catch (Exception)
                {
                    bb.SetUInt8((byte)ErrorCode.HardwareFault);
                }
                if (settings.Index != settings.Count)
                {
                    server.transaction = new GXDLMSLongTransaction(list.ToArray(), Command.GetRequest, null);
                }
                ++pos;
            }
            GXDLMSLNParameters p = new GXDLMSLNParameters(settings, Command.GetResponse, 3, null, bb, 0xFF);
            GXDLMS.GetLNPdu(p, replyData);
        }
 /// <summary>
 /// Handle get request next data block command.
 /// </summary>
 /// <param name="data">Received data.</param>
 private static void GetRequestNextDataBlock(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
 {
     GXByteBuffer bb = new GXByteBuffer();
     UInt32 index;
     // Get block index.
     index = data.GetUInt32();
     if (xml != null)
     {
         xml.AppendLine(TranslatorTags.BlockNumber, null, xml.IntegerToHex(index, 8));
         return;
     }
     if (index != settings.BlockIndex)
     {
         Debug.WriteLine("handleGetRequest failed. Invalid block number. " + settings.BlockIndex + "/" + index);
         GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, Command.GetResponse, 2, null, bb, (byte)ErrorCode.DataBlockNumberInvalid), replyData);
     }
     else
     {
         settings.IncreaseBlockIndex();
         GXDLMSLNParameters p = new GXDLMSLNParameters(settings, Command.GetResponse, 2, null, bb, (byte)ErrorCode.Ok);
         //If transaction is not in progress.
         if (server.transaction == null)
         {
             p.status = (byte)ErrorCode.NoLongGetOrReadInProgress;
         }
         else
         {
             bb.Set(server.transaction.data);
             bool moreData = settings.Index != settings.Count;
             if (moreData)
             {
                 //If there is multiple blocks on the buffer.
                 //This might happen when Max PDU size is very small.
                 if (bb.Size < settings.MaxPduSize)
                 {
                     foreach (ValueEventArgs arg in server.transaction.targets)
                     {
                         object value;
                         if (arg.Handled)
                         {
                             server.NotifyRead(new ValueEventArgs[] { arg });
                             value = arg.Value;
                         }
                         else
                         {
                             value = (arg.Target as IGXDLMSBase).GetValue(settings, arg);
                         }
                         //Add data.
                         GXDLMS.AppendData(settings, arg.Target, arg.Index, bb, value);
                     }
                     moreData = settings.Index != settings.Count;
                 }
             }
             p.multipleBlocks = true;
             GXDLMS.GetLNPdu(p, replyData);
             if (moreData || bb.Size - bb.Position != 0)
             {
                 server.transaction.data = bb;
             }
             else
             {
                 server.transaction = null;
             }
         }
     }
 }
        /// <summary>
        /// Handle get request normal command.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void GetRequestNormal(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            ValueEventArgs e = null;
            GXByteBuffer bb = new GXByteBuffer();
            // Get type.
            ErrorCode status = ErrorCode.Ok;

            settings.Count = settings.Index = 0;
            settings.ResetBlockIndex();
            // CI
            ObjectType ci = (ObjectType)data.GetUInt16();
            byte[] ln = new byte[6];
            data.Get(ln);
            // Attribute Id
            byte attributeIndex = data.GetUInt8();

            // AccessSelection
            byte selection = data.GetUInt8();
            byte selector = 0;
            object parameters = null;
            GXDataInfo info = new GXDataInfo();
            if (selection != 0)
            {
                selector = data.GetUInt8();
            }
            if (xml != null)
            {
                AppendAttributeDescriptor(xml, (int)ci, ln, attributeIndex);
                if (selection != 0)
                {
                    info.xml = xml;
                    xml.AppendStartTag(TranslatorTags.AccessSelection);
                    xml.AppendLine(TranslatorTags.AccessSelector, "Value", xml.IntegerToHex(selector, 2));
                    xml.AppendStartTag(TranslatorTags.AccessParameters);
                    GXCommon.GetData(settings, data, info);
                    xml.AppendEndTag(TranslatorTags.AccessParameters);
                    xml.AppendEndTag(TranslatorTags.AccessSelection);
                }
                return;
            }
            if (selection != 0)
            {
                parameters = GXCommon.GetData(settings, data, info);
            }

            GXDLMSObject obj = settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln));
            if (obj == null)
            {
                obj = server.NotifyFindObject(ci, 0, GXDLMSObject.ToLogicalName(ln));
            }
            if (obj == null)
            {
                // "Access Error : Device reports a undefined object."
                status = ErrorCode.UndefinedObject;
            }
            else
            {
                if (obj.GetAccess(attributeIndex) == AccessMode.NoAccess)
                {
                    //Read Write denied.
                    status = ErrorCode.ReadWriteDenied;
                }
                else
                {
                    e = new ValueEventArgs(settings, obj, attributeIndex, selector, parameters);
                    server.NotifyRead(new ValueEventArgs[] { e });
                    object value;
                    if (e.Handled)
                    {
                        value = e.Value;
                    }
                    else
                    {
                        value = (obj as IGXDLMSBase).GetValue(settings, e);
                    }
                    GXDLMS.AppendData(settings, obj, attributeIndex, bb, value);
                    status = e.Error;
                }
            }
            GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, Command.GetResponse, 1, null, bb, (byte)status), replyData);
            if (settings.Count != settings.Index || bb.Size != bb.Position)
            {
                server.transaction = new GXDLMSLongTransaction(new ValueEventArgs[] { e }, Command.GetRequest, bb);
            }
        }
        /// <summary>
        /// Handle read request.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="server">DLMS server.</param>
        /// <param name="data">Received data.</param>
        public static void HandleReadRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            GXByteBuffer bb = new GXByteBuffer();
            int cnt = 0xFF;
            byte type = 0;
            List<ValueEventArgs> list = new List<ValueEventArgs>();
            //If get next frame.
            if (xml == null && data.Size == 0)
            {
                if (server.transaction != null)
                {
                    return;
                }
                bb.Set(replyData);
                replyData.Clear();
                foreach (ValueEventArgs it in server.transaction.targets)
                {
                    list.Add(it);
                }
            }
            else
            {
                cnt = GXCommon.GetObjectCount(data);
                List<ValueEventArgs> reads = new List<ValueEventArgs>();
                List<ValueEventArgs> actions = new List<ValueEventArgs>();
                if (xml != null)
                {
                    xml.AppendStartTag(Command.ReadRequest, "Qty", xml.IntegerToHex(cnt, 2));
                }

                for (int pos = 0; pos != cnt; ++pos)
                {
                    type = data.GetUInt8();
                    if (type == (byte)VariableAccessSpecification.VariableName ||
                            type == (byte)VariableAccessSpecification.ParameterisedAccess)
                    {
                        HandleRead(settings, server, type, data, list, reads, actions, replyData, xml);
                    }
                    else if (type == (byte)VariableAccessSpecification.BlockNumberAccess)
                    {
                        HandleReadBlockNumberAccess(settings, server, data, replyData, xml);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                    else if (type == (byte)VariableAccessSpecification.ReadDataBlockAccess)
                    {
                        HandleReadDataBlockAccess(settings, server, Command.ReadResponse, data, cnt, replyData, xml);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                    else
                    {
                        ReturnSNError(settings, server, Command.ReadResponse, ErrorCode.ReadWriteDenied, replyData);
                        if (xml != null)
                        {
                            xml.AppendEndTag(Command.ReadRequest);
                        }
                        return;
                    }
                }
                if (reads.Count != 0)
                {
                    server.NotifyRead(reads.ToArray());
                }

                if (actions.Count != 0)
                {
                    server.NotifyAction(actions.ToArray());
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(Command.ReadRequest);
                return;
            }

            byte requestType = (byte)GetReadData(settings, list.ToArray(), bb);
            GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.ReadResponse, list.Count, requestType, null, bb);
            GXDLMS.GetSNPdu(p, replyData);
            if (server.transaction == null && (bb.Size != bb.Position || settings.Count != settings.Index))
            {
                List<ValueEventArgs> reads = new List<ValueEventArgs>();
                foreach (var it in list)
                {
                    reads.Add(it);
                }
                server.transaction = new GXDLMSLongTransaction(reads.ToArray(), Command.ReadRequest, bb);
            }
            else if (server.transaction != null)
            {
                replyData.Set(bb);
                return;
            }
        }
        /// <summary>
        /// Handle read Block in blocks.
        /// </summary>
        /// <param name="data">Received data.</param>
        private static void HandleReadBlockNumberAccess(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml)
        {
            UInt16 blockNumber = data.GetUInt16();
            if (xml != null)
            {
                xml.AppendStartTag(Command.ReadRequest, VariableAccessSpecification.BlockNumberAccess);
                xml.AppendLine("<BlockNumber Value=\"" + xml.IntegerToHex(blockNumber, 4) + "\" />");
                xml.AppendEndTag(Command.ReadRequest, VariableAccessSpecification.BlockNumberAccess);
                return;
            }

            if (blockNumber != settings.BlockIndex)
            {
                GXByteBuffer bb = new GXByteBuffer();
                Debug.WriteLine("handleReadRequest failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber);
                bb.SetUInt8(ErrorCode.DataBlockNumberInvalid);
                GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, Command.ReadResponse, 1, (byte)SingleReadResponse.DataAccessError, bb, null), replyData);
                settings.ResetBlockIndex();
                return;
            }
            if (settings.Index != settings.Count && server.transaction.data.Size < settings.MaxPduSize)
            {
                List<ValueEventArgs> reads = new List<ValueEventArgs>();
                List<ValueEventArgs> actions = new List<ValueEventArgs>();
                foreach (ValueEventArgs it in server.transaction.targets)
                {
                    if (it.action)
                    {
                        actions.Add(it);
                    }
                    else
                    {
                        reads.Add(it);
                    }
                }
                if (reads.Count != 0)
                {
                    server.NotifyRead(reads.ToArray());
                }

                if (actions.Count != 0)
                {
                    server.NotifyAction(actions.ToArray());
                }
                GetReadData(settings, server.transaction.targets, server.transaction.data);
            }
            settings.IncreaseBlockIndex();
            GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.ReadResponse, 1,
                    (byte)SingleReadResponse.DataBlockResult, null, server.transaction.data);
            p.multipleBlocks = true;
            GXDLMS.GetSNPdu(p, replyData);
            //If all data is sent.
            if (server.transaction.data.Size == server.transaction.data.Position)
            {
                server.transaction = null;
                settings.ResetBlockIndex();
            }
            else
            {
                server.transaction.data.Trim();
            }
        }