/// <summary> /// Constructor. /// </summary> /// <param name="more">Is more data available.</param> /// <param name="cmd"> Received command.</param> /// <param name="buff">Received data.</param> /// <param name="complete">Is frame complete.</param> /// <param name="error">Received error ID.</param> internal GXReplyData(RequestTypes more, Command cmd, GXByteBuffer buff, bool complete, byte error) { Data = new GXByteBuffer(); Clear(); MoreData = more; Command = cmd; Data = buff; IsComplete = complete; Error = error; }
public static void HandleGetRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && !settings.Connected) { replyData.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } GetCommandType type = (GetCommandType)data.GetUInt8(); // Get invoke ID and priority. byte invokeID = data.GetUInt8(); if (xml != null) { xml.AppendStartTag(Command.GetRequest); xml.AppendStartTag(Command.GetRequest, type); xml.AppendLine(TranslatorTags.InvokeId, "Value", xml.IntegerToHex(invokeID, 2)); } // GetRequest normal if (type == GetCommandType.Normal) { GetRequestNormal(settings, server, data, replyData, xml); } else if (type == GetCommandType.NextDataBlock) { // Get request for next data block GetRequestNextDataBlock(settings, server, data, replyData, xml); } else if (type == GetCommandType.WithList) { // Get request with a list. GetRequestWithList(settings, server, data, replyData, xml); } else { Debug.WriteLine("HandleGetRequest failed. Invalid command type."); settings.ResetBlockIndex(); GXByteBuffer bb = new GXByteBuffer(); // Access Error : Device reports a hardware fault. bb.SetUInt8((byte)ErrorCode.HardwareFault); GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, Command.GetResponse, (byte)type, null, bb, (byte)ErrorCode.Ok), replyData); } if (xml != null) { xml.AppendEndTag(Command.GetRequest, type); xml.AppendEndTag(Command.GetRequest); } }
public void ParseUAResponse(GXByteBuffer data) { client.ParseUAResponse(data); }
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> /// Generates data notification message(s). /// </summary> /// <param name="time">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[][] GenerateDataNotificationMessages(DateTime time, GXByteBuffer data) { byte[][] reply; if (UseLogicalNameReferencing) { GXDLMSLNParameters p = new GXDLMSLNParameters(Settings, Command.DataNotification, 0, null, data, 0xff); p.time = time; p.time.Skip |= DateTimeSkips.Ms; reply = GXDLMS.GetLnMessages(p); } else { GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, Command.DataNotification, 1, 0, data, null); reply = GXDLMS.GetSnMessages(p); } return reply; }
/// <summary> /// Get sertificates as byte buffer. /// </summary> /// <returns></returns> private byte[] GetSertificates() { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); GXCommon.SetObjectCount(Certificates.Count, bb); foreach (GXDLMSCertificateInfo it in Certificates) { bb.SetUInt8((byte)DataType.Structure); GXCommon.SetObjectCount(6, bb); bb.SetUInt8((byte)DataType.Enum); bb.SetUInt8((byte)it.Entity); bb.SetUInt8((byte)DataType.Enum); bb.SetUInt8((byte)it.Type); GXCommon.AddString(it.SerialNumber, bb); GXCommon.AddString(it.Issuer, bb); GXCommon.AddString(it.Subject, bb); GXCommon.AddString(it.SubjectAltName, bb); } return bb.Array(); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { int cnt = 0; if (SapAssignmentList != null) { cnt = SapAssignmentList.Count; } GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); //Add count GXCommon.SetObjectCount(cnt, data); if (cnt != 0) { foreach (var it in SapAssignmentList) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)2); //Count GXCommon.SetData(settings, data, DataType.UInt16, it.Key); GXCommon.SetData(settings, data, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(it.Value)); } } return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
private byte[] ReportError(Command cmd, ErrorCode error) { switch (cmd) { case Command.ReadRequest: cmd = Command.ReadResponse; break; case Command.WriteRequest: cmd = Command.WriteResponse; break; case Command.GetRequest: cmd = Command.GetResponse; break; case Command.SetRequest: cmd = Command.SetResponse; break; case Command.MethodRequest: cmd = Command.MethodResponse; break; default: //Return HW error and close connection.. break; } if (Settings.UseLogicalNameReferencing) { GXDLMS.GetLNPdu(new GXDLMSLNParameters(Settings, cmd, 1, null, null, (byte)error), replyData); } else { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(error); GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, cmd, 1, (byte)error, null, bb); GXDLMS.GetSNPdu(p, replyData); } if (this.InterfaceType == Enums.InterfaceType.WRAPPER) { return GXDLMS.GetWrapperFrame(Settings, replyData); } else { return GXDLMS.GetHdlcFrame(Settings, 0, replyData); } }
///<summary> ///Convert object to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="type"> ///Data type. ///</param> ///<param name="value"> /// Added Value. ///</param> public static void SetData(GXByteBuffer buff, DataType type, object value) { GXCommon.SetData(null, buff, type, value); }
/// <summary> /// Get object count. If first byte is 0x80 or higger it will tell bytes count. /// </summary> /// <param name="data">Received data.</param> /// <returns>Object count.</returns> public static int GetObjectCount(GXByteBuffer data) { return(GXCommon.GetObjectCount(data)); }
/// <summary> /// Set item count. /// </summary> /// <param name="count"></param> /// <param name="data"></param> internal static void SetObjectCount(int count, GXByteBuffer data) { GXCommon.SetObjectCount(count, data); }
/// <summary> /// Load XML commands from the file. /// </summary> /// <param name="fileName"></param> /// <returns></returns> public byte[][] PduToMessages(GXDLMSXmlPdu pdu) { List <byte[]> messages = new List <byte[]>(); if (pdu.Command == Command.Snrm) { messages.Add(pdu.Data); } else if (pdu.Command == Command.Ua) { messages.Add(pdu.Data); } else if (pdu.Command == Command.DisconnectRequest) { messages.Add(GXDLMS.GetHdlcFrame(Settings, (byte)Command.DisconnectRequest, new GXByteBuffer(pdu.Data))); } else { GXByteBuffer reply; if (Settings.InterfaceType == InterfaceType.WRAPPER) { if (Ciphering.Security != Security.None) { GXDLMSLNParameters p = new GXDLMSLNParameters(this, Settings, 0, pdu.Command, 0x0, null, null, 0xff, Command.None); reply = new GXByteBuffer(GXDLMS.Cipher0(p, pdu.Data)); } else { reply = new GXByteBuffer(pdu.Data); } } else { if (Ciphering.Security != Security.None) { GXDLMSLNParameters p = new GXDLMSLNParameters(this, Settings, 0, pdu.Command, 0x0, null, null, 0xff, Command.None); byte[] tmp = GXDLMS.Cipher0(p, pdu.Data); reply = new GXByteBuffer((UInt16)(3 + tmp.Length)); reply.Set(GXCommon.LLCSendBytes); reply.Set(tmp); } else { reply = new GXByteBuffer((UInt16)(3 + pdu.Data.Length)); reply.Set(GXCommon.LLCSendBytes); reply.Set(pdu.Data); } } byte frame = 0; while (reply.Position != reply.Size) { if (Settings.InterfaceType == Enums.InterfaceType.WRAPPER) { messages.Add(GXDLMS.GetWrapperFrame(Settings, pdu.Command, reply)); } else if (GXDLMS.UseHdlc(Settings.InterfaceType)) { if (pdu.Command == Command.Aarq) { frame = 0x10; } else if (pdu.Command == Command.Aare) { frame = 0x30; } else if (pdu.Command == Command.EventNotification) { frame = 0x13; } messages.Add(GXDLMS.GetHdlcFrame(Settings, frame, reply)); if (reply.Position != reply.Size) { frame = Settings.NextSend(false); } } else if (Settings.InterfaceType == Enums.InterfaceType.PDU) { messages.Add(reply.Array()); break; } else { throw new ArgumentOutOfRangeException("InterfaceType"); } } } return(messages.ToArray()); }
private List <GXDLMSXmlPdu> Load(XmlDocument doc, GXXmlLoadSettings settings) { //Remove comments. List <XmlNode> comments = new List <XmlNode>(); foreach (XmlNode node in doc.SelectNodes("//comment()")) { comments.Add(node); } foreach (XmlNode node in comments) { node.ParentNode.RemoveChild(node); } List <GXDLMSXmlPdu> actions = new List <GXDLMSXmlPdu>(); string description = null, error = null, errorUrl = null, sleep = null; foreach (XmlNode m1 in doc.ChildNodes) { if (m1.NodeType == XmlNodeType.Element) { if (m1.Name == "AssociationRequest") { GXDLMSXmlSettings s = new GXDLMSXmlSettings(translator.OutputType, translator.Hex, translator.ShowStringAsHex, translator.tagsByName); s.settings.ClientAddress = Settings.ClientAddress; s.settings.ServerAddress = Settings.ServerAddress; ((GXCiphering)s.settings.Cipher).TestMode = this.Ciphering.TestMode; byte[] reply = translator.XmlToPdu(m1.OuterXml, s); GXDLMSXmlPdu p = new GXDLMSXmlPdu(s.command, m1, reply); actions.Add(p); return(actions); } foreach (XmlNode node in m1.ChildNodes) { if (node.NodeType == XmlNodeType.Element) { if (node.Name == "Description") { description = node.Value; continue; } if (node.Name == "Error") { error = node.Value; continue; } if (node.Name == "ErrorUrl") { errorUrl = node.Value; continue; } if (node.Name == "Sleep") { sleep = node.Value; continue; } if (settings != null && node.Name == "GetRequest") { if (settings.Start != DateTime.MinValue && settings.End != DateTime.MinValue) { foreach (XmlNode n1 in node.ChildNodes) { if (n1.Name == "GetRequestNormal") { foreach (XmlNode n2 in n1.ChildNodes) { if (n2.Name == "AccessSelection") { foreach (XmlNode n3 in n2.ChildNodes) { if (n3.Name == "AccessSelector") { if (n3.Attributes["Value"].Value != "1") { break; } } else if (n3.Name == "AccessParameters") { foreach (XmlNode n4 in n3.ChildNodes) { if (n4.Name == "Structure") { bool start = true; foreach (XmlNode n5 in n4.ChildNodes) { if (n5.Name == "OctetString") { if (start) { GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetData(this.Settings, bb, DataType.OctetString, settings.Start); n5.Attributes["Value"].Value = bb.ToHex(false, 2); start = false; } else { GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetData(this.Settings, bb, DataType.OctetString, settings.End); n5.Attributes["Value"].Value = bb.ToHex(false, 2); break; } } } } break; } break; } } break; } } break; } } } } GXDLMSXmlSettings s = new GXDLMSXmlSettings(translator.OutputType, translator.ShowStringAsHex, translator.Hex, translator.tagsByName);; s.settings.ClientAddress = Settings.ClientAddress; s.settings.ServerAddress = Settings.ServerAddress; byte[] reply = translator.XmlToPdu(node.OuterXml, s); if (s.command == Command.Snrm && !s.settings.IsServer) { Settings.Hdlc.MaxInfoTX = s.settings.Hdlc.MaxInfoTX; Settings.Hdlc.MaxInfoRX = s.settings.Hdlc.MaxInfoRX; Settings.Hdlc.WindowSizeRX = s.settings.Hdlc.WindowSizeRX; Settings.Hdlc.WindowSizeTX = s.settings.Hdlc.WindowSizeTX; } else if (s.command == Command.Ua && s.settings.IsServer) { Settings.Hdlc.MaxInfoTX = s.settings.Hdlc.MaxInfoTX; Settings.Hdlc.MaxInfoRX = s.settings.Hdlc.MaxInfoRX; Settings.Hdlc.WindowSizeRX = s.settings.Hdlc.WindowSizeRX; Settings.Hdlc.WindowSizeTX = s.settings.Hdlc.WindowSizeTX; } if (s.template) { reply = null; } GXDLMSXmlPdu p = new GXDLMSXmlPdu(s.command, node, reply); if (description != "") { p.Description = description; } if (error != "") { p.Error = error; } if (errorUrl != "") { p.ErrorUrl = errorUrl; } if (!string.IsNullOrEmpty(sleep)) { p.Sleep = int.Parse(sleep); } actions.Add(p); } } } } return(actions); }
ulong IConvertible.ToUInt64(IFormatProvider provider) { GXByteBuffer bb = GetByteBuffer(Value, 8); return(bb.GetUInt64()); }
uint IConvertible.ToUInt32(IFormatProvider provider) { GXByteBuffer bb = GetByteBuffer(Value, 4); return(bb.GetUInt32()); }
/// <summary> /// Get data for Read command. /// </summary> /// <param name="list">received objects.</param> /// <param name="data">Data as byte array.</param> /// <returns>Response type.</returns> private static SingleReadResponse GetReadData(GXDLMSSettings settings, ValueEventArgs[] list, GXByteBuffer data) { object value; bool first = true; SingleReadResponse type = SingleReadResponse.Data; foreach (ValueEventArgs e in list) { if (e.Handled) { value = e.Value; } else { //If action. if (e.action) { value = ((IGXDLMSBase)e.Target).Invoke(settings, e); } else { value = (e.Target as IGXDLMSBase).GetValue(settings, e); } } if (e.Error == 0) { if (!first && list.Length != 1) { data.SetUInt8(SingleReadResponse.Data); } //If action. if (e.action) { GXCommon.SetData(settings, data, GXCommon.GetValueType(value), value); } else { GXDLMS.AppendData(settings, e.Target, e.Index, data, value); } } else { if (!first && list.Length != 1) { data.SetUInt8(SingleReadResponse.DataAccessError); } data.SetUInt8(e.Error); type = SingleReadResponse.DataAccessError; } first = false; } return(type); }
public GXByteBuffer(GXByteBuffer value) { Capacity = (value.Size - value.Position); Set(value); }
/// <summary> /// Load XML commands from the file. /// </summary> /// <param name="fileName"></param> /// <returns></returns> public byte[][] PduToMessages(GXDLMSXmlPdu pdu) { List <byte[]> messages = new List <byte[]>(); if (pdu.Command == Command.Snrm) { messages.Add(pdu.Data); } else if (pdu.Command == Command.Ua) { messages.Add(pdu.Data); } else if (pdu.Command == Command.DisconnectRequest) { messages.Add(GXDLMS.GetHdlcFrame(Settings, (byte)Command.DisconnectRequest, new GXByteBuffer(pdu.Data))); } else { GXByteBuffer reply; if (Settings.InterfaceType == Enums.InterfaceType.WRAPPER) { reply = new GXByteBuffer(pdu.Data); } else { reply = new GXByteBuffer((UInt16)(3 + pdu.Data.Length)); reply.Set(GXCommon.LLCSendBytes); reply.Set(pdu.Data); } while (reply.Position != reply.Size) { if (Settings.InterfaceType == Enums.InterfaceType.WRAPPER) { messages.Add(GXDLMS.GetWrapperFrame(Settings, reply)); } else if (Settings.InterfaceType == Enums.InterfaceType.HDLC) { byte frame = 0; if (pdu.Command == Command.Aarq) { frame = 0x10; } else if (pdu.Command == Command.Aare) { frame = 0x30; } else if (pdu.Command == Command.EventNotification) { frame = 0x13; } messages.Add(GXDLMS.GetHdlcFrame(Settings, frame, reply)); if (reply.Position != reply.Size) { if (Settings.IsServer || pdu.Command == Command.SetRequest || pdu.Command == Command.MethodRequest) { frame = 0; } else { frame = Settings.NextSend(false); } } } else if (Settings.InterfaceType == Enums.InterfaceType.PDU) { messages.Add(reply.Array()); break; } else { throw new ArgumentOutOfRangeException("InterfaceType"); } } } return(messages.ToArray()); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return (byte)Mode; } if (e.Index == 3) { return (byte)Speed; } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (PrimaryAddresses == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)PrimaryAddresses.Length); foreach (byte it in PrimaryAddresses) { data.SetUInt8((byte)DataType.UInt8); data.SetUInt8(it); } } return data.Array(); } if (e.Index == 5) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (Tabis == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)Tabis.Length); foreach (sbyte it in Tabis) { data.SetUInt8((byte)DataType.UInt8); data.SetUInt8((byte)it); } } return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
public byte[][] ImageBlockTransfer(GXDLMSClient client, byte[] imageBlockValue, out int ImageBlockCount) { ImageBlockCount = (int)(imageBlockValue.Length / ImageBlockSize); if (imageBlockValue.Length % ImageBlockSize != 0) { ++ImageBlockCount; } List<byte[]> packets = new List<byte[]>(); for (int pos = 0; pos != ImageBlockCount; ++pos) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)2); GXCommon.SetData(client.Settings, data, DataType.UInt32, pos); byte[] tmp; int bytes = (int)(imageBlockValue.Length - ((pos + 1) * ImageBlockSize)); //If last packet if (bytes < 0) { bytes = (int)(imageBlockValue.Length - (pos * ImageBlockSize)); tmp = new byte[bytes]; Array.Copy(imageBlockValue, pos * ImageBlockSize, tmp, 0, bytes); } else { tmp = new byte[ImageBlockSize]; Array.Copy(imageBlockValue, (pos * ImageBlockSize), tmp, 0, ImageBlockSize); } GXCommon.SetData(client.Settings, data, DataType.OctetString, tmp); packets.AddRange(client.Method(this, 2, data.Array(), DataType.Array)); } return packets.ToArray(); }
/// <summary> /// Removes X.509 v3 certificate from the server using entity. /// </summary> /// <param name="client">DLMS client that is used to generate action.</param> /// <param name="entity">Certificate entity type.</param> /// <param name="type">Certificate type.</param> /// <param name="systemTitle">System title.</param> /// <returns>Generated action.</returns> public byte[][] RemoveCertificateByEntity(GXDLMSClient client, CertificateEntity entity, CertificateType type, byte[] systemTitle) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); //Add enum bb.SetUInt8(DataType.Enum); bb.SetUInt8(0); //Add certificate_identification_by_entity bb.SetUInt8(DataType.Structure); bb.SetUInt8(3); //Add certificate_entity bb.SetUInt8(DataType.Enum); bb.SetUInt8(entity); //Add certificate_type bb.SetUInt8(DataType.Enum); bb.SetUInt8(type); //system_title GXCommon.SetData(client.Settings, bb, DataType.OctetString, systemTitle); return client.Method(this, 8, bb.Array(), DataType.OctetString); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return ImageBlockSize; } if (e.Index == 3) { return ImageTransferredBlocksStatus; } if (e.Index == 4) { return ImageFirstNotTransferredBlockNumber; } if (e.Index == 5) { return ImageTransferEnabled; } if (e.Index == 6) { return ImageTransferStatus; } if (e.Index == 7) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (ImageActivateInfo == null) { GXCommon.SetObjectCount(0, data); } else { GXCommon.SetObjectCount(ImageActivateInfo.Length, data); foreach (GXDLMSImageActivateInfo it in ImageActivateInfo) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8(3); GXCommon.SetData(settings, data, DataType.UInt32, it.Size); GXCommon.SetData(settings, data, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(Convert.ToString(it.Identification))); if (it.Signature == null || it.Signature.Length == 0) { GXCommon.SetData(settings, data, DataType.OctetString, null); } else { GXCommon.SetData(settings, data, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(it.Signature)); } } } return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
/// <summary> /// Add value of COSEM object to byte buffer. /// </summary> /// <param name="obj">COSEM object.</param> /// <param name="index">Attribute index.</param> /// <param name="buff">Byte buffer.</param> /// <remarks> /// AddData method can be used with GetDataNotificationMessage -method. /// DLMS spesification do not specify the structure of Data-Notification body. /// So each manufacture can sent different data. /// </remarks> /// <seealso cref="GetDataNotificationMessages"/> internal static void AddData(GXDLMSSettings settings, GXDLMSObject obj, int index, GXByteBuffer buff) { DataType dt; object value = (obj as IGXDLMSBase).GetValue(settings, new ValueEventArgs(settings, obj, index, 0, null)); dt = obj.GetDataType(index); if (dt == DataType.None && value != null) { dt = GXCommon.GetValueType(value); } GXCommon.SetData(settings, buff, dt, value); }
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> /// Generates push setup message. /// </summary> /// <param name="date"> Date time. Set To Min or Max if not added.</param> /// <param name="push">Target Push object.</param> /// <returns>Generated data notification message(s).</returns> public byte[][] GeneratePushSetupMessages(DateTime date, GXDLMSPushSetup push) { if (push == null) { throw new ArgumentNullException("push"); } GXByteBuffer buff = new GXByteBuffer(); buff.SetUInt8((byte)DataType.Structure); GXCommon.SetObjectCount(push.PushObjectList.Count, buff); foreach (KeyValuePair<GXDLMSObject, GXDLMSCaptureObject> it in push.PushObjectList) { AddData(it.Key, it.Value.AttributeIndex, buff); } return GenerateDataNotificationMessages(date, buff); }
///<summary> /// Handle received command. ///</summary> private byte[] HandleCommand(Command cmd, GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo) { byte frame = 0; switch (cmd) { case Command.AccessRequest: GXDLMSLNCommandHandler.HandleAccessRequest(Settings, this, data, replyData, null); break; case Command.SetRequest: GXDLMSLNCommandHandler.HandleSetRequest(Settings, this, data, replyData, null); break; case Command.WriteRequest: GXDLMSSNCommandHandler.HandleWriteRequest(Settings, this, data, replyData, null); break; case Command.GetRequest: if (data.Size != 0) { GXDLMSLNCommandHandler.HandleGetRequest(Settings, this, data, replyData, null); } break; case Command.ReadRequest: GXDLMSSNCommandHandler.HandleReadRequest(Settings, this, data, replyData, null); break; case Command.MethodRequest: GXDLMSLNCommandHandler.HandleMethodRequest(Settings, this, data, connectionInfo, replyData, null); break; case Command.Snrm: HandleSnrmRequest(); frame = (byte)Command.Ua; break; case Command.Aarq: HandleAarqRequest(data, connectionInfo); break; case Command.ReleaseRequest: HandleReleaseRequest(data, connectionInfo); break; case Command.DisconnectRequest: GenerateDisconnectRequest(); Settings.Connected = false; Disconnected(connectionInfo); frame = (byte)Command.Ua; break; case Command.None: //Get next frame. break; default: Debug.WriteLine("Invalid command: " + (int)cmd); break; } byte[] reply; if (this.InterfaceType == Enums.InterfaceType.WRAPPER) { reply = GXDLMS.GetWrapperFrame(Settings, replyData); } else { reply = GXDLMS.GetHdlcFrame(Settings, frame, replyData); } return(reply); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return this.CurrentAverageValue; } if (e.Index == 3) { return this.LastAverageValue; } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.Int8, _scaler); GXCommon.SetData(settings, data, DataType.Enum, Unit); return data.Array(); } if (e.Index == 5) { return this.Status; } if (e.Index == 6) { return CaptureTime; } if (e.Index == 7) { return StartTimeCurrent; } if (e.Index == 8) { return Period; } if (e.Index == 9) { return NumberOfPeriods; } e.Error = ErrorCode.ReadWriteDenied; return null; }
///<summary> ///Parse AARQ request that client send and returns AARE request. /// </summary> ///<returns> ///Reply to the client. ///</returns> private void HandleAarqRequest(GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo) { GXByteBuffer error = null; AssociationResult result = AssociationResult.Accepted; Settings.CtoSChallenge = null; if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = null; } // Reset settings for wrapper. if (Settings.InterfaceType == InterfaceType.WRAPPER) { Reset(true); } SourceDiagnostic diagnostic = SourceDiagnostic.NoReasonGiven; try { diagnostic = GXAPDU.ParsePDU(Settings, Settings.Cipher, data, null); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; diagnostic = SourceDiagnostic.ApplicationContextNameNotSupported; InvalidConnection(connectionInfo); } else { diagnostic = ValidateAuthentication(Settings.Authentication, Settings.Password); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; InvalidConnection(connectionInfo); } else if (Settings.Authentication > Authentication.Low) { // If High authentication is used. if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = GXSecure.GenerateChallenge(Settings.Authentication); } result = AssociationResult.Accepted; diagnostic = SourceDiagnostic.AuthenticationRequired; } else { Connected(connectionInfo); Settings.Connected = true; } } Settings.IsAuthenticationRequired = diagnostic == SourceDiagnostic.AuthenticationRequired; } catch (GXDLMSConfirmedServiceError e) { result = AssociationResult.PermanentRejected; diagnostic = SourceDiagnostic.NoReasonGiven; error = new GXByteBuffer(); error.SetUInt8(0xE); error.SetUInt8(e.ConfirmedServiceError); error.SetUInt8(e.ServiceError); error.SetUInt8(e.ServiceErrorValue); } if (Settings.InterfaceType == Enums.InterfaceType.HDLC) { replyData.Set(GXCommon.LLCReplyBytes); } // Generate AARE packet. GXAPDU.GenerateAARE(Settings, replyData, result, diagnostic, Settings.Cipher, error, null); }
/// <summary> /// Set new value to byte array. /// </summary> /// <param name="value">Byte array to add.</param> /// <param name="index">Byte index.</param> /// <param name="count">Byte count.</param> public void Set(GXByteBuffer value, int count) { if (Size + count > Capacity) { Capacity = (Size + count + ArrayCapacity); } if (count != 0) { Buffer.BlockCopy(value.Data, value.Position, Data, Size, count); Size += count; value.Position += (ushort)count; } }
///<summary> ///Handle set request. ///</summary> ///<returns> ///Reply to the client. ///</returns> public static void HandleSetRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && !settings.Connected) { replyData.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } // Get type. SetRequestType type = (SetRequestType)data.GetUInt8(); // Get invoke ID and priority. byte invoke = data.GetUInt8(); // SetRequest normal or Set Request With First Data Block GXDLMSLNParameters p = new GXDLMSLNParameters(settings, invoke, Command.SetResponse, (byte)type, null, null, 0); if (xml != null) { xml.AppendStartTag(Command.SetRequest); xml.AppendStartTag(Command.SetRequest, type); //InvokeIdAndPriority xml.AppendLine(TranslatorTags.InvokeId, "Value", xml.IntegerToHex(invoke, 2)); } switch (type) { case SetRequestType.Normal: case SetRequestType.FirstDataBlock: HandleSetRequestNormal(settings, server, data, (byte)type, p, replyData, xml); break; case SetRequestType.WithDataBlock: HanleSetRequestWithDataBlock(settings, server, data, p, replyData, xml); break; default: System.Diagnostics.Debug.WriteLine("HandleSetRequest failed. Unknown command."); settings.ResetBlockIndex(); p.status = (byte)ErrorCode.HardwareFault; break; } if (xml != null) { xml.AppendEndTag(Command.SetRequest, type); xml.AppendEndTag(Command.SetRequest); return; } GXDLMS.GetLNPdu(p, replyData); }
private static void ReturnSNError(GXDLMSSettings settings, GXDLMSServer server, Command cmd, ErrorCode error, GXByteBuffer replyData) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(error); GXDLMS.GetSNPdu(new GXDLMSSNParameters(settings, cmd, 1, (byte)SingleReadResponse.DataAccessError, bb, null), replyData); settings.ResetBlockIndex(); }
///<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(); // 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 && (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, GXCommon.GetValueType(actionReply), actionReply); } else { error = e.Error; //Add return parameters bb.SetUInt8(0); } } invokeId = (byte)e.InvokeId; } GXDLMSLNParameters p = new GXDLMSLNParameters(settings, invokeId, 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> /// Constructor. ///</summary> public GXReplyData() { Data = new GXByteBuffer(); Clear(); }
/// <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); if (obj == null) { // "Access Error : Device reports a undefined object." status = ErrorCode.UndefinedObject; } else { e.InvokeId = invokeID; 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; } } GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, e.InvokeId, 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 received command. ///</summary> private byte[] HandleCommand(Command cmd, GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo) { byte frame = 0; switch (cmd) { case Command.AccessRequest: GXDLMSLNCommandHandler.HandleAccessRequest(Settings, this, data, replyData, null); break; case Command.SetRequest: GXDLMSLNCommandHandler.HandleSetRequest(Settings, this, data, replyData, null); break; case Command.WriteRequest: GXDLMSSNCommandHandler.HandleWriteRequest(Settings, this, data, replyData, null); break; case Command.GetRequest: if (data.Size != 0) { GXDLMSLNCommandHandler.HandleGetRequest(Settings, this, data, replyData, null); } break; case Command.ReadRequest: GXDLMSSNCommandHandler.HandleReadRequest(Settings, this, data, replyData, null); break; case Command.MethodRequest: GXDLMSLNCommandHandler.HandleMethodRequest(Settings, this, data, connectionInfo, replyData, null); break; case Command.Snrm: HandleSnrmRequest(); frame = (byte)Command.Ua; break; case Command.Aarq: HandleAarqRequest(data, connectionInfo); break; case Command.ReleaseRequest: case Command.DisconnectRequest: GenerateDisconnectRequest(); Settings.Connected = false; Disconnected(connectionInfo); frame = (byte)Command.Ua; break; case Command.None: //Get next frame. break; default: Debug.WriteLine("Invalid command: " + (int)cmd); break; } byte[] reply; if (this.InterfaceType == Enums.InterfaceType.WRAPPER) { reply = GXDLMS.GetWrapperFrame(Settings, replyData); } else { reply = GXDLMS.GetHdlcFrame(Settings, frame, replyData); } return reply; }
/// <summary> /// Handle get request next data block command. /// </summary> /// <param name="data">Received data.</param> private static void GetRequestNextDataBlock(GXDLMSSettings settings, byte invokeID, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { GXByteBuffer bb = new GXByteBuffer(); uint index; // Get block index. index = data.GetUInt32(); if (xml != null) { xml.AppendLine(TranslatorTags.BlockNumber, null, xml.IntegerToHex(index, 8)); return; } if (index != settings.BlockIndex) { Debug.WriteLine("handleGetRequest failed. Invalid block number. " + settings.BlockIndex + "/" + index); GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, 0, Command.GetResponse, 2, null, bb, (byte)ErrorCode.DataBlockNumberInvalid), replyData); } else { settings.IncreaseBlockIndex(); GXDLMSLNParameters p = new GXDLMSLNParameters(settings, invokeID, Command.GetResponse, 2, null, bb, (byte)ErrorCode.Ok); //If transaction is not in progress. if (server.transaction == null) { p.status = (byte)ErrorCode.NoLongGetOrReadInProgress; } else { bb.Set(server.transaction.data); bool moreData = settings.Index != settings.Count; if (moreData) { //If there is multiple blocks on the buffer. //This might happen when Max PDU size is very small. if (bb.Size < settings.MaxPduSize) { foreach (ValueEventArgs arg in server.transaction.targets) { object value; server.NotifyRead(new ValueEventArgs[] { arg }); if (arg.Handled) { value = arg.Value; } else { value = (arg.Target as IGXDLMSBase).GetValue(settings, arg); } //Add data. if (arg.ByteArray) { bb.Set((byte[])value); } else { GXDLMS.AppendData(settings, arg.Target, arg.Index, bb, value); } } moreData = settings.Index != settings.Count; } } p.multipleBlocks = true; GXDLMS.GetLNPdu(p, replyData); if (moreData || bb.Size - bb.Position != 0) { server.transaction.data = bb; } else { server.transaction = null; settings.ResetBlockIndex(); } } } }
///<summary> ///Parse AARQ request that client send and returns AARE request. /// </summary> ///<returns> ///Reply to the client. ///</returns> private void HandleAarqRequest(GXByteBuffer data, GXDLMSConnectionEventArgs connectionInfo) { AssociationResult result = AssociationResult.Accepted; Settings.CtoSChallenge = null; if (!Settings.UseCustomChallenge) { Settings.StoCChallenge = null; } // Reset settings for wrapper. if (Settings.InterfaceType == InterfaceType.WRAPPER) { Reset(true); } SourceDiagnostic diagnostic = GXAPDU.ParsePDU(Settings, Settings.Cipher, data, null); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; diagnostic = SourceDiagnostic.ApplicationContextNameNotSupported; InvalidConnection(connectionInfo); } else { diagnostic = ValidateAuthentication(Settings.Authentication, Settings.Password); if (diagnostic != SourceDiagnostic.None) { result = AssociationResult.PermanentRejected; InvalidConnection(connectionInfo); } else if (Settings.Authentication > Authentication.Low) { // If High authentication is used. Settings.StoCChallenge = GXSecure.GenerateChallenge(Settings.Authentication); result = AssociationResult.Accepted; diagnostic = SourceDiagnostic.AuthenticationRequired; } else { Connected(connectionInfo); Settings.Connected = true; } } Settings.IsAuthenticationRequired = diagnostic == SourceDiagnostic.AuthenticationRequired; if (Settings.InterfaceType == Enums.InterfaceType.HDLC) { replyData.Set(GXCommon.LLCReplyBytes); } // Generate AARE packet. GXAPDU.GenerateAARE(Settings, replyData, result, diagnostic, Settings.Cipher, null); }
/// <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(settings, invokeID, Command.GetResponse, 3, null, bb, 0xFF); GXDLMS.GetLNPdu(p, replyData); }
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; } }
public static void HandleGetRequest(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { //Return error if connection is not established. if (xml == null && !settings.Connected) { replyData.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } GetCommandType type = (GetCommandType)data.GetUInt8(); // Get invoke ID and priority. byte invokeID = data.GetUInt8(); if (xml != null) { xml.AppendStartTag(Command.GetRequest); xml.AppendStartTag(Command.GetRequest, type); xml.AppendLine(TranslatorTags.InvokeId, "Value", xml.IntegerToHex(invokeID, 2)); } // GetRequest normal if (type == GetCommandType.Normal) { GetRequestNormal(settings, invokeID, server, data, replyData, xml); } else if (type == GetCommandType.NextDataBlock) { // Get request for next data block GetRequestNextDataBlock(settings, invokeID, server, data, replyData, xml); } else if (type == GetCommandType.WithList) { // Get request with a list. GetRequestWithList(settings, invokeID, server, data, replyData, xml); } else { Debug.WriteLine("HandleGetRequest failed. Invalid command type."); settings.ResetBlockIndex(); GXByteBuffer bb = new GXByteBuffer(); // Access Error : Device reports a hardware fault. bb.SetUInt8((byte)ErrorCode.HardwareFault); GXDLMS.GetLNPdu(new GXDLMSLNParameters(settings, invokeID, Command.GetResponse, (byte)type, null, bb, (byte)ErrorCode.Ok), replyData); } if (xml != null) { xml.AppendEndTag(Command.GetRequest, type); xml.AppendEndTag(Command.GetRequest); } }
/// <summary> /// Agree on one or more symmetric keys using the key agreement algorithm. /// </summary> /// <param name="client"> DLMS client that is used to generate action.</param> /// <param name="list"> List of keys.</param> /// <returns>Generated action.</returns> public byte[][] keyAgreement(GXDLMSClient client, List<KeyValuePair<GlobalKeyType, byte[]>> list) { if (list == null || list.Count == 0) { throw new ArgumentException("Invalid list. It is empty."); } GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Array); bb.SetUInt8((byte)list.Count); foreach (KeyValuePair<GlobalKeyType, byte[]> it in list) { bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); GXCommon.SetData(client.Settings, bb, DataType.Enum, it.Key); GXCommon.SetData(client.Settings, bb, DataType.OctetString, it.Value); } return client.Method(this, 3, bb.Array(), DataType.Array); }
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; uint 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, 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> /// Removes X.509 v3 certificate from the server using serial number. /// </summary> /// <param name="client">DLMS client that is used to generate action.</param> /// <param name="serialNumber">Serial number.</param> /// <param name="issuer">Issuer.</param> /// <returns>Generated action.</returns> public byte[][] RemoveCertificateBySerial(GXDLMSClient client, byte[] serialNumber, byte[] issuer) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); //Add enum bb.SetUInt8(DataType.Enum); bb.SetUInt8(1); //Add certificate_identification_by_entity bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); //serialNumber GXCommon.SetData(client.Settings, bb, DataType.OctetString, serialNumber); //issuer GXCommon.SetData(client.Settings, bb, DataType.OctetString, issuer); return client.Method(this, 8, bb.Array(), DataType.OctetString); }
private static void HanleSetRequestWithDataBlock(GXDLMSSettings settings, GXDLMSServer server, GXByteBuffer data, GXDLMSLNParameters p, GXByteBuffer replyData, GXDLMSTranslatorStructure xml) { GXDataInfo reply = new GXDataInfo(); reply.xml = xml; byte lastBlock = data.GetUInt8(); p.multipleBlocks = lastBlock == 0; uint blockNumber = data.GetUInt32(); if (xml == null && blockNumber != settings.BlockIndex) { Debug.WriteLine("HanleSetRequestWithDataBlock failed. Invalid block number. " + settings.BlockIndex + "/" + blockNumber); p.status = (byte)ErrorCode.DataBlockNumberInvalid; } else { settings.IncreaseBlockIndex(); int size = GXCommon.GetObjectCount(data); int realSize = data.Size - data.Position; if (size != realSize) { Debug.WriteLine("HanleSetRequestWithDataBlock failed. Invalid block size."); p.status = (byte)ErrorCode.DataBlockUnavailable; } if (xml != null) { 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; } server.transaction.data.Set(data); //If all data is received. if (!p.multipleBlocks) { try { object value = GXCommon.GetData(settings, server.transaction.data, reply); if (value is byte[]) { DataType dt = (server.transaction.targets[0].Target as IGXDLMSBase).GetDataType(server.transaction.targets[0].Index); if (dt != DataType.None && dt != DataType.OctetString) { value = GXDLMSClient.ChangeType((byte[])value, dt, settings.UseUtc2NormalTime); } } server.transaction.targets[0].Value = value; server.NotifyWrite(server.transaction.targets); if (!server.transaction.targets[0].Handled && !p.multipleBlocks) { (server.transaction.targets[0].Target as IGXDLMSBase).SetValue(settings, server.transaction.targets[0]); server.NotifyPostWrite(server.transaction.targets); } } catch (Exception) { p.status = (byte)ErrorCode.HardwareFault; } finally { server.transaction = null; } settings.ResetBlockIndex(); } } p.multipleBlocks = true; }
///<summary> /// Removes the HDLC frame from the packet, and returns COSEM data only. ///</summary> ///<param name="reply"> /// The received data from the device. ///</param> ///<param name="data"> /// Information from the received data. ///</param> ///<returns> /// Is frame complete. ///</returns> public bool GetData(GXByteBuffer reply, GXReplyData data) { return GXDLMS.GetData(Settings, reply, data); }
///<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) { reply.Set(GXDLMSServer.GenerateConfirmedServiceError(ConfirmedServiceError.InitiateError, ServiceError.Service, (byte)Service.Unsupported)); return; } //Get long invoke id and priority. uint 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); } }
/// <summary> /// Add value of COSEM object to byte buffer. /// </summary> /// <param name="obj">COSEM object.</param> /// <param name="index">Attribute index.</param> /// <param name="buff">Byte buffer.</param> /// <remarks> /// AddData method can be used with GetDataNotificationMessage -method. /// DLMS spesification do not specify the structure of Data-Notification body. /// So each manufacture can sent different data. /// </remarks> /// <seealso cref="GetDataNotificationMessages"/> public void AddData(GXDLMSObject obj, int index, GXByteBuffer buff) { AddData(Settings, obj, index, buff); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (Entries == null) { data.SetUInt8(0); } else { int cnt = Entries.Length; //Add count GXCommon.SetObjectCount(cnt, data); if (cnt != 0) { foreach (GXDLMSSpecialDay it in Entries) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); //Count GXCommon.SetData(settings, data, DataType.UInt16, it.Index); GXCommon.SetData(settings, data, DataType.OctetString, it.Date); GXCommon.SetData(settings, data, DataType.UInt8, it.DayId); } } } return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
/// <summary> /// Generates data notification message. /// </summary> /// <param name="time">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[][] GenerateDataNotificationMessages(DateTime time, List<KeyValuePair<GXDLMSObject, int>> objects) { if (objects == null) { throw new ArgumentNullException("objects"); } GXByteBuffer buff = new GXByteBuffer(); buff.SetUInt8(DataType.Structure); GXCommon.SetObjectCount(objects.Count, buff); foreach (KeyValuePair<GXDLMSObject, int> it in objects) { AddData(it.Key, it.Value, buff); } byte[][] reply; if (UseLogicalNameReferencing) { GXDLMSLNParameters p = new GXDLMSLNParameters(Settings, Command.DataNotification, 0, null, buff, 0xff); p.time = time; reply = GXDLMS.GetLnMessages(p); } else { GXDLMSSNParameters p = new GXDLMSSNParameters(Settings, Command.DataNotification, 1, 0, buff, null); reply = GXDLMS.GetSnMessages(p); } return reply; }
///<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); } } 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 PHYReference; } if (e.Index == 3) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (LCPOptions == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)IPCPOptions.Length); foreach (GXDLMSPppSetupLcpOption it in LCPOptions) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.UInt8, it.Type); GXCommon.SetData(settings, data, DataType.UInt8, it.Length); GXCommon.SetData(settings, data, GXCommon.GetValueType(it.Data), it.Data); } } return data.Array(); } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (IPCPOptions == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)IPCPOptions.Length); foreach (GXDLMSPppSetupIPCPOption it in IPCPOptions) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.UInt8, it.Type); GXCommon.SetData(settings, data, DataType.UInt8, it.Length); GXCommon.SetData(settings, data, GXCommon.GetValueType(it.Data), it.Data); } } return data.Array(); } else if (e.Index == 5) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.OctetString, UserName); GXCommon.SetData(settings, data, DataType.OctetString, Password); return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
/// <summary> /// Generate write reply. /// </summary> /// <param name="settings"></param> /// <param name="results"></param> /// <param name="replyData"></param> internal static void GenerateWriteResponse(GXDLMSSettings settings, GXByteBuffer results, GXByteBuffer replyData) { GXByteBuffer bb = new GXByteBuffer((UInt16)(2 * results.Size)); byte ret; for (int pos = 0; pos != results.Size; ++pos) { ret = results.GetUInt8(pos); // If meter returns error. if (ret != 0) { bb.SetUInt8(1); } bb.SetUInt8(ret); } GXDLMSSNParameters p = new GXDLMSSNParameters(settings, Command.WriteResponse, results.Size, 0xFF, null, bb); GXDLMS.GetSNPdu(p, replyData); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return Value; } if (e.Index == 3) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.Int8, scaler); GXCommon.SetData(settings, data, DataType.Enum, Unit); return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
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); } } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return (byte)Mode; } if (e.Index == 3) { return Repetitions; } if (e.Index == 4) { return RepetitionDelay; } if (e.Index == 5) { int cnt = CallingWindow.Count; GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); //Add count GXCommon.SetObjectCount(cnt, data); if (cnt != 0) { foreach (var it in CallingWindow) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)2); //Count GXCommon.SetData(settings, data, DataType.OctetString, it.Key); //start_time GXCommon.SetData(settings, data, DataType.OctetString, it.Value); //end_time } } return data.Array(); } if (e.Index == 6) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (Destinations == null) { //Add count GXCommon.SetObjectCount(0, data); } else { int cnt = Destinations.Length; //Add count GXCommon.SetObjectCount(cnt, data); foreach (string it in Destinations) { GXCommon.SetData(settings, data, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(it)); //destination } } return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
/// <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(); } }
public void Set(GXByteBuffer value) { if (value != null) { Set(value, value.Size - value.Position); } }
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 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) { 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); } 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); 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; } }