/// <summary> /// Initialize connection to the meter. /// </summary> public void InitializeConnection() { UpdateFrameCounter(); InitializeOpticalHead(); GXReplyData reply = new GXReplyData(); byte[] data; data = Client.SNRMRequest(); if (data != null) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send SNRM request." + GXCommon.ToHex(data, true)); } ReadDataBlock(data, reply); if (Trace == TraceLevel.Verbose) { Console.WriteLine("Parsing UA reply." + reply.ToString()); } //Has server accepted client. Client.ParseUAResponse(reply.Data); if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing UA reply succeeded."); } } //Generate AARQ request. //Split requests to multiple packets if needed. //If password is used all data might not fit to one packet. foreach (byte[] it in Client.AARQRequest()) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send AARQ request", GXCommon.ToHex(it, true)); } reply.Clear(); ReadDataBlock(it, reply); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply" + reply.ToString()); } //Parse reply. Client.ParseAAREResponse(reply.Data); reply.Clear(); //Get challenge Is HLS authentication is used. if (Client.IsAuthenticationRequired) { foreach (byte[] it in Client.GetApplicationAssociationRequest()) { reply.Clear(); ReadDataBlock(it, reply); } Client.ParseApplicationAssociationResponse(reply.Data); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply succeeded."); } }
public void Write(GXDLMSObject obj, object target, int index, List <object> UpdatedObjects) { object value; GXReplyData reply = new GXReplyData(); for (int it = 1; it != (obj as IGXDLMSBase).GetAttributeCount() + 1; ++it) { reply.Clear(); if (obj.GetDirty(it, out value)) { //Read DLMS data type if not known. DataType type = obj.GetDataType(it); if (type == DataType.None) { byte[] data = client.Read(obj, it)[0]; ReadDataBlock(data, "Write object type " + obj.ObjectType, reply); type = reply.DataType; if (type == DataType.None) { throw new Exception("Failed to write value. Data type not set."); } obj.SetDataType(it, type); } try { ValueEventArgs e = new ValueEventArgs(obj, it, 0, null); e.Value = value; ((IGXDLMSBase)obj).SetValue(null, e); foreach (byte[] tmp in client.Write(obj, it)) { ReadDataBlock(tmp, "Write object", reply); } obj.ClearDirty(it); //Read data once again to make sure it is updated. reply.Clear(); byte[] data = client.Read(obj, it)[0]; ReadDataBlock(data, "Read object " + obj.ObjectType, reply); value = reply.Value; if (value is byte[] && (type = obj.GetUIDataType(it)) != DataType.None) { value = GXDLMSClient.ChangeType((byte[])value, type); } client.UpdateValue(obj, it, value); } catch (GXDLMSException ex) { if (ex.ErrorCode == 3) { throw new Exception("Read/Write Failed."); } else { throw ex; } } } } }
/// <summary> /// Initialize connection to the meter. /// </summary> public void InitializeConnection() { Console.WriteLine("Standard: " + Client.Standard); if (Client.Ciphering.Security != (byte)Security.None) { Console.WriteLine("Security: " + Client.Ciphering.Security); Console.WriteLine("System title: " + GXCommon.ToHex(Client.Ciphering.SystemTitle, true)); Console.WriteLine("Authentication key: " + GXCommon.ToHex(Client.Ciphering.AuthenticationKey, true)); Console.WriteLine("Block cipher key " + GXCommon.ToHex(Client.Ciphering.BlockCipherKey, true)); if (Client.Ciphering.DedicatedKey != null) { Console.WriteLine("Dedicated key: " + GXCommon.ToHex(Client.Ciphering.DedicatedKey, true)); } } UpdateFrameCounter(); InitializeOpticalHead(); GXReplyData reply = new GXReplyData(); SNRMRequest(); //Generate AARQ request. //Split requests to multiple packets if needed. //If password is used all data might not fit to one packet. foreach (byte[] it in Client.AARQRequest()) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send AARQ request", GXCommon.ToHex(it, true)); } reply.Clear(); ReadDataBlock(it, reply); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply" + reply.ToString()); } //Parse reply. Client.ParseAAREResponse(reply.Data); reply.Clear(); //Get challenge Is HLS authentication is used. if (Client.IsAuthenticationRequired) { foreach (byte[] it in Client.GetApplicationAssociationRequest()) { reply.Clear(); ReadDataBlock(it, reply); } Client.ParseApplicationAssociationResponse(reply.Data); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply succeeded."); } }
/// <summary> /// Read attribute value. /// </summary> /// <param name="it">COSEM object to read.</param> /// <param name="attributeIndex">Attribute index.</param> /// <returns>Read value.</returns> public object Read(GXDLMSObject it, int attributeIndex) { if ((it.GetAccess(attributeIndex) & AccessMode.Read) != 0) { GXReplyData reply = new GXReplyData(); if (!ReadDataBlock(Client.Read(it, attributeIndex), reply)) { if (reply.Error != (short)ErrorCode.Rejected) { throw new GXDLMSException(reply.Error); } reply.Clear(); Thread.Sleep(1000); if (!ReadDataBlock(Client.Read(it, attributeIndex), reply)) { throw new GXDLMSException(reply.Error); } } //Update data type. if (it.GetDataType(attributeIndex) == DataType.None) { it.SetDataType(attributeIndex, reply.DataType); } return(Client.UpdateValue(it, attributeIndex, reply.Value)); } return(null); }
/// <summary> /// Close connection to the meter. /// </summary> public void Close() { if (Media != null && Client != null) { try { if (Trace > TraceLevel.Info) { Console.WriteLine("Disconnecting from the meter."); } GXReplyData reply = new GXReplyData(); try { ReadDataBlock(Client.ReleaseRequest(), reply); } catch (Exception) { //All meters don't support release. } reply.Clear(); ReadDLMSPacket(Client.DisconnectRequest(), reply); Media.Close(); } catch { } Media = null; Client = null; } }
/// <summary> /// Read list of attributes. /// </summary> public void ReadList(List <KeyValuePair <GXDLMSObject, int> > list) { byte[][] data = Client.ReadList(list); GXReplyData reply = new GXReplyData(); List <object> values = new List <object>(); foreach (byte[] it in data) { ReadDataBlock(it, reply); if (reply.Value is object[]) { values.AddRange((object[])reply.Value); } else if (reply.Value != null) { //Value is null if data is send multiple frames. values.Add(reply.Value); } reply.Clear(); } if (values.Count != list.Count) { throw new Exception("Invalid reply. Read items count do not match."); } Client.UpdateValues(list, values); }
/// <summary> /// Close connection to the meter. /// </summary> public void Close() { if (Media != null && Client != null) { try { if (Trace > TraceLevel.Info) { Console.WriteLine("Disconnecting from the meter."); } GXReplyData reply = new GXReplyData(); //Release is called only for secured connections. Some older meters don't support release and it might kill them. if (Client is GXDLMSSecureClient && (Client as GXDLMSSecureClient).Ciphering.Security != Security.None) { ReadDataBlock(Client.ReleaseRequest(), reply); } reply.Clear(); ReadDLMSPacket(Client.DisconnectRequest(), reply); Media.Close(); } catch { } Media = null; Client = null; } }
/// <summary> /// Read DLMS Data from the device. /// </summary> /// <remarks> /// If access is denied return null. /// </remarks> /// <param name="data">Data to send.</param> /// <returns>Received data.</returns> public void ReadDLMSPacket(byte[] data, GXReplyData reply) { if ((data == null || data.Length == 0) && !reply.IsStreaming()) { return; } GXReplyData notify = new GXReplyData(); reply.Error = 0; object eop = (byte)0x7E; //In network connection terminator is not used. if (client.InterfaceType == InterfaceType.WRAPPER && !parent.UseRemoteSerial) { eop = null; } ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { AllData = false, Eop = eop, Count = 5, WaitTime = parent.WaitTime * 1000, }; var answer = Send(data); GXByteBuffer rd = new GXByteBuffer(answer.Body); try { //Loop until whole COSEM packet is received. while (!client.GetData(rd, reply, notify)) { p.Reply = null; if (notify.Data.Size != 0) { // Handle notify. if (!notify.IsMoreData) { rd.Trim(); notify.Clear(); p.Eop = eop; } continue; } //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = client.GetFrameSize(rd); } rd.Set(p.Reply); } } catch (Exception ex) { throw ex; } if (reply.Error != 0) { throw new GXDLMSException(reply.Error); } }
public void Disconnect() { GXReplyData reply = new GXReplyData(); try { //Release is call only for secured connections. //All meters are not supporting Release and it's causing problems. if (client.InterfaceType == InterfaceType.WRAPPER || (client.InterfaceType == InterfaceType.HDLC && client.Ciphering.Security != Security.None && !parent.PreEstablished)) { byte[] data = ReleaseRequest(); if (data != null) { ReadDataBlock(data, "Release request", reply); } } reply.Clear(); if (client.InterfaceType == InterfaceType.HDLC && !parent.PreEstablished) { ReadDataBlock(DisconnectRequest(), "Disconnect request", reply); } } catch (Exception) { //All meters don't support release. } }
public void MethodRequest(GXDLMSObject target, int methodIndex, object data, string text, GXReplyData reply) { byte[][] tmp; if (data is byte[]) { tmp = client.Method(target, methodIndex, data, DataType.Array); } else { tmp = client.Method(target, methodIndex, data, GXDLMSConverter.GetDLMSDataType(data)); } int pos = 0; string str = string.Format("Method object {0}, interface {1}", target.LogicalName, target.ObjectType); foreach (byte[] it in tmp) { reply.Clear(); if (tmp.Length != 1) { ++pos; NotifyProgress(text, pos, tmp.Length); } ReadDataBlock(it, str, reply); } NotifyProgress(text, 1, 1); }
internal void ReadDataBlock(byte[][] data, string text, int multiplier, GXReplyData reply) { foreach (byte[] it in data) { reply.Clear(); ReadDataBlock(it, text, multiplier, reply); } }
void ReadDataBlock(byte[][] data, string text, GXReplyData reply) { foreach (byte[] it in data) { reply.Clear(); ReadDataBlock(it, text, reply); } }
/// <summary> /// Read all data from the meter. /// </summary> public void ReadAll(bool useCache) { try { InitializeConnection(); GetAssociationView(useCache); //Mikko GXDLMSAssociationLogicalName ln = Client.Objects.GetObjects(ObjectType.AssociationLogicalName)[0] as GXDLMSAssociationLogicalName; Read(ln, 10); Read(ln, 11); if (ln.UserList.Count != 0) { throw new Exception("Mikko"); } GXReplyData reply = new GXReplyData(); if (!ReadDataBlock(ln.AddUser(Client, 1, "Mikko"), reply)) { if (reply.Error != (short)ErrorCode.Rejected) { throw new GXDLMSException(reply.Error); } } //Update data type. Read(ln, 10); if (ln.UserList.Count != 1) { throw new Exception("Mikko"); } if (ln.UserList[0].Key != 1 || ln.UserList[0].Value != "Mikko") { throw new Exception("Mikko"); } reply.Clear(); if (!ReadDataBlock(ln.RemoveUser(Client, 1, "Mikko"), reply)) { if (reply.Error != (short)ErrorCode.Rejected) { throw new GXDLMSException(reply.Error); } } Read(ln, 10); if (ln.UserList.Count != 0) { throw new Exception("Mikko"); } /* * GetScalersAndUnits(); * GetProfileGenericColumns(); * GetReadOut(); * GetProfileGenerics(); */ } finally { Close(); } }
public bool ReadDataBlock(byte[][] data, GXReplyData reply) { foreach (byte[] it in data) { reply.Clear(); ReadDataBlock(it, reply); } return(true); }
/// <summary> /// Write list of attributes. /// </summary> public void WriteList(List <KeyValuePair <GXDLMSObject, int> > list) { byte[][] data = Client.WriteList(list); GXReplyData reply = new GXReplyData(); foreach (byte[] it in data) { ReadDataBlock(it, reply); reply.Clear(); } }
/// <summary> /// Send AARQ Request to the meter. /// </summary> public void AarqRequest() { GXReplyData reply = new GXReplyData(); //Generate AARQ request. //Split requests to multiple packets if needed. //If password is used all data might not fit to one packet. foreach (byte[] it in Client.AARQRequest()) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send AARQ request" + GXCommon.ToHex(it, true)); GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); Console.WriteLine(t.MessageToXml(it)); } reply.Clear(); ReadDataBlock(it, reply); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply\r\n" + reply.ToString()); } //Parse reply. Client.ParseAAREResponse(reply.Data); reply.Clear(); //Get challenge Is HLS authentication is used. if (Client.IsAuthenticationRequired) { foreach (byte[] it in Client.GetApplicationAssociationRequest()) { reply.Clear(); ReadDataBlock(it, reply); } Client.ParseApplicationAssociationResponse(reply.Data); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply succeeded."); } }
/// <summary> /// Send data block(s) to the meter. /// </summary> /// <param name="data">Send data block(s).</param> /// <param name="reply">Received reply from the meter.</param> /// <returns>Return false if frame is rejected.</returns> public bool ReadDataBlock(byte[][] data, GXReplyData reply) { if (data == null) { return(true); } foreach (byte[] it in data) { reply.Clear(); ReadDataBlock(it, reply); } return(reply.Error == 0); }
public bool ReadDataBlock(byte[][] data, GXReplyData reply) { foreach (byte[] it in data) { reply.Clear(); ReadDataBlock(it, reply); if (reply.Error == (short)ErrorCode.Rejected) { return(false); } } return(true); }
/// <summary> /// Client has send data. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnReceived(object sender, Gurux.Common.ReceiveEventArgs e) { try { lock (this) { if (trace) { Console.WriteLine("<- " + Gurux.Common.GXCommon.ToHex((byte[])e.Data, true)); } reply.Set((byte[])e.Data); GetData(reply, data); // If all data is received. if (data.IsComplete && !data.IsMoreData) { try { List <KeyValuePair <GXDLMSObject, int> > list; list = ParsePush((Object[])data.Value); // Print received data. foreach (KeyValuePair <GXDLMSObject, int> it in list) { // Print LN. Console.WriteLine(it.Key.ToString()); // Print Value. Console.WriteLine(it.Key.GetValues()[it.Value - 1]); } } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { data.Clear(); } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// Read object. /// </summary> public void ReadMineCommunicator(string objectName, ObjectType objectType, int it) { GXReplyData reply = new GXReplyData(); { reply.Clear(); { byte[] data = client.Read(objectName, objectType, it)[0]; try { ReadDataBlock(data, $"Read object type {objectName} index: {it}", reply); object value = reply.Value; log($"{objectName}: value = {value}"); } catch (Exception ex) { throw ex; } } } }
/// <summary> /// Read attribute value. /// </summary> /// <param name="it">COSEM object to read.</param> /// <param name="attributeIndex">Attribute index.</param> /// <returns>Read value.</returns> public object Read(GXDLMSObject it, int attributeIndex) { GXReplyData reply = new GXReplyData(); if (!ReadDataBlock(Client.Read(it, attributeIndex), reply)) { if (reply.Error != (short)ErrorCode.Rejected) { throw new GXDLMSException(reply.Error); } reply.Clear(); Thread.Sleep(1000); if (!ReadDataBlock(Client.Read(it, attributeIndex), reply)) { throw new GXDLMSException(reply.Error); } } //Update data type. DataType dt = it.GetDataType(attributeIndex); if (dt == DataType.None) { it.SetDataType(attributeIndex, reply.DataType); dt = reply.DataType; } if (dt == DataType.Array || dt == DataType.Structure || reply.Value is GXStructure || reply.Value is GXArray) { if (it is GXDLMSProfileGeneric && attributeIndex == 2) { return(reply.Value); } if (reply.Value == null) { return(""); } return(GXDLMSTranslator.ValueToXml(reply.Value)); } return(Client.UpdateValue(it, attributeIndex, reply.Value)); }
void ReadDataBlock(byte[][] data, string text, GXReplyData reply) { foreach (byte[] it in data) { reply.Clear(); try { ReadDataBlock(it, text, reply); } catch (Exception ex) { //Update frame ID if meter returns error. if (client.InterfaceType == InterfaceType.HDLC) { int target, source; byte type; GXDLMSClient.GetHdlcAddressInfo(new GXByteBuffer(it), out target, out source, out type); client.Limits.SenderFrame = type; } throw ex; } } }
/// <summary> /// Close connection to the meter. /// </summary> public void Close() { if (Media != null && Client != null) { try { if (Trace > TraceLevel.Info) { Console.WriteLine("Disconnecting from the meter."); } GXReplyData reply = new GXReplyData(); try { if ((Client.ConnectionState & ConnectionState.Dlms) != 0 && (Client.InterfaceType == InterfaceType.WRAPPER || Client.Ciphering.Security != (byte)Security.None)) { ReadDataBlock(Client.ReleaseRequest(), reply); } } catch (Exception ex) { //All meters don't support Release. Console.WriteLine("Release failed. " + ex.Message); } reply.Clear(); if (Client.ConnectionState != 0) { ReadDLMSPacket(Client.DisconnectRequest(), reply); } Media.Close(); } catch { } Media = null; Client = null; } }
/// <summary> /// Close connection to the meter. /// </summary> public void Close() { if (Media != null && Client != null) { try { if (Trace > TraceLevel.Info) { Console.WriteLine("Disconnecting from the meter."); } GXReplyData reply = new GXReplyData(); try { //Release is call only for secured connections. //All meters are not supporting Release and it's causing problems. if (Client.InterfaceType == InterfaceType.WRAPPER || (Client.InterfaceType == InterfaceType.HDLC && Client.Ciphering.Security != (byte)Security.None)) { ReadDataBlock(Client.ReleaseRequest(), reply); } } catch (Exception ex) { //All meters don't support Release. Console.WriteLine("Release failed. " + ex.Message); } reply.Clear(); ReadDLMSPacket(Client.DisconnectRequest(), reply); Media.Close(); } catch { } Media = null; Client = null; } }
public void Disconnect() { if (media != null && media.IsOpen) { try { GXReplyData reply = new GXReplyData(); try { //Release is call only for secured connections. //Add meters are not supporting Release and it's causing problems. if (client.Ciphering.Security != Security.None) { ReadDataBlock(ReleaseRequest(), "Release request", reply); } } catch (Exception) { //All meters don't support release. } reply.Clear(); ReadDataBlock(DisconnectRequest(), "Disconnect request", reply); } finally { if (media != null) { media.Close(); //Restore old settings. if (media is GXSerial) { media.Settings = parent.StartMediaSettings; } } } } }
/// <summary> /// Read Invocation counter (frame counter) from the meter and update it. /// </summary> private void UpdateFrameCounter() { //Read frame counter if GeneralProtection is used. if (!string.IsNullOrEmpty(InvocationCounter) && Client.Ciphering != null && Client.Ciphering.Security != (byte)Security.None) { InitializeOpticalHead(); byte[] data; GXReplyData reply = new GXReplyData(); Client.ProposedConformance |= Conformance.GeneralProtection; int add = Client.ClientAddress; Authentication auth = Client.Authentication; Security security = Client.Ciphering.Security; byte[] challenge = Client.CtoSChallenge; try { Client.ClientAddress = 16; Client.Authentication = Authentication.None; Client.Ciphering.Security = (byte)Security.None; data = Client.SNRMRequest(); if (data != null) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send SNRM request." + GXCommon.ToHex(data, true)); } ReadDataBlock(data, reply); if (Trace == TraceLevel.Verbose) { Console.WriteLine("Parsing UA reply." + reply.ToString()); } //Has server accepted client. Client.ParseUAResponse(reply.Data); if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing UA reply succeeded."); } } //Generate AARQ request. //Split requests to multiple packets if needed. //If password is used all data might not fit to one packet. foreach (byte[] it in Client.AARQRequest()) { if (Trace > TraceLevel.Info) { Console.WriteLine("Send AARQ request", GXCommon.ToHex(it, true)); } reply.Clear(); ReadDataBlock(it, reply); } if (Trace > TraceLevel.Info) { Console.WriteLine("Parsing AARE reply" + reply.ToString()); } try { //Parse reply. Client.ParseAAREResponse(reply.Data); reply.Clear(); GXDLMSData d = new GXDLMSData(InvocationCounter); Read(d, 2); Client.Ciphering.InvocationCounter = 1 + Convert.ToUInt32(d.Value); Console.WriteLine("Invocation counter: " + Convert.ToString(Client.Ciphering.InvocationCounter)); reply.Clear(); Disconnect(); } catch (Exception Ex) { Disconnect(); throw Ex; } } finally { Client.ClientAddress = add; Client.Authentication = auth; Client.Ciphering.Security = security; Client.CtoSChallenge = challenge; } } }
/// <summary> /// Read DLMS Data from the device. /// </summary> /// <param name="data">Data to send.</param> /// <returns>Received data.</returns> public void ReadDLMSPacket(byte[] data, GXReplyData reply) { if (data == null && !reply.IsStreaming()) { return; } GXReplyData notify = new GXReplyData(); reply.Error = 0; object eop = (byte)0x7E; //In network connection terminator is not used. if (Client.InterfaceType == InterfaceType.WRAPPER) { eop = null; } int pos = 0; bool succeeded = false; ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { Eop = eop, WaitTime = WaitTime, }; if (eop == null) { p.Count = 8; } else { p.Count = 5; } GXByteBuffer rd = new GXByteBuffer(); lock (Media.Synchronous) { while (!succeeded && pos != 3) { if (!reply.IsStreaming()) { WriteTrace("TX:\t" + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(data, true)); Media.Send(data, null); } succeeded = Media.Receive(p); if (!succeeded) { if (++pos >= RetryCount) { throw new Exception("Failed to receive reply from the device in given time."); } //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } //Try to read again... System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); } } rd = new GXByteBuffer(p.Reply); try { pos = 0; //Loop until whole COSEM packet is received. while (!Client.GetData(rd, reply, notify)) { p.Reply = null; if (notify.IsComplete && notify.Data.Data != null) { //Handle notify. if (!notify.IsMoreData) { //Show received push message as XML. string xml; GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); t.DataToXml(notify.Data, out xml); Console.WriteLine(xml); notify.Clear(); continue; } } if (p.Eop == null) { p.Count = Client.GetFrameSize(rd); } while (!Media.Receive(p)) { if (++pos >= RetryCount) { throw new Exception("Failed to receive reply from the device in given time."); } //If echo. if (rd == null || rd.Size == data.Length) { Media.Send(data, null); } //Try to read again... System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); } rd.Set(p.Reply); } } catch (Exception ex) { WriteTrace("RX:\t" + DateTime.Now.ToLongTimeString() + "\t" + rd); throw ex; } } WriteTrace("RX:\t" + DateTime.Now.ToLongTimeString() + "\t" + rd); if (reply.Error != 0) { if (reply.Error == (short)ErrorCode.Rejected) { Thread.Sleep(1000); ReadDLMSPacket(data, reply); } else { throw new GXDLMSException(reply.Error); } } }
/// <summary> /// Client has send data. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnReceived(object sender, Gurux.Common.ReceiveEventArgs e) { try { lock (this) { if (trace) { Console.WriteLine("<- " + Gurux.Common.GXCommon.ToHex((byte[])e.Data, true)); } reply.Set((byte[])e.Data); //Example handles only notify messages. GXReplyData data = new GXReplyData(); client.GetData(reply, data, notify); // If all data is received. if (notify.IsComplete && !notify.IsMoreData) { try { //Show data as XML. string xml; GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); t.DataToXml(notify.Data, out xml); Console.WriteLine(xml); // Print received data. PrintData(notify.Value, 0); //Example is sending list of push messages in first parameter. if (notify.Value is object[]) { object[] tmp = notify.Value as object[]; List <KeyValuePair <GXDLMSObject, int> > objects = client.ParsePushObjects((object[])tmp[0]); //Remove first item because it's not needed anymore. objects.RemoveAt(0); //Update clock. int Valueindex = 1; foreach (KeyValuePair <GXDLMSObject, int> it in objects) { client.UpdateValue(it.Key, it.Value, tmp[Valueindex]); ++Valueindex; //Print value Console.WriteLine(it.Key.ObjectType + " " + it.Key.LogicalName + " " + it.Value + ":" + it.Key.GetValues()[it.Value - 1]); } } Console.WriteLine("Server address:" + notify.ServerAddress + " Client Address:" + notify.ClientAddress); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { notify.Clear(); } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// Read DLMS Data from the device. /// </summary> /// <param name="data">Data to send.</param> /// <returns>Received data.</returns> public void ReadDLMSPacket(byte[] data, GXReplyData reply) { if (data == null && !reply.IsStreaming()) { return; } reply.Error = 0; object eop = (byte)0x7E; //In network connection terminator is not used. if (Client.InterfaceType == InterfaceType.WRAPPER && Media is GXNet) { eop = null; } int pos = 0; bool succeeded = false; ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { Eop = eop, Count = 5, WaitTime = WaitTime, }; GXReplyData notify = new GXReplyData(); lock (Media.Synchronous) { while (!succeeded && pos != 3) { if (!reply.IsStreaming()) { WriteTrace(true, "TX:\t" + DateTime.Now.ToString("hh:mm:ss") + "\t" + GXCommon.ToHex(data, true)); Media.Send(data, null); } succeeded = Media.Receive(p); if (!succeeded) { if (++pos >= RetryCount) { throw new Exception("Failed to receive reply from the device in given time."); } //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } //Try to read again... System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); } } try { pos = 0; //Loop until whole COSEM packet is received. while (!Client.GetData(p.Reply, reply, notify)) { // If all data is received. if (notify.IsComplete && !notify.IsMoreData) { /* * try * { * if (GXNotifyListener.Parser != null) * { * GXAMIClient cl = new GXAMIClient(); * GXNotifyListener.Parser.Parse(Media.ToString(), notify.Value, cl.GetData, cl.SetData); * } * } * catch (Exception ex) * { * //TODO: Save error to the database. * } */ notify.Clear(); } //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } while (!Media.Receive(p)) { if (++pos >= RetryCount) { throw new Exception("Failed to receive reply from the device in given time."); } //If echo. if (p.Reply == null || p.Reply.Length == data.Length) { Media.Send(data, null); } //Try to read again... System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); } } } catch (Exception ex) { WriteTrace(false, "RX:\t" + DateTime.Now.ToString("hh:mm:ss") + "\t" + GXCommon.ToHex(p.Reply, true)); throw ex; } } WriteTrace(false, "RX:\t" + DateTime.Now.ToString("hh:mm:ss") + "\t" + GXCommon.ToHex(p.Reply, true)); if (reply.Error != 0) { if (reply.Error == (short)ErrorCode.Rejected) { Thread.Sleep(1000); ReadDLMSPacket(data, reply); } else { throw new GXDLMSException(reply.Error); } } }
/// <summary> /// Client has send data for for the gateway. /// </summary> /// <remarks> /// GW finds the correct client and sends data for it. /// </remarks> /// <param name="sender"></param> /// <param name="e"></param> public static void OnGatewayReceived(object sender, Gurux.Common.ReceiveEventArgs e) { try { lock (buffers) { GXByteBuffer bb; if (!buffers.ContainsKey(e.SenderInfo)) { bb = new GXByteBuffer(); buffers[e.SenderInfo] = bb; } else { bb = buffers[e.SenderInfo]; } bb.Set((byte[])e.Data); GXServerReply sr = new GXServerReply(bb.Data); GatewayServer.Reset(); try { GatewayServer.HandleRequest(sr); if (sr.Reply != null) { if (Trace > TraceLevel.Info) { Console.WriteLine("TX:\t" + Gurux.Common.GXCommon.ToHex(sr.Reply, true)); } ((IGXMedia)sender).Send(sr.Reply, e.SenderInfo); return; } } catch (Exception) { //Return error. sr.Reply = GatewayServer.ReportError(sr.Command, ErrorCode.HardwareFault); } if (sr.Gateway != null && sr.Data != null) { GXByteBuffer pdu = new GXByteBuffer(sr.Data); InterfaceType type = (InterfaceType)sr.Gateway.NetworkId; GXByteBuffer address = new GXByteBuffer(); address.Set(sr.Gateway.PhysicalDeviceAddress); int addr = address.GetUInt8(); //Find correct meter using GW information. if (meters.ContainsKey(addr)) { //Find client for the server or create a new one. GXDLMSClient cl; if (!clients.ContainsKey(addr)) { //Set client address if data is send without framing. if (GatewayServer.Settings.ClientAddress == 0) { GatewayServer.Settings.ClientAddress = 0x10; } cl = new GXDLMSClient(true, GatewayServer.Settings.ClientAddress, addr, GatewayServer.Authentication, null, type); clients.Add(addr, cl); } else { cl = clients[addr]; } GXReplyData data = new GXReplyData(); GXReplyData notify = new GXReplyData(); GXDLMSMeter m = meters[addr]; //Send SNRM if needed. if (sr.Command == Command.Aarq && (type == InterfaceType.HDLC || type == InterfaceType.HdlcWithModeE)) { GXServerReply sr2 = new GXServerReply(cl.SNRMRequest()); m.HandleRequest(sr2); if (cl.GetData(sr2.Reply, data, notify)) { data.Clear(); notify.Clear(); } else { //If the meter doesn't reply. bb.Clear(); return; } } byte[][] frames = cl.CustomFrameRequest(Command.None, pdu); foreach (byte[] it in frames) { sr.Data = it; m.HandleRequest(sr); if (Trace > TraceLevel.Info) { Console.WriteLine("RX:\t" + Gurux.Common.GXCommon.ToHex(sr.Reply, true)); } data.RawPdu = true; if (cl.GetData(sr.Reply, data, notify)) { while (data.IsMoreData) { sr.Data = cl.ReceiverReady(data); m.HandleRequest(sr); if (Trace > TraceLevel.Info) { Console.WriteLine("RX:\t" + Gurux.Common.GXCommon.ToHex(sr.Reply, true)); } cl.GetData(sr.Reply, data, notify); } byte[] reply = sr.Reply; try { GXByteBuffer tmp = new GXByteBuffer(); tmp.Set(data.Data); GatewayServer.Gateway = sr.Gateway; reply = GatewayServer.CustomFrameRequest(Command.None, tmp); } finally { GatewayServer.Gateway = null; } if (Trace > TraceLevel.Info) { Console.WriteLine("TX:\t" + Gurux.Common.GXCommon.ToHex(reply, true)); } ((IGXMedia)sender).Send(reply, e.SenderInfo); } } } bb.Clear(); } } } catch (Exception ex) { if (!(ex is SocketException)) { Console.WriteLine(ex.Message); } } }