private async void DoWork() { //Give some time DB server to start up. Thread.Sleep(1000); GetNextTaskResponse ret = null; System.Net.Http.HttpResponseMessage response; _logger.LogInformation("Reader Service is started."); while (!_cancellationToken.IsCancellationRequested) { try { using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/GetNextTask", new GetNextTask())) { Helpers.CheckStatus(response); ret = await response.Content.ReadAsAsync <GetNextTaskResponse>(); } if (ret.Tasks != null) { int pos = 0; GXDevice dev; GXDLMSSecureClient cl; using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/device/ListDevices", new ListDevices() { Ids = new[] { ret.Tasks[0].Object.DeviceId } })) { Helpers.CheckStatus(response); ListDevicesResponse r = await response.Content.ReadAsAsync <ListDevicesResponse>(); if (r.Devices == null || r.Devices.Length == 0) { continue; } dev = r.Devices[0]; } IGXMedia media; if (string.Compare(dev.MediaType, typeof(GXNet).FullName, true) == 0) { media = new GXNet(); } else if (string.Compare(dev.MediaType, typeof(GXSerial).FullName, true) == 0) { media = new GXSerial(); } else if (string.Compare(dev.MediaType, typeof(GXTerminal).FullName, true) == 0) { media = new GXTerminal(); } else { Type type = Type.GetType(dev.MediaType); if (type == null) { string ns = ""; pos = dev.MediaType.LastIndexOf('.'); if (pos != -1) { ns = dev.MediaType.Substring(0, pos); } foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (assembly.GetName().Name == ns) { if (assembly.GetType(dev.MediaType, false, true) != null) { type = assembly.GetType(dev.MediaType); } } } } if (type == null) { throw new Exception("Invalid media type: " + dev.MediaType); } media = (IGXMedia)Activator.CreateInstance(type); } if (media == null) { throw new Exception("Unknown media type '" + dev.MediaType + "'."); } media.Settings = dev.MediaSettings; int deviceAddress; if (dev.HDLCAddressing == ManufacturerSettings.HDLCAddressType.SerialNumber) { deviceAddress = GXDLMSClient.GetServerAddressFromSerialNumber(dev.PhysicalAddress, dev.LogicalAddress); } else { if (dev.LogicalAddress != 0 && (dev.InterfaceType == InterfaceType.HDLC || dev.InterfaceType == InterfaceType.HdlcWithModeE)) { deviceAddress = GXDLMSClient.GetServerAddress(dev.LogicalAddress, dev.PhysicalAddress); } else { deviceAddress = dev.PhysicalAddress; } } TraceLevel trace = _traceLevel; if (dev.TraceLevel > trace) { trace = dev.TraceLevel; } UInt64 devId = 0; if (dev.TraceLevel != TraceLevel.Off) { devId = dev.Id; } GXDLMSReader reader; //Read frame counter from the meter. if (dev.Security != 0) { cl = new GXDLMSSecureClient(dev.UseLogicalNameReferencing, 16, deviceAddress, Authentication.None, null, (InterfaceType)dev.InterfaceType); reader = new GXDLMSReader(cl, media, _logger, trace, dev.WaitTime, dev.ResendCount, devId); media.Open(); reader.InitializeConnection(); //Read Innovation counter. GXDLMSData d = new GXDLMSData(dev.FrameCounter); reader.Read(d, 2); dev.InvocationCounter = 1 + Convert.ToUInt32(d.Value); reader.Disconnect(); media.Close(); } cl = new GXDLMSSecureClient(dev.UseLogicalNameReferencing, dev.ClientAddress, deviceAddress, (Authentication)dev.Authentication, dev.Password, (InterfaceType)dev.InterfaceType); if (dev.HexPassword != null && dev.HexPassword.Length != 0) { cl.Password = dev.HexPassword; } cl.UseUtc2NormalTime = dev.UtcTimeZone; cl.Standard = dev.Standard; cl.Ciphering.SystemTitle = GXCommon.HexToBytes(dev.ClientSystemTitle); if (cl.Ciphering.SystemTitle != null && cl.Ciphering.SystemTitle.Length == 0) { cl.Ciphering.SystemTitle = null; } cl.Ciphering.BlockCipherKey = GXCommon.HexToBytes(dev.BlockCipherKey); if (cl.Ciphering.BlockCipherKey != null && cl.Ciphering.BlockCipherKey.Length == 0) { cl.Ciphering.BlockCipherKey = null; } cl.Ciphering.AuthenticationKey = GXCommon.HexToBytes(dev.AuthenticationKey); if (cl.Ciphering.AuthenticationKey != null && cl.Ciphering.AuthenticationKey.Length == 0) { cl.Ciphering.AuthenticationKey = null; } cl.ServerSystemTitle = GXCommon.HexToBytes(dev.DeviceSystemTitle); if (cl.ServerSystemTitle != null && cl.ServerSystemTitle.Length == 0) { cl.ServerSystemTitle = null; } cl.Ciphering.InvocationCounter = dev.InvocationCounter; cl.Ciphering.Security = dev.Security; reader = new GXDLMSReader(cl, media, _logger, trace, dev.WaitTime, dev.ResendCount, devId); media.Open(); reader.InitializeConnection(); pos = 0; int count = ret.Tasks.Length; foreach (GXTask task in ret.Tasks) { ++pos; try { GXDLMSObject obj = GXDLMSClient.CreateObject((ObjectType)task.Object.ObjectType); obj.Version = task.Object.Version; obj.LogicalName = task.Object.LogicalName; obj.ShortName = task.Object.ShortName; if (task.TaskType == TaskType.Write) { if (obj.LogicalName == "0.0.1.1.0.255" && task.Index == 2) { cl.UpdateValue(obj, task.Index, GXDateTime.ToUnixTime(DateTime.UtcNow)); } else { cl.UpdateValue(obj, task.Index, GXDLMSTranslator.XmlToValue(task.Data)); } reader.Write(obj, task.Index); } else if (task.TaskType == TaskType.Action) { reader.Method(obj, task.Index, GXDLMSTranslator.XmlToValue(task.Data), DataType.None); } else if (task.TaskType == TaskType.Read) { //Reading the meter. if (task.Object.Attributes[0].DataType != 0) { obj.SetDataType(task.Index, (DataType)task.Object.Attributes[0].DataType); } if (task.Object.Attributes[0].UIDataType != 0) { obj.SetUIDataType(task.Index, (DataType)task.Object.Attributes[0].UIDataType); } Reader.Read(_logger, client, reader, task, obj); if (task.Object.Attributes[0].DataType == 0) { task.Object.Attributes[0].DataType = (int)obj.GetDataType(task.Index); if (task.Object.Attributes[0].UIDataType == 0) { task.Object.Attributes[0].UIDataType = (int)obj.GetUIDataType(task.Index); } UpdateDatatype u = new UpdateDatatype() { Items = new GXAttribute[] { task.Object.Attributes[0] } }; response = client.PostAsJsonAsync(Startup.ServerAddress + "/api/Object/UpdateDatatype", u).Result; Helpers.CheckStatus(response); } } } catch (Exception ex) { task.Result = ex.Message; AddError error = new AddError(); error.Error = new GXError() { DeviceId = dev.Id, Error = "Failed to " + task.TaskType + " " + task.Object.LogicalName + ":" + task.Index + ". " + ex.Message }; _logger.LogError(error.Error.Error); using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error)) { Helpers.CheckStatus(response); await response.Content.ReadAsAsync <AddErrorResponse>(); } } task.End = DateTime.Now; //Close connection after last task is executed. //This must done because there might be new task to execute. if (count == pos) { try { reader.Close(); } catch (Exception ex) { task.Result = ex.Message; AddError error = new AddError(); error.Error = new GXError() { DeviceId = dev.Id, Error = "Failed to close the connection. " + ex.Message }; _logger.LogError(error.Error.Error); using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error)) { Helpers.CheckStatus(response); await response.Content.ReadAsAsync <AddErrorResponse>(); } } } //Update execution time. response = client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/TaskReady", new TaskReady() { Tasks = new GXTask[] { task } }).Result; Helpers.CheckStatus(response); } } else { try { using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/WaitChange", new WaitChange() { Change = TargetType.Tasks, Time = lastUpdated, WaitTime = _waitTime })) { Helpers.CheckStatus(response); { WaitChangeResponse r = await response.Content.ReadAsAsync <WaitChangeResponse>(); if (r.Time > lastUpdated) { lastUpdated = r.Time; } } } } catch (Exception) { if (!_cancellationToken.IsCancellationRequested) { break; } _cancellationToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(10)); } } } catch (Exception ex) { //If app is closing. if (_cancellationToken.IsCancellationRequested) { break; } if (ret == null) { _logger.LogError("Failed to connect to the DB server."); } else { AddError error = new AddError(); error.Error = new GXError() { DeviceId = ret.Tasks[0].Object.DeviceId, Error = "Failed to " + ret.Tasks[0].TaskType + " " + ret.Tasks[0].Object.LogicalName + ":" + ret.Tasks[0].Index + ". " + ex.Message }; using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error)) { if (ret.Tasks != null) { DateTime now = DateTime.Now; foreach (GXTask it in ret.Tasks) { it.Result = ex.Message; it.End = now; } response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/TaskReady", new TaskReady() { Tasks = ret.Tasks }); } } } _logger.LogError(ex.Message); } } }
public static int GetParameters(string[] args, Settings settings) { GXSerial serial; //Has user give the custom serial port settings or are the default values used in mode E. bool modeEDefaultValues = true; string[] tmp; List <GXCmdParameter> parameters = GXCommon.GetParameters(args, "h:p:c:s:r:i:It:a:P:g:S:C:n:v:o:T:A:B:D:d:l:F:m:"); GXNet net = null; foreach (GXCmdParameter it in parameters) { switch (it.Tag) { case 'r': if (string.Compare(it.Value, "sn", true) == 0) { settings.client.UseLogicalNameReferencing = false; } else if (string.Compare(it.Value, "ln", true) == 0) { settings.client.UseLogicalNameReferencing = true; } else { throw new ArgumentException("Invalid reference option."); } break; case 'h': //Host address. if (settings.media == null) { settings.media = new GXNet(); } net = settings.media as GXNet; net.HostName = it.Value; break; case 't': //Trace. try { settings.trace = (TraceLevel)Enum.Parse(typeof(TraceLevel), it.Value); } catch (Exception) { throw new ArgumentException("Invalid trace level option. (Error, Warning, Info, Verbose, Off)"); } break; case 'p': //Port. if (settings.media == null) { settings.media = new GXNet(); } net = settings.media as GXNet; net.Port = int.Parse(it.Value); break; case 'P': //Password settings.client.Password = ASCIIEncoding.ASCII.GetBytes(it.Value); break; case 'i': try { settings.client.InterfaceType = (InterfaceType)Enum.Parse(typeof(InterfaceType), it.Value); settings.client.Plc.Reset(); if (modeEDefaultValues && settings.client.InterfaceType == InterfaceType.HdlcWithModeE && settings.media is GXSerial) { serial = settings.media as GXSerial; serial.BaudRate = 300; serial.DataBits = 7; serial.Parity = Parity.Even; serial.StopBits = StopBits.One; } } catch (Exception) { throw new ArgumentException("Invalid interface type option. (HDLC, WRAPPER, HdlcWithModeE, Plc, PlcHdlc)"); } break; case 'I': //AutoIncreaseInvokeID. settings.client.AutoIncreaseInvokeID = true; break; case 'v': settings.invocationCounter = it.Value.Trim(); Objects.GXDLMSObject.ValidateLogicalName(settings.invocationCounter); break; case 'g': //Get (read) selected objects. foreach (string o in it.Value.Split(new char[] { ';', ',' })) { tmp = o.Split(new char[] { ':' }); if (tmp.Length != 2) { throw new ArgumentOutOfRangeException("Invalid Logical name or attribute index."); } settings.readObjects.Add(new KeyValuePair <string, int>(tmp[0].Trim(), int.Parse(tmp[1].Trim()))); } break; case 'S': //Serial Port settings.media = new GXSerial(); serial = settings.media as GXSerial; tmp = it.Value.Split(':'); serial.PortName = tmp[0]; if (tmp.Length > 1) { modeEDefaultValues = false; serial.BaudRate = int.Parse(tmp[1]); serial.DataBits = int.Parse(tmp[2].Substring(0, 1)); serial.Parity = (Parity)Enum.Parse(typeof(Parity), tmp[2].Substring(1, tmp[2].Length - 2)); serial.StopBits = (StopBits)int.Parse(tmp[2].Substring(tmp[2].Length - 1, 1)); } else { if (settings.client.InterfaceType == InterfaceType.HdlcWithModeE) { serial.BaudRate = 300; serial.DataBits = 7; serial.Parity = Parity.Even; serial.StopBits = StopBits.One; } else { serial.BaudRate = 9600; serial.DataBits = 8; serial.Parity = Parity.None; serial.StopBits = StopBits.One; } } break; case 'a': try { if (string.Compare("None", it.Value, true) == 0) { settings.client.Authentication = Authentication.None; } else if (string.Compare("Low", it.Value, true) == 0) { settings.client.Authentication = Authentication.Low; } else if (string.Compare("High", it.Value, true) == 0) { settings.client.Authentication = Authentication.High; } else if (string.Compare("HighMd5", it.Value, true) == 0) { settings.client.Authentication = Authentication.HighMD5; } else if (string.Compare("HighSha1", it.Value, true) == 0) { settings.client.Authentication = Authentication.HighSHA1; } else if (string.Compare("HighSha256", it.Value, true) == 0) { settings.client.Authentication = Authentication.HighSHA256; } else if (string.Compare("HighGMac", it.Value, true) == 0) { settings.client.Authentication = Authentication.HighGMAC; } else if (string.Compare("HighECDSA", it.Value, true) == 0) { settings.client.Authentication = Authentication.HighECDSA; } else { throw new ArgumentException("Invalid Authentication option: '" + it.Value + "'. (None, Low, High, HighMd5, HighSha1, HighGMac, HighSha256)"); } } catch (Exception) { throw new ArgumentException("Invalid Authentication option: '" + it.Value + "'. (None, Low, High, HighMd5, HighSha1, HighGMac, HighSha256)"); } break; case 'C': try { settings.client.Ciphering.Security = (Security)Enum.Parse(typeof(Security), it.Value); } catch (Exception) { throw new ArgumentException("Invalid Ciphering option '" + it.Value + "'. (None, Authentication, Encryption, AuthenticationEncryption)"); } break; case 'T': settings.client.Ciphering.SystemTitle = GXCommon.HexToBytes(it.Value); break; case 'A': settings.client.Ciphering.AuthenticationKey = GXCommon.HexToBytes(it.Value); break; case 'B': settings.client.Ciphering.BlockCipherKey = GXCommon.HexToBytes(it.Value); break; case 'D': settings.client.Ciphering.DedicatedKey = GXCommon.HexToBytes(it.Value); break; case 'F': settings.client.Ciphering.InvocationCounter = UInt32.Parse(it.Value.Trim()); break; case 'o': settings.outputFile = it.Value; break; case 'd': try { settings.client.Standard = (Standard)Enum.Parse(typeof(Standard), it.Value); if (settings.client.Standard == Standard.Italy || settings.client.Standard == Standard.India || settings.client.Standard == Standard.SaudiArabia) { settings.client.UseUtc2NormalTime = true; } } catch (Exception) { throw new ArgumentException("Invalid DLMS standard option '" + it.Value + "'. (DLMS, India, Italy, SaudiArabia, IDIS)"); } break; case 'c': settings.client.ClientAddress = int.Parse(it.Value); break; case 's': if (settings.client.ServerAddress != 1) { settings.client.ServerAddress = GXDLMSClient.GetServerAddress(settings.client.ServerAddress, int.Parse(it.Value)); } else { settings.client.ServerAddress = int.Parse(it.Value); } break; case 'l': settings.client.ServerAddress = GXDLMSClient.GetServerAddress(int.Parse(it.Value), settings.client.ServerAddress); break; case 'n': settings.client.ServerAddress = GXDLMSClient.GetServerAddressFromSerialNumber(int.Parse(it.Value), 1); break; case 'm': settings.client.Plc.MacDestinationAddress = UInt16.Parse(it.Value); break; case '?': switch (it.Tag) { case 'c': throw new ArgumentException("Missing mandatory client option."); case 's': throw new ArgumentException("Missing mandatory server option."); case 'h': throw new ArgumentException("Missing mandatory host name option."); case 'p': throw new ArgumentException("Missing mandatory port option."); case 'r': throw new ArgumentException("Missing mandatory reference option."); case 'a': throw new ArgumentException("Missing mandatory authentication option."); case 'S': throw new ArgumentException("Missing mandatory Serial port option."); case 't': throw new ArgumentException("Missing mandatory trace option."); case 'g': throw new ArgumentException("Missing mandatory OBIS code option."); case 'C': throw new ArgumentException("Missing mandatory Ciphering option."); case 'v': throw new ArgumentException("Missing mandatory invocation counter logical name option."); case 'T': throw new ArgumentException("Missing mandatory system title option."); case 'A': throw new ArgumentException("Missing mandatory authentication key option."); case 'B': throw new ArgumentException("Missing mandatory block cipher key option."); case 'D': throw new ArgumentException("Missing mandatory dedicated key option."); case 'F': throw new ArgumentException("Missing mandatory frame counter option."); case 'd': throw new ArgumentException("Missing mandatory DLMS standard option."); case 'K': throw new ArgumentException("Missing mandatory private key file option."); case 'k': throw new ArgumentException("Missing mandatory public key file option."); case 'l': throw new ArgumentException("Missing mandatory logical server address option."); case 'm': throw new ArgumentException("Missing mandatory MAC destination address option."); case 'i': throw new ArgumentException("Missing mandatory interface type option."); default: ShowHelp(); return(1); } default: ShowHelp(); return(1); } } if (settings.media == null) { ShowHelp(); return(1); } return(0); }