/// <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); }
public void ReadValue(GXDLMSObject it, int attributeOrdinal) { GXReplyData reply = new GXReplyData(); string str = string.Format("Reading object {0}, interface {1}", it.LogicalName, it.ObjectType); ReadDataBlock(client.Read(it, attributeOrdinal), str, reply); //If data type is unknown if (it.GetDataType(attributeOrdinal) == DataType.None) { it.SetDataType(attributeOrdinal, reply.DataType); } client.UpdateValue(it, attributeOrdinal, reply.Value); }
public void MethodRequest(GXDLMSObject target, int methodIndex, object data, GXReplyData reply) { lastTransaction = DateTime.Now; byte[][] tmp; if (data is byte[]) { tmp = client.Method(target, methodIndex, data, DataType.Array); } else { tmp = client.Method(target, methodIndex, data, GXDLMSConverter.GetDLMSDataType(data)); } ReadDataBlock(tmp, "", reply); }
/// <summary> /// Read association view. /// </summary> public void GetAssociationView(string outputFile) { if (outputFile != null) { //Save Association view to the cache so it is not needed to retrieve every time. if (File.Exists(outputFile)) { try { Client.Objects.Clear(); Client.Objects.AddRange(GXDLMSObjectCollection.Load(outputFile)); return; } catch (Exception) { if (File.Exists(outputFile)) { File.Delete(outputFile); } } } } GXReplyData reply = new GXReplyData(); ReadDataBlock(Client.GetObjectsRequest(), reply); Client.ParseObjects(reply.Data, true); //Access rights must read differently when short Name referencing is used. if (!Client.UseLogicalNameReferencing) { GXDLMSAssociationShortName sn = (GXDLMSAssociationShortName)Client.Objects.FindBySN(0xFA00); if (sn != null && sn.Version > 0) { Read(sn, 3); } } if (outputFile != null) { try { Client.Objects.Save(outputFile, new GXXmlWriterSettings() { Values = false }); } catch (Exception) { //It's OK if this fails. } } }
/// <summary> /// Connect to the meter and try to send HDLC frame that is too big. /// </summary> /// <param name="settings">Settings.</param> /// <param name="output">Generated output.</param> public static void InvalidHdlcFrame(GXSettings settings, GXOutput output) { if (settings.client.InterfaceType == InterfaceType.HDLC) { Reader.GXDLMSReader reader = new Reader.GXDLMSReader(settings.client, settings.media, settings.trace, settings.iec); reader.WaitTime = settings.WaitTime; settings.media.Open(); settings.client.Limits.MaxInfoRX = settings.client.Limits.MaxInfoTX = 64; reader.SNRMRequest(); byte[] data = GXDLMSTranslator.HexToBytes("7E A0 41 03 21 10 B1 EA E6 E6 00 60 33 A1 09 06 07 60 85 74 05 08 01 01 8A 02 07 80 8B 07 60 85 74 05 08 02 01 AC 07 80 05 47 75 72 75 78 BE 10 04 0E 01 00 00 00 06 5F 1F 04 00 00 1E 1D FF FF ED 2C 7E"); GXReplyData reply = new GXReplyData(); reader.ReadDataBlock(data, reply); } }
void OnProfileGenericDataReceived(object sender, GXReplyData reply) { if (reply.Value != null) { lock (reply) { client.UpdateValue(CurrentProfileGeneric, 2, reply.Value); reply.Value = new Object[0]; } if (OnAfterRead != null) { OnAfterRead(CurrentProfileGeneric, 2); } } }
/// <summary> /// Read data block from the device. /// </summary> /// <param name="data">data to send</param> /// <param name="text">Progress text.</param> /// <param name="multiplier"></param> /// <returns>Received data.</returns> internal void ReadDataBlock(byte[] data, string text, int multiplier, GXReplyData reply) { lastTransaction = DateTime.Now; GXLogWriter.WriteLog(text, data); if (parent.OnTrace != null) { parent.OnTrace(parent, text + "\r\n<-\t" + DateTime.Now.ToLongTimeString(), data, 0, LogFile); } ReadDLMSPacket(data, reply); if (OnDataReceived != null) { OnDataReceived(this, reply); } if (reply.IsMoreData) { if (reply.TotalCount != 1) { NotifyProgress(text, 1, multiplier * reply.TotalCount); } while (reply.IsMoreData) { data = client.ReceiverReady(reply.MoreData); if ((reply.MoreData & RequestTypes.Frame) != 0) { GXLogWriter.WriteLog("Get next frame."); } else { GXLogWriter.WriteLog("Get Next Data block."); } if (parent.OnTrace != null) { parent.OnTrace(parent, "<-\t" + DateTime.Now.ToLongTimeString(), data, 0, LogFile); } GXLogWriter.WriteLog(text, data); ReadDLMSPacket(data, reply); if (OnDataReceived != null) { OnDataReceived(this, reply); } if (reply.TotalCount != 1) { NotifyProgress(text, reply.Count, multiplier * reply.TotalCount); } } } }
/// <summary> /// Handle received notify message. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> internal void OnNotifyReceived(object sender, ReceiveEventArgs e) { GXNotifyClient reply; lock (notifyMessages) { if (notifyMessages.ContainsKey(e.SenderInfo)) { reply = notifyMessages[e.SenderInfo]; } else { reply = new GXNotifyClient(_useLogicalNameReferencing, _interfaceType, _systemTitle, _blockCipherKey); notifyMessages.Add(e.SenderInfo, reply); } } DateTime now = DateTime.Now; //If received data is expired. if (ExpirationTime != 0 && (now - reply.DataReceived).TotalSeconds > ExpirationTime) { reply.Reply.Clear(); } reply.DataReceived = now; reply.Reply.Set((byte[])e.Data); GXReplyData data = new GXReplyData(); reply.Client.GetData(reply.Reply, data, reply.Notify); // If all data is received. if (reply.Notify.IsComplete && !reply.Notify.IsMoreData) { try { } catch (Exception ex) { _logger.LogError(ex.Message); //TODO: Save error to the database. Console.WriteLine(ex.Message); } finally { reply.Notify.Clear(); reply.Reply.Clear(); } } }
public void Close() { if (Media != null && Client != null) { try { Console.WriteLine("Disconnecting from the meter."); GXReplyData reply = new GXReplyData(); ReadDLMSPacket(Client.DisconnectRequest(), reply); Media.Close(); } catch { } Media = null; Client = null; } }
/// <summary> /// Disconnect. /// </summary> public void Disconnect() { if (Media != null && Client != null) { try { if (Trace > TraceLevel.Info) { Console.WriteLine("Disconnecting from the meter."); } GXReplyData reply = new GXReplyData(); ReadDLMSPacket(Client.DisconnectRequest(), reply); } catch { } } }
/// <summary> /// Read data block from the device. /// </summary> /// <param name="data">data to send</param> /// <param name="text">Progress text.</param> /// <param name="multiplier"></param> /// <returns>Received data.</returns> internal void ReadDataBlock(byte[] data, string text, int multiplier, GXReplyData reply) { if (parent.InactivityMode == InactivityMode.ReopenActive && media is GXSerial && DateTime.Now.Subtract(connectionStartTime).TotalSeconds > 40) { parent.Disconnect(); parent.InitializeConnection(); } GXLogWriter.WriteLog(text, data); ReadDLMSPacket(data, reply); if (OnDataReceived != null) { OnDataReceived(this, reply); } if (reply.IsMoreData) { if (reply.TotalCount != 1) { NotifyProgress(text, 1, multiplier * reply.TotalCount); } while (reply.IsMoreData) { data = client.ReceiverReady(reply.MoreData); if ((reply.MoreData & RequestTypes.Frame) != 0) { GXLogWriter.WriteLog("Get next frame: ", data); } else { GXLogWriter.WriteLog("Get Next Data block: ", data); } ReadDLMSPacket(data, reply); if (OnDataReceived != null) { OnDataReceived(this, reply); } if (reply.TotalCount != 1) { NotifyProgress(text, reply.Count, multiplier * reply.TotalCount); } } } }
public GXDLMSObjectCollection GetObjects() { GXLogWriter.WriteLog("--- Collecting objects. ---"); GXReplyData reply = new GXReplyData() { }; try { ReadDataBlock(client.GetObjectsRequest(), "Collecting objects", 3, reply); } catch (Exception Ex) { throw new Exception("GetObjects failed. " + Ex.Message); } GXDLMSObjectCollection objs = client.ParseObjects(reply.Data, true); GXLogWriter.WriteLog("--- Collecting " + objs.Count.ToString() + " objects. ---"); return(objs); }
/// <summary> /// Release. /// </summary> public void Release() { if (Media != null && Client != null) { try { if (Trace > TraceLevel.Info) { Console.WriteLine("Release from the meter."); } GXReplyData reply = new GXReplyData(); ReadDataBlock(Client.ReleaseRequest(), reply); } catch (Exception ex) { //All meters don't support Release. Console.WriteLine("Release failed. " + 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 data block from the device. /// </summary> /// <param name="data">data to send</param> /// <param name="text">Progress text.</param> /// <param name="multiplier"></param> /// <returns>Received data.</returns> public void ReadDataBlock(byte[] data, GXReplyData reply) { ReadDLMSPacket(data, reply); while (reply.IsMoreData) { data = Client.ReceiverReady(reply.MoreData); ReadDLMSPacket(data, reply); if (Trace > TraceLevel.Info) { //If data block is read. if ((reply.MoreData & RequestTypes.Frame) == 0) { Console.Write("+"); } else { Console.Write("-"); } } } }
/// <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> /// Register selected meters. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void RegisterMnu_Click(object sender, EventArgs e) { try { if (MetersView.SelectedItems.Count == 1) { ListViewItem li = MetersView.SelectedItems[0]; GXDLMSPlcMeterInfo mi = (GXDLMSPlcMeterInfo)li.Tag; GXPlcRegisterDlg dlg = new GXPlcRegisterDlg(GXDLMSTranslator.HexToBytes(Settings.Default.PlcSerialSettingsActiveInitiator), mi.SystemTitle); if (dlg.ShowDialog(this) == DialogResult.OK) { GXDLMSDevice dev = new GXDLMSDevice(media); dev.Comm.client.InterfaceType = (InterfaceType)Settings.Default.PlcInterface; media.Open(); GXReplyData reply = new GXReplyData(); dev.Comm.client.Plc.MacSourceAddress = dlg.MacAddress; Settings.Default.PlcSerialSettingsActiveInitiator = GXDLMSTranslator.ToHex(dlg.ActiveInitiatorSystemTitle); byte[] data = dev.Comm.client.Plc.RegisterRequest(dlg.ActiveInitiatorSystemTitle, dlg.NewSystemTitle); dev.Comm.ReadDLMSPacket(data, reply); data = dev.Comm.client.Plc.DiscoverRequest(); dev.Comm.ReadDLMSPacket(data, reply); } } } catch (Exception ex) { MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { try { media.Close(); } catch (Exception ex) { MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
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> /// 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); //Value is null if data is send in multiple frames. if (reply.Value is object[]) { values.AddRange((object[])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> /// Read association view. /// </summary> public void GetAssociationView(bool useCache) { if (useCache) { string path = GetCacheName(); List <Type> extraTypes = new List <Type>(Gurux.DLMS.GXDLMSClient.GetObjectTypes()); extraTypes.Add(typeof(GXDLMSAttributeSettings)); extraTypes.Add(typeof(GXDLMSAttribute)); XmlSerializer x = new XmlSerializer(typeof(GXDLMSObjectCollection), extraTypes.ToArray()); //You can save association view, but make sure that it is not change. //Save Association view to the cache so it is not needed to retrieve every time. if (File.Exists(path)) { try { using (Stream stream = File.Open(path, FileMode.Open)) { Console.WriteLine("Get available objects from the cache."); Client.Objects.AddRange(x.Deserialize(stream) as GXDLMSObjectCollection); stream.Close(); } return; } catch (Exception ex) { if (File.Exists(path)) { File.Delete(path); } throw ex; } } } GXReplyData reply = new GXReplyData(); ReadDataBlock(Client.GetObjectsRequest(), reply); Client.ParseObjects(reply.Data, true); SaveObjects(); }
/// <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> /// 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)); }
public void Disconnect() { if (media != null && media.IsOpen) { try { GXReplyData reply = new GXReplyData(); ReadDLMSPacket(DisconnectRequest(), 1, reply); } finally { if (media != null) { media.Close(); //Restore old settings. if (media is GXSerial) { media.Settings = parent.StartMediaSettings; } } } } }
/// <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(); ReadDataBlock(Client.ReleaseRequest(), reply); reply.Clear(); ReadDLMSPacket(Client.DisconnectRequest(), reply); Media.Close(); } catch { } Media = null; Client = null; } }
/// <summary> /// Read attribute value. /// </summary> public object Read(GXDLMSObject it, int attributeIndex) { GXReplyData reply = new GXReplyData(); if (!ReadDataBlock(Client.Read(it, attributeIndex), reply)) { reply.Clear(); Thread.Sleep(1000); if (!ReadDataBlock(Client.Read(it, attributeIndex), reply)) { if (reply.Error != 0) { 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)); }
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> /// 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; } }
/// <summary> /// Release connection to the meter. /// </summary> public void Release() { if (Media != null && Client != null) { if (Trace > TraceLevel.Info) { Console.WriteLine("Release from the meter."); } GXReplyData reply = new GXReplyData(); try { if (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); } } }
/// <summary> /// Method attribute value. /// </summary> public void Method(GXDLMSObject it, int attributeIndex, object value, DataType type) { GXReplyData reply = new GXReplyData(); ReadDataBlock(Client.Method(it, attributeIndex, value, type), reply); }