static public byte[] ReadReadout(IGXMedia media, string data, int wt) { ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { Eop = GetEops(), WaitTime = wt }; lock (media.Synchronous) { if (data != null) { media.Send(data, null); } do { if (!media.Receive(p)) { //There is no eop or CRC. break; } }while (p.Reply[p.Reply.Length - 1] != 0x3); //Read CRC if EOP is found. if (p.Reply[p.Reply.Length - 1] == 0x3) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } } } return(p.Reply); }
/// <summary> /// Try to find client and server address from the meter. /// </summary> private void DiscoverMeters(object sender, GXAsyncWork work, object[] parameters) { GXDLMSClient cl = new GXDLMSClient(true, 16, 1, Authentication.None, null, (InterfaceType)Settings.Default.PlcInterface); byte[] data = cl.Plc.DiscoverRequest(); ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { AllData = false, Count = 8, WaitTime = 10000, }; DateTime start = DateTime.Now; GXByteBuffer rd = new GXByteBuffer(); lock (media.Synchronous) { if (data != null) { media.Send(data, null); start = DateTime.Now; } GXReplyData reply = new GXReplyData(); rd = new GXByteBuffer(p.Reply); try { while (!work.IsCanceled) { p.Reply = null; //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = cl.GetFrameSize(rd); } if (!media.IsOpen) { throw new InvalidOperationException("Media is closed."); } if (!media.Receive(p)) { //It's OK if there is no reply. Read again continue; } rd.Position = 0; rd.Set(p.Reply); if (cl.GetData(rd, reply)) { List <GXDLMSPlcMeterInfo> list = cl.Plc.ParseDiscover(reply.Data, (UInt16)reply.TargetAddress, (UInt16)reply.SourceAddress); BeginInvoke(new AppendMeterEventHandler(OnAppendMeter), list); } } } catch (Exception) { //Throw original exception. throw; } } }
/// <summary> /// Disconnect. /// </summary> /// <param name="serial"></param> /// <param name="tryCount"></param> public static void Disconnect(IGXMedia media, int tryCount) { lock (media.Synchronous) { ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { Eop = GetEops(), WaitTime = 1000 }; List <byte> data = new List <byte>(); data.Add(0x01); data.Add((byte)'B'); data.Add((byte)'0'); data.Add(0x03); data.Add(CalculateChecksum(data, 1, data.Count - 1)); byte[] data1 = data.ToArray(); string header, frame; media.Send(data1, null); media.Receive(p); while (--tryCount > -1) { if (media.Receive(p)) { GetPacket(new List <byte>(p.Reply), false, out header, out frame); if (header == "B0") { break; } if (p.Reply.Length > 11) { p.Reply = null; } } media.Send(data1, null); } } }
/// <summary> /// Send IEC disconnect message. /// </summary> void DiscIEC() { ReceiveParameters <string> p = new ReceiveParameters <string>() { AllData = false, Eop = (byte)0x0A, WaitTime = WaitTime * 1000 }; string data = (char)0x01 + "B0" + (char)0x03 + "\r\n"; Media.Send(data, null); p.Count = 1; Media.Receive(p); }
/// <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) { 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, }; lock (Media.Synchronous) { while (!succeeded && pos != 3) { WriteTrace("<- " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(data, true)); Media.Send(data, null); succeeded = Media.Receive(p); if (!succeeded) { //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } //Try to read again... if (++pos != 3) { System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); continue; } throw new Exception("Failed to receive reply from the device in given time."); } } try { //Loop until whole COSEM packet is received. while (!Client.GetData(p.Reply, reply)) { //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } while (!Media.Receive(p)) { //If echo. if (p.Reply.Length == data.Length) { Media.Send(data, null); } //Try to read again... if (++pos != 3) { System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); continue; } throw new Exception("Failed to receive reply from the device in given time."); } } } catch (Exception ex) { WriteTrace("-> " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(p.Reply, true)); throw ex; } } WriteTrace("-> " + DateTime.Now.ToLongTimeString() + "\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); } } }
private void StartWithIec() { //Query device information. GXSerial serial = Media as GXSerial; if (serial == null) { return; } if (UseIec) { serial.BaudRate = 300; serial.DataBits = 7; serial.Parity = System.IO.Ports.Parity.Even; serial.StopBits = System.IO.Ports.StopBits.One; } else { serial.BaudRate = 9600; serial.DataBits = 8; serial.Parity = System.IO.Ports.Parity.None; serial.StopBits = System.IO.Ports.StopBits.One; } byte Terminator = (byte)0x0A; string data = "/?!\r\n"; if (Trace > TraceLevel.Info) { Console.WriteLine("IEC sending:" + data); } ReceiveParameters <string> p = new ReceiveParameters <string>() { Eop = Terminator, WaitTime = WaitTime }; lock (Media.Synchronous) { WriteTrace("<- " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(ASCIIEncoding.ASCII.GetBytes(data), true)); Media.Send(data, null); if (!Media.Receive(p)) { //Try to move away from mode E. try { GXReplyData reply = new GXReplyData(); ReadDLMSPacket(Client.DisconnectRequest(), reply); } catch (Exception) { } data = (char)0x01 + "B0" + (char)0x03; Media.Send(data, null); p.Count = 1; if (!Media.Receive(p)) { } data = "Failed to receive reply from the device in given time."; Console.WriteLine(data); throw new Exception(data); } WriteTrace("-> " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(ASCIIEncoding.ASCII.GetBytes(p.Reply), true)); //If echo is used. if (p.Reply == data) { p.Reply = null; if (!Media.Receive(p)) { //Try to move away from mode E. GXReplyData reply = new GXReplyData(); ReadDLMSPacket(Client.DisconnectRequest(), reply); if (serial != null) { data = (char)0x01 + "B0" + (char)0x03; Media.Send(data, null); p.Count = 1; Media.Receive(p); serial.BaudRate = 9600; data = (char)0x01 + "B0" + (char)0x03 + "\r\n"; Media.Send(data, null); p.Count = 1; Media.Receive(p); } data = "Failed to receive reply from the device in given time."; Console.WriteLine(data); throw new Exception(data); } WriteTrace("-> " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(ASCIIEncoding.ASCII.GetBytes(p.Reply), true)); } } Console.WriteLine("IEC received: " + p.Reply); if (p.Reply[0] != '/') { p.WaitTime = 100; Media.Receive(p); throw new Exception("Invalid responce."); } string manufactureID = p.Reply.Substring(1, 3); char baudrate = p.Reply[4]; int BaudRate = 0; switch (baudrate) { case '0': BaudRate = 300; break; case '1': BaudRate = 600; break; case '2': BaudRate = 1200; break; case '3': BaudRate = 2400; break; case '4': BaudRate = 4800; break; case '5': BaudRate = 9600; break; case '6': BaudRate = 19200; break; default: throw new Exception("Unknown baud rate."); } Console.WriteLine("BaudRate is : " + BaudRate.ToString()); //Send ACK //Send Protocol control character byte controlCharacter = (byte)'2'; // "2" HDLC protocol procedure (Mode E) //Send Baudrate character //Mode control character byte ModeControlCharacter = (byte)'2'; //"2" //(HDLC protocol procedure) (Binary mode) //Set mode E. byte[] arr = new byte[] { 0x06, controlCharacter, (byte)baudrate, ModeControlCharacter, 13, 10 }; Console.WriteLine("Moving to mode E.", arr); lock (Media.Synchronous) { WriteTrace("<- " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(arr, true)); Media.Send(arr, null); p.Reply = null; p.WaitTime = 2000; //Note! All meters do not echo this. Media.Receive(p); if (p.Reply != null) { WriteTrace("-> " + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(ASCIIEncoding.ASCII.GetBytes(p.Reply), true)); Console.WriteLine("Received: " + p.Reply); } if (serial != null) { Media.Close(); serial.BaudRate = BaudRate; serial.DataBits = 8; serial.Parity = Parity.None; serial.StopBits = StopBits.One; Media.Open(); //Some meters need this sleep. Do not remove. Thread.Sleep(1000); } } }
/// <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> /// 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 && Media is GXNet) { 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.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; } else 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); } } }
/// <summary> /// Import properties from the device. /// </summary> /// <param name="addinPages">Addin pages.</param> /// <param name="device">The target GXDevice to put imported items.</param> /// <param name="media">A media connection to the device.</param> /// <returns>True if there were no errors, otherwise false.</returns> public override void ImportFromDevice(Control[] addinPages, GXDevice device, IGXMedia media) { media.Open(); GXDLMSDevice Device = (GXDLMSDevice)device; int wt = Device.WaitTime; GXDLMSClient cosem = null; byte[] data, reply = null; IGXManufacturerExtension Extension = null; try { //Initialize connection. cosem = new GXDLMSClient(); cosem.UseLogicalNameReferencing = Device.UseLogicalNameReferencing; if (Device.Manufacturers == null) { Device.Manufacturers = new GXManufacturerCollection(); GXManufacturerCollection.ReadManufacturerSettings(Device.Manufacturers); } GXManufacturer man = Device.Manufacturers.FindByIdentification(Device.Identification); if (!string.IsNullOrEmpty(man.Extension)) { Type t = Type.GetType(man.Extension); Extension = Activator.CreateInstance(t) as IGXManufacturerExtension; } if (!Device.UseRemoteSerial && media is GXNet) //If media is network. { if (Device.SupportNetworkSpecificSettings) { cosem.InterfaceType = Gurux.DLMS.InterfaceType.Net; } } else if (media is GXSerial) //If media is serial. { byte terminator = 0xA; if (Device.StartProtocol == StartProtocolType.IEC) { GXSerial serial = media as GXSerial; serial.Eop = terminator; serial.Eop = terminator; //Init IEC connection. This must done first with serial connections. string str = "/?" + Device.SerialNumber + "!\r\n"; ReceiveParameters<string> args = new ReceiveParameters<string>() { Eop = terminator, WaitTime = wt }; lock (media.Synchronous) { media.Send(str, null); do { args.Reply = null; if (!media.Receive(args)) { throw new Exception("Failed to receive reply from the device in given time."); } } while (str == args.Reply);//Remove echo } string answer = args.Reply.ToString(); if (answer[0] != '/') { throw new Exception("Invalid responce."); } string manufactureID = answer.Substring(1, 3); char baudrate = answer[4]; if (baudrate == ' ') { baudrate = '5'; } int baudRate = 0; switch (baudrate) { case '0': baudRate = 300; break; case '1': baudRate = 600; break; case '2': baudRate = 1200; break; case '3': baudRate = 2400; break; case '4': baudRate = 4800; break; case '5': baudRate = 9600; break; case '6': baudRate = 19200; break; default: throw new Exception("Unknown baud rate."); } //Send ACK //Send Protocol control character byte controlCharacter = (byte)'2';// "2" HDLC protocol procedure (Mode E) //Send Baudrate character //Mode control character byte ModeControlCharacter = (byte)'2';//"2" //(HDLC protocol procedure) (Binary mode) //We are not receive anything. data = new byte[] { 0x06, controlCharacter, (byte)baudrate, ModeControlCharacter, 0x0D, 0x0A }; lock (media.Synchronous) { args.Reply = null; media.Send(data, null); //This is in standard. Do not remove sleep. //Some meters work without it, but some do not. System.Threading.Thread.Sleep(500); serial.BaudRate = baudRate; ReceiveParameters<byte[]> args2 = new ReceiveParameters<byte[]>() { Eop = terminator, WaitTime = 100 }; //If this fails, just read all data. if (!media.Receive(args2)) { //Read buffer. args2.AllData = true; args2.WaitTime = 1; media.Receive(args2); } serial.DataBits = 8; serial.Parity = Parity.None; serial.StopBits = StopBits.One; serial.DiscardInBuffer(); serial.DiscardOutBuffer(); serial.ResetSynchronousBuffer(); } } } media.Eop = (byte) 0x7E; cosem.Authentication = (Gurux.DLMS.Authentication)Device.Authentication; object clientAdd = null; if (cosem.Authentication == Authentication.None) { clientAdd = Device.ClientID; } else if (cosem.Authentication == Authentication.Low) { clientAdd = Device.ClientIDLow; } else if (cosem.Authentication == Authentication.High) { clientAdd = Device.ClientIDHigh; } if (!string.IsNullOrEmpty(Device.Password)) { cosem.Password = ASCIIEncoding.ASCII.GetBytes(Device.Password); } else { cosem.Password = null; } //If network media is used check is manufacturer supporting IEC 62056-47 if (!Device.UseRemoteSerial && media is GXNet && Device.SupportNetworkSpecificSettings) { cosem.InterfaceType = InterfaceType.Net; media.Eop = null; cosem.ClientID = Convert.ToUInt16(clientAdd); cosem.ServerID = Convert.ToUInt16(Device.PhysicalAddress); } else { if (Device.HDLCAddressing == HDLCAddressType.Custom) { cosem.ClientID = clientAdd; } else { cosem.ClientID = (byte)(Convert.ToByte(clientAdd) << 1 | 0x1); } if (Device.HDLCAddressing == HDLCAddressType.SerialNumber) { cosem.ServerID = GXManufacturer.CountServerAddress(Device.HDLCAddressing, Device.SNFormula, Convert.ToUInt32(Device.SerialNumber), Device.LogicalAddress); } else { cosem.ServerID = GXManufacturer.CountServerAddress(Device.HDLCAddressing, Device.SNFormula, Device.PhysicalAddress, Device.LogicalAddress); } } byte[] allData = null; data = cosem.SNRMRequest(); //General Network connection don't need SNRMRequest. if (data != null) { Trace("--- Initialize DLMS connection\r\n"); try { reply = ReadDLMSPacket(cosem, media, data, wt); } catch (Exception Ex) { throw new Exception("DLMS Initialize failed. " + Ex.Message); } //Has server accepted client. cosem.ParseUAResponse(reply); } Trace("Connecting\r\n"); media.ResetSynchronousBuffer(); try { foreach (byte[] it in cosem.AARQRequest(null)) { reply = ReadDLMSPacket(cosem, media, it, wt); } } catch (Exception Ex) { throw new Exception("DLMS AARQRequest failed. " + Ex.Message); } cosem.ParseAAREResponse(reply); //Now 1/5 or actions is done. Progress(1, 5); Trace("Read Objects\r\n"); try { allData = ReadDataBlock(cosem, media, cosem.GetObjectsRequest(), wt, 1); } catch (Exception Ex) { throw new Exception("DLMS AARQRequest failed. " + Ex.Message); } Trace("--- Parse Objects ---\r\n"); GXDLMSObjectCollection objs = cosem.ParseObjects((byte[])allData, true); allData = null; //Now we know exact number of read registers. Update progress bar again. int max = objs.Count; Trace("--- Read scalars ---\r\n"); //Now 2/5 or actions is done. Progress(2 * max, 5 * max); GXCategory dataItems = new GXCategory(); dataItems.Name = "Data Items"; GXCategory registers = new GXCategory(); registers.Name = "Registers"; Device.Categories.Add(dataItems); Device.Categories.Add(registers); int pos = 0; foreach (GXDLMSObject it in objs) { ++pos; //Skip association views. if (it.ObjectType == ObjectType.AssociationLogicalName || it.ObjectType == ObjectType.AssociationShortName) { continue; } if (it.ObjectType != ObjectType.ProfileGeneric) { object prop = UpdateData(media, Device, wt, cosem, man, it, dataItems, registers); //Read scaler and unit if (it.ObjectType == ObjectType.Register) { try { data = cosem.Read(it.Name, it.ObjectType, 3)[0]; allData = ReadDataBlock(cosem, media, data, wt, 2); cosem.UpdateValue(allData, it, 3); Gurux.DLMS.Objects.GXDLMSRegister item = it as Gurux.DLMS.Objects.GXDLMSRegister; GXDLMSRegister r = prop as GXDLMSRegister; r.Scaler = item.Scaler; r.Unit = item.Unit.ToString(); } //Ignore HW error and read next. catch (GXDLMSException) { continue; } catch (Exception Ex) { throw new Exception("DLMS Register Scaler and Unit read failed. " + Ex.Message); } } //Read scaler and unit else if (it.ObjectType == ObjectType.ExtendedRegister) { try { data = cosem.Read(it.Name, it.ObjectType, 3)[0]; allData = ReadDataBlock(cosem, media, data, wt, 2); cosem.UpdateValue(allData, it, 3); Gurux.DLMS.Objects.GXDLMSExtendedRegister item = it as Gurux.DLMS.Objects.GXDLMSExtendedRegister; GXDLMSCategory cat = prop as GXDLMSCategory; GXDLMSRegister r = cat.Properties[0] as GXDLMSRegister; r.Scaler = item.Scaler; r.Unit = item.Unit.ToString(); cat.Properties[1].SetValue(item.Scaler.ToString() + ", " + item.Unit.ToString(), true, PropertyStates.None); } //Ignore HW error and read next. catch (GXDLMSException) { continue; } catch (Exception Ex) { throw new Exception("DLMS Register Scaler and Unit read failed. " + Ex.Message); } } //Read scaler and unit else if (it.ObjectType == ObjectType.DemandRegister) { try { data = cosem.Read(it.Name, it.ObjectType, 3)[0]; allData = ReadDataBlock(cosem, media, data, wt, 2); cosem.UpdateValue(allData, it, 3); Gurux.DLMS.Objects.GXDLMSDemandRegister item = it as Gurux.DLMS.Objects.GXDLMSDemandRegister; GXDLMSCategory cat = prop as GXDLMSCategory; cat.Properties[2].SetValue(item.Scaler.ToString() + ", " + item.Unit.ToString(), true, PropertyStates.None); GXDLMSRegister r = cat.Properties[0] as GXDLMSRegister; r.Scaler = item.Scaler; r.Unit = item.Unit.ToString(); r = cat.Properties[1] as GXDLMSRegister; r.Scaler = item.Scaler; r.Unit = item.Unit.ToString(); } //Ignore HW error and read next. catch (GXDLMSException) { continue; } catch (Exception Ex) { throw new Exception("DLMS Register Scaler and Unit read failed. " + Ex.Message); } } } //Now 3/5 actions is done. double tmp = pos * max; tmp /= max; tmp += 2 * max; Progress((int) tmp , 5 * max); } //Now 3/5 actions is done. Progress(3 * max, 5 * max); Trace("--- Read Generic profiles ---\r\n"); GXDLMSObjectCollection pg = objs.GetObjects(ObjectType.ProfileGeneric); foreach (GXDLMSProfileGeneric it in pg) { try { allData = ReadDataBlock(cosem, media, cosem.Read(it.Name, it.ObjectType, 3)[0], wt, 3); cosem.UpdateValue(allData, it, 3); UpdateData(media, Device, wt, cosem, man, it, dataItems, registers); } //Ignore HW error and read next. catch (GXDLMSException) { continue; } catch (Exception Ex) { Trace("DLMS Generic Profile read failed. " + Ex.Message + Environment.NewLine); } } //Now 4/5 actions is done. Progress(4 * max, 5 * max); //Update IEC HDLC interval if found. GXDLMSObjectCollection objects = objs.GetObjects(ObjectType.IecHdlcSetup); if (objects.Count != 0) { allData = ReadDataBlock(cosem, media, cosem.Read(objects[0].Name, objects[0].ObjectType, 8)[0], wt, 5); //Minus 10 second. Device.Keepalive.Interval = (Convert.ToInt32(cosem.GetValue(allData)) - 10) * 1000; } //Now all actions are done. Progress(max, max); Trace("--- Succeeded ---\r\n"); } finally { if (cosem != null && media != null) { Trace("--- Disconnecting ---\r\n"); byte[] allData = null; if (cosem != null) { //Network standard don't need this. if (!(media is GXNet && Device.SupportNetworkSpecificSettings)) { try { reply = ReadDLMSPacket(cosem, media, cosem.DisconnectRequest(), wt); cosem.GetDataFromPacket(reply, ref allData); } catch (Exception Ex) { Trace("DisconnectRequest failed. " + Ex.Message); } } } if (media != null) { media.Close(); media = null; } Trace("--- Disconnected ---\r\n--- Done---\r\n"); } } }
public override void ImportFromDevice(Control[] addinPages, GXDevice device, IGXMedia media) { media.Open(); GXMBusDevice dev = device as GXMBusDevice; object data; //Handshake ShortFrame sf = new ShortFrame(); sf.AddressField = dev.DeviceAddress; sf.ControlField = (byte)CFieldFunctions.SendSlaveInit; sf.CountChecksum(); data = sf.ToByteArray(); ReceiveParameters<byte[]> recParams = new ReceiveParameters<byte[]>() { Count = 1, Peek = false, WaitTime = device.WaitTime }; lock (media.Synchronous) { media.Send(data, null); if (!media.Receive(recParams)) { throw new Exception("Failed to receive reply from the device in given time."); } if (recParams.Reply.Length < 1 || recParams.Reply[0] != 0xE5) { throw new Exception("Handshake failed."); } bool morePacketsAvailable = false; byte fcb = 1; List<MBusRegister> items = new List<MBusRegister>(); do { sf = new ShortFrame(); sf.AddressField = dev.DeviceAddress; if (fcb == 1) { sf.ControlField = (byte)CFieldFunctions.RequestClass2Data; } else { sf.ControlField = (byte)CFieldFunctions.RequestClass2Data | (byte)CFieldRequest.FrameCountBit; } sf.CountChecksum(); recParams.AllData = true; recParams.Count = 1; recParams.Eop = (byte)0x16; recParams.Reply = null; int cnt = 0; //Some meters can't answer right a way. do { media.Send(sf.ToByteArray(), null); if (++cnt == 6) { throw new Exception("Failed to receive reply from the device in given time."); } } while (!media.Receive(recParams)); while (!VerifyReadReplyCheckSum(recParams.Reply)) { recParams.Count = 0; recParams.Reply = null; bool gotData = media.Receive(recParams); if (!gotData) { break; } } morePacketsAvailable = recParams.Reply.Length > 5 && (recParams.Reply[4] & 0x10) != 0; items.AddRange(ParseReadReply(recParams.Reply)); } while (morePacketsAvailable); GXMBusCategory defaultCategory = null; if ((defaultCategory = (GXMBusCategory)device.Categories.Find("Default")) == null) { defaultCategory = new GXMBusCategory(); defaultCategory.Name = "Default"; device.Categories.Add(defaultCategory); } for (int pos = 0; pos < items.Count; ++pos) { MBusRegister item = items[pos]; GXMBusProperty prop = new GXMBusProperty(); prop.Ordinal = pos; if (item.IsVariableData) { string name = item.MBusType; int len = name.IndexOf('_'); if (len != -1) { name = name.Substring(0, len); } name += " " + item.Function.ToString(); if (item.Tariff != 0) { name += " Tariff " + item.Tariff.ToString(); } prop.Name = name; prop.Unit = item.Unit; prop.DataLength = item.DataLength; item.Mask.Reverse(); prop.InfoMask = item.Mask.ToArray(); prop.Type = item.Type; if (item.MBusType.ToLower().Contains("date") || item.MBusType.ToLower().Contains("timepoint")) { prop.ValueType = typeof(DateTime); } else { prop.ValueType = typeof(string); } } else { prop.Name = item.MBusType; prop.Unit = item.Unit; prop.ValueType = typeof(string); prop.DataLength = 4; } prop.InfoBytes = item.InformationBytes.Reverse().ToArray(); defaultCategory.Properties.Add(prop); } } }
static byte[] SendData(IGXMedia media, byte[] data, char baudRate, int wt, bool useCrcSend, bool useCrcReply, bool readAllDataOnce) { ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { Eop = GetEops(), WaitTime = wt }; lock (media.Synchronous) { if (data != null) { media.Send(data, null); if (baudRate != '\0' && media.MediaType == "Serial") { Gurux.Serial.GXSerial serial = media as Gurux.Serial.GXSerial; while (serial.BytesToWrite != 0) { System.Threading.Thread.Sleep(100); } System.Threading.Thread.Sleep(200); switch (baudRate) { case '0': serial.BaudRate = 300; break; case '1': case 'A': serial.BaudRate = 600; break; case '2': case 'B': serial.BaudRate = 1200; break; case '3': case 'C': serial.BaudRate = 2400; break; case '4': case 'D': serial.BaudRate = 4800; break; case '5': case 'E': serial.BaudRate = 9600; break; case '6': case 'F': serial.BaudRate = 19200; break; default: throw new Exception("Unknown baud rate."); } } } if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } List <byte> reply2 = new List <byte>(); reply2.AddRange(p.Reply); p.Reply = null; string header, frame; byte[] packet = null; if (useCrcSend && data != null) { while ((packet = GetPacket(reply2, false, out header, out frame)) == null) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } reply2.AddRange(p.Reply); p.Reply = null; } p.Eop = GetEops(); } else { for (int pos = 0; pos != reply2.Count; ++pos) { if (reply2[pos] == 0xA) { ++pos; packet = new byte[pos]; reply2.CopyTo(0, packet, 0, pos); break; } } } //Remove echo. if (data != null && EqualBytes(data, packet)) { reply2.RemoveRange(0, data.Length); if (useCrcReply && reply2.Count != 0)// && !(data != null && data[data.Length - 1] == 0xA)) { while (GetPacket(reply2, false, out header, out frame) == null) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } reply2.AddRange(p.Reply); p.Reply = null; } } else { if (GetPacket(reply2, false, out header, out frame) == null) { reply2.AddRange(SendData(media, null, baudRate, wt, useCrcSend, useCrcReply, readAllDataOnce)); } } //If there is more data available. if (readAllDataOnce && reply2[reply2.Count - 2] == 0x4) { reply2.AddRange(SendData(media, new byte[] { 6 }, '\0', wt, useCrcSend, useCrcReply, readAllDataOnce)); } return(reply2.ToArray()); } if (useCrcReply && !(data != null && data[data.Length - 1] == 0xA)) { while (GetPacket(reply2, false, out header, out frame) == null) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } reply2.AddRange(p.Reply); p.Reply = null; } } return(reply2.ToArray()); } }
/// <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, int tryCount, GXReplyData reply) { if (data == null) { return; } object eop = (byte)0x7E; //In network connection terminator is not used. if (client.InterfaceType == InterfaceType.WRAPPER && media is GXNet && !parent.UseRemoteSerial) { eop = null; } int pos = 0; bool succeeded = false; ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { AllData = false, Eop = eop, Count = 5, WaitTime = parent.WaitTime * 1000, }; lock (media.Synchronous) { if (data != null) { media.Send(data, null); } while (!succeeded && pos != 3) { succeeded = media.Receive(p); if (!succeeded) { //Try to read again... if (++pos != tryCount) { //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); media.Send(data, null); continue; } string err = "Failed to receive reply from the device in given time."; GXLogWriter.WriteLog(err, p.Reply); throw new Exception(err); } } try { //Loop until whole COSEM packet is received. while (!client.GetData(p.Reply, reply)) { //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } if (!media.Receive(p)) { //Try to read again... if (++pos != tryCount) { System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); continue; } string err = "Failed to receive reply from the device in given time."; GXLogWriter.WriteLog(err, p.Reply); throw new Exception(err); } } } catch (Exception ex) { GXLogWriter.WriteLog("Received data:", p.Reply); throw ex; } } GXLogWriter.WriteLog(null, p.Reply); if (parent.OnTrace != null) { parent.OnTrace(parent, "-> " + DateTime.Now.ToLongTimeString(), p.Reply); } if (reply.Error != 0) { if (reply.Error == (int)ErrorCode.Rejected) { Thread.Sleep(1000); ReadDLMSPacket(data, tryCount, reply); } else { throw new GXDLMSException(reply.Error); } } }
/// <summary> /// Disconnect. /// </summary> /// <param name="serial"></param> /// <param name="tryCount"></param> public static void Disconnect(IGXMedia media, int tryCount) { lock (media.Synchronous) { ReceiveParameters<byte[]> p = new ReceiveParameters<byte[]>() { Eop = GetEops(), WaitTime = 1000 }; List<byte> data = new List<byte>(); data.Add(0x01); data.Add((byte)'B'); data.Add((byte)'0'); data.Add(0x03); data.Add(CalculateChecksum(data, 1, data.Count - 1)); byte[] data1 = data.ToArray(); string header, frame; media.Send(data1, null); media.Receive(p); while (--tryCount > -1) { if (media.Receive(p)) { GetPacket(new List<byte>(p.Reply), false, out header, out frame); if (header == "B0") { break; } if (p.Reply.Length > 11) { p.Reply = null; } } media.Send(data1, null); } } }
static byte[] SendData(IGXMedia media, byte[] data, char baudRate, int wt, bool useCrcSend, bool useCrcReply, bool readAllDataOnce) { ReceiveParameters<byte[]> p = new ReceiveParameters<byte[]>() { Eop = GetEops(), WaitTime = wt }; lock (media.Synchronous) { if (data != null) { media.Send(data, null); if (baudRate != '\0' && media.MediaType == "Serial") { Gurux.Serial.GXSerial serial = media as Gurux.Serial.GXSerial; while (serial.BytesToWrite != 0) { System.Threading.Thread.Sleep(100); } System.Threading.Thread.Sleep(200); switch (baudRate) { case '0': serial.BaudRate = 300; break; case '1': case 'A': serial.BaudRate = 600; break; case '2': case 'B': serial.BaudRate = 1200; break; case '3': case 'C': serial.BaudRate = 2400; break; case '4': case 'D': serial.BaudRate = 4800; break; case '5': case 'E': serial.BaudRate = 9600; break; case '6': case 'F': serial.BaudRate = 19200; break; default: throw new Exception("Unknown baud rate."); } } } if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } List<byte> reply2 = new List<byte>(); reply2.AddRange(p.Reply); p.Reply = null; string header, frame; byte[] packet = null; if (useCrcSend && data != null) { while ((packet = GetPacket(reply2, false, out header, out frame)) == null) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } reply2.AddRange(p.Reply); p.Reply = null; } p.Eop = GetEops(); } else { for (int pos = 0; pos != reply2.Count; ++pos) { if (reply2[pos] == 0xA) { ++pos; packet = new byte[pos]; reply2.CopyTo(0, packet, 0, pos); break; } } } //Remove echo. if (data != null && EqualBytes(data, packet)) { reply2.RemoveRange(0, data.Length); if (useCrcReply && reply2.Count != 0)// && !(data != null && data[data.Length - 1] == 0xA)) { while (GetPacket(reply2, false, out header, out frame) == null) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } reply2.AddRange(p.Reply); p.Reply = null; } } else { if (GetPacket(reply2, false, out header, out frame) == null) { reply2.AddRange(SendData(media, null, baudRate, wt, useCrcSend, useCrcReply, readAllDataOnce)); } } //If there is more data available. if (readAllDataOnce && reply2[reply2.Count - 2] == 0x4) { reply2.AddRange(SendData(media, new byte[] { 6 }, '\0', wt, useCrcSend, useCrcReply, readAllDataOnce)); } return reply2.ToArray(); } if (useCrcReply && !(data != null && data[data.Length - 1] == 0xA)) { while (GetPacket(reply2, false, out header, out frame) == null) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } reply2.AddRange(p.Reply); p.Reply = null; } } return reply2.ToArray(); } }
static public byte[] ReadReadout(IGXMedia media, string data, int wt) { ReceiveParameters<byte[]> p = new ReceiveParameters<byte[]>() { Eop = GetEops(), WaitTime = wt }; lock (media.Synchronous) { if (data != null) { media.Send(data, null); } do { if (!media.Receive(p)) { //There is no eop or CRC. break; } } while (p.Reply[p.Reply.Length - 1] != 0x3); //Read CRC if EOP is found. if (p.Reply[p.Reply.Length - 1] == 0x3) { p.Eop = null; p.Count = 1; if (!media.Receive(p)) { throw new Exception("Failed to receive reply from the device in given time."); } } } return p.Reply; }
void InitSerial() { GXSerial serial = Media as GXSerial; byte Terminator = (byte)0x0A; if (serial != null && InitializeIEC) { serial.BaudRate = 300; serial.DataBits = 7; serial.Parity = Parity.Even; serial.StopBits = StopBits.One; } Media.Open(); //Query device information. if (Media != null && InitializeIEC) { string data = "/?001!\r\n"; if (Trace) { Console.WriteLine("HDLC sending:" + data); } ReceiveParameters <string> p = new ReceiveParameters <string>() { Eop = Terminator, WaitTime = WaitTime }; lock (Media.Synchronous) { Media.Send(data, null); if (!Media.Receive(p)) { //Try to move away from mode E. throw new Exception("Failed to receive reply from the device in given time."); } //If echo is used. if (p.Reply == data) { p.Reply = null; if (!Media.Receive(p)) { //Try to move away from mode E. throw new Exception("Failed to receive reply from the device in given time."); } } } if (Trace) { Console.WriteLine("HDLC received: " + p.Reply); } if (p.Reply[0] != '/') { p.WaitTime = 100; Media.Receive(p); throw new Exception("Invalid responce."); } string manufactureID = p.Reply.Substring(1, 3); //UpdateManufactureSettings(manufactureID); char baudrate = p.Reply[4]; int BaudRate = 0; switch (baudrate) { case '0': BaudRate = 300; break; case '1': BaudRate = 600; break; case '2': BaudRate = 1200; break; case '3': BaudRate = 2400; break; case '4': BaudRate = 4800; break; case '5': BaudRate = 9600; break; case '6': BaudRate = 19200; break; default: throw new Exception("Unknown baud rate."); } Console.WriteLine("BaudRate is :", BaudRate.ToString()); //Send ACK //Send Protocol control character byte controlCharacter = (byte)'2';// "2" HDLC protocol procedure (Mode E) //Send Baudrate character //Mode control character byte ModeControlCharacter = (byte)'2';//"2" //(HDLC protocol procedure) (Binary mode) //Set mode E. byte[] arr = new byte[] { 0x06, controlCharacter, (byte)baudrate, ModeControlCharacter, 13, 10 }; if (Trace) { Console.WriteLine("Moving to mode E", BitConverter.ToString(arr)); } lock (Media.Synchronous) { Media.Send(arr, null); p.Reply = null; p.WaitTime = 500; if (!Media.Receive(p)) { //Try to move away from mode E. this.ReadDLMSPacket(m_Parser.DisconnectRequest()); throw new Exception("Failed to receive reply from the device in given time."); } } if (serial != null) { serial.BaudRate = BaudRate; serial.DataBits = 8; serial.Parity = Parity.None; serial.StopBits = StopBits.One; } } }