///<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> /// Handles release reuest. /// </summary> /// <param name="data">Received data.</param> /// <param name="connectionInfo">Connection info.</param> private void HandleReleaseRequest(GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo) { //Return error if connection is not established. if (!Settings.Connected && !Settings.IsAuthenticationRequired && !Settings.AllowAnonymousAccess) { replyData.Add(GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } if (Settings.InterfaceType == InterfaceType.HDLC) { replyData.Set(0, GXCommon.LLCReplyBytes); } replyData.SetUInt8(0x63); //LEN. replyData.SetUInt8(0x03); replyData.SetUInt8(0x80); replyData.SetUInt8(0x01); replyData.SetUInt8(0x00); }
///<summary> ///Generates disconnect request. /// </summary> ///<returns> ///Disconnect request. ///</returns> private byte[][] GenerateDisconnectRequest() { GXByteBuffer buff; if (this.InterfaceType == InterfaceType.WRAPPER) { buff = new GXByteBuffer(2); buff.SetUInt8(0x63); buff.SetUInt8(0x0); return(GXDLMS.SplitToWrapperFrames(Settings, buff)); } else { buff = new GXByteBuffer(22); buff.SetUInt8(0x81); // FromatID buff.SetUInt8(0x80); // GroupID buff.SetUInt8(0); // Length buff.SetUInt8(HDLCInfo.MaxInfoTX); buff.SetUInt8(GXCommon.GetSize(Limits.MaxInfoTX)); buff.Add(Limits.MaxInfoTX); buff.SetUInt8(HDLCInfo.MaxInfoRX); buff.SetUInt8(GXCommon.GetSize(Limits.MaxInfoRX)); buff.Add(Limits.MaxInfoRX); buff.SetUInt8(HDLCInfo.WindowSizeTX); buff.SetUInt8(GXCommon.GetSize(Limits.WindowSizeTX)); buff.Add(Limits.WindowSizeTX); buff.SetUInt8(HDLCInfo.WindowSizeRX); buff.SetUInt8(GXCommon.GetSize(Limits.WindowSizeRX)); buff.Add(Limits.WindowSizeRX); int len = buff.Position - 3; buff.SetUInt8(2, (byte)len); // Length. } return(GXDLMS.SplitToHdlcFrames(Settings, (byte)Command.Ua, buff)); }
///<summary> ///Parse SNRM Request. If server do not accept client empty byte array is returned. /// </summary> ///<returns> ///Returns returned UA packet. ///</returns> private byte[][] HandleSnrmRequest() { GXByteBuffer bb = new GXByteBuffer(25); bb.SetUInt8(0x81); // FromatID bb.SetUInt8(0x80); // GroupID bb.SetUInt8(0); // Length bb.SetUInt8(HDLCInfo.MaxInfoTX); bb.SetUInt8(GXCommon.GetSize(Limits.MaxInfoTX)); bb.Add(Limits.MaxInfoTX); bb.SetUInt8(HDLCInfo.MaxInfoRX); bb.SetUInt8(GXCommon.GetSize(Limits.MaxInfoRX)); bb.Add(Limits.MaxInfoRX); bb.SetUInt8(HDLCInfo.WindowSizeTX); bb.SetUInt8(GXCommon.GetSize(Limits.WindowSizeTX)); bb.Add(Limits.WindowSizeTX); bb.SetUInt8(HDLCInfo.WindowSizeRX); bb.SetUInt8(GXCommon.GetSize(Limits.WindowSizeRX)); bb.Add(Limits.WindowSizeRX); bb.SetUInt8(2, (byte)(bb.Size - 3)); return(GXDLMS.SplitToHdlcFrames(Settings, (byte)Command.Ua, bb)); }
///<summary> ///Parse SNRM Request. If server do not accept client empty byte array is returned. /// </summary> ///<returns> ///Returns returned UA packet. ///</returns> private void HandleSnrmRequest() { Reset(true); replyData.SetUInt8(0x81); // FromatID replyData.SetUInt8(0x80); // GroupID replyData.SetUInt8(0); // Length replyData.SetUInt8(HDLCInfo.MaxInfoTX); replyData.SetUInt8(GXCommon.GetSize(Limits.MaxInfoTX)); replyData.Add(Limits.MaxInfoTX); replyData.SetUInt8(HDLCInfo.MaxInfoRX); replyData.SetUInt8(GXCommon.GetSize(Limits.MaxInfoRX)); replyData.Add(Limits.MaxInfoRX); replyData.SetUInt8(HDLCInfo.WindowSizeTX); replyData.SetUInt8(GXCommon.GetSize(Limits.WindowSizeTX)); replyData.Add(Limits.WindowSizeTX); replyData.SetUInt8(HDLCInfo.WindowSizeRX); replyData.SetUInt8(GXCommon.GetSize(Limits.WindowSizeRX)); replyData.Add(Limits.WindowSizeRX); replyData.SetUInt8(2, (byte)(replyData.Size - 3)); }
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); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return MBusPortReference; } if (e.Index == 3) { GXByteBuffer buff = new GXByteBuffer(); buff.Add((byte)DataType.Array); GXCommon.SetObjectCount(CaptureDefinition.Count, buff); foreach (KeyValuePair<string, string> it in CaptureDefinition) { buff.Add((byte)DataType.Structure); buff.Add(2); GXCommon.SetData(settings, buff, DataType.UInt8, it.Key); GXCommon.SetData(settings, buff, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(it.Value)); } return buff.Array(); } if (e.Index == 4) { return CapturePeriod; } if (e.Index == 5) { return PrimaryAddress; } if (e.Index == 6) { return IdentificationNumber; } if (e.Index == 7) { return ManufacturerID; } if (e.Index == 8) { return DataHeaderVersion; } if (e.Index == 9) { return DeviceType; } if (e.Index == 10) { return AccessNumber; } if (e.Index == 11) { return Status; } if (e.Index == 12) { return Alarm; } if (Version > 0) { if (e.Index == 13) { return Configuration; } if (e.Index == 14) { return EncryptionKeyStatus; } } e.Error = ErrorCode.ReadWriteDenied; return null; }
/// <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; } }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { if (e.Value is string) { LogicalName = e.Value.ToString(); } else { LogicalName = GXDLMSClient.ChangeType((byte[])e.Value, DataType.OctetString).ToString(); } } else if (e.Index == 2) { Mode = (IecTwistedPairSetupMode)e.Value; } else if (e.Index == 3) { Speed = (BaudRate)e.Value; } else if (e.Index == 4) { GXByteBuffer list = new GXByteBuffer(); foreach (object it in (object[])e.Value) { list.Add((byte)it); } PrimaryAddresses = list.Array(); } else if (e.Index == 5) { List<sbyte> list = new List<sbyte>(); foreach (object it in (object[])e.Value) { list.Add((sbyte)it); } Tabis = list.ToArray(); } else { e.Error = ErrorCode.ReadWriteDenied; } }
/// ///<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]); }
/// <summary> /// Presets the time to a new value (preset_time) and defines a validity_interval within which the new time can be activated. /// </summary> /// <param name="presetTime"></param> /// <param name="validityIntervalStart"></param> /// <param name="validityIntervalEnd"></param> /// <returns></returns> public byte[][] PresetAdjustingTime(GXDLMSClient client, DateTime presetTime, DateTime validityIntervalStart, DateTime validityIntervalEnd) { GXByteBuffer buff = new GXByteBuffer(); buff.Add((byte)DataType.Structure); buff.Add((byte)3); GXCommon.SetData(client.Settings, buff, DataType.OctetString, presetTime); GXCommon.SetData(client.Settings, buff, DataType.OctetString, validityIntervalStart); GXCommon.SetData(client.Settings, buff, DataType.OctetString, validityIntervalEnd); return client.Method(this, 5, buff.Array(), DataType.Array); }
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(settings, 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; } list.Add(e); if (!e.action && info.Item.GetAccess(info.Index) == AccessMode.NoAccess) { e.Error = ErrorCode.ReadWriteDenied; } else if (e.action && info.Item.GetMethodAccess(info.Index) == MethodAccessMode.NoAccess) { e.Error = ErrorCode.ReadWriteDenied; } else { if (e.action) { actions.Add(e); } else { reads.Add(e); } } }
///<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); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { GXByteBuffer buff = new GXByteBuffer(); buff.Add((byte)DataType.Array); GXCommon.SetObjectCount(ListeningWindow.Count, buff); foreach (KeyValuePair<GXDateTime, GXDateTime> it in ListeningWindow) { buff.Add((byte)DataType.Structure); buff.Add(2); GXCommon.SetData(settings, buff, DataType.OctetString, it.Key); GXCommon.SetData(settings, buff, DataType.OctetString, it.Value); } return buff.Array(); } if (e.Index == 3) { GXByteBuffer buff = new GXByteBuffer(); buff.Add((byte)DataType.Array); GXCommon.SetObjectCount(AllowedSenders.Length, buff); foreach (string it in AllowedSenders) { GXCommon.SetData(settings, buff, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(it)); } return buff.Array(); } if (e.Index == 4) { GXByteBuffer buff = new GXByteBuffer(); buff.Add((byte)DataType.Array); GXCommon.SetObjectCount(SendersAndActions.Count, buff); foreach (KeyValuePair<string, KeyValuePair<int, GXDLMSScriptAction>> it in SendersAndActions) { buff.Add((byte)DataType.Structure); buff.Add(2); GXCommon.SetData(settings, buff, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(it.Key)); //TODO: GXCommon.SetData(buff, DataType.OctetString, (it.Value.)); } return buff.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }