/// <summary> /// Generates Push message. /// </summary> /// <param name="objects">List of objects and attribute indexes to push.</param> /// <returns>Generated push message(s).</returns> public byte[][] GeneratePushMessage(DateTime date, List <KeyValuePair <GXDLMSObject, int> > objects) { DataType dt; object value; if (objects == null) { throw new ArgumentNullException("objects"); } GXByteBuffer buff = new GXByteBuffer(); //Add data buff.SetUInt8(DataType.Structure); GXCommon.SetObjectCount(objects.Count, buff); foreach (KeyValuePair <GXDLMSObject, int> it in objects) { dt = it.Key.GetDataType(it.Value); value = (it.Key as IGXDLMSBase).GetValue(Settings, it.Value, 0, null); if (dt == DataType.None && value != null) { dt = GXCommon.GetValueType(value); } GXCommon.SetData(buff, dt, value); } List <byte[][]> list = GXDLMS.SplitPdu(Settings, Command.Push, 0, buff, ErrorCode.Ok, DateTime.MinValue); List <byte[]> arr = new List <byte[]>(); foreach (byte[][] it in list) { arr.AddRange(it); } return(arr.ToArray()); }
///<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> /// Generates data notification message. /// </summary> /// <param name="date">Date time. Set To Min or Max if not added</param> /// <param name="data">Notification body.</param> /// <returns>Generated data notification message(s).</returns> public byte[][] GetDataNotificationMessage(DateTime date, byte[] data) { GXByteBuffer buff = new GXByteBuffer(); if (date == DateTime.MinValue || date == DateTime.MaxValue) { buff.SetUInt8(DataType.None); } else { GXCommon.SetData(buff, DataType.DateTime, date); } buff.Set(data); return(GXDLMS.SplitPdu(Settings, Command.DataNotification, 0, buff, ErrorCode.Ok, DateTime.MinValue)[0]); }
///<summary> ///Parse AARQ request that client send and returns AARE request. /// </summary> ///<returns> ///Reply to the client. ///</returns> private byte[][] HandleAarqRequest() { AssociationResult result = AssociationResult.Accepted; Settings.CtoSChallenge = null; if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = null; } SourceDiagnostic diagnostic = GXAPDU.ParsePDU(Settings, Settings.Cipher, Reply.Data); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; diagnostic = SourceDiagnostic.ApplicationContextNameNotSupported; } else { // Check that user can access server. diagnostic = ValidateAuthentication(Settings.Authentication, Settings.Password); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; } else if (Settings.Authentication > Authentication.Low) { // If High authentication is used. Settings.StoCChallenge = GXSecure.GenerateChallenge(Settings.Authentication); result = AssociationResult.Accepted; diagnostic = SourceDiagnostic.AuthenticationRequired; } } // Generate AARE packet. GXByteBuffer buff = new GXByteBuffer(150); GXAPDU.GenerateAARE(Settings, buff, result, diagnostic, Settings.Cipher); return(GXDLMS.SplitPdu(Settings, Command.Aare, 0, buff, ErrorCode.Ok, DateTime.MinValue)[0]); }
/// <summary> /// Generates data notification message. /// </summary> /// <param name="date">Date time. Set To Min or Max if not added</param> /// <param name="objects">List of objects and attribute indexes to notify.</param> /// <returns>Generated data notification message(s).</returns> public byte[][] GenerateDataNotificationMessage(DateTime date, List <KeyValuePair <GXDLMSObject, int> > objects) { if (objects == null) { throw new ArgumentNullException("objects"); } GXByteBuffer buff = new GXByteBuffer(); if (date == DateTime.MinValue || date == DateTime.MaxValue) { buff.SetUInt8(DataType.None); } else { GXCommon.SetData(buff, DataType.DateTime, date); } buff.SetUInt8(DataType.Array); GXCommon.SetObjectCount(objects.Count, buff); foreach (KeyValuePair <GXDLMSObject, int> it in objects) { AddData(it.Key, it.Value, buff); } return(GXDLMS.SplitPdu(Settings, Command.DataNotification, 0, buff, ErrorCode.Ok, DateTime.MinValue)[0]); }
/// ///<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 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]); }
///<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> /// 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]); }