/// <summary> /// Parse register request. /// </summary> /// <param name="value"></param> /// <returns>System title mac address.</returns> public void ParseRegisterRequest(GXByteBuffer value) { //Get System title. byte[] st; if (settings.InterfaceType == Enums.InterfaceType.PlcHdlc) { st = new byte[8]; } else { st = new byte[6]; } value.Get(st); byte count = value.GetUInt8(); for (int pos = 0; pos != count; ++pos) { //Get System title. if (settings.InterfaceType == Enums.InterfaceType.PlcHdlc) { st = new byte[8]; } else { st = new byte[6]; } value.Get(st); SystemTitle = st; //MAC address. MacSourceAddress = value.GetUInt16(); } }
/// <summary> /// Parse discover request. /// </summary> /// <param name="value"></param> /// <returns></returns> public GXDLMSPlcRegister ParseDiscoverRequest(GXByteBuffer value) { GXDLMSPlcRegister ret = new GXDLMSPlcRegister(); ret.ResponseProbability = value.GetUInt8(); ret.AllowedTimeSlots = value.GetUInt16(); ret.DiscoverReportInitialCredit = value.GetUInt8(); ret.ICEqualCredit = value.GetUInt8(); return(ret); }
///<summary> /// Handle action request. ///</summary> ///<param name="Reply"> /// Received data from the client. ///</param> ///<returns> ///Reply. ///</returns> private byte[][] HandleMethodRequest() { GXByteBuffer data = Reply.Data; GXByteBuffer bb = new GXByteBuffer(); // Get type. data.GetUInt8(); // Get invoke ID and priority. data.GetUInt8(); // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute Id int id = data.GetUInt8(); // Get parameters. object parameters = null; if (data.GetUInt8() != 0) { GXDataInfo info = new GXDataInfo(); parameters = GXCommon.GetData(data, info); } GXDLMSObject obj = Settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = FindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } if (obj == null) { // Device reports a undefined object. addError(ErrorCode.UndefinedObject, bb); Debug.WriteLine("Undefined object."); } else { ValueEventArgs e = new ValueEventArgs(obj, id, 0, parameters); Action(e); if (e.Handled) { bb.Add((obj as IGXDLMSBase).Invoke(Settings, id, parameters)); } else { bb.Add((obj as IGXDLMSBase).Invoke(Settings, id, parameters)); } } return(GXDLMS.SplitPdu(Settings, Command.MethodResponse, 1, bb, ErrorCode.Ok, DateTime.MinValue)[0]); }
/// <summary> /// Handle get request with list command. /// </summary> /// <param name="data">Received data.</param> private static void GetRequestWithList(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { ValueEventArgs e; GXByteBuffer bb = new GXByteBuffer(); int pos; int cnt = GXCommon.GetObjectCount(data); GXCommon.SetObjectCount(cnt, bb); List <ValueEventArgs> list = new List <ValueEventArgs>(); if (xml != null) { xml.AppendStartTag(TranslatorTags.AttributeDescriptorList, "Qty", xml.IntegerToHex(cnt, 2)); } try { for (pos = 0; pos != cnt; ++pos) { ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); short attributeIndex = data.GetUInt8(); // AccessSelection int selection = data.GetUInt8(); int selector = 0; object parameters = null; if (selection != 0) { selector = data.GetUInt8(); GXDataInfo info = new GXDataInfo(); parameters = GXCommon.GetData(settings, data, info); } if (xml != null) { xml.AppendStartTag(TranslatorTags.AttributeDescriptorWithSelection); xml.AppendStartTag(TranslatorTags.AttributeDescriptor); xml.AppendComment(ci.ToString()); xml.AppendLine(TranslatorTags.ClassId, "Value", xml.IntegerToHex((int)ci, 4)); xml.AppendComment(GXCommon.ToLogicalName(ln)); xml.AppendLine(TranslatorTags.InstanceId, "Value", GXCommon.ToHex(ln, false)); xml.AppendLine(TranslatorTags.AttributeId, "Value", xml.IntegerToHex(attributeIndex, 2)); xml.AppendEndTag(TranslatorTags.AttributeDescriptor); xml.AppendEndTag(TranslatorTags.AttributeDescriptorWithSelection); } else { GXDLMSObject obj = settings.Objects.FindByLN(ci, GXCommon.ToLogicalName(ln)); if (obj == null) { obj = server.NotifyFindObject(ci, 0, GXCommon.ToLogicalName(ln)); } if (obj == null) { // "Access Error : Device reports a undefined object." e = new ValueEventArgs(server, obj, attributeIndex, 0, 0); e.Error = ErrorCode.UndefinedObject; list.Add(e); } else { ValueEventArgs arg = new ValueEventArgs(server, obj, attributeIndex, selector, parameters); arg.InvokeId = invokeID; if (server.NotifyGetAttributeAccess(arg) == AccessMode.NoAccess) { //Read Write denied. arg.Error = ErrorCode.ReadWriteDenied; list.Add(arg); } else { list.Add(arg); } } } } } catch (Exception ex) { if (xml == null) { throw ex; } } if (xml != null) { xml.AppendEndTag(TranslatorTags.AttributeDescriptorList); return; } server.NotifyRead(list.ToArray()); object value; pos = 0; foreach (ValueEventArgs it in list) { try { if (it.Handled) { value = it.Value; } else { value = (it.Target as IGXDLMSBase).GetValue(settings, it); } bb.SetUInt8(it.Error); if (it.ByteArray) { bb.Set((byte[])value); } else { GXDLMS.AppendData(settings, it.Target, it.Index, bb, value); } invokeID = (byte)it.InvokeId; } catch (Exception) { bb.SetUInt8((byte)ErrorCode.HardwareFault); } if (settings.Index != settings.Count) { server.transaction = new GXDLMSLongTransaction(list.ToArray(), Command.GetRequest, null); } ++pos; } server.NotifyPostRead(list.ToArray()); GXDLMSLNParameters p = new GXDLMSLNParameters(null, settings, invokeID, Command.GetResponse, 3, null, bb, 0xFF); GXDLMS.GetLNPdu(p, replyData); }
///<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; } } }
/// <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(); } }
ushort IConvertible.ToUInt16(IFormatProvider provider) { GXByteBuffer bb = GetByteBuffer(Value, 2); return(bb.GetUInt16()); }
private byte[][] HandleGetRequest() { ErrorCode error = ErrorCode.Ok; GXByteBuffer data = Reply.Data; GXByteBuffer bb = new GXByteBuffer(); short type; int index = 0; object parameters = null; // Get type. type = data.GetUInt8(); // Get invoke ID and priority. data.GetUInt8(); // GetRequest normal if (type == 1) { Settings.ResetBlockIndex(); ServerReply.Index = 0; parameters = null; // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute Id int attributeIndex = data.GetUInt8(); GXDLMSObject obj = Settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = FindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } if (obj == null) { // "Access Error : Device reports a undefined object." error = ErrorCode.UndefinedObject; } else { // AccessSelection int selection = data.GetUInt8(); int selector = 0; if (selection != 0) { selector = data.GetUInt8(); GXDataInfo info = new GXDataInfo(); parameters = GXCommon.GetData(data, info); } ValueEventArgs e = new ValueEventArgs(obj, attributeIndex, 0, parameters); Read(e); object value; if (e.Handled) { value = e.Value; } else { value = (obj as IGXDLMSBase).GetValue(Settings, attributeIndex, selector, parameters); } GXDLMS.AppedData(obj, attributeIndex, bb, value); } ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 1, bb, error, DateTime.MinValue); } else if (type == 2) { // Get request for next data block // Get block index. index = (int)data.GetUInt32(); if (index != Settings.BlockIndex + 1) { Debug.WriteLine("handleGetRequest failed. Invalid block number. " + Settings.BlockIndex + "/" + index); ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 1, bb, ErrorCode.DataBlockNumberInvalid, DateTime.MinValue); index = 0; ServerReply.Index = index; } else { Settings.IncreaseBlockIndex(); index = ServerReply.Index + 1; ServerReply.Index = index; } } else if (type == 3) { // Get request with a list. int cnt = GXCommon.GetObjectCount(data); GXCommon.SetObjectCount(cnt, bb); for (int pos = 0; pos != cnt; ++pos) { ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); short attributeIndex = data.GetUInt8(); GXDLMSObject obj = Settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = FindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } if (obj == null) { // "Access Error : Device reports a undefined object." error = ErrorCode.UndefinedObject; } else { // AccessSelection int selection = data.GetUInt8(); int selector = 0; if (selection != 0) { selector = data.GetUInt8(); GXDataInfo info = new GXDataInfo(); parameters = GXCommon.GetData(data, info); } try { ValueEventArgs e = new ValueEventArgs(obj, attributeIndex, 0, parameters); Read(e); object value; if (e.Handled) { value = e.Value; } else { value = (obj as IGXDLMSBase).GetValue(Settings, attributeIndex, selector, parameters); } bb.SetUInt8(ErrorCode.Ok); GXDLMS.AppedData(obj, attributeIndex, bb, value); } catch (Exception) { bb.SetUInt8(1); bb.SetUInt8(ErrorCode.HardwareFault); } } } ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 3, bb, error, DateTime.MinValue); } else { Debug.WriteLine("handleGetRequest failed. Invalid command type."); Settings.ResetBlockIndex(); // Access Error : Device reports a hardware fault. ServerReply.ReplyMessages = GXDLMS.SplitPdu(Settings, Command.GetResponse, 1, bb, ErrorCode.HardwareFault, DateTime.MinValue); } ServerReply.Index = index; return(ServerReply.ReplyMessages[index]); }
private static void HandleReadDataBlockAccess( GXDLMSSettings settings, GXDLMSServer server, Command command, GXByteBuffer data, int cnt, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { GXByteBuffer bb = new GXByteBuffer(); byte lastBlock = data.GetUInt8(); UInt16 blockNumber = data.GetUInt16(); if (xml != null) { if (command == Command.WriteResponse) { xml.AppendStartTag(TranslatorTags.WriteDataBlockAccess); } else { xml.AppendStartTag(TranslatorTags.ReadDataBlockAccess); } xml.AppendLine("<LastBlock Value=\"" + xml.IntegerToHex(lastBlock, 2) + "\" />"); xml.AppendLine("<BlockNumber Value=\"" + xml.IntegerToHex(blockNumber, 4) + "\" />"); if (command == Command.WriteResponse) { xml.AppendEndTag(TranslatorTags.WriteDataBlockAccess); } else { xml.AppendEndTag(TranslatorTags.ReadDataBlockAccess); } return; } if (blockNumber != settings.BlockIndex) { Debug.WriteLine("handleReadRequest failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber); bb.SetUInt8(ErrorCode.DataBlockNumberInvalid); GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, command, 1, (byte)SingleReadResponse.DataAccessError, bb, null), replyData); settings.ResetBlockIndex(); return; } int count = 1; byte type = (byte)DataType.OctetString; if (command == Command.WriteResponse) { count = GXCommon.GetObjectCount(data); type = data.GetUInt8(); } int size = GXCommon.GetObjectCount(data); int realSize = data.Size - data.Position; if (count != 1 || type != (byte)DataType.OctetString || size != realSize) { Debug.WriteLine("handleGetRequest failed. Invalid block size."); bb.SetUInt8(ErrorCode.DataBlockUnavailable); GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, command, cnt, (byte)SingleReadResponse.DataAccessError, bb, null), replyData); settings.ResetBlockIndex(); return; } if (server.transaction == null) { server.transaction = new GXDLMSLongTransaction(null, command, data); } else { server.transaction.data.Set(data); } if (lastBlock == 0) { bb.SetUInt16(blockNumber); settings.IncreaseBlockIndex(); if (command == Command.ReadResponse) { type = (byte)SingleReadResponse.BlockNumber; } else { type = (byte)SingleWriteResponse.BlockNumber; } GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, command, cnt, type, null, bb), replyData); return; } else { if (server.transaction != null) { data.Size = 0; data.Set(server.transaction.data); server.transaction = null; } if (command == Command.ReadResponse) { HandleReadRequest(settings, server, data, replyData, xml); } else { HandleWriteRequest(settings, server, data, replyData, xml); } settings.ResetBlockIndex(); } }
/// <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> /// Handle write request. ///</summary> ///<param name="Reply"> /// Received data from the client. /// </param> ///<returns> /// Reply. ///</returns> 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); } } AccessMode am = target.Item.GetAccess(target.Index); // If write is denied. if (am != AccessMode.Write && am != AccessMode.ReadWrite) { results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied); } else { ValueEventArgs e = new ValueEventArgs(settings, target.Item, target.Index, 0, null); 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); } } } } if (xml != null) { xml.AppendEndTag(TranslatorTags.ListOfData); xml.AppendEndTag(Command.WriteRequest); return; } GenerateWriteResponse(settings, results, replyData); }
private void GetUa(GXByteBuffer data, GXDLMSTranslatorStructure xml) { xml.AppendStartTag(Command.Ua); data.GetUInt8(); // Skip FromatID data.GetUInt8(); // Skip Group ID. data.GetUInt8(); // Skip Group len Object val; while (data.Position < data.Size) { HDLCInfo id = (HDLCInfo)data.GetUInt8(); short len = data.GetUInt8(); switch (len) { case 1: val = data.GetUInt8(); break; case 2: val = data.GetUInt16(); break; case 4: val = data.GetUInt32(); break; default: throw new GXDLMSException("Invalid Exception."); } // RX / TX are delivered from the partner's point of view => // reversed to ours switch (id) { case HDLCInfo.MaxInfoTX: xml.AppendLine("<MaxInfoRX Value=\"" + val.ToString() + "\" />"); break; case HDLCInfo.MaxInfoRX: xml.AppendLine("<MaxInfoTX Value=\"" + val.ToString() + "\" />"); break; case HDLCInfo.WindowSizeTX: xml.AppendLine("<WindowSizeRX Value=\"" + val.ToString() + "\" />"); break; case HDLCInfo.WindowSizeRX: xml.AppendLine("<WindowSizeTX Value=\"" + val.ToString() + "\" />"); break; default: throw new GXDLMSException("Invalid UA response."); } } xml.AppendEndTag(Command.Ua); }
/// <summary> /// Convert message to xml. /// </summary> /// <param name="value">Bytes to convert.</param> /// <returns>Converted xml.</returns> /// <seealso cref="PduOnly"/> /// <seealso cref="CompletePdu"/> public string MessageToXml(GXByteBuffer value) { if (value == null || value.Size == 0) { throw new ArgumentNullException("value"); } try { GXReplyData data = new GXReplyData(); GXDLMSTranslatorStructure xml = new GXDLMSTranslatorStructure(OutputType, Hex, ShowStringAsHex, tags); data.Xml = xml; //If HDLC framing. int offset = value.Position; if (value.GetUInt8(value.Position) == 0x7e) { GXDLMSSettings settings = new GXDLMSSettings(true); settings.InterfaceType = Enums.InterfaceType.HDLC; if (GXDLMS.GetData(settings, value, data)) { if (!PduOnly) { xml.AppendLine("<HDLC len=\"" + (data.PacketLength - offset).ToString("X") + "\" >"); xml.AppendLine("<TargetAddress Value=\"" + settings.ServerAddress.ToString("X") + "\" />"); xml.AppendLine("<SourceAddress Value=\"" + settings.ClientAddress.ToString("X") + "\" />"); } if (data.Data.Size == 0) { if ((data.FrameId & 1) != 0 && data.Command == Command.None) { if (!CompletePdu) { xml.AppendLine("<Command Value=\"NextFrame\" />"); } multipleFrames = true; } else { xml.AppendStartTag(data.Command); xml.AppendEndTag(data.Command); } } else { if (multipleFrames || (data.MoreData & Enums.RequestTypes.Frame) != 0) { if (CompletePdu) { pduFrames.Set(data.Data.Data); } else { xml.AppendLine("<NextFrame Value=\"" + GXCommon.ToHex(data.Data.Data, false, data.Data.Position, data.Data.Size - data.Data.Position) + "\" />"); } multipleFrames = false; } if (!data.IsMoreData) { if (!PduOnly) { xml.AppendLine("<PDU>"); } if (pduFrames.Size != 0) { if (!CompletePdu) { pduFrames.Set(data.Data.Data); } xml.AppendLine(PduToXml(pduFrames)); pduFrames.Clear(); } else { xml.AppendLine(PduToXml(data.Data)); } //Remove \r\n. xml.sb.Length -= 2; if (!PduOnly) { xml.AppendLine("</PDU>"); } } } if (!PduOnly) { xml.AppendLine("</HDLC>"); } } return xml.sb.ToString(); } //If wrapper. if (value.GetUInt16(value.Position) == 1) { GXDLMSSettings settings = new GXDLMSSettings(true); settings.InterfaceType = Enums.InterfaceType.WRAPPER; GXDLMS.GetData(settings, value, data); if (!PduOnly) { xml.AppendLine("<WRAPPER len=\"" + (data.PacketLength - offset).ToString("X") + "\" >"); xml.AppendLine("<TargetAddress Value=\"" + settings.ClientAddress.ToString("X") + "\" />"); xml.AppendLine("<SourceAddress Value=\"" + settings.ServerAddress.ToString("X") + "\" />"); } if (data.Data.Size == 0) { xml.AppendLine("<Command Value=\"" + data.Command.ToString().ToUpper() + "\" />"); } else { if (data.Data.Size == 0) { if ((data.FrameId & 1) != 0 && data.Command == Command.None) { if (!CompletePdu) { xml.AppendLine("<Command Value=\"NextFrame\" />"); } multipleFrames = true; } else { xml.AppendStartTag(data.Command); xml.AppendEndTag(data.Command); } } else { if (multipleFrames || (data.MoreData & Enums.RequestTypes.Frame) != 0) { if (CompletePdu) { pduFrames.Set(data.Data.Data); } else { xml.AppendLine("<NextFrame Value=\"" + GXCommon.ToHex(data.Data.Data, false, data.Data.Position, data.Data.Size - data.Data.Position) + "\" />"); } multipleFrames = false; } if (!data.IsMoreData) { if (!PduOnly) { xml.AppendLine("<PDU>"); } if (pduFrames.Size != 0) { if (!CompletePdu) { pduFrames.Set(data.Data.Data); } xml.AppendLine(PduToXml(pduFrames)); pduFrames.Clear(); } else { xml.AppendLine(PduToXml(data.Data)); } //Remove \r\n. xml.sb.Length -= 2; if (!PduOnly) { xml.AppendLine("</PDU>"); } } } } if (!PduOnly) { xml.AppendLine("</WRAPPER>"); } return xml.sb.ToString(); } } catch (Exception ex) { System.Diagnostics.Debug.Write(ex.ToString()); } throw new ArgumentNullException("Invalid DLMS framing."); }
public byte[] GetPdu(GXByteBuffer value) { GXReplyData data = new GXReplyData(); data.Xml = new GXDLMSTranslatorStructure(OutputType, Hex, ShowStringAsHex, tags); GXDLMSSettings settings = new GXDLMSSettings(true); if (value.GetUInt8(0) == 0x7e) { settings.InterfaceType = Enums.InterfaceType.HDLC; } //If wrapper. else if (value.GetUInt16(0) == 1) { settings.InterfaceType = Enums.InterfaceType.WRAPPER; } else { throw new ArgumentNullException("Invalid DLMS framing."); } GXDLMS.GetData(settings, value, data); //Only fully PDUs are returned. if (data.IsMoreData) { return null; } return data.Data.Array(); }
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; } } }
/// <summary> /// Find next frame from the string. /// </summary> /// <remarks> /// Position of data is set to the begin of new frame. If Pdu is null it is not updated. /// </remarks> /// <param name="data">Data where frame is search.</param> /// <param name="pdu">Pdu of received frame is set here.</param> /// <returns>Is new frame found.</returns> public bool FindNextFrame(GXByteBuffer data, GXByteBuffer pdu) { GXDLMSSettings settings = new GXDLMSSettings(true); GXReplyData reply = new GXReplyData(); reply.Xml = new GXDLMSTranslatorStructure(OutputType, Hex, ShowStringAsHex, null); int pos; while (data.Position != data.Size) { if (data.GetUInt8(data.Position) == 0x7e) { pos = data.Position; settings.InterfaceType = Enums.InterfaceType.HDLC; GXDLMS.GetData(settings, data, reply); data.Position = pos; break; } else if (data.Position + 2 < data.Size && data.GetUInt16(data.Position) == 0x1) { pos = data.Position; settings.InterfaceType = Enums.InterfaceType.WRAPPER; GXDLMS.GetData(settings, data, reply); data.Position = pos; break; } ++data.Position; } if (pdu != null) { pdu.Clear(); pdu.Set(reply.Data.Data, 0, reply.Data.Size); } return data.Position != data.Size; }
static byte GetHdlcData(bool server, GXDLMSSettings settings, GXByteBuffer reply, GXReplyData data) { short ch; int pos, packetStartID = reply.Position, frameLen = 0; int crc, crcRead; // If whole frame is not received yet. if (reply.Size - reply.Position < 9) { data.IsComplete = false; return 0; } data.IsComplete = true; // Find start of HDLC frame. for (pos = reply.Position; pos < reply.Size; ++pos) { ch = reply.GetUInt8(); if (ch == GXCommon.HDLCFrameStartEnd) { packetStartID = pos; break; } } // Not a HDLC frame. // Sometimes meters can send some strange data between DLMS frames. if (reply.Position == reply.Size) { data.IsComplete = false; // Not enough data to parse; return 0; } byte frame = reply.GetUInt8(); if ((frame & 0xF0) != 0xA0) { //If same strage data. return GetHdlcData(server, settings, reply, data); } // Check frame length. if ((frame & 0x7) != 0) { frameLen = ((frame & 0x7) << 8); } ch = reply.GetUInt8(); // If not enough data. frameLen += ch; if (reply.Size - reply.Position + 1 < frameLen) { data.IsComplete = false; reply.Position = packetStartID; // Not enough data to parse; return 0; } int eopPos = frameLen + packetStartID + 1; ch = reply.GetUInt8(eopPos); if (ch != GXCommon.HDLCFrameStartEnd) { throw new GXDLMSException("Invalid data format."); } // Check addresses. if (!CheckHdlcAddress(server, settings, reply, eopPos)) { //If echo, reply.Position = 1 + eopPos; return GetHdlcData(server, settings, reply, data); } // Is there more data available. if ((frame & 0x8) != 0) { data.MoreData = (RequestTypes)(data.MoreData | RequestTypes.Frame); } else { data.MoreData = (RequestTypes)(data.MoreData & ~RequestTypes.Frame); } // Get frame type. frame = reply.GetUInt8(); if (data.Xml == null && !settings.CheckFrame(frame)) { reply.Position = (eopPos + 1); return GetHdlcData(server, settings, reply, data); } // Check that header CRC is correct. crc = GXFCS16.CountFCS16(reply.Data, packetStartID + 1, reply.Position - packetStartID - 1); crcRead = reply.GetUInt16(); if (crc != crcRead) { throw new Exception("Wrong CRC."); } // Check that packet CRC match only if there is a data part. if (reply.Position != packetStartID + frameLen + 1) { crc = GXFCS16.CountFCS16(reply.Data, packetStartID + 1, frameLen - 2); crcRead = reply.GetUInt16(packetStartID + frameLen - 1); if (crc != crcRead) { throw new Exception("Wrong CRC."); } // Remove CRC and EOP from packet length. data.PacketLength = eopPos - 2; } else { data.PacketLength = reply.Position + 1; } if ((frame & (byte)HdlcFrameType.Uframe) == (byte)HdlcFrameType.Uframe) { //Get Eop if there is no data. if (reply.Position == packetStartID + frameLen + 1) { // Get EOP. reply.GetUInt8(); } data.Command = (Command)frame; } //If S-frame else if ((frame & (byte)HdlcFrameType.Sframe) == (byte)HdlcFrameType.Sframe) { //If frame is rejected. int tmp = (frame >> 2) & 0x3; if (tmp == (byte)HdlcControlFrame.Reject) { data.Error = (int)ErrorCode.Rejected; } else if (tmp == (byte)HdlcControlFrame.ReceiveNotReady) { data.Error = (int)ErrorCode.Rejected; } else if (tmp == (byte)HdlcControlFrame.ReceiveReady) { System.Diagnostics.Debug.WriteLine("Get next frame."); } //Get Eop if there is no data. if (reply.Position == packetStartID + frameLen + 1) { // Get EOP. reply.GetUInt8(); } } else //Iframe { //Get Eop if there is no data. if (reply.Position == packetStartID + frameLen + 1) { // Get EOP. reply.GetUInt8(); if ((frame & 0x1) == 0x1) { data.MoreData = RequestTypes.Frame; } } else { if (!GetLLCBytes(server, reply) && data.Xml != null) { GetLLCBytes(!server, reply); } } } return frame; }
///<summary> ///Handle set request. ///</summary> ///<returns> ///Reply to the client. ///</returns> private byte[][] HandleSetRequest() { ErrorCode error = ErrorCode.Ok; GXByteBuffer data = Reply.Data; GXDataInfo info = new GXDataInfo(); GXByteBuffer bb = new GXByteBuffer(); // Get type. short type = data.GetUInt8(); // Get invoke ID and priority. data.GetUInt8(); // SetRequest normal if (type == 1) { Settings.ResetBlockIndex(); ServerReply.Index = 0; // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute index. int index = data.GetUInt8(); // Get Access Selection. data.GetUInt8(); object value = GXCommon.GetData(data, info); GXDLMSObject obj = Settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = FindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } // If target is unknown. if (obj == null) { Debug.WriteLine("Undefined object."); // Device reports a undefined object. error = ErrorCode.UndefinedObject; } else { AccessMode am = obj.GetAccess(index); // If write is denied. if (am != AccessMode.Write && am != AccessMode.ReadWrite) { Debug.WriteLine("Read Write denied."); error = ErrorCode.ReadWriteDenied; } else { try { if (value is byte[]) { DataType dt = (obj as IGXDLMSBase).GetDataType(index); if (dt != DataType.None) { value = GXDLMSClient.ChangeType((byte[])value, dt); } } ValueEventArgs e = new ValueEventArgs(obj, index, 0, null); Write(e); if (!e.Handled) { (obj as IGXDLMSBase).SetValue(Settings, index, value); } } catch (Exception e) { Debug.WriteLine(e.Message); error = ErrorCode.HardwareFault; } } } } else { Debug.WriteLine("handleSetRequest failed. Unknown command."); Settings.ResetBlockIndex(); error = ErrorCode.HardwareFault; } return(GXDLMS.SplitPdu(Settings, Command.SetResponse, 1, bb, error, DateTime.MinValue)[0]); }
/// <summary> /// Get data from TCP/IP frame. /// </summary> /// <param name="settings">DLMS settings.</param> /// <param name="buff">Received data.</param> /// <param name="data"> Reply information.</param> static void GetTcpData(GXDLMSSettings settings, GXByteBuffer buff, GXReplyData data) { // If whole frame is not received yet. if (buff.Size - buff.Position < 8) { data.IsComplete = false; return; } int pos = buff.Position; int value; // Get version value = buff.GetUInt16(); if (value != 1) { throw new GXDLMSException("Unknown version."); } // Check TCP/IP addresses. CheckWrapperAddress(settings, buff); // Get length. value = buff.GetUInt16(); data.IsComplete = !((buff.Size - buff.Position) < value); if (!data.IsComplete) { buff.Position = pos; } else { data.PacketLength = buff.Position + value; } }
/// ///<summary>Handle read request. /// </summary> ///<returns> Reply to the client. </returns> /// private byte[][] HandleReadRequest() { GXByteBuffer data = Reply.Data; short type; object value = null; GXByteBuffer bb = new GXByteBuffer(); int cnt = GXCommon.GetObjectCount(data); GXCommon.SetObjectCount(cnt, bb); GXSNInfo info; for (int pos = 0; pos != cnt; ++pos) { type = data.GetUInt8(); // GetRequest normal if (type == 2) { int sn = data.GetUInt16(); info = FindSNObject(sn); if (!info.IsAction) { ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, null); Read(e); if (e.Handled) { value = e.Value; } else { value = (info.Item as IGXDLMSBase).GetValue(Settings, info.Index, 0, null); } // Set status. bb.SetUInt8(0); GXDLMS.AppedData(info.Item, info.Index, bb, value); } else { ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, null); Action(e); if (e.Handled) { value = e.Value; } else { value = ((IGXDLMSBase)info.Item).Invoke(Settings, info.Index, null); } // Set status. bb.SetUInt8(0); // Add value bb.SetUInt8(GXCommon.GetValueType(value)); bb.Add(value); } } else if (type == 2) { // Get request for next data block throw new System.ArgumentException("TODO: Invalid Command."); } else if (type == 4) { // Parameterised access. int sn = data.GetUInt16(); int selector = data.GetUInt8(); GXDataInfo di = new GXDataInfo(); object parameters = GXCommon.GetData(data, di); info = FindSNObject(sn); if (!info.IsAction) { ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, parameters); Read(e); if (e.Handled) { value = e.Value; } else { value = (info.Item as IGXDLMSBase).GetValue(Settings, info.Index, selector, parameters); } // Set status. bb.SetUInt8(0); GXDLMS.AppedData(info.Item, info.Index, bb, value); } else { ValueEventArgs e = new ValueEventArgs(info.Item, info.Index, 0, parameters); e.Value = parameters; Action(e); if (e.Handled) { value = e.Value; } else { value = ((IGXDLMSBase)info.Item).Invoke(Settings, info.Index, parameters); } // Add value bb.Add(value); } } else { throw new System.ArgumentException("Invalid Command."); } } return(GXDLMS.SplitPdu(Settings, Command.ReadResponse, 1, bb, ErrorCode.Ok, DateTime.MinValue)[0]); }
private static void CheckWrapperAddress(GXDLMSSettings settings, GXByteBuffer buff) { int value; if (settings.IsServer) { value = buff.GetUInt16(); // Check that client addresses match. if (settings.ClientAddress != 0 && settings.ClientAddress != value) { throw new GXDLMSException( "Source addresses do not match. It is " + value.ToString() + ". It should be " + settings.ClientAddress.ToString() + "."); } else { settings.ClientAddress = value; } value = buff.GetUInt16(); // Check that server addresses match. if (settings.ServerAddress != 0 && settings.ServerAddress != value) { throw new GXDLMSException( "Destination addresses do not match. It is " + value.ToString() + ". It should be " + settings.ServerAddress.ToString() + "."); } else { settings.ServerAddress = value; } } else { value = buff.GetUInt16(); // Check that server addresses match. if (settings.ClientAddress != 0 && settings.ServerAddress != value) { throw new GXDLMSException( "Source addresses do not match. It is " + value.ToString() + ". It should be " + settings.ServerAddress.ToString() + "."); } else { settings.ServerAddress = value; } value = buff.GetUInt16(); // Check that client addresses match. if (settings.ClientAddress != 0 && settings.ClientAddress != value) { throw new GXDLMSException( "Destination addresses do not match. It is " + value.ToString() + ". It should be " + settings.ClientAddress.ToString() + "."); } else { settings.ClientAddress = value; } } }
///<summary> /// Handle action request. ///</summary> ///<param name="Reply"> /// Received data from the client. ///</param> ///<returns> ///Reply. ///</returns> 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(); // 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, GXDLMSObject.ToLogicalName(ln)); if (!settings.Connected && (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, GXDLMSObject.ToLogicalName(ln)); } if (obj == null) { // Device reports a undefined object. error = ErrorCode.UndefinedObject; } else { if (obj.GetMethodAccess(id) == MethodAccessMode.NoAccess) { error = ErrorCode.ReadWriteDenied; } else { ValueEventArgs e = new ValueEventArgs(settings, obj, id, 0, parameters); server.NotifyAction(new ValueEventArgs[] { e }); byte[] actionReply; if (e.Handled) { actionReply = (byte[])e.Value; } else { actionReply = (obj as IGXDLMSBase).Invoke(settings, 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, GXCommon.GetValueType(actionReply), actionReply); } else { error = e.Error; //Add return parameters bb.SetUInt8(0); } } } GXDLMSLNParameters p = new GXDLMSLNParameters(settings, Command.MethodResponse, 1, null, bb, (byte)error); GXDLMS.GetLNPdu(p, replyData); //If High level authentication fails. if (!settings.Connected && obj is GXDLMSAssociationLogicalName && id == 1) { server.NotifyInvalidConnection(connectionInfo); } }
/// <summary> /// Handle get request normal command. /// </summary> /// <param name="data">Received data.</param> private static void GetRequestNormal(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { ValueEventArgs e = null; GXByteBuffer bb = new GXByteBuffer(); // Get type. ErrorCode status = ErrorCode.Ok; settings.Count = settings.Index = 0; settings.ResetBlockIndex(); // CI ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); // Attribute Id byte attributeIndex = data.GetUInt8(); // AccessSelection byte selection = data.GetUInt8(); byte selector = 0; object parameters = null; GXDataInfo info = new GXDataInfo(); if (selection != 0) { selector = data.GetUInt8(); } if (xml != null) { AppendAttributeDescriptor(xml, (int)ci, ln, attributeIndex); if (selection != 0) { info.xml = xml; xml.AppendStartTag(TranslatorTags.AccessSelection); xml.AppendLine(TranslatorTags.AccessSelector, "Value", xml.IntegerToHex(selector, 2)); xml.AppendStartTag(TranslatorTags.AccessParameters); GXCommon.GetData(settings, data, info); xml.AppendEndTag(TranslatorTags.AccessParameters); xml.AppendEndTag(TranslatorTags.AccessSelection); } return; } if (selection != 0) { parameters = GXCommon.GetData(settings, data, info); } GXDLMSObject obj = settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = server.NotifyFindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } if (obj == null) { // "Access Error : Device reports a undefined object." status = ErrorCode.UndefinedObject; } else { if (obj.GetAccess(attributeIndex) == AccessMode.NoAccess) { //Read Write denied. status = ErrorCode.ReadWriteDenied; } else { e = new ValueEventArgs(settings, obj, attributeIndex, selector, parameters); server.NotifyRead(new ValueEventArgs[] { e }); object value; if (e.Handled) { value = e.Value; } else { value = (obj as IGXDLMSBase).GetValue(settings, e); } GXDLMS.AppendData(settings, obj, attributeIndex, bb, value); status = e.Error; } } GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, Command.GetResponse, 1, null, bb, (byte)status), replyData); if (settings.Count != settings.Index || bb.Size != bb.Position) { server.transaction = new GXDLMSLongTransaction(new ValueEventArgs[] { e }, Command.GetRequest, bb); } }
///<summary> /// Handle 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 get request with list command. /// </summary> /// <param name="data">Received data.</param> private static void GetRequestWithList(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { ValueEventArgs e; GXByteBuffer bb = new GXByteBuffer(); int pos; int cnt = GXCommon.GetObjectCount(data); GXCommon.SetObjectCount(cnt, bb); List<ValueEventArgs> list = new List<ValueEventArgs>(); if (xml != null) { xml.AppendStartTag(TranslatorTags.AttributeDescriptorList, "Qty", xml.IntegerToHex(cnt, 2)); } try { for (pos = 0; pos != cnt; ++pos) { ObjectType ci = (ObjectType)data.GetUInt16(); byte[] ln = new byte[6]; data.Get(ln); short attributeIndex = data.GetUInt8(); // AccessSelection int selection = data.GetUInt8(); int selector = 0; object parameters = null; if (selection != 0) { selector = data.GetUInt8(); GXDataInfo info = new GXDataInfo(); parameters = GXCommon.GetData(settings, data, info); } if (xml != null) { xml.AppendStartTag(TranslatorTags.AttributeDescriptorWithSelection); xml.AppendStartTag(TranslatorTags.AttributeDescriptor); xml.AppendLine(TranslatorTags.ClassId, "Value", xml.IntegerToHex((int)ci, 4)); xml.AppendLine(TranslatorTags.InstanceId, "Value", GXCommon.ToHex(ln, false)); xml.AppendLine(TranslatorTags.AttributeId, "Value", xml.IntegerToHex(attributeIndex, 2)); xml.AppendEndTag(TranslatorTags.AttributeDescriptor); xml.AppendEndTag(TranslatorTags.AttributeDescriptorWithSelection); } else { GXDLMSObject obj = settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = server.NotifyFindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } if (obj == null) { // "Access Error : Device reports a undefined object." e = new ValueEventArgs(settings, obj, attributeIndex, 0, 0); e.Error = ErrorCode.UndefinedObject; list.Add(e); } else { if (obj.GetAccess(attributeIndex) == AccessMode.NoAccess) { //Read Write denied. ValueEventArgs arg = new ValueEventArgs(settings, obj, attributeIndex, 0, null); arg.Error = ErrorCode.ReadWriteDenied; list.Add(arg); } else { ValueEventArgs arg = new ValueEventArgs(settings, obj, attributeIndex, selector, parameters); list.Add(arg); } } } } } catch (Exception ex) { if (xml == null) { throw ex; } } if (xml != null) { xml.AppendEndTag(TranslatorTags.AttributeDescriptorList); return; } server.NotifyRead(list.ToArray()); object value; pos = 0; foreach (ValueEventArgs it in list) { try { if (it.Handled) { value = it.Value; } else { value = (it.Target as IGXDLMSBase).GetValue(settings, it); } bb.SetUInt8(it.Error); GXDLMS.AppendData(settings, it.Target, it.Index, bb, value); } catch (Exception) { bb.SetUInt8((byte)ErrorCode.HardwareFault); } if (settings.Index != settings.Count) { server.transaction = new GXDLMSLongTransaction(list.ToArray(), Command.GetRequest, null); } ++pos; } GXDLMSLNParameters p = new GXDLMSLNParameters(settings, Command.GetResponse, 3, null, bb, 0xFF); GXDLMS.GetLNPdu(p, replyData); }
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 (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 (type == 2) { p.multipleBlocks = data.GetUInt8() == 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 (!p.multipleBlocks) { settings.ResetBlockIndex(); value = GXCommon.GetData(settings, data, reply); } GXDLMSObject obj = settings.Objects.FindByLN(ci, GXDLMSObject.ToLogicalName(ln)); if (obj == null) { obj = server.NotifyFindObject(ci, 0, GXDLMSObject.ToLogicalName(ln)); } // If target is unknown. if (obj == null) { // Device reports a undefined object. p.status = (byte)ErrorCode.UndefinedObject; } else { AccessMode am = obj.GetAccess(index); // 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) { value = GXDLMSClient.ChangeType((byte[])value, dt); } } ValueEventArgs e = new ValueEventArgs(settings, obj, index, 0, null); 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); } } catch (Exception) { p.status = (byte)ErrorCode.HardwareFault; } } } }
/// <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); } }
///<summary> /// Handle Access request. ///</summary> ///<param name="Reply"> /// Received data from the client. /// </param> ///<returns> /// Reply. ///</returns> 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) { reply.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } //Get long invoke id and priority. UInt32 invokeId = data.GetUInt32(); 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); } }
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 write request. ///</summary> ///<param name="Reply"> /// Received data from the client. /// </param> ///<returns> /// Reply. ///</returns> private byte[][] HandleWriteRequest() { GXByteBuffer data = Reply.Data; short type; object value; // Get object count. IList <GXSNInfo> targets = new List <GXSNInfo>(); int cnt = GXCommon.GetObjectCount(data); GXByteBuffer results = new GXByteBuffer((ushort)cnt); for (int pos = 0; pos != cnt; ++pos) { type = data.GetUInt8(); if (type == 2) { int sn = data.GetUInt16(); GXSNInfo info = FindSNObject(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 { // Device reports a HW error. results.SetUInt8(ErrorCode.HardwareFault); } } // Get data count. cnt = GXCommon.GetObjectCount(data); GXDataInfo di = new GXDataInfo(); for (int pos = 0; pos != cnt; ++pos) { if (results.GetUInt8(pos) == 0) { // If object has found. GXSNInfo target = targets[pos]; value = GXCommon.GetData(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); } } di.Clear(); AccessMode am = target.Item.GetAccess(target.Index); // If write is denied. if (am != AccessMode.Write && am != AccessMode.ReadWrite) { results.SetUInt8((byte)pos, (byte)ErrorCode.ReadWriteDenied); } else { ValueEventArgs e = new ValueEventArgs(target.Item, target.Index, 0, null); e.Value = value; Write(e); if (!e.Handled) { (target.Item as IGXDLMSBase).SetValue(Settings, target.Index, value); } } } } GXByteBuffer bb = new GXByteBuffer((UInt16)(2 * cnt + 2)); GXCommon.SetObjectCount(cnt, bb); byte ret; for (int pos = 0; pos != cnt; ++pos) { ret = results.GetUInt8(pos); // If meter returns error. if (ret != 0) { bb.SetUInt8(1); } bb.SetUInt8(ret); } return(GXDLMS.SplitPdu(Settings, Command.WriteResponse, 1, bb, ErrorCode.Ok, DateTime.MinValue)[0]); }
///<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> /// Identify used DLMS framing type. /// </summary> /// <param name="value">Input data.</param> /// <returns>Interface type.</returns> public static InterfaceType GetDlmsFraming(GXByteBuffer value) { for (int pos = value.Position; pos != value.Size; ++pos) { if (value.GetUInt8(pos) == 0x7e) { return InterfaceType.HDLC; } if (value.GetUInt16(pos) == 1) { return InterfaceType.WRAPPER; } } throw new ArgumentException("Invalid DLMS framing."); }