Пример #1
0
 /// <summary>
 /// Generates data notification message(s).
 /// </summary>
 /// <param name="time">Date time. Set To Min or Max if not added</param>
 /// <param name="data">Notification body.</param>
 /// <returns>Generated data notification message(s).</returns>
 public byte[][] GenerateDataNotificationMessages(DateTime time, byte[] data)
 {
     byte[][] reply;
     if (UseLogicalNameReferencing)
     {
         GXDLMSLNParameters p = new GXDLMSLNParameters(null, Settings, 0, Command.DataNotification, 0, null, new GXByteBuffer(data), 0xff);
         p.time = time;
         reply  = GXDLMS.GetLnMessages(p);
     }
     else
     {
         GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, Command.DataNotification, 1, 0, new GXByteBuffer(data), null);
         reply = GXDLMS.GetSnMessages(p);
     }
     if ((Settings.NegotiatedConformance & Conformance.GeneralBlockTransfer) == 0 && reply.Length != 1)
     {
         throw new ArgumentException("Data is not fit to one PDU. Use general block transfer.");
     }
     return(reply);
 }
Пример #2
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;
            }
        }
Пример #3
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();
            }
        }
Пример #4
0
 /// <summary>
 /// Generates data notification message.
 /// </summary>
 /// <param name="time">Date time. Set To Min or Max if not added</param>
 /// <param name="objects">List of objects and attribute indexes to notify.</param>
 /// <returns>Generated data notification message(s).</returns>
 public byte[][] GenerateDataNotificationMessages(DateTime time, List<KeyValuePair<GXDLMSObject, int>> objects)
 {
     if (objects == null)
     {
         throw new ArgumentNullException("objects");
     }
     GXByteBuffer buff = new GXByteBuffer();
     buff.SetUInt8(DataType.Structure);
     GXCommon.SetObjectCount(objects.Count, buff);
     foreach (KeyValuePair<GXDLMSObject, int> it in objects)
     {
         AddData(it.Key, it.Value, buff);
     }
     byte[][] reply;
     if (UseLogicalNameReferencing)
     {
         GXDLMSLNParameters p = new GXDLMSLNParameters(Settings, Command.DataNotification, 0, null, buff, 0xff);
         p.time = time;
         reply = GXDLMS.GetLnMessages(p);
     }
     else
     {
         GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, Command.DataNotification, 1, 0, buff, null);
         reply = GXDLMS.GetSnMessages(p);
     }
     return reply;
 }
Пример #5
0
 /// <summary>
 /// Generates data notification message(s).
 /// </summary>
 /// <param name="time">Date time. Set To Min or Max if not added</param>
 /// <param name="data">Notification body.</param>
 /// <returns>Generated data notification message(s).</returns>
 public byte[][] GenerateDataNotificationMessages(DateTime time, GXByteBuffer data)
 {
     byte[][] reply;
     if (UseLogicalNameReferencing)
     {
         GXDLMSLNParameters p = new GXDLMSLNParameters(Settings, Command.DataNotification, 0, null, data, 0xff);
         p.time = time;
         p.time.Skip |= DateTimeSkips.Ms;
         reply = GXDLMS.GetLnMessages(p);
     }
     else
     {
         GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, Command.DataNotification, 1, 0, data, null);
         reply = GXDLMS.GetSnMessages(p);
     }
     return reply;
 }
Пример #6
0
 /// <summary>
 /// Generates data notification message(s).
 /// </summary>
 /// <param name="time">Date time. Set To Min or Max if not added</param>
 /// <param name="data">Notification body.</param>
 /// <returns>Generated data notification message(s).</returns>
 public byte[][] GenerateDataNotificationMessages(DateTime time, byte[] data)
 {
     byte[][] reply;
     if (UseLogicalNameReferencing)
     {
         GXDLMSLNParameters p = new GXDLMSLNParameters(Settings, Command.DataNotification, 0, null, new GXByteBuffer(data), 0xff);
         p.time = time;
         reply = GXDLMS.GetLnMessages(p);
     }
     else
     {
         GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, Command.DataNotification, 1, 0, new GXByteBuffer(data), null);
         reply = GXDLMS.GetSnMessages(p);
     }
     if (!GeneralBlockTransfer && reply.Length != 1)
     {
         throw new ArgumentException("Data is not fit to one PDU. Use general block transfer.");
     }
     return reply;
 }
Пример #7
0
 private byte[] ReportError(Command cmd, ErrorCode error)
 {
     switch (cmd)
     {
         case Command.ReadRequest:
             cmd = Command.ReadResponse;
             break;
         case Command.WriteRequest:
             cmd = Command.WriteResponse;
             break;
         case Command.GetRequest:
             cmd = Command.GetResponse;
             break;
         case Command.SetRequest:
             cmd = Command.SetResponse;
             break;
         case Command.MethodRequest:
             cmd = Command.MethodResponse;
             break;
         default:
             //Return HW error and close connection..
             break;
     }
     if (Settings.UseLogicalNameReferencing)
     {
         GXDLMS.GetLNPdu(new GXDLMSLNParameters(Settings, cmd, 1, null, null, (byte)error), replyData);
     }
     else
     {
         GXByteBuffer bb = new GXByteBuffer();
         bb.SetUInt8(error);
         GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, cmd, 1, (byte)error, null, bb);
         GXDLMS.GetSNPdu(p, replyData);
     }
     if (this.InterfaceType == Enums.InterfaceType.WRAPPER)
     {
         return GXDLMS.GetWrapperFrame(Settings, replyData);
     }
     else
     {
         return GXDLMS.GetHdlcFrame(Settings, 0, replyData);
     }
 }
Пример #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="p"></param>
        /// <param name="reply"></param>
        internal static void GetSNPdu(GXDLMSSNParameters p, GXByteBuffer reply)
        {
            bool ciphering = p.settings.Cipher != null && p.settings.Cipher.Security != Gurux.DLMS.Enums.Security.None;
            if (!ciphering && p.settings.InterfaceType == InterfaceType.HDLC)
            {
                if (p.settings.IsServer)
                {
                    reply.Set(GXCommon.LLCReplyBytes);
                }
                else if (reply.Size == 0)
                {
                    reply.Set(GXCommon.LLCSendBytes);
                }
            }
            int cnt = 0, cipherSize = 0;
            if (ciphering)
            {
                cipherSize = CipheringHeaderSize;
                /*
                if (p.settings.Cipher.Security == Security.Encryption)
                {
                    cipherSize = 7;
                }
                else if (p.settings.Cipher.Security == Security.Authentication)
                {
                    cipherSize = 19;
                }
                else if (p.settings.Cipher.Security == Security.AuthenticationEncryption)
                {
                    cipherSize = 7;
                }
                 * */
            }
            if (p.data != null)
            {
                cnt = p.data.Size - p.data.Position;
            }
            // Add command.
            if (p.command != Command.Aarq && p.command != Command.Aare)
            {
                reply.SetUInt8((byte)p.command);
                if (p.count != 0xFF)
                {
                    GXCommon.SetObjectCount(p.count, reply);
                }
                if (p.requestType != 0xFF)
                {
                    reply.SetUInt8(p.requestType);
                }
                reply.Set(p.attributeDescriptor);

                if (!p.multipleBlocks)
                {
                    p.multipleBlocks = reply.Size + cipherSize + cnt > p.settings.MaxPduSize;
                    //If reply data is not fit to one PDU.
                    if (p.multipleBlocks)
                    {
                        //Remove command.
                        GXByteBuffer tmp = new GXByteBuffer();
                        int offset = 1;
                        if (!ciphering && p.settings.InterfaceType == InterfaceType.HDLC)
                        {
                            offset = 4;
                        }
                        tmp.Set(reply.Data, offset, reply.Size - offset);
                        reply.Size = 0;
                        if (!ciphering && p.settings.InterfaceType == InterfaceType.HDLC)
                        {
                            if (p.settings.IsServer)
                            {
                                reply.Set(GXCommon.LLCReplyBytes);
                            }
                            else if (reply.Size == 0)
                            {
                                reply.Set(GXCommon.LLCSendBytes);
                            }
                        }
                        if (p.command == Command.WriteRequest)
                        {
                            p.requestType = (byte)VariableAccessSpecification.WriteDataBlockAccess;
                        }
                        else if (p.command == Command.ReadRequest)
                        {
                            p.requestType = (byte)VariableAccessSpecification.ReadDataBlockAccess;
                        }
                        else if (p.command == Command.ReadResponse)
                        {
                            p.requestType = (byte)SingleReadResponse.DataBlockResult;
                        }
                        else
                        {
                            throw new ArgumentException("Invalid command.");
                        }
                        reply.SetUInt8((byte)p.command);
                        //Set object count.
                        reply.SetUInt8(1);
                        if (p.requestType != 0xFF)
                        {
                            reply.SetUInt8(p.requestType);
                        }
                        cnt = GXDLMS.AppendMultipleSNBlocks(p, tmp, reply);
                    }
                }
                else
                {
                    cnt = GXDLMS.AppendMultipleSNBlocks(p, null, reply);
                }
            }
            // Add data.
            reply.Set(p.data, cnt);
            //Af all data is transfered.
            if (p.data != null && p.data.Position == p.data.Size)
            {
                p.settings.Index = p.settings.Count = 0;
            }
            // If Ciphering is used.
            if (ciphering && p.command != Command.Aarq && p.command != Command.Aare)
            {
                byte[] tmp = p.settings.Cipher.Encrypt((byte)GetGloMessage(p.command), p.settings.Cipher.SystemTitle, reply.Array());
                System.Diagnostics.Debug.Assert(!(p.settings.MaxPduSize < tmp.Length));
                reply.Size = 0;
                if (p.settings.InterfaceType == InterfaceType.HDLC)
                {
                    if (p.settings.IsServer)
                    {
                        reply.Set(GXCommon.LLCReplyBytes);
                    }
                    else if (reply.Size == 0)
                    {
                        reply.Set(GXCommon.LLCSendBytes);
                    }
                }
                reply.Set(tmp);
            }
        }
Пример #9
0
        ///<summary>
        /// Handle write request.
        ///</summary>
        public static void HandleWriteRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data,
                                              GXByteBuffer replyData, GXDLMSTranslatorStructure xml, Command cipheredCommand)
        {
            short  type;
            object value;
            // Get object count.
            List <GXSNInfo> targets = new List <GXSNInfo>();
            int             cnt     = GXCommon.GetObjectCount(data);

            if (xml != null)
            {
                xml.AppendStartTag(Command.WriteRequest);
                xml.AppendStartTag(
                    TranslatorTags.ListOfVariableAccessSpecification, "Qty",
                    xml.IntegerToHex(cnt, 2));
                if (xml.OutputType == TranslatorOutputType.StandardXml)
                {
                    xml.AppendStartTag(
                        TranslatorTags.VariableAccessSpecification);
                }
            }
            GXDataInfo   di;
            GXSNInfo     info;
            GXByteBuffer results = new GXByteBuffer((ushort)cnt);

            for (int pos = 0; pos != cnt; ++pos)
            {
                type = data.GetUInt8();
                if (type == (byte)VariableAccessSpecification.VariableName)
                {
                    int sn = data.GetUInt16();
                    if (xml != null)
                    {
                        xml.AppendLine(
                            (int)Command.WriteRequest << 8
                                | type,
                                "Value", xml.IntegerToHex(sn, 4));
                    }
                    else
                    {
                        info = FindSNObject(server, sn);
                        targets.Add(info);
                        // If target is unknown.
                        if (info == null)
                        {
                            // Device reports a undefined object.
                            results.SetUInt8(ErrorCode.UndefinedObject);
                        }
                        else
                        {
                            results.SetUInt8(ErrorCode.Ok);
                        }
                    }
                }
                else if (type == (byte)VariableAccessSpecification.WriteDataBlockAccess)
                {
                    //Return error if connection is not established.
                    if (xml == null && (settings.Connected & ConnectionState.Dlms) == 0 && cipheredCommand == Command.None)
                    {
                        replyData.Add(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError,
                                                                                 ServiceError.Service, (byte)Service.Unsupported));
                        return;
                    }
                    HandleReadDataBlockAccess(settings, server, Command.WriteResponse, data, cnt, replyData, xml, cipheredCommand);
                    if (xml == null)
                    {
                        return;
                    }
                }
                else
                {
                    // Device reports a HW error.
                    results.SetUInt8(ErrorCode.HardwareFault);
                }
            }

            if (xml != null)
            {
                if (xml.OutputType == TranslatorOutputType.StandardXml)
                {
                    xml.AppendEndTag(TranslatorTags.VariableAccessSpecification);
                }
                xml.AppendEndTag(
                    TranslatorTags.ListOfVariableAccessSpecification);
            }
            // Get data count.
            cnt    = GXCommon.GetObjectCount(data);
            di     = new GXDataInfo();
            di.xml = xml;
            if (xml != null)
            {
                xml.AppendStartTag(TranslatorTags.ListOfData, "Qty", xml.IntegerToHex(cnt, 2));
            }
            for (int pos = 0; pos != cnt; ++pos)
            {
                di.Clear();
                if (xml != null)
                {
                    if (xml.OutputType == TranslatorOutputType.StandardXml)
                    {
                        xml.AppendStartTag(Command.WriteRequest,
                                           SingleReadResponse.Data);
                    }
                    value = GXCommon.GetData(settings, data, di);
                    if (!di.Complete)
                    {
                        value = GXCommon.ToHex(data.Data, false,
                                               data.Position, data.Size - data.Position);
                        xml.AppendLine(
                            GXDLMS.DATA_TYPE_OFFSET + (int)di.Type,
                            "Value", value.ToString());
                    }
                    if (xml.OutputType == TranslatorOutputType.StandardXml)
                    {
                        xml.AppendEndTag(Command.WriteRequest, SingleReadResponse.Data);
                    }
                }
                else if (results.GetUInt8(pos) == 0)
                {
                    bool access = true;
                    // If object has found.
                    GXSNInfo target = targets[pos];
                    value = GXCommon.GetData(settings, data, di);
                    ValueEventArgs e = new ValueEventArgs(server, target.Item, target.Index, 0, null);
                    if (target.IsAction)
                    {
                        MethodAccessMode am = server.NotifyGetMethodAccess(e);
                        // If action is denied.
                        if (am != MethodAccessMode.Access)
                        {
                            access = false;
                        }
                    }
                    else
                    {
                        if (value is byte[])
                        {
                            DataType dt = target.Item.GetDataType(target.Index);
                            if (dt != DataType.None && dt != DataType.OctetString)
                            {
                                value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime);
                            }
                        }
                        AccessMode am = server.NotifyGetAttributeAccess(e);
                        // If write is denied.
                        if (am != AccessMode.Write && am != AccessMode.ReadWrite)
                        {
                            access = false;
                        }
                    }
                    if (access)
                    {
                        if (target.IsAction)
                        {
                            e.Parameters = value;
                            ValueEventArgs[] actions = new ValueEventArgs[] { e };
                            server.NotifyAction(actions);
                            if (!e.Handled)
                            {
                                byte[] reply = (target.Item as IGXDLMSBase).Invoke(settings, e);
                                server.NotifyPostAction(actions);
                                if (target.Item is GXDLMSAssociationShortName && target.Index == 8 && reply != null)
                                {
                                    GXByteBuffer bb = new GXByteBuffer();
                                    bb.SetUInt8((byte)DataType.OctetString);
                                    bb.SetUInt8((byte)reply.Length);
                                    bb.Set(reply);
                                    GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.ReadResponse, 1, 0, null, bb);
                                    GXDLMS.GetSNPdu(p, replyData);
                                }
                            }
                        }
                        else
                        {
                            e.Value = value;
                            server.NotifyWrite(new ValueEventArgs[] { e });
                            if (e.Error != 0)
                            {
                                results.SetUInt8((byte)pos, (byte)e.Error);
                            }
                            else if (!e.Handled)
                            {
                                (target.Item as IGXDLMSBase).SetValue(settings, e);
                                server.NotifyPostWrite(new ValueEventArgs[] { e });
                            }
                        }
                    }
                    else
                    {
                        results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied);
                    }
                }
            }
            if (xml != null)
            {
                xml.AppendEndTag(TranslatorTags.ListOfData);
                xml.AppendEndTag(Command.WriteRequest);
                return;
            }
            GenerateWriteResponse(settings, results, replyData);
        }
Пример #10
0
 /// <summary>
 /// Get all Short Name messages. Client uses this to generate messages.
 /// </summary>
 /// <param name="settings">DLMS settings.</param>
 /// <param name="command">DLMS command.</param>
 /// <param name="count">Attribute descriptor.</param>
 /// <param name="data">Data.</param>
 /// <returns>Generated messages.</returns>
 internal static byte[][] GetSnMessages(GXDLMSSNParameters p)
 {
     GXByteBuffer reply = new GXByteBuffer();
     List<byte[]> messages = new List<byte[]>();
     byte frame = 0x0;
     if (p.command == Command.Aarq)
     {
         frame = 0x10;
     }
     else if (p.command == Command.None)
     {
         frame = p.settings.NextSend();
     }
     do
     {
         GetSNPdu(p, reply);
         if (p.command != Command.Aarq && p.command != Command.Aare)
         {
             System.Diagnostics.Debug.Assert(!(p.settings.MaxPduSize < reply.Size));
         }
         //Command is not add to next PDUs.
         while (reply.Position != reply.Size)
         {
             if (p.settings.InterfaceType == Enums.InterfaceType.WRAPPER)
             {
                 messages.Add(GXDLMS.GetWrapperFrame(p.settings, reply));
             }
             else if (p.settings.InterfaceType == Enums.InterfaceType.HDLC)
             {
                 messages.Add(GXDLMS.GetHdlcFrame(p.settings, frame, reply));
                 frame = 0;
             }
             else if (p.settings.InterfaceType == Enums.InterfaceType.PDU)
             {
                 messages.Add(reply.Array());
                 frame = 0;
                 break;
             }
             else
             {
                 throw new ArgumentOutOfRangeException("InterfaceType");
             }
         }
         reply.Clear();
     } while (p.data != null && p.data.Position != p.data.Size);
     return messages.ToArray();
 }
Пример #11
0
 static int AppendMultipleSNBlocks(GXDLMSSNParameters p, GXByteBuffer header, GXByteBuffer reply)
 {
     bool ciphering = p.settings.Cipher != null && p.settings.Cipher.Security != Gurux.DLMS.Enums.Security.None;
     int hSize = reply.Size + 3;
     if (header != null)
     {
         hSize += header.Size;
     }
     //Add LLC bytes.
     if (p.command == Command.WriteRequest ||
             p.command == Command.ReadRequest)
     {
         hSize += 1 + GXCommon.GetObjectCountSizeInBytes(p.count);
     }
     int maxSize = p.settings.MaxPduSize - hSize;
     if (ciphering)
     {
         maxSize -= CipheringHeaderSize;
         if (p.settings.InterfaceType == InterfaceType.HDLC)
         {
             maxSize -= 3;
         }
     }
     maxSize -= GXCommon.GetObjectCountSizeInBytes(maxSize);
     if (p.data.Size - p.data.Position > maxSize)
     {
         //More blocks.
         reply.SetUInt8(0);
     }
     else
     {
         //Last block.
         reply.SetUInt8(1);
         maxSize = p.data.Size - p.data.Position;
     }
     //Add block index.
     reply.SetUInt16(p.blockIndex);
     if (p.command == Command.WriteRequest)
     {
         ++p.blockIndex;
         GXCommon.SetObjectCount(p.count, reply);
         reply.SetUInt8(DataType.OctetString);
     }
     if (p.command == Command.ReadRequest)
     {
         ++p.blockIndex;
     }
     if (header != null)
     {
         GXCommon.SetObjectCount(maxSize + header.Size, reply);
         reply.Set(header);
     }
     else
     {
         GXCommon.SetObjectCount(maxSize, reply);
     }
     return maxSize;
 }
Пример #12
0
 ///<summary>
 ///Generates an acknowledgment message, with which the server is informed to send next packets.
 ///</summary>
 ///<param name="type">
 /// Frame type.
 /// </param>
 ///<returns>
 ///Acknowledgment message as byte array.
 ///</returns>
 internal static byte[] ReceiverReady(GXDLMSSettings settings, RequestTypes type)
 {
     if (type == RequestTypes.None)
     {
         throw new ArgumentException("Invalid receiverReady RequestTypes parameter.");
     }
     // Get next frame.
     if ((type & RequestTypes.Frame) != 0)
     {
         byte id = settings.ReceiverReady();
         return GetHdlcFrame(settings, id, null);
     }
     Command cmd;
     if (settings.UseLogicalNameReferencing)
     {
         if (settings.IsServer)
         {
             cmd = Command.GetResponse;
         }
         else
         {
             cmd = Command.GetRequest;
         }
     }
     else
     {
         if (settings.IsServer)
         {
             cmd = Command.ReadResponse;
         }
         else
         {
             cmd = Command.ReadRequest;
         }
     }
     // Get next block.
     GXByteBuffer bb = new GXByteBuffer(6);
     if (settings.UseLogicalNameReferencing)
     {
         bb.SetUInt32(settings.BlockIndex);
     }
     else
     {
         bb.SetUInt16((UInt16)settings.BlockIndex);
     }
     settings.IncreaseBlockIndex();
     byte[][] reply;
     if (settings.UseLogicalNameReferencing)
     {
         GXDLMSLNParameters p = new GXDLMSLNParameters(settings, cmd, (byte)GetCommandType.NextDataBlock, bb, null, 0xff);
         reply = GXDLMS.GetLnMessages(p);
     }
     else
     {
         GXDLMSSNParameters p = new GXDLMSSNParameters(settings, cmd, 1, (byte)VariableAccessSpecification.BlockNumberAccess, bb, null);
         reply = GXDLMS.GetSnMessages(p);
     }
     return reply[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>();
            //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();
            }
        }
 /// <summary>
 /// Generate write reply.
 /// </summary>
 /// <param name="settings"></param>
 /// <param name="results"></param>
 /// <param name="replyData"></param>
 internal static void GenerateWriteResponse(GXDLMSSettings settings, GXByteBuffer results, GXByteBuffer replyData)
 {
     GXByteBuffer bb = new GXByteBuffer((UInt16)(2 * results.Size));
     byte ret;
     for (int pos = 0; pos != results.Size; ++pos)
     {
         ret = results.GetUInt8(pos);
         // If meter returns error.
         if (ret != 0)
         {
             bb.SetUInt8(1);
         }
         bb.SetUInt8(ret);
     }
     GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.WriteResponse, results.Size, 0xFF, null, bb);
     GXDLMS.GetSNPdu(p, replyData);
 }
Пример #16
0
 /// <summary>
 /// Convert xml to byte array.
 /// </summary>
 /// <param name="xml">Converted xml.</param>
 /// <returns>Converted bytes.</returns>
 public byte[] XmlToPdu(string xml)
 {
     XmlDocument doc = new XmlDocument();
     doc.LoadXml(xml);
     GXDLMSXmlSettings s = new GXDLMSXmlSettings(OutputType, Hex, ShowStringAsHex, tagsByName);
     ReadAllNodes(doc, s);
     GXByteBuffer bb = new GXByteBuffer();
     GXDLMSLNParameters ln;
     GXDLMSSNParameters sn;
     switch (s.command)
     {
         case Command.InitiateRequest:
         case Command.InitiateResponse:
             break;
         case Command.ReadRequest:
         case Command.WriteRequest:
         case Command.ReadResponse:
         case Command.WriteResponse:
             sn = new GXDLMSSNParameters(s.settings, s.command, s.count,
                                         s.requestType, s.attributeDescriptor, s.data);
             GXDLMS.GetSNPdu(sn, bb);
             break;
         case Command.GetRequest:
         case Command.GetResponse:
         case Command.SetRequest:
         case Command.SetResponse:
         case Command.MethodRequest:
         case Command.MethodResponse:
             ln = new GXDLMSLNParameters(s.settings, s.command, s.requestType,
                                         s.attributeDescriptor, s.data, 0xff);
             GXDLMS.GetLNPdu(ln, bb);
             break;
         case Command.GloGetRequest:
         case Command.GloGetResponse:
         case Command.GloSetRequest:
         case Command.GloSetResponse:
         case Command.GloMethodRequest:
         case Command.GloMethodResponse:
         case Command.GloReadRequest:
         case Command.GloWriteRequest:
         case Command.GloReadResponse:
         case Command.GloWriteResponse:
             bb.SetUInt8((byte)s.command);
             GXCommon.SetObjectCount(s.data.Size, bb);
             bb.Set(s.data);
             break;
         case Command.Rejected:
             break;
         case Command.Snrm:
             s.settings.IsServer = false;
             bb.Set(GXDLMS.GetHdlcFrame(s.settings, (byte)Command.Snrm, null));
             break;
         case Command.Ua:
             break;
         case Command.Aarq:
         case Command.GloInitiateRequest:
             GXAPDU.GenerateAarq(s.settings, s.settings.Cipher, s.data, bb);
             break;
         case Command.Aare:
         case Command.GloInitiateResponse:
             GXAPDU.GenerateAARE(s.settings, bb, s.result, s.diagnostic, s.settings.Cipher, s.data);
             break;
         case Command.DisconnectRequest:
             break;
         case Command.ReleaseRequest:
             bb.SetUInt8((byte)s.command);
             bb.SetUInt8(0);
             break;
         case Command.ReleaseResponse:
             bb.SetUInt8((byte)s.command);
             //Len
             bb.SetUInt8(3);
             //BerType
             bb.SetUInt8(BerType.Context);
             //Len.
             bb.SetUInt8(1);
             bb.SetUInt8(s.reason);
             break;
         case Command.ConfirmedServiceError:
             break;
         case Command.ExceptionResponse:
             break;
         case Command.GeneralBlockTransfer:
             break;
         case Command.AccessRequest:
             ln = new GXDLMSLNParameters(s.settings, s.command, s.requestType,
                                         s.attributeDescriptor, s.data, 0xff);
             GXDLMS.GetLNPdu(ln, bb);
             break;
         case Command.AccessResponse:
             ln = new GXDLMSLNParameters(s.settings, s.command, s.requestType,
                                         s.attributeDescriptor, s.data, 0xff);
             GXDLMS.GetLNPdu(ln, bb);
             break;
         case Command.DataNotification:
             ln = new GXDLMSLNParameters(s.settings, s.command, s.requestType,
                                         s.attributeDescriptor, s.data, 0xff);
             ln.time = s.time;
             GXDLMS.GetLNPdu(ln, bb);
             break;
         case Command.GloGeneralCiphering:
             break;
         case Command.GloEventNotificationRequest:
             break;
         default:
         case Command.None:
             throw new ArgumentException("Invalid command.");
     }
     return bb.Array();
 }