static private GenerateConfirmedServiceError ( ConfirmedServiceError service, ServiceError type, byte code ) : byte[] | ||
service | ConfirmedServiceError | Confirmed service error. |
type | ServiceError | Service error. |
code | byte | code |
return | byte[] |
public static void HandleGetRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && settings.Connected == ConnectionState.None && !settings.CanAccess()) { replyData.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } byte invokeID = 0; GetCommandType type = GetCommandType.NextDataBlock; //If GBT is used data is empty. if (data.Size != 0) { type = (GetCommandType)data.GetUInt8(); // Get invoke ID and priority. invokeID = data.GetUInt8(); settings.UpdateInvokeId(invokeID); if (xml != null) { xml.AppendStartTag(Command.GetRequest); xml.AppendStartTag(Command.GetRequest, type); xml.AppendLine(TranslatorTags.InvokeId, "Value", xml.IntegerToHex(invokeID, 2)); } } // GetRequest normal if (type == GetCommandType.Normal) { GetRequestNormal(settings, invokeID, server, data, replyData, xml); } else if (type == GetCommandType.NextDataBlock) { // Get request for next data block GetRequestNextDataBlock(settings, invokeID, server, data, replyData, xml, false); } else if (type == GetCommandType.WithList) { // Get request with a list. GetRequestWithList(settings, invokeID, server, data, replyData, xml); } else { Debug.WriteLine("HandleGetRequest failed. Invalid command type."); settings.ResetBlockIndex(); GXByteBuffer bb = new GXByteBuffer(); // Access Error : Device reports a hardware fault. bb.SetUInt8((byte)ErrorCode.HardwareFault); GXDLMS.GetLNPdu(new GXDLMSLNParameters(null, settings, invokeID, Command.GetResponse, (byte)type, null, bb, (byte)ErrorCode.Ok), replyData); } if (xml != null) { xml.AppendEndTag(Command.GetRequest, type); xml.AppendEndTag(Command.GetRequest); } }
///<summary> ///Handle set request. ///</summary> ///<returns> ///Reply to the client. ///</returns> public static void HandleSetRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && settings.Connected == ConnectionState.None && !settings.CanAccess()) { replyData.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } // Get type. SetRequestType type = (SetRequestType)data.GetUInt8(); // Get invoke ID and priority. byte invoke = data.GetUInt8(); settings.UpdateInvokeId(invoke); // SetRequest normal or Set Request With First Data Block GXDLMSLNParameters p = new GXDLMSLNParameters(null, settings, invoke, Command.SetResponse, (byte)type, null, null, 0); if (xml != null) { xml.AppendStartTag(Command.SetRequest); xml.AppendStartTag(Command.SetRequest, type); //InvokeIdAndPriority xml.AppendLine(TranslatorTags.InvokeId, "Value", xml.IntegerToHex(invoke, 2)); } switch (type) { case SetRequestType.Normal: case SetRequestType.FirstDataBlock: HandleSetRequestNormal(settings, server, data, (byte)type, p, replyData, xml); break; case SetRequestType.WithDataBlock: HanleSetRequestWithDataBlock(settings, server, data, p, replyData, xml); break; case SetRequestType.WithList: HanleSetRequestWithList(settings, invoke, server, data, p, replyData, xml); break; default: System.Diagnostics.Debug.WriteLine("HandleSetRequest failed. Unknown command."); settings.ResetBlockIndex(); p.status = (byte)ErrorCode.HardwareFault; break; } if (xml != null) { xml.AppendEndTag(Command.SetRequest, type); xml.AppendEndTag(Command.SetRequest); return; } GXDLMS.GetLNPdu(p, replyData); }
///<summary> /// Handle Access request. ///</summary> public static void HandleAccessRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer reply, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && settings.Connected == ConnectionState.None && !settings.CanAccess()) { reply.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } //Get long invoke id and priority. UInt32 invokeId = data.GetUInt32(); settings.longInvokeID = invokeId; int len = GXCommon.GetObjectCount(data); byte[] tmp = null; // If date time is given. if (len != 0) { tmp = new byte[len]; data.Get(tmp); if (xml == null) { DataType dt = DataType.DateTime; if (len == 4) { dt = DataType.Time; } else if (len == 5) { dt = DataType.Date; } GXDataInfo info = new GXDataInfo(); info.Type = dt; GXCommon.GetData(settings, new GXByteBuffer(tmp), info); } } // Get object count. int cnt = GXCommon.GetObjectCount(data); if (xml != null) { xml.AppendStartTag(Command.AccessRequest); xml.AppendLine(TranslatorTags.LongInvokeId, "Value", xml.IntegerToHex(invokeId, 2)); xml.AppendLine(TranslatorTags.DateTime, "Value", GXCommon.ToHex(tmp, false)); xml.AppendStartTag(TranslatorTags.AccessRequestBody); xml.AppendStartTag(TranslatorTags.ListOfAccessRequestSpecification, "Qty", xml.IntegerToHex(cnt, 2)); } AccessServiceCommandType type; for (int pos = 0; pos != cnt; ++pos) { type = (AccessServiceCommandType)data.GetUInt8(); if (!(type == AccessServiceCommandType.Get || type == AccessServiceCommandType.Set || type == AccessServiceCommandType.Action)) { throw new ArgumentException("Invalid access service command type."); } // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute Id byte attributeIndex = data.GetUInt8(); if (xml != null) { xml.AppendStartTag(TranslatorTags.AccessRequestSpecification); xml.AppendStartTag(Command.AccessRequest, type); AppendAttributeDescriptor(xml, (int)ci, ln, attributeIndex); xml.AppendEndTag(Command.AccessRequest, type); xml.AppendEndTag(TranslatorTags.AccessRequestSpecification); } } if (xml != null) { xml.AppendEndTag(TranslatorTags.ListOfAccessRequestSpecification); xml.AppendStartTag(TranslatorTags.AccessRequestListOfData, "Qty", xml.IntegerToHex(cnt, 2)); } // Get data count. cnt = GXCommon.GetObjectCount(data); for (int pos = 0; pos != cnt; ++pos) { GXDataInfo di = new GXDataInfo(); di.xml = xml; if (xml != null && xml.OutputType == TranslatorOutputType.StandardXml) { xml.AppendStartTag(Command.WriteRequest, SingleReadResponse.Data); } object value = GXCommon.GetData(settings, data, di); if (!di.Complete) { value = GXCommon.ToHex(data.Data, false, data.Position, data.Size - data.Position); } else if (value is byte[]) { value = GXCommon.ToHex((byte[])value, false); } if (xml != null && xml .OutputType == TranslatorOutputType.StandardXml) { xml.AppendEndTag(Command.WriteRequest, SingleReadResponse.Data); } } if (xml != null) { xml.AppendEndTag(TranslatorTags.AccessRequestListOfData); xml.AppendEndTag(TranslatorTags.AccessRequestBody); xml.AppendEndTag(Command.AccessRequest); } }
///<summary> /// Handle action request. ///</summary> public static void HandleMethodRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { ErrorCode error = ErrorCode.Ok; GXByteBuffer bb = new GXByteBuffer(); // Get type. ActionRequestType type = (ActionRequestType)data.GetUInt8(); // Get invoke ID and priority. byte invokeId = data.GetUInt8(); settings.UpdateInvokeId(invokeId); // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute Id byte id = data.GetUInt8(); // Get parameters. object parameters = null; byte selection = data.GetUInt8(); if (xml != null) { xml.AppendStartTag(Command.MethodRequest); if (type == ActionRequestType.Normal) { xml.AppendStartTag(Command.MethodRequest, ActionRequestType.Normal); xml.AppendLine(TranslatorTags.InvokeId, "Value", xml.IntegerToHex(invokeId, 2)); AppendMethodDescriptor(xml, (int)ci, ln, id); if (selection != 0) { //MethodInvocationParameters xml.AppendStartTag(TranslatorTags.MethodInvocationParameters); GXDataInfo di = new GXDataInfo(); di.xml = xml; GXCommon.GetData(settings, data, di); xml.AppendEndTag(TranslatorTags.MethodInvocationParameters); } xml.AppendEndTag(Command.MethodRequest, ActionRequestType.Normal); } xml.AppendEndTag(Command.MethodRequest); return; } if (selection != 0) { GXDataInfo info = new GXDataInfo(); parameters = GXCommon.GetData(settings, data, info); } GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln)); if (settings.Connected == ConnectionState.None && !settings.CanAccess() && (ci != ObjectType.AssociationLogicalName || id != 1)) { replyData.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } if (obj == null) { obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln)); } if (obj == null) { // Device reports a undefined object. error = ErrorCode.UndefinedObject; } else { ValueEventArgs e = new ValueEventArgs(server, obj, id, 0, parameters); e.InvokeId = invokeId; if (server.NotifyGetMethodAccess(e) == MethodAccessMode.NoAccess) { error = ErrorCode.ReadWriteDenied; } else { server.NotifyAction(new ValueEventArgs[] { e }); byte[] actionReply; if (e.Handled) { actionReply = (byte[])e.Value; } else { actionReply = (obj as IGXDLMSBase).Invoke(settings, e); server.NotifyPostAction(new ValueEventArgs[] { e }); } //Set default action reply if not given. if (actionReply != null && e.Error == 0) { //Add return parameters bb.SetUInt8(1); //Add parameters error code. bb.SetUInt8(0); GXCommon.SetData(settings, bb, GXDLMSConverter.GetDLMSDataType(actionReply), actionReply); } else { error = e.Error; //Add return parameters bb.SetUInt8(0); } } invokeId = (byte)e.InvokeId; } GXDLMSLNParameters p = new GXDLMSLNParameters(null, settings, invokeId, Command.MethodResponse, 1, null, bb, (byte)error); GXDLMS.GetLNPdu(p, replyData); //If High level authentication fails. if (obj is GXDLMSAssociationLogicalName && id == 1) { if ((obj as GXDLMSAssociationLogicalName).AssociationStatus == Objects.Enums.AssociationStatus.Associated) { server.NotifyConnected(connectionInfo); settings.Connected |= ConnectionState.Dlms; } else { server.NotifyInvalidConnection(connectionInfo); settings.Connected &= ~ConnectionState.Dlms; } } }
private static void HandleRead(GXDLMSSettings settings, GXDLMSServer server, byte type, GXByteBuffer data, List <ValueEventArgs> list, List <ValueEventArgs> reads, List <ValueEventArgs> actions, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { int sn = data.GetInt16(); if (xml != null) { if (xml.OutputType == TranslatorOutputType.StandardXml) { xml.AppendStartTag( TranslatorTags.VariableAccessSpecification); } else { sn &= 0xFFFF; } if (type == (byte)VariableAccessSpecification.ParameterisedAccess) { xml.AppendStartTag(Command.ReadRequest, VariableAccessSpecification.ParameterisedAccess); xml.AppendLine( (int)Command.ReadRequest << 8 | (int)VariableAccessSpecification.VariableName, "Value", xml.IntegerToHex(sn, 4)); xml.AppendLine(TranslatorTags.Selector, "Value", xml.IntegerToHex(data.GetUInt8(), 2)); GXDataInfo di = new GXDataInfo(); di.xml = xml; xml.AppendStartTag(TranslatorTags.Parameter); GXCommon.GetData(settings, data, di); xml.AppendEndTag(TranslatorTags.Parameter); xml.AppendEndTag(Command.ReadRequest, VariableAccessSpecification.ParameterisedAccess); } else { xml.AppendLine( (int)Command.ReadRequest << 8 | (int)VariableAccessSpecification.VariableName, "Value", xml.IntegerToHex(sn, 4)); } if (xml.OutputType == TranslatorOutputType.StandardXml) { xml.AppendEndTag(TranslatorTags.VariableAccessSpecification); } return; } GXSNInfo info = FindSNObject(server, sn & 0xFFFF); ValueEventArgs e = new ValueEventArgs(server, info.Item, info.Index, 0, null); e.action = info.IsAction; if (type == (byte)VariableAccessSpecification.ParameterisedAccess) { e.Selector = data.GetUInt8(); GXDataInfo di = new GXDataInfo(); e.Parameters = GXCommon.GetData(settings, data, di); } //Return error if connection is not established. if (!settings.Connected && (!e.action || e.Target.ShortName != 0xFA00 || e.Index != 8)) { replyData.Add(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } if (e.Target is GXDLMSProfileGeneric && info.Index == 2) { e.RowToPdu = GXDLMS.RowsToPdu(settings, (GXDLMSProfileGeneric)e.Target); } list.Add(e); if (!e.action && server.NotifyGetAttributeAccess(e) == AccessMode.NoAccess) { e.Error = ErrorCode.ReadWriteDenied; } else if (e.action && server.NotifyGetMethodAccess(e) == MethodAccessMode.NoAccess) { e.Error = ErrorCode.ReadWriteDenied; } else { if (e.action) { actions.Add(e); } else { reads.Add(e); } } }
///<summary> /// Handle write request. ///</summary> public static void HandleWriteRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && !settings.Connected) { replyData.Add(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } 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); } } 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 | (int)VariableAccessSpecification.VariableName, "Value", xml.IntegerToHex(sn, 4)); } else { GXSNInfo 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) { HandleReadDataBlockAccess(settings, server, Command.WriteResponse, data, cnt, replyData, xml); 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); GXDataInfo 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); } GXCommon.GetData(settings, data, di); } else if (results.GetUInt8(pos) == 0) { // If object has found. GXSNInfo target = targets[pos]; value = GXCommon.GetData(settings, data, di); 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); } } ValueEventArgs e = new ValueEventArgs(server, target.Item, target.Index, 0, null); AccessMode am = server.NotifyGetAttributeAccess(e); // If write is denied. if (am != AccessMode.Write && am != AccessMode.ReadWrite) { results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied); } 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 }); } } } } if (xml != null) { xml.AppendEndTag(TranslatorTags.ListOfData); xml.AppendEndTag(Command.WriteRequest); return; } GenerateWriteResponse(settings, results, replyData); }
/// <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, Command cipheredCommand) { //Return error if connection is not established. if (xml == null && (settings.Connected & ConnectionState.Hdlc) == 0 && cipheredCommand == Command.None) { replyData.Add(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } 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, cipheredCommand); } 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, cipheredCommand); 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; } }