private static void ReadNode( XmlNode node, GXDLMSXmlSettings s) { int tag = 0; String str; if (s.OutputType == TranslatorOutputType.SimpleXml) { str = node.Name.ToLower(); } else { str = node.Name; } if (s.command != Command.ConfirmedServiceError || s.tags.ContainsKey(str)) { tag = s.tags[str]; } ErrorCode err; UInt32 value; byte[] tmp; GXByteBuffer preData = null; if (s.command == Command.None) { if (!((s.settings.ClientAddress == 0 || s.settings.ServerAddress == 0) && GetFrame(node, s, tag) || tag == (int)TranslatorTags.PduDlms || tag == (int)TranslatorTags.PduCse)) { GetCommand(node, s, tag); } } else if (s.command == Command.Aarq || s.command == Command.Aare) { HandleAarqAare(node, s, tag); } else if (tag >= GXDLMS.DATA_TYPE_OFFSET) { if (tag == (int)DataType.DateTime + GXDLMS.DATA_TYPE_OFFSET) { preData = UpdateDateTime(node, s, preData); } else { preData = UpdateDataType(node, s, tag); } } else if (s.command == Command.ConfirmedServiceError) { if (s.OutputType == TranslatorOutputType.StandardXml) { if (tag == (int)TranslatorTags.InitiateError) { s.attributeDescriptor.SetUInt8(1); } else { ServiceError se = TranslatorStandardTags.GetServiceError(str.Substring(2)); s.attributeDescriptor.SetUInt8(se); s.attributeDescriptor.SetUInt8(TranslatorStandardTags.GetError(se, GetValue(node, s))); } } else { if (tag == (int)TranslatorTags.ServiceError) { } else { if (s.attributeDescriptor.Size == 0) { s.attributeDescriptor.SetUInt8((byte)s.ParseShort(GetValue(node, s))); } else { ServiceError se = TranslatorSimpleTags.GetServiceError(str); s.attributeDescriptor.SetUInt8(se); s.attributeDescriptor.SetUInt8(TranslatorSimpleTags.GetError(se, GetValue(node, s))); } } } } else { switch (tag) { case (int)(Command.GetRequest) << 8 | (byte)GetCommandType.Normal: case (int)(Command.GetRequest) << 8 | (byte)GetCommandType.NextDataBlock: case (int)(Command.GetRequest) << 8 | (byte)GetCommandType.WithList: case (int)(Command.SetRequest) << 8 | (byte)SetRequestType.Normal: case (int)(Command.SetRequest) << 8 | (byte)SetRequestType.FirstDataBlock: case (int)(Command.SetRequest) << 8 | (byte)SetRequestType.WithDataBlock: case (int)(Command.SetRequest) << 8 | (byte)SetRequestType.WithList: s.requestType = (byte)(tag & 0xF); break; case (int)(Command.GetResponse) << 8 | (byte)GetCommandType.Normal: case (int)(Command.GetResponse) << 8 | (byte)GetCommandType.NextDataBlock: case (int)(Command.GetResponse) << 8 | (byte)GetCommandType.WithList: case (int)(Command.SetResponse) << 8 | (byte)SetResponseType.Normal: case (int)(Command.SetResponse) << 8 | (byte)SetResponseType.DataBlock: case (int)(Command.SetResponse) << 8 | (byte)SetResponseType.LastDataBlock: case (int)(Command.SetResponse) << 8 | (byte)SetResponseType.WithList: case (int)(Command.SetResponse) << 8 | (byte)SetResponseType.LastDataBlockWithList: s.requestType = (byte)(tag & 0xF); break; case (int)(Command.ReadResponse) << 8 | (byte)SingleReadResponse.DataBlockResult: ++s.count; s.requestType = (byte)(tag & 0xF); break; case (int)(Command.ReadRequest) << 8 | (byte)VariableAccessSpecification.ParameterisedAccess: s.requestType = (byte)VariableAccessSpecification.ParameterisedAccess; break; case (int)(Command.ReadRequest) << 8 | (byte)VariableAccessSpecification.BlockNumberAccess: s.requestType = (byte)VariableAccessSpecification.BlockNumberAccess; ++s.count; break; case (byte)(int)(Command.MethodRequest) << 8 | (byte)ActionRequestType.Normal: s.requestType = (byte)(tag & 0xFF); break; case (byte)(int)(Command.MethodRequest) << 8 | (byte)ActionRequestType.NextBlock: s.requestType = (byte)(tag & 0xFF); break; case (byte)(int)(Command.MethodRequest) << 8 | (byte)ActionRequestType.WithList: s.requestType = (byte)(tag & 0xFF); break; case (byte)(int)(Command.MethodResponse) << 8 | (byte)ActionRequestType.Normal: //MethodResponseNormal s.requestType = (byte)(tag & 0xFF); break; case (int)(Command.ReadResponse) << 8 | (byte)SingleReadResponse.Data: case (int)TranslatorTags.Data: if (s.command == Command.ReadRequest || s.command == Command.ReadResponse || s.command == Command.GetRequest) { ++s.count; s.requestType = 0; } else if (s.command == Command.GetResponse || s.command == Command.MethodResponse) { s.data.SetUInt8(0); // Add status. } break; case (int)TranslatorTags.Success: ++s.count; s.attributeDescriptor.Add((byte)ErrorCode.Ok); break; case (int)TranslatorTags.DataAccessError: ++s.count; s.attributeDescriptor.SetUInt8(1); s.attributeDescriptor.SetUInt8(ValueOfErrorCode(s.OutputType, GetValue(node, s))); break; case (int)TranslatorTags.ListOfVariableAccessSpecification: case (int)TranslatorTags.VariableAccessSpecification: break; case (int)TranslatorTags.ListOfData: if (s.command == Command.AccessResponse && s.data.Size == 0) { // If access-request-specification is not given. s.data.SetUInt8(0); } if (s.OutputType == TranslatorOutputType.SimpleXml || s.command != Command.WriteRequest) { GXCommon.SetObjectCount(node.ChildNodes.Count, s.data); } break; case (int)Command.AccessResponse << 8 | (byte)AccessServiceCommandType.Get: case (int)Command.AccessResponse << 8 | (byte)AccessServiceCommandType.Set: case (int)Command.AccessResponse << 8 | (byte)AccessServiceCommandType.Action: s.data.SetUInt8((byte)(0xFF & tag)); break; case (int)TranslatorTags.DateTime: preData = UpdateDateTime(node, s, preData); break; case (int)TranslatorTags.InvokeId: value = (uint)s.ParseShort(GetValue(node, s)); if ((value & 0x80) != 0) { s.settings.Priority = Priority.High; } else { s.settings.Priority = Priority.Normal; } if ((value & 0x40) != 0) { s.settings.ServiceClass = ServiceClass.Confirmed; } else { s.settings.ServiceClass = ServiceClass.UnConfirmed; } s.settings.InvokeID = (byte)(value & 0xF); break; case (int)TranslatorTags.LongInvokeId: value = (uint)s.ParseLong(GetValue(node, s)); if ((value & 0x80000000) != 0) { s.settings.Priority = Priority.High; } else { s.settings.Priority = Priority.Normal; } if ((value & 0x40000000) != 0) { s.settings.ServiceClass = ServiceClass.Confirmed; } else { s.settings.ServiceClass = ServiceClass.UnConfirmed; } s.settings.longInvokeID = (UInt16)(value & 0xFFFFFFF); break; case 0x88: //ResponderACSERequirement break; case 0x80: //RespondingAuthentication s.settings.StoCChallenge = GXCommon.HexToBytes(GetValue(node, s)); break; case (int)TranslatorTags.AttributeDescriptor: break; case (int)TranslatorTags.ClassId: s.attributeDescriptor.SetUInt16((UInt16)s.ParseInt(GetValue(node, s))); break; case (int)TranslatorTags.InstanceId: s.attributeDescriptor.Add(GXCommon.HexToBytes(GetValue(node, s))); break; case (int)TranslatorTags.AttributeId: s.attributeDescriptor.SetUInt8((byte)s.ParseShort(GetValue(node, s))); //Add AccessSelection. if (s.command != Command.AccessRequest) { s.attributeDescriptor.SetUInt8(0); } break; case (int)TranslatorTags.MethodInvocationParameters: s.attributeDescriptor.SetUInt8(s.attributeDescriptor.Size - 1, 1); break; case (int)TranslatorTags.Selector: s.attributeDescriptor.Set(GXCommon.HexToBytes(GetValue(node, s))); break; case (int)TranslatorTags.Parameter: break; case (int)TranslatorTags.LastBlock: s.data.SetUInt8((byte)s.ParseShort(GetValue(node, s))); break; case (int)TranslatorTags.BlockNumber: //BlockNumber if (s.command == Command.GetRequest || s.command == Command.GetResponse) { s.data.SetUInt32((UInt32)s.ParseLong(GetValue(node, s))); } else { s.data.SetUInt16((UInt16)s.ParseInt(GetValue(node, s))); } break; case (int)TranslatorTags.RawData: //RawData if (s.command == Command.GetResponse) { s.data.SetUInt8(0); } tmp = GXCommon.HexToBytes(GetValue(node, s)); GXCommon.SetObjectCount(tmp.Length, s.data); s.data.Set(tmp); break; case (int)TranslatorTags.MethodDescriptor: break; case (int)TranslatorTags.MethodId: s.attributeDescriptor.SetUInt8((byte)s.ParseShort(GetValue(node, s))); //Add MethodInvocationParameters s.attributeDescriptor.SetUInt8(0); break; case (int)TranslatorTags.Result: case (int)TranslatorGeneralTags.AssociationResult: //Result. if (s.command == Command.GetRequest || s.requestType == 3) { GXCommon.SetObjectCount(node.ChildNodes.Count, s.attributeDescriptor); } else if (s.command == Command.MethodResponse || s.command == Command.SetResponse) { str = GetValue(node, s); if (str != "") { s.attributeDescriptor.SetUInt8((byte)ValueOfErrorCode(s.OutputType, str)); } } else if (s.command == Command.AccessResponse) { str = GetValue(node, s); if (str != "") { s.data.SetUInt8(ValueOfErrorCode(s.OutputType, str)); } } break; case (int)TranslatorTags.Reason: s.reason = (ReleaseRequestReason)Enum.Parse(typeof(ReleaseRequestReason), GetValue(node, s)); break; case (int)TranslatorTags.ReturnParameters: s.attributeDescriptor.SetUInt8(1); break; case (int)TranslatorTags.AccessSelection: s.attributeDescriptor.SetUInt8(s.attributeDescriptor.Size - 1, 1); break; case (int)TranslatorTags.Value: break; case (int)TranslatorTags.AccessSelector: s.data.SetUInt8((byte)s.ParseShort(GetValue(node, s))); break; case (int)TranslatorTags.AccessParameters: break; case (int)TranslatorTags.AttributeDescriptorList: GXCommon.SetObjectCount(node.ChildNodes.Count, s.attributeDescriptor); break; case (int)TranslatorTags.AttributeDescriptorWithSelection: case (int)Command.AccessRequest << 8 | (byte)AccessServiceCommandType.Get: case (int)Command.AccessRequest << 8 | (byte)AccessServiceCommandType.Set: case (int)Command.AccessRequest << 8 | (byte)AccessServiceCommandType.Action: s.attributeDescriptor.SetUInt8((byte)(tag & 0xFF)); break; case (int)Command.ReadRequest << 8 | (byte)VariableAccessSpecification.VariableName: case (int)Command.WriteRequest << 8 | (byte)VariableAccessSpecification.VariableName: case (int)Command.WriteRequest << 8 | (byte)SingleReadResponse.Data: if (s.command != Command.AccessRequest && s.command != Command.AccessResponse) { if (!(s.OutputType == TranslatorOutputType.StandardXml && tag == ((int)Command.WriteRequest << 8 | (int)SingleReadResponse.Data))) { if (s.requestType == 0xFF) { s.attributeDescriptor.SetUInt8( VariableAccessSpecification.VariableName); } else { s.attributeDescriptor.SetUInt8(s.requestType); s.requestType = 0xFF; } ++s.count; } else { s.attributeDescriptor.SetUInt8((byte)s.count); } if (s.OutputType == TranslatorOutputType.SimpleXml) { s.attributeDescriptor.SetUInt16((UInt16)s.ParseShort(GetValue(node, s))); } else { str = GetValue(node, s); if (!String.IsNullOrEmpty(str)) { s.attributeDescriptor.SetInt16(Int16.Parse(str)); } } } break; case (int)TranslatorTags.Choice: break; case (int)Command.ReadResponse << 8 | (int)SingleReadResponse.DataAccessError: err = ValueOfErrorCode(s.OutputType, GetValue(node, s)); ++s.count; s.data.SetUInt8(1); s.data.SetUInt8(err); break; case (int)TranslatorTags.NotificationBody: break; case (int)TranslatorTags.DataValue: break; case (int)TranslatorTags.AccessRequestBody: break; case (int)TranslatorTags.PduDlms: break; case (int)TranslatorTags.ListOfAccessRequestSpecification: s.attributeDescriptor.SetUInt8((byte)node.ChildNodes.Count); break; case (int)TranslatorTags.AccessRequestSpecification: break; case (int)TranslatorTags.AccessRequestListOfData: s.attributeDescriptor.SetUInt8((byte)node.ChildNodes.Count); break; case (int)TranslatorTags.AccessResponseBody: break; case (int)TranslatorTags.ListOfAccessResponseSpecification: s.data.SetUInt8((byte)node.ChildNodes.Count); break; case (int)TranslatorTags.AccessResponseSpecification: break; case (int)TranslatorTags.AccessResponseListOfData: // Add access-response-list-of-data. Optional s.data.SetUInt8(0); s.data.SetUInt8((byte)node.ChildNodes.Count); break; case (int)TranslatorTags.SingleResponse: break; default: throw new ArgumentException("Invalid node: " + node.Name); } } foreach (XmlNode childNode in node.ChildNodes) { if (childNode.NodeType == XmlNodeType.Element) { ReadNode(childNode, s); } } if (preData != null) { GXCommon.SetObjectCount(node.ChildNodes.Count, preData); preData.Set(s.data); s.data.Size = 0; s.data.Set(preData); } }
/// <summary> /// Handle AARE and AARQ XML tags. /// </summary> /// <param name="node">XML node.</param> /// <param name="s">XML Settings.</param> /// <param name="tag">XML tag.</param> private static void HandleAarqAare(XmlNode node, GXDLMSXmlSettings s, int tag) { byte[] tmp; byte[] conformanceBlock; int value; switch (tag) { case (int)TranslatorGeneralTags.ApplicationContextName: if (s.OutputType == TranslatorOutputType.StandardXml) { value = int.Parse(node.InnerText); switch (value) { case 1: s.settings.UseLogicalNameReferencing = true; break; case 2: s.settings.UseLogicalNameReferencing = false; break; case 3: s.settings.UseLogicalNameReferencing = true; break; case 4: s.settings.UseLogicalNameReferencing = false; break; default: throw new ArgumentException("Invalid dedicated key."); } } else { string str = node.Attributes[0].InnerText; if (string.Compare(str, "SN") == 0 || string.Compare(str, "SN_WITH_CIPHERING") == 0) { s.settings.UseLogicalNameReferencing = false; } else if (string.Compare(str, "LN") == 0 || string.Compare(str, "LN_WITH_CIPHERING") == 0) { s.settings.UseLogicalNameReferencing = true; } else { throw new ArgumentException("Invalid Reference type name."); } } break; case (byte)Command.GloInitiateRequest: case (byte)Command.GloGetRequest: case (byte)Command.GloSetRequest: case (byte)Command.GloMethodRequest: case (byte)Command.GloReadRequest: case (byte)Command.GloWriteRequest: s.settings.IsServer = false; tmp = GXCommon.HexToBytes(GetValue(node, s)); s.settings.Cipher.Security = (Security)tmp[0]; s.data.Set(tmp); break; case (byte)Command.GloInitiateResponse: case (byte)Command.GloGetResponse: case (byte)Command.GloSetResponse: case (byte)Command.GloMethodResponse: case (byte)Command.GloReadResponse: case (byte)Command.GloWriteResponse: tmp = GXCommon.HexToBytes(GetValue(node, s)); s.settings.Cipher.Security = (Security)tmp[0]; s.data.Set(tmp); break; case (byte)Command.InitiateRequest: case (byte)Command.InitiateResponse: if (s.OutputType == TranslatorOutputType.StandardXml) { GXByteBuffer bb = new GXByteBuffer(); tmp = GXCommon.HexToBytes(GetValue(node, s)); GXCommon.SetObjectCount(tmp.Length, bb); bb.Set(tmp); GXAPDU.ParseUserInformation(s.settings, s.settings.Cipher, bb, null); if (s.command == Command.Aarq) { if (s.settings.UseLogicalNameReferencing) { s.settings.LnSettings.ConformanceBlock = s.settings.ConformanceBlock; } else { s.settings.SnSettings.ConformanceBlock = s.settings.ConformanceBlock; } } } break; case 0xBE00: //NegotiatedQualityOfService break; case 0xBE06: case 0xBE01: //NegotiatedDlmsVersionNumber or ProposedDlmsVersionNumber is skipped. break; case 0xBE04: //VaaName is not needed. break; case 0x8A: //SenderACSERequirements is not needed. break; case 0x8B: case 0x89: //MechanismName. s.settings.Authentication = (Authentication)Enum.Parse(typeof(Authentication), GetValue(node, s)); if (s.OutputType == TranslatorOutputType.SimpleXml) { s.settings.Authentication = (Authentication)Enum.Parse(typeof(Authentication), GetValue(node, s)); } else { s.settings.Authentication = (Authentication)int.Parse(GetValue(node, s)); } break; case 0xAC: //CallingAuthentication. if (s.settings.Authentication == Authentication.Low) { s.settings.Password = GXCommon.HexToBytes(GetValue(node, s)); } else { s.settings.CtoSChallenge = GXCommon.HexToBytes(GetValue(node, s)); } break; case (int)TranslatorGeneralTags.DedicatedKey: tmp = GXCommon.HexToBytes(GetValue(node, s)); s.settings.DedicatedKey = tmp; break; case (int)TranslatorGeneralTags.CallingAPTitle: s.settings .CtoSChallenge = GXCommon.HexToBytes(GetValue(node, s)); break; case 0xA4: //RespondingAPTitle. s.settings.StoCChallenge = GXCommon.HexToBytes(GetValue(node, s)); break; case 0xBE03: case 0xBE05: //ProposedConformance or NegotiatedConformance if (s.settings.UseLogicalNameReferencing) { s.settings.LnSettings.Clear(); } else { s.settings.SnSettings.Clear(); } if (s.OutputType == TranslatorOutputType.StandardXml) { String nodes = node.InnerText; if (s.settings.UseLogicalNameReferencing) { conformanceBlock = s.settings.LnSettings.ConformanceBlock; } else { conformanceBlock = s.settings.SnSettings.ConformanceBlock; } foreach (String it in nodes.Split(' ')) { if (it.Trim() != string.Empty) { value = (int)ValueOfConformance(it.Trim()); if (value < 0x100) { conformanceBlock[2] |= (byte)value; } else if (value < 0x10000) { conformanceBlock[1] |= (byte)(value >> 8); } else { conformanceBlock[0] |= (byte)(value >> 16); } } } } break; case 0xBE08: //ConformanceBit. value = (int)Enum.Parse(typeof(Conformance), node.Attributes["Name"].InnerText); if (s.settings.UseLogicalNameReferencing) { conformanceBlock = s.settings.LnSettings.ConformanceBlock; } else { conformanceBlock = s.settings.SnSettings.ConformanceBlock; } if (value < 0x100) { conformanceBlock[2] |= (byte)value; } else if (value < 0x10000) { conformanceBlock[1] |= (byte)(value >> 8); } else { conformanceBlock[0] |= (byte)(value >> 16); } break; case 0xA2: //AssociationResult s.result = (AssociationResult)Enum.Parse(typeof(AssociationResult), GetValue(node, s)); break; case 0xBE02: case 0xBE07: //NegotiatedMaxPduSize or ProposedMaxPduSize. s.settings.MaxPduSize = (UInt16)s.ParseInt(GetValue(node, s)); break; case 0xA3: //ResultSourceDiagnostic s.diagnostic = SourceDiagnostic.None; break; case 0xA301: //ACSEServiceUser s.diagnostic = (SourceDiagnostic)s.ParseInt(GetValue(node, s)); break; case 0xBE09: // ProposedQualityOfService break; case (int)TranslatorGeneralTags.CharString: // Get PW if (s.settings.Authentication == Authentication.Low) { s.settings .Password = GXCommon.HexToBytes(GetValue(node, s)); } else { if (s.command == Command.Aarq) { s.settings.CtoSChallenge = GXCommon.HexToBytes(GetValue(node, s)); } else { s.settings.StoCChallenge = GXCommon.HexToBytes(GetValue(node, s)); } } break; case (int)TranslatorGeneralTags.ResponderACSERequirement: break; case (int)TranslatorGeneralTags.RespondingAuthentication: s.settings .StoCChallenge = GXCommon.HexToBytes(GetValue(node, s)); break; case (int)TranslatorTags.Result: s.result = (AssociationResult) int.Parse(GetValue(node, s)); break; default: throw new ArgumentException("Invalid AARQ node: " + node.Name); } }
private static GXByteBuffer UpdateDataType(XmlNode node, GXDLMSXmlSettings s, int tag) { GXByteBuffer preData = null; switch ((DataType)(tag - GXDLMS.DATA_TYPE_OFFSET)) { case DataType.Array: s.data.SetUInt8(DataType.Array); preData = new GXByteBuffer(s.data); s.data.Size = 0; break; case DataType.Bcd: GXCommon.SetData(s.settings, s.data, DataType.Bcd, s.ParseShort(GetValue(node, s))); break; case DataType.BitString: GXCommon.SetData(s.settings, s.data, DataType.BitString, GetValue(node, s)); break; case DataType.Boolean: GXCommon.SetData(s.settings, s.data, DataType.Boolean, s.ParseShort(GetValue(node, s))); break; case DataType.Date: GXCommon.SetData(s.settings, s.data, DataType.Date, GXDLMSClient.ChangeType(GXCommon.HexToBytes(GetValue(node, s)), DataType.DateTime)); break; case DataType.DateTime: GXCommon.SetData(s.settings, s.data, DataType.DateTime, GXDLMSClient.ChangeType(GXCommon.HexToBytes(GetValue(node, s)), DataType.DateTime)); break; case DataType.Enum: GXCommon.SetData(s.settings, s.data, DataType.Enum, s.ParseShort(GetValue(node, s))); break; case DataType.Float32: GetFloat32(node, s); break; case DataType.Float64: GetFloat64(node, s); break; case DataType.Int16: GXCommon.SetData(s.settings, s.data, DataType.Int16, s.ParseShort(GetValue(node, s))); break; case DataType.Int32: GXCommon.SetData(s.settings, s.data, DataType.Int32, s.ParseInt(GetValue(node, s))); break; case DataType.Int64: GXCommon.SetData(s.settings, s.data, DataType.Int64, s.ParseLong(GetValue(node, s))); break; case DataType.Int8: GXCommon.SetData(s.settings, s.data, DataType.Int8, s.ParseShort(GetValue(node, s))); break; case DataType.None: GXCommon.SetData(s.settings, s.data, DataType.None, null); break; case DataType.OctetString: GetOctetString(node, s); break; case DataType.String: if (s.showStringAsHex) { GXCommon.SetData(s.settings, s.data, DataType.String, GXCommon.HexToBytes(GetValue(node, s))); } else { GXCommon.SetData(s.settings, s.data, DataType.String, GetValue(node, s)); } break; case DataType.StringUTF8: if (s.showStringAsHex) { GXCommon.SetData(s.settings, s.data, DataType.StringUTF8, GXCommon.HexToBytes(GetValue(node, s))); } else { GXCommon.SetData(s.settings, s.data, DataType.StringUTF8, GetValue(node, s)); } break; case DataType.Structure: s.data.SetUInt8(DataType.Structure); preData = new GXByteBuffer(s.data); s.data.Size = 0; break; case DataType.Time: GXCommon.SetData(s.settings, s.data, DataType.Time, GXDLMSClient.ChangeType(GXCommon.HexToBytes(GetValue(node, s)), DataType.DateTime)); break; case DataType.UInt16: GXCommon.SetData(s.settings, s.data, DataType.UInt16, s.ParseInt(GetValue(node, s))); break; case DataType.UInt32: GXCommon.SetData(s.settings, s.data, DataType.UInt32, s.ParseLong(GetValue(node, s))); break; case DataType.UInt64: GXCommon.SetData(s.settings, s.data, DataType.UInt64, s.ParseULong(GetValue(node, s))); break; case DataType.UInt8: GXCommon.SetData(s.settings, s.data, DataType.UInt8, s.ParseShort(GetValue(node, s))); break; default: throw new ArgumentException("Invalid node: " + node.Name); } return preData; }