private static void HanleSetRequestWithList(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXDLMSLNParameters p, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { ValueEventArgs e; int cnt = GXCommon.GetObjectCount(data); List <ValueEventArgs> list = new List <ValueEventArgs>(); if (xml != null) { xml.AppendStartTag(TranslatorTags.AttributeDescriptorList, "Qty", xml.IntegerToHex(cnt, 2)); } try { for (int 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); } } } } cnt = GXCommon.GetObjectCount(data); if (xml != null) { xml.AppendEndTag(TranslatorTags.AttributeDescriptorList); xml.AppendStartTag(TranslatorTags.ValueList, "Qty", xml.IntegerToHex(cnt, 2)); } 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.ValueList); } } catch (Exception ex) { if (xml == null) { throw ex; } } }
private static void HandleSetRequestNormal(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, byte type, GXDLMSLNParameters p, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { object value = null; GXDataInfo reply = new GXDataInfo(); // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute index. byte index = data.GetUInt8(); // Get Access Selection. data.GetUInt8(); if (type == 2) { byte lastBlock = data.GetUInt8(); p.multipleBlocks = lastBlock == 0; UInt32 blockNumber = data.GetUInt32(); if (blockNumber != settings.BlockIndex) { Debug.WriteLine("HandleSetRequest failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber); p.status = (byte)ErrorCode.DataBlockNumberInvalid; return; } settings.IncreaseBlockIndex(); int size = GXCommon.GetObjectCount(data); int realSize = data.Size - data.Position; if (size != realSize) { Debug.WriteLine("HandleSetRequest failed. Invalid block size."); p.status = (byte)ErrorCode.DataBlockUnavailable; return; } if (xml != null) { AppendAttributeDescriptor(xml, (int)ci, ln, index); xml.AppendStartTag(TranslatorTags.DataBlock); xml.AppendLine(TranslatorTags.LastBlock, "Value", xml.IntegerToHex(lastBlock, 2)); xml.AppendLine(TranslatorTags.BlockNumber, "Value", xml.IntegerToHex(blockNumber, 8)); xml.AppendLine(TranslatorTags.RawData, "Value", data.RemainingHexString(false)); xml.AppendEndTag(TranslatorTags.DataBlock); } return; } if (xml != null) { AppendAttributeDescriptor(xml, (int)ci, ln, index); xml.AppendStartTag(TranslatorTags.Value); GXDataInfo di = new GXDataInfo(); di.xml = xml; 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); } xml.AppendEndTag(TranslatorTags.Value); return; } if (!p.multipleBlocks) { settings.ResetBlockIndex(); value = GXCommon.GetData(settings, data, reply); } GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln)); if (obj == null) { obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln)); } // If target is unknown. if (obj == null) { // Device reports a undefined object. p.status = (byte)ErrorCode.UndefinedObject; } else { ValueEventArgs e = new ValueEventArgs(server, obj, index, 0, null); e.InvokeId = p.InvokeId; AccessMode am = server.NotifyGetAttributeAccess(e); // If write is denied. if (am != AccessMode.Write && am != AccessMode.ReadWrite) { //Read Write denied. p.status = (byte)ErrorCode.ReadWriteDenied; } else { try { if (value is byte[]) { DataType dt = (obj as IGXDLMSBase).GetDataType(index); if (dt != DataType.None && dt != DataType.OctetString && dt != DataType.Structure) { value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime); } } e.Value = value; ValueEventArgs[] list = new ValueEventArgs[] { e }; if (p.multipleBlocks) { server.transaction = new GXDLMSLongTransaction(list, Command.GetRequest, data); } server.NotifyWrite(list); if (e.Error != 0) { p.status = (byte)e.Error; } else if (!e.Handled && !p.multipleBlocks) { (obj as IGXDLMSBase).SetValue(settings, e); server.NotifyPostWrite(list); if (e.Error != 0) { p.status = (byte)e.Error; } } p.InvokeId = e.InvokeId; } catch (Exception) { p.status = (byte)ErrorCode.HardwareFault; } } } }
/// <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); }
/// <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); } }
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); }