/// <summary> /// Constructor. /// </summary> public GXCommunicatation(Gurux.DLMS.GXDLMSClient dlms, IGXMedia media, bool initializeIEC, Authentication authentication, string password) { Client = dlms; Media = media; InitializeIEC = initializeIEC; Client.Authentication = authentication; Client.Password = ASCIIEncoding.ASCII.GetBytes(password); //Delete trace file if exists. if (File.Exists("trace.txt")) { File.Delete("trace.txt"); } }
/// <summary> /// Constructor. /// </summary> public GXCommunicatation(Gurux.DLMS.GXDLMSClient dlms, IGXMedia media, bool initializeIEC, Gurux.DLMS.Authentication authentication, string password) { Client = dlms; Media = media; InitializeIEC = initializeIEC; Client.Authentication = authentication; Client.Password = ASCIIEncoding.ASCII.GetBytes(password); //Delete trace file if exists. if (File.Exists("trace.txt")) { File.Delete("trace.txt"); } }
public void Close() { if (Media != null && Client != null) { try { //Console.WriteLine("Disconnecting from the meter."); ReadDLMSPacket(Client.DisconnectRequest()); Media.Close(); } catch { } Media = null; Client = null; } }
void AddColumn(GXDLMSClient cosem, GXManufacturer man, GXDLMSTable table, byte[] ln, object scalar, int index, string name) { string logicanName = null; if (ln != null) { logicanName = GXHelpers.ConvertFromDLMS(ln, DataType.OctetString, DataType.OctetString, false).ToString(); if (string.IsNullOrEmpty(name)) { GXObisCode code = man.ObisCodes.FindByLN(ObjectType.None, logicanName, null); if (code != null) { name = code.Description; } else { name = logicanName; } } } if (scalar == null) { GXDLMSProperty prop = new GXDLMSProperty(ObjectType.Data, logicanName, 0, name, index, DataType.DateTime); prop.ValueType = DataType.DateTime; prop.AccessMode = Gurux.Device.AccessMode.Read; table.Columns.Add(prop); } else { object[] tmp = (object[])scalar; Gurux.DLMS.AddIn.GXDLMSRegister prop = new Gurux.DLMS.AddIn.GXDLMSRegister(); prop.Scaler = Math.Pow(10, Convert.ToInt32(tmp[0])); prop.Unit = tmp[1].ToString(); prop.LogicalName = logicanName; prop.Name = name; prop.AttributeOrdinal = index; prop.DLMSType = DataType.UInt32; prop.ValueType = DataType.Float64; prop.AccessMode = Gurux.Device.AccessMode.Read; table.Columns.Add(prop); } }
public byte[][] ImageVerify(GXDLMSClient client) { return client.Method(this, 3, 0, DataType.Int8); }
public byte[][] ImageTransferInitiate(GXDLMSClient client, string imageIdentifier, long imageSize) { if (ImageBlockSize == 0) { throw new Exception("Invalid image block size"); } List<byte> data = new List<byte>(); data.Add((byte)DataType.Structure); data.Add((byte)2); GXCommon.SetData(data, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(imageIdentifier)); GXCommon.SetData(data, DataType.UInt32, imageSize); return client.Method(this, 1, data.ToArray(), DataType.Array); }
/// <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); }
/// <summary> /// Imports an X.509 v3 certificate of a public key. /// </summary> /// <param name="client">DLMS client that is used to generate action.</param> /// <param name="key">Public key.</param> /// <returns>Generated action.</returns> public byte[][] Import(GXDLMSClient client, CngKey key) { return ImportCertificate(client, key.Export(CngKeyBlobFormat.EccPublicBlob)); }
/// <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); }
/// <summary> /// Shifts the time by n (-900 <= n <= 900) s. /// </summary> /// <param name="time"></param> /// <returns></returns> public byte[][] ShiftTime(GXDLMSClient client, int time) { if (time < -900 || time > 900) { throw new ArgumentOutOfRangeException("Invalid shift time."); } return client.Method(this, 6, time, DataType.Int16); }
internal void CreateColumns(Gurux.Common.IGXMedia media, GXDLMSDevice Device, GXManufacturer man, int wt, GXDLMSClient cosem, IGXManufacturerExtension Extension, GXCategory dataItems, GXCategory registers, GXDLMSObject it, GXDLMSTable table) { }
/// <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"); } } }
internal byte[] ReadDLMSPacket(GXDLMSClient cosem, Gurux.Common.IGXMedia media, byte[] data, int wt) { if (data == null) { return null; } ReceiveParameters<byte[]> args = new ReceiveParameters<byte[]>() { Eop = (byte)0x7E, Count = 5, WaitTime = wt }; if (cosem.InterfaceType == InterfaceType.Net) { args.Eop = null; args.Count = 8; args.AllData = true; } int pos = 0; bool succeeded = false; lock (media.Synchronous) { media.Send(data, null); while (!succeeded && pos != 3) { succeeded = media.Receive(args); if (!succeeded) { //Try to read again... if (++pos != 3) { 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, (byte[])args.Reply); throw new Exception(err); } } //Loop until whole m_Cosem packet is received. while (!(succeeded = cosem.IsDLMSPacketComplete(args.Reply))) { if (!media.Receive(args)) { //Try to read again... if (++pos != 3) { System.Diagnostics.Debug.WriteLine("Data receive failed. Try to resend " + pos.ToString() + "/3"); continue; } string err = "Failed to receive reply from the device in given time."; GXLogWriter.WriteLog(err, (byte[])args.Reply); throw new Exception(err); } } } object[,] errors = cosem.CheckReplyErrors(data, args.Reply); if (errors != null) { int error = (int)errors[0, 0]; throw new GXDLMSException(error); } return args.Reply; }
public GXDLMSCommunicator(GXDLMSDevice parent, Gurux.Common.IGXMedia media) { Parent = parent; Media = media; m_Cosem = new Gurux.DLMS.GXDLMSClient(); }
public void UpdateColumns(GXDLMSDevice Device, GXManufacturer man, GXDLMSClient cosem, Gurux.Common.IGXMedia media, int wt, Gurux.DLMS.Objects.GXDLMSObject it, GXDLMSTable table, GXDLMSAddIn parent, GXCategory dataItems, GXCategory registers) { //Reading data. //If Load profile1 if (it.LogicalName == "0.0.99.1.2.255") { //Read Load Profile 1 information byte[] allData = parent.ReadDataBlock(cosem, media, cosem.Read("0.0.99.128.1.255", ObjectType.ProfileGeneric, 2)[0], wt, 0); object[] items = (object[])((object[])cosem.GetValue(allData)).GetValue(0); int pos = 0; AddColumn(cosem, man, table, null, null, 0, "DateTime"); AddColumn(cosem, man, table, null, null, 1, "Status"); AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 2, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 3, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 4, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 5, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 6, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 7, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 8, null); pos += 2; AddColumn(cosem, man, table, (byte[])items.GetValue(pos), items.GetValue(pos + 1), 9, null); return; } parent.CreateColumns(media, Device, man, wt, cosem, this, dataItems, registers, it, table); }
/// <summary> /// Update categories data. /// </summary> /// <param name="trace"></param> /// <param name="progressbar"></param> /// <param name="media"></param> /// <param name="Device"></param> /// <param name="wt"></param> /// <param name="cosem"></param> /// <param name="man"></param> /// <param name="objs"></param> /// <param name="dataItems"></param> /// <param name="registers"></param> private object UpdateData(Gurux.Common.IGXMedia media, GXDLMSDevice Device, int wt, GXDLMSClient cosem, GXManufacturer man, GXDLMSObject it, GXCategory dataItems, GXCategory registers) { GXObisCode code = man.ObisCodes.FindByLN(it.ObjectType, it.LogicalName, null); if (it.ObjectType == ObjectType.Register) { GXDLMSRegister prop = new GXDLMSRegister(); UpdateObject(it, prop, 2); registers.Properties.Add(prop); return prop; } else if (it.ObjectType == Gurux.DLMS.ObjectType.Data) { GXDLMSProperty prop = new GXDLMSProperty(); prop.ObjectType = ObjectType.Data; UpdateObject(it, prop, 2); dataItems.Properties.Add(prop); return prop; } else if (it.ObjectType == Gurux.DLMS.ObjectType.ProfileGeneric) { GXDLMSProfileGeneric pg = it as GXDLMSProfileGeneric; GXDLMSTable table = new GXDLMSTable(); table.Name = it.LogicalName + " " + it.Description; table.ShortName = it.ShortName; table.LogicalName = it.LogicalName; table.AccessMode = Gurux.Device.AccessMode.Read; foreach(var it2 in pg.CaptureObjects) { GXDLMSProperty prop; if (it2.Key is Gurux.DLMS.Objects.GXDLMSRegister) { Gurux.DLMS.Objects.GXDLMSRegister tmp = it2.Key as Gurux.DLMS.Objects.GXDLMSRegister; GXDLMSRegister r = new GXDLMSRegister(); prop = r; r.Scaler = tmp.Scaler; r.Unit = tmp.Unit.ToString(); } else { prop = new GXDLMSProperty(); } int index = it2.Value.AttributeIndex; prop.Name = it2.Key.LogicalName + " " + it2.Key.Description; prop.ObjectType = it2.Key.ObjectType; prop.AttributeOrdinal = index; prop.LogicalName = it2.Key.LogicalName; table.Columns.Add(prop); prop.DLMSType = it.GetDataType(index); prop.ValueType = it2.Key.GetUIDataType(index); } Device.Tables.Add(table); return table; } GXDLMSCategory cat = new GXDLMSCategory(); cat.ObjectType = it.ObjectType; UpdateObject(it, cat); Device.Categories.Add(cat); return cat; }
/// <summary> /// Activates and strengthens the security policy. /// </summary> /// <param name="client">DLMS client that is used to generate action.</param> /// <param name="security">New security level.</param> /// <returns>Generated action.</returns> public byte[][] Activate(GXDLMSClient client, Gurux.DLMS.Enums.Security security) { return client.Method(this, 1, GetSecurityValue(security), DataType.Enum); }
private static void MainProcessing(object state) { IGXMedia media = null; GXCommunicatation comm = null; Gurux.Net.GXNet net = null; if ((!Environment.UserInteractive) && (args.Length == 0)) // when in service mode, get arguments from commandline if failed from onStart method args = Environment.CommandLine.Split(new char[] { ' ' }); if (!Environment.UserInteractive && !running) return; try { logFile = new StreamWriter(File.Open(logFileName, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)); logFile.WriteLine("\n"); //Handle command line parameters. String id = "lgz", host = "", port = "4095", pw = ""; String lt = "-1"; bool trace = false, iec = true; int loopTime = -1; Authentication auth = Authentication.None; foreach (string it in args) { String item = it.Trim().ToLower(); if (string.Compare(item, "/u", true) == 0)//Update { //Get latest manufacturer settings from Gurux web server. GXManufacturerCollection.UpdateManufactureSettings(); } else if (item.StartsWith("/m="))//Manufacturer { id = item.Replace("/m=", ""); } else if (item.StartsWith("/host=")) //Host { host = item.Replace("/host=", ""); } else if (item.StartsWith("/p="))// TCP/IP Port { media = new Gurux.Net.GXNet(); port = item.Replace("/p=", ""); } else if (item.StartsWith("/sp="))//Serial Port { port = item.Replace("/sp=", ""); media = new GXSerial(); } else if (item.StartsWith("/t"))//Are messages traced. { trace = true; } else if (item.StartsWith("/s="))//Start { String tmp = item.Replace("/s=", ""); iec = string.Compare(tmp, "dlms", true) != 0; } else if (item.StartsWith("/a="))//Authentication { auth = (Authentication)Enum.Parse(typeof(Authentication), it.Trim().Replace("/a=", "")); } else if (item.StartsWith("/pw="))//Password { pw = it.Trim().Replace("/pw=", ""); } else if (item.StartsWith("/l="))// loop time { lt = item.Replace("/l=", ""); } else if (item.StartsWith("/h"))// help { ShowHelp(); return; } else if (item.StartsWith("/sm=")) //sitemap { sitesMapPath = it.Trim().Replace("/sm=", ""); } else if (item.StartsWith("/is=")) //IAM server { IAMServer = it.Trim().Replace("/is=", ""); } } if (media == null) media = new Gurux.Net.GXNet(); int.TryParse(lt, out loopTime); Version version = Assembly.GetExecutingAssembly().GetName().Version; if (!Environment.UserInteractive) TraceLine(logFile, string.Format("IAM Reader OPEN SOURCE EXAMPLE Service ver. {0} started with loop time={1} min.", version.ToString(3), loopTime)); else TraceLine(logFile, string.Format("IAM Reader OPEN SOURCE EXAMPLE ver. {0} started with loop time={1} min.", version.ToString(3), loopTime)); logFile.Flush(); //Initialize connection settings. if (media is GXSerial) { GXSerial serial = media as GXSerial; serial.PortName = port; if (iec) { 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; } } else if (media is GXNet) { /*Gurux.Net.GXNet*/ net = media as GXNet; net.Port = Convert.ToInt32(port); net.HostName = host; net.Protocol = Gurux.Net.NetworkType.Tcp; } else { throw new Exception("Unknown media type."); } //Update manufacturer debended settings. GXManufacturerCollection Manufacturers = new GXManufacturerCollection(); GXManufacturerCollection.ReadManufacturerSettings(Manufacturers); GXManufacturer man = Manufacturers.FindByIdentification(id); if (man == null) { throw new Exception("Unknown manufacturer: " + id); } GXDLMSClient dlms = new GXDLMSClient(); //Update Obis code list so we can get right descriptions to the objects. dlms.ObisCodes = man.ObisCodes; List<IAM.DLMSSite> DlmsSites = null; IAM.ArrayOfDLMSSite aods = null; XmlSerializer y = new XmlSerializer(typeof(IAM.ArrayOfDLMSSite)); if (File.Exists(sitesMapPath)) { try { using (Stream stream = File.Open(sitesMapPath, FileMode.Open)) { TraceLine(logFile, "Get configured sites map from file."); aods = y.Deserialize(stream) as IAM.ArrayOfDLMSSite; DlmsSites = aods.DLMSSite; stream.Close(); } } catch (Exception ex) { throw ex; } } else { TraceLine(logFile, "Error. SitesMap file not found."); return; } List<Type> extraTypes = new List<Type>(Gurux.DLMS.GXDLMSClient.GetObjectTypes()); extraTypes.Add(typeof(GXDLMSAttributeSettings)); extraTypes.Add(typeof(GXDLMSAttribute)); //TraceLine(logFile, "Memory32: " + GC.GetTotalMemory(true)); 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. extraTypes.Clear(); foreach (IAM.DLMSSite site in DlmsSites) // { site.DataProcessing.EnergyPeriodDateTime = DateTime.MinValue; site.DataProcessing.PowerPeriodDateTime = DateTime.MinValue; } //bool keyAvailable = false; DateTime startTime; FileInfo infoFileSite = new FileInfo(sitesMapPath); DateTime lastWriteMapFile = infoFileSite.LastWriteTime; do { try { FileInfo f = new FileInfo(logFileName); //output log file if (f.Length > maxLogFileSize) { logFile.Flush(); logFile.Close(); File.Delete(rotatedLogFileName); File.Move(logFileName, rotatedLogFileName); logFile = new StreamWriter(File.Open(logFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)); } infoFileSite.Refresh(); if (infoFileSite.LastWriteTime != lastWriteMapFile) { try { using (Stream stream = File.Open(sitesMapPath, FileMode.Open)) { TraceLine(logFile, "Get updated sites map from file."); aods = y.Deserialize(stream) as IAM.ArrayOfDLMSSite; DlmsSites = aods.DLMSSite; stream.Close(); lastWriteMapFile = infoFileSite.LastWriteTime; } } catch (Exception ex) { throw ex; } } startTime = DateTime.Now; TraceLine(logFile, "Start new iteration"); foreach (IAM.DLMSSite site in DlmsSites) //cycle for each remote meter (listed in the sitemap.xml) { TraceLine(logFile, "Now processing: " + site.Name); //current remote meter if (!site.Enabled) { TraceLine(logFile, "Disabled: skip to next"); continue; } try { host = site.Device.Host; //ip address of the current remote meter port = site.Device.Port; if (site.Device.Manufacturer != "") id = site.Device.Manufacturer.ToLower(); if (site.Device.Protocol != "") iec = site.Device.Protocol.ToLower() == "dlms"; if (media is GXNet) { /*Gurux.Net.GXNet*/ net = media as GXNet; net.Port = Convert.ToInt32(port); net.HostName = host; net.Protocol = Gurux.Net.NetworkType.Tcp; } comm = new GXCommunicatation(dlms, media, iec, auth, pw); comm.Trace = trace; TraceLine(logFile, "Initializing Network connection."); comm.InitializeConnection(man); } catch (Exception ex) { TraceLine(logFile, "Error. " + ex.Message); if (comm != null) { comm.Close(); } continue; } GXDLMSObjectCollection objects = null; string meterPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\" +host.Replace('.', '_') + "_" + port.ToString() + ".xml"; if (File.Exists(meterPath)) //list of OBIS objects for remote meter { try { using (Stream stream = File.Open(meterPath, FileMode.Open)) { TraceLine(logFile, "Get available objects from the cache."); objects = x.Deserialize(stream) as GXDLMSObjectCollection; stream.Close(); } } catch (Exception ex) { if (File.Exists(meterPath)) { File.Delete(meterPath); } throw ex; } } else { TraceLine(logFile, "Get available objects from the device."); objects = comm.GetAssociationView(); // Save to file try { using (Stream stream = File.Open(meterPath, FileMode.Create)) { TextWriter writer = new StreamWriter(stream); x.Serialize(writer, objects); writer.Close(); stream.Close(); } TraceLine(logFile, "Available objects saved to the cache."); } catch (Exception ex) { if (File.Exists(meterPath)) { File.Delete(meterPath); } throw ex; } } // start remote meter reading try { int EPeriod = 15; // energy integration period if (site.DataProcessing.EnergyPeriod != 0) EPeriod = site.DataProcessing.EnergyPeriod; else site.DataProcessing.EnergyPeriod = EPeriod; //if (EPeriod <= 0) // EPeriod = 15; int PPeriod = 15; // power integration period if (site.DataProcessing.PowerPeriod != 0) PPeriod = site.DataProcessing.PowerPeriod; else site.DataProcessing.PowerPeriod = PPeriod; //if (PPeriod <= 0) // PPeriod = 15; DateTime now = DateTime.Now; DateTime nowRnd = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute / EPeriod * EPeriod, 0); if (site.DataProcessing.EnergyPeriodDateTime == DateTime.MinValue) { site.DataProcessing.EnergyPeriodDateTime = now; TraceLine(logFile, "Initialize energy period from null."); } // default OBIS codes for energies string AEP = "1.0.1.8.0.255"; string AEM = "1.0.2.8.0.255"; string REP = "1.0.3.8.0.255"; string REM = "1.0.4.8.0.255"; if (!string.IsNullOrEmpty(site.ArrayOfOBIS.DataObjects.ActiveEnergyP)) //plus = absorbed energy AEP = site.ArrayOfOBIS.DataObjects.ActiveEnergyP; if (!string.IsNullOrEmpty(site.ArrayOfOBIS.DataObjects.ActiveEnergyM)) //minus = supplied energy AEM = site.ArrayOfOBIS.DataObjects.ActiveEnergyM; if (!string.IsNullOrEmpty(site.ArrayOfOBIS.DataObjects.ReactiveEnergyP)) //plus = absorbed energy REP = site.ArrayOfOBIS.DataObjects.ReactiveEnergyP; if (!string.IsNullOrEmpty(site.ArrayOfOBIS.DataObjects.ReactiveEnergyM)) //minus = supplied energy REM = site.ArrayOfOBIS.DataObjects.ReactiveEnergyM; GXDLMSObject aepObj = objects.FindByLN(ObjectType.Register, AEP); if (aepObj == null) throw new System.InvalidOperationException(string.Format("Error: Active Energy Positive Object not defined for site {0}.", site.Name)); GXDLMSObject aemObj = objects.FindByLN(ObjectType.Register, AEM); if (aemObj == null) throw new System.InvalidOperationException(string.Format("Active Energy Negative Object not defined for site {0}.", site.Name)); GXDLMSObject repObj = objects.FindByLN(ObjectType.Register, REP); if (repObj == null) throw new System.InvalidOperationException(string.Format("Reactive Energy Positive Object not defined for site {0}.", site.Name)); GXDLMSObject remObj = objects.FindByLN(ObjectType.Register, REM); if (remObj == null) throw new System.InvalidOperationException(string.Format("Reactive Energy Negative Object not defined for site {0}.", site.Name)); Regex regex = new Regex(@"^Scaler:(.*) Unit:(.*)$"); double scaler = 1; object value = comm.Read(aepObj, 2); string scalerAttr = (string)comm.Read(aepObj, 3); Match match = regex.Match(scalerAttr); if (match.Groups.Count >= 2) scaler = double.Parse(match.Groups[1].Value); double ActiveEnergyP = double.Parse(value.ToString()) * scaler; TraceLine(logFile, "Positive Active Energy reading completed."); value = comm.Read(aemObj, 2); scalerAttr = (string)comm.Read(aemObj, 3); match = regex.Match(scalerAttr); if (match.Groups.Count >= 2) scaler = double.Parse(match.Groups[1].Value); double ActiveEnergyM = double.Parse(value.ToString()) * scaler; TraceLine(logFile, "Negative Active Energy reading completed."); value = comm.Read(repObj, 2); scalerAttr = (string)comm.Read(repObj, 3); match = regex.Match(scalerAttr); if (match.Groups.Count >= 2) scaler = double.Parse(match.Groups[1].Value); double ReactiveEnergyP = double.Parse(value.ToString()) * scaler; TraceLine(logFile, "Positive Reactive Energy reading completed."); value = comm.Read(remObj, 2); scalerAttr = (string)comm.Read(remObj, 3); match = regex.Match(scalerAttr); if (match.Groups.Count >= 2) scaler = double.Parse(match.Groups[1].Value); double ReactiveEnergyM = double.Parse(value.ToString()) * scaler; TraceLine(logFile, "Negative Reactive Energy reading completed."); // end of remote meter reading if (site.DataProcessing.ActiveEnergyPStart == 0) site.DataProcessing.ActiveEnergyPStart = ActiveEnergyP; site.DataProcessing.ActiveEnergyPCurrent = ActiveEnergyP; if (site.DataProcessing.ActiveEnergyMStart == 0) site.DataProcessing.ActiveEnergyMStart = ActiveEnergyM; site.DataProcessing.ActiveEnergyMCurrent = ActiveEnergyM; if (site.DataProcessing.ReactiveEnergyPStart == 0) site.DataProcessing.ReactiveEnergyPStart = ReactiveEnergyP; site.DataProcessing.ReactiveEnergyPCurrent = ReactiveEnergyP; if (site.DataProcessing.ReactiveEnergyMStart == 0) site.DataProcessing.ReactiveEnergyMStart = ReactiveEnergyM; site.DataProcessing.ReactiveEnergyMCurrent = ReactiveEnergyM; DateTime tStart = new DateTime(site.DataProcessing.EnergyPeriodDateTime.Year, site.DataProcessing.EnergyPeriodDateTime.Month, site.DataProcessing.EnergyPeriodDateTime.Day, site.DataProcessing.EnergyPeriodDateTime.Hour, site.DataProcessing.EnergyPeriodDateTime.Minute / EPeriod * EPeriod, 0); TimeSpan ts = now.Subtract(tStart); if (EPeriod > 0) // if energy recording enabled { if (((ts.Hours * 60) + ts.Minutes) >= EPeriod) // if end of period { ts = now.Subtract(site.DataProcessing.EnergyPeriodDateTime); double ratio = (double)((ts.Hours * 3600) + (ts.Minutes * 60) + ts.Seconds) / (EPeriod * 60); if (ratio > 0.9) ratio = 1; ratio = Math.Round(ratio, 2); TraceLine(logFile, string.Format("End of integration energy period (ratio = {0})", ratio)); double deltaActiveEnergyP = site.DataProcessing.ActiveEnergyPCurrent - site.DataProcessing.ActiveEnergyPStart; double deltaActiveEnergyM = site.DataProcessing.ActiveEnergyMCurrent - site.DataProcessing.ActiveEnergyMStart; double deltaReactiveEnergyP = site.DataProcessing.ReactiveEnergyPCurrent - site.DataProcessing.ReactiveEnergyPStart; double deltaReactiveEnergyM = site.DataProcessing.ReactiveEnergyMCurrent - site.DataProcessing.ReactiveEnergyMStart; if (deltaActiveEnergyP > deltaActiveEnergyM) // quadrants prevalent: I or IV { PublishEnergy(site, nowRnd, deltaActiveEnergyP, deltaActiveEnergyM, deltaReactiveEnergyP, 0, 0, deltaReactiveEnergyM, ratio, logFile); } else // quadrants prevalent: II or III { PublishEnergy(site, nowRnd, deltaActiveEnergyP, deltaActiveEnergyM, 0, deltaReactiveEnergyP, deltaReactiveEnergyM, 0, ratio, logFile); } site.DataProcessing.EnergyPeriodDateTime = now; site.DataProcessing.ActiveEnergyPStart = ActiveEnergyP; site.DataProcessing.ActiveEnergyMStart = ActiveEnergyM; site.DataProcessing.ReactiveEnergyPStart = ReactiveEnergyP; site.DataProcessing.ReactiveEnergyMStart = ReactiveEnergyM; } } if (site.DataProcessing.ActivePowerPStart == 0) site.DataProcessing.ActivePowerPStart = ActiveEnergyP; site.DataProcessing.ActivePowerPCurrent = ActiveEnergyP; if (site.DataProcessing.ActivePowerMStart == 0) site.DataProcessing.ActivePowerMStart = ActiveEnergyM; site.DataProcessing.ActivePowerMCurrent = ActiveEnergyM; if (site.DataProcessing.ReactivePowerPStart == 0) site.DataProcessing.ReactivePowerPStart = ReactiveEnergyP; site.DataProcessing.ReactivePowerPCurrent = ReactiveEnergyP; if (site.DataProcessing.ReactivePowerMStart == 0) site.DataProcessing.ReactivePowerMStart = ReactiveEnergyM; site.DataProcessing.ReactivePowerMCurrent = ReactiveEnergyM; tStart = new DateTime(site.DataProcessing.PowerPeriodDateTime.Year, site.DataProcessing.PowerPeriodDateTime.Month, site.DataProcessing.PowerPeriodDateTime.Day, site.DataProcessing.PowerPeriodDateTime.Hour, site.DataProcessing.PowerPeriodDateTime.Minute / PPeriod * PPeriod, 0); ts = now.Subtract(tStart); if (PPeriod > 0) // if power recording enabled { if (((ts.Hours * 60) + ts.Minutes) >= PPeriod) // if end of period { ts = now.Subtract(site.DataProcessing.PowerPeriodDateTime); double ratio = (double)((ts.Hours * 3600) + (ts.Minutes * 60) + ts.Seconds) / (PPeriod * 60); if (ratio > 0.9) ratio = 1; ratio = Math.Round(ratio, 2); TraceLine(logFile, string.Format("End of integration power period (ratio = {0})", ratio)); double deltaActivePowerP = (site.DataProcessing.ActivePowerPCurrent - site.DataProcessing.ActivePowerPStart) / PPeriod * 60; double deltaActivePowerM = (site.DataProcessing.ActivePowerMCurrent - site.DataProcessing.ActivePowerMStart) / PPeriod * 60; double deltaReactivePowerP = (site.DataProcessing.ReactivePowerPCurrent - site.DataProcessing.ReactivePowerPStart) / PPeriod * 60; double deltaReactivePowerM = (site.DataProcessing.ReactivePowerMCurrent - site.DataProcessing.ReactivePowerMStart) / PPeriod * 60; // since ZXF meter has no capability to supply Q1-Q4 (but only 2 quadrants), we calculate Q1, Q2, Q3, Q4 here if (deltaActivePowerP > deltaActivePowerM) // quadrants prevalent: I or IV { PublishPower(site, nowRnd, deltaActivePowerP, deltaActivePowerM, deltaReactivePowerP, 0, 0, deltaReactivePowerM, ratio, logFile); } else // quadrants prevalent: II or III { PublishPower(site, nowRnd, deltaActivePowerP, deltaActivePowerM, 0, deltaReactivePowerP, deltaReactivePowerM, 0, ratio, logFile); } // site.DataProcessing.PowerPeriodDateTime = now; site.DataProcessing.ActivePowerPStart = ActiveEnergyP; site.DataProcessing.ActivePowerMStart = ActiveEnergyM; site.DataProcessing.ReactivePowerPStart = ReactiveEnergyP; site.DataProcessing.ReactivePowerMStart = ReactiveEnergyM; } } } catch (Exception ex) { TraceLine(logFile, "Error. " + ex.Message); if (comm != null) { comm.Close(); } continue; } #if ZERO foreach (GXDLMSObject it in objects) { if (!string.IsNullOrEmpty(site.ArrayOfOBIS.DataObjects.ActiveEnergyP)) // if is requested the ActiveEnergy+ obis code { if (it.LogicalName == AEP) { try { object value = comm.Read(it, 2); string scalerAttr = (string)comm.Read(it, 3); Regex regex = new Regex(@"^Scaler:(.*) Unit:(.*)$"); Match match = regex.Match(scalerAttr); double scaler = 1; if (match.Groups.Count >= 2) scaler = double.Parse(match.Groups[1].Value); double Energy = double.Parse(value.ToString()) * scaler; // First time initialize the value of initial energy if (site.DataProcessing.ActiveEnergyPStart == 0) { site.DataProcessing.ActiveEnergyPStart = Energy; TraceLine(logFile, "Initial ActiveEnergy+ : " + Energy + " Wh"); } } catch (Exception ex) { TraceLine(logFile, "Error. Failed to get ActiveEnergy+: " + ex.Message); //Continue reading. } } } // Read meter inst. values if (!string.IsNullOrEmpty(site.ArrayOfOBIS.DataObjects.ActivePower)) { try { if (it.LogicalName == site.ArrayOfOBIS.DataObjects.ActivePower) { //Console.WriteLine(it.Name); object value = comm.Read(it, 2); string scalerAttr = (string)comm.Read(it, 3); Regex regex = new Regex(@"^Scaler:(.*) Unit:(.*)$"); Match match = regex.Match(scalerAttr); double scaler = 1; if (match.Groups.Count >= 2) scaler = double.Parse(match.Groups[1].Value); double activePower = double.Parse(value.ToString()) * scaler; TraceLine(logFile, "Active Power: " + activePower + " W"); int period = 15; if (site.DataProcessing.Period != 0) { period = site.DataProcessing.Period; } DateTime now = DateTime.Now; DateTime nowRnd = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute / period * period, 0); if (site.DataProcessing.IntervalDateTime.Ticks == 0) { site.DataProcessing.IntervalDateTime = nowRnd; site.DataProcessing.Count = 0; site.DataProcessing.Sum = 0; TraceLine(logFile, "Initialize period from null."); } else { long elapsedTicks = now.Ticks - site.DataProcessing.IntervalDateTime.Ticks; TimeSpan elapsedSpan = new TimeSpan(elapsedTicks); if (elapsedSpan.TotalMinutes >= period) // if end of period { // Round date to minute multiple of "period" if (site.DataProcessing.Count > 0) // compute avg quantities { TraceLine(logFile, "End of inst. readings integration period."); double avgActivePower = site.DataProcessing.Sum / site.DataProcessing.Count; site.DataProcessing.IntervalDateTime = nowRnd; site.DataProcessing.Count = 0; site.DataProcessing.Sum = 0; // PublishReading(site, site.DataProcessing.IntervalDateTime.AddMinutes(period), avgActivePower, logFile); PublishReading(site, site.DataProcessing.IntervalDateTime, avgActivePower, 0, 0, 0, 0, 0, logFile); } else { TraceLine(logFile, "Zero counts period: initialize only."); site.DataProcessing.IntervalDateTime = nowRnd; site.DataProcessing.Count = 0; site.DataProcessing.Sum = 0; } } site.DataProcessing.Sum += activePower; site.DataProcessing.Count++; } } } catch (Exception ex) { TraceLine(logFile, "Error. Failed to get inst. readings: " + ex.Message); //Continue reading. } } // Read load profiles if (string.IsNullOrEmpty(site.ArrayOfOBIS.GenericProfileObjects.LoadProfile)) continue; if (it.LogicalName == site.ArrayOfOBIS.GenericProfileObjects.LoadProfile) { //Console.WriteLine(it.Name); try { int period = 15; if (site.DataProcessing.ProfilePeriod != 0) { period = site.DataProcessing.ProfilePeriod; } DateTime now = DateTime.Now; DateTime nowRnd = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute / period * period, 0); long elapsedTicks = now.Ticks - site.DataProcessing.ProfileDateTime.Ticks; TimeSpan elapsedSpan = new TimeSpan(elapsedTicks); double totalMinutes = elapsedSpan.TotalMinutes; int maxDays = 1; if (totalMinutes > 1440 * maxDays) { // max one week totalMinutes = 1440 * maxDays; site.DataProcessing.ProfileDateTime = nowRnd.AddMinutes(-totalMinutes); } if (totalMinutes >= period) // if end of period { //Read from Profile Generic. object[] rows = comm.ReadRowsByRange(it, site.DataProcessing.ProfileDateTime, nowRnd, (it as GXDLMSProfileGeneric).CaptureObjects); StringBuilder sb = new StringBuilder(); foreach (object[] row in rows) { object dto = row[0]; DateTime dt; if (DateTime.TryParse(dto.ToString(), out dt)) { dt = dt.ToLocalTime(); row[0] = dt; } foreach (object cell in row) { if (cell is byte[]) { sb.Append(GXCommon.ToHex((byte[])cell, true)); } else { sb.Append(Convert.ToString(cell)); } sb.Append(" | "); } sb.Append("\r\n"); } site.DataProcessing.ProfileDateTime = nowRnd; PublishProfile(site, site.DataProcessing.ProfileDateTime, sb, logFile); } } catch (Exception ex) { TraceLine(logFile, "Error. Failed to get load profile: " + ex.Message); //Continue reading. } } } #endif try { using (Stream stream = File.Open(sitesMapPath, FileMode.Create)) { TraceLine(logFile, "Save site map to file."); TextWriter writer = new StreamWriter(stream); y.Serialize(writer, aods); // aods = y.Deserialize(stream) as IAM.ArrayOfDLMSSite; stream.Close(); infoFileSite.Refresh(); lastWriteMapFile = infoFileSite.LastWriteTime; } } catch (Exception ex) { throw ex; } TraceLine(logFile, "Disconnecting from the meter."); comm.Close(); objects.Clear(); } } catch (Exception ex) { TraceLine(logFile, ex.Message); if (comm != null) { comm.Close(); } // Continue reading } logFile.Flush(); if (loopTime > 0) // wait until next loop time { DateTime when = DateTime.Now; int nextMinutes = (when.Minute / loopTime) * loopTime + loopTime; DateTime nextTime = new DateTime(when.Year, when.Month, when.Day); nextTime = nextTime.AddHours(when.Hour); nextTime = nextTime.AddMinutes(nextMinutes); int waitSeconds = (int)(new TimeSpan(nextTime.Ticks - when.Ticks).TotalSeconds); waitSeconds++; TraceLine(logFile, "Waiting for next loop (in "+waitSeconds+" sec.)...\r\n"); logFile.Flush(); do { Thread.Sleep(1000); waitSeconds--; //if (Environment.UserInteractive) // keyAvailable = Console.KeyAvailable; } while ((waitSeconds > 0) && !keyAvailable && running); } Console.WriteLine(""); //if (Environment.UserInteractive) // keyAvailable = Console.KeyAvailable; } while (!keyAvailable && (loopTime != -1) && running); if (keyAvailable) { TraceLine(logFile, "Program interrupted by user."); } else if (!running) { TraceLine(logFile, "Service stopped."); } else { TraceLine(logFile, "Single run ended."); if (!Environment.UserInteractive) { logFile.Flush(); logFile.Close(); Environment.Exit(0); } } } catch (Exception ex) { if (logFile != null) TraceLine(logFile, ex.Message); if (comm != null) { comm.Close(); } Console.WriteLine("Error. " + ex.Message); } finally { logFile.Flush(); logFile.Close(); if (comm != null) { comm.Close(); } Console.WriteLine("Now stop."); } }
/// <summary> /// Ask Server sends the Certificate Signing Request (CSR) data. /// </summary> /// <param name="client">DLMS client that is used to generate action.</param> /// <param name="type">identifies the key pair for which the certificate will be requested.</param> /// <returns>Generated action.</returns> public byte[][] GenerateCertificate(GXDLMSClient client, CertificateType type) { return client.Method(this, 5, type, DataType.Enum); }
/// <summary> /// Presets the time to a new value (preset_time) and defines a validity_interval within which the new time can be activated. /// </summary> /// <param name="presetTime"></param> /// <param name="validityIntervalStart"></param> /// <param name="validityIntervalEnd"></param> /// <returns></returns> public byte[][] PresetAdjustingTime(GXDLMSClient client, DateTime presetTime, DateTime validityIntervalStart, DateTime validityIntervalEnd) { GXByteBuffer buff = new GXByteBuffer(); buff.Add((byte)DataType.Structure); buff.Add((byte)3); GXCommon.SetData(client.Settings, buff, DataType.OctetString, presetTime); GXCommon.SetData(client.Settings, buff, DataType.OctetString, validityIntervalStart); GXCommon.SetData(client.Settings, buff, DataType.OctetString, validityIntervalEnd); return client.Method(this, 5, buff.Array(), DataType.Array); }
/// <summary> /// Imports an X.509 v3 certificate of a public key. /// </summary> /// <param name="client">DLMS client that is used to generate action.</param> /// <param name="key">Public key.</param> /// <returns>Generated action.</returns> public byte[][] ImportCertificate(GXDLMSClient client, byte[] key) { return client.Method(this, 6, key, DataType.OctetString); }
/// <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); }
/// <summary> /// Sets the meter’s time to the nearest (+/-) quarter of an hour value (*:00, *:15, *:30, *:45). /// </summary> /// <returns></returns> public byte[][] AdjustToQuarter(GXDLMSClient client) { return client.Method(this, 1, 0, DataType.Int8); }
/// <summary> /// Sets the meter’s time to the nearest (+/-) starting point of a measuring period. /// </summary> /// <returns></returns> public byte[][] AdjustToMeasuringPeriod(GXDLMSClient client) { return client.Method(this, 2, 0, DataType.Int8); }
/// <summary> /// Sets the meter’s time to the nearest minute. /// If second_counter < 30 s, so second_counter is set to 0. /// If second_counter ³ 30 s, so second_counter is set to 0, and /// minute_counter and all depending clock values are incremented if necessary. /// </summary> /// <returns></returns> public byte[][] AdjustToMinute(GXDLMSClient client) { return client.Method(this, 3, 0, DataType.Int8); }
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) { List<byte> data = new List<byte>(); data.Add((byte)DataType.Structure); data.Add((byte)2); GXCommon.SetData(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(data, DataType.OctetString, tmp); packets.AddRange(client.Method(this, 2, data.ToArray(), DataType.Array)); } return packets.ToArray(); }
/// <summary> /// This Method is used in conjunction with the preset_adjusting_time /// Method. If the meter’s time lies between validity_interval_start and /// validity_interval_end, then time is set to preset_time. /// </summary> /// <returns></returns> public byte[][] AdjustToPresetTime(GXDLMSClient client) { return client.Method(this, 4, 0, DataType.Int8); }
public byte[][] ImageActivate(GXDLMSClient client) { return client.Method(this, 4, 0, DataType.Int8); }
/// <summary> /// Presets the time to a new value (preset_time) and defines a validity_interval within which the new time can be activated. /// </summary> /// <param name="presetTime"></param> /// <param name="validityIntervalStart"></param> /// <param name="validityIntervalEnd"></param> /// <returns></returns> public byte[][] PresetAdjustingTime(GXDLMSClient client, DateTime presetTime, DateTime validityIntervalStart, DateTime validityIntervalEnd) { List<byte> buff = new List<byte>(); buff.Add((byte)DataType.Structure); buff.Add((byte)3); GXCommon.SetData(buff, DataType.DateTime, presetTime); GXCommon.SetData(buff, DataType.DateTime, validityIntervalStart); GXCommon.SetData(buff, DataType.DateTime, validityIntervalEnd); return client.Method(this, 5, buff.ToArray(), DataType.Array); }
/// <summary> /// Reset value. /// </summary> /// <returns></returns> public byte[][] Reset(GXDLMSClient client) { return client.Method(this, 1, (int)0); }
/// <summary> /// Activates the push process. /// </summary> /// <returns></returns> public byte[][] Activate(GXDLMSClient client) { return client.Method(this, 1, (byte)0); }