public ActionResult <GetNextTaskResponse> Post(GetNextTask request) { GetNextTaskResponse ret = new GetNextTaskResponse(); lock (host) { GXSelectArgs arg = GXSelectArgs.Select <GXTask>(c => c.Id, q => q.Start == DateTime.MinValue); arg.Joins.AddInnerJoin <GXTask, GXObject>(a => a.Object, b => b.Id); arg.Joins.AddInnerJoin <GXObject, GXDevice>(a => a.DeviceId, b => b.Id); //Don't get meters that are mapped to other readers. arg.Joins.AddLeftJoin <GXDevice, GXDeviceToReader>(a => a.Id, b => b.DeviceId); if (request.DeviceId != 0) { arg.Where.And <GXDevice>(q => q.Id == request.DeviceId); } if (!request.Listener) { arg.Where.And <GXDevice>(q => q.Dynamic == false); } arg.OrderBy.Add <GXTask>(q => q.Id); GXSelectArgs onProgress = GXSelectArgs.Select <GXObject>(c => c.DeviceId, q => q.Removed == DateTime.MinValue); onProgress.Joins.AddInnerJoin <GXTask, GXObject>(a => a.Object, b => b.Id); onProgress.Where.And <GXTask>(q => q.Start != DateTime.MinValue && q.End == DateTime.MinValue); arg.Where.And <GXObject>(q => !GXSql.Exists <GXObject, GXDevice>(a => a.DeviceId, b => b.Id, onProgress)); GXTask task = host.Connection.SingleOrDefault <GXTask>(arg); if (task != null) { //Get task device ID and creation time. arg = GXSelectArgs.SelectAll <GXTask>(q => q.Id == task.Id); arg.Columns.Add <GXObject>(); arg.Joins.AddInnerJoin <GXTask, GXObject>(a => a.Object, b => b.Id); arg.Joins.AddInnerJoin <GXObject, GXDevice>(a => a.DeviceId, b => b.Id); task = host.Connection.SingleOrDefault <GXTask>(arg); //Get all tasks that are created at the same time for same meter. arg = GXSelectArgs.SelectAll <GXTask>(q => q.Generation == task.Generation); arg.Where.And <GXDevice>(q => q.Id == task.Object.DeviceId); arg.Where.And <GXObject>(q => q.Removed == DateTime.MinValue); arg.Columns.Add <GXObject>(); arg.Columns.Add <GXDevice>(); arg.Columns.Add <GXAttribute>(); arg.Joins.AddInnerJoin <GXTask, GXObject>(a => a.Object, b => b.Id); arg.Joins.AddInnerJoin <GXObject, GXDevice>(a => a.DeviceId, b => b.Id); arg.Joins.AddInnerJoin <GXObject, GXAttribute>(a => a.Id, b => b.ObjectId); ret.Tasks = host.Connection.Select <GXTask>(arg).ToArray(); DateTime now = DateTime.Now; foreach (GXTask it in ret.Tasks) { it.Start = now; host.Connection.Update(GXUpdateArgs.Update(it, q => q.Start)); } host.SetChange(TargetType.Tasks, DateTime.Now); } } return(ret); }
private async void DoWork(object ínfo) { //Give some time DB server to start up. Thread.Sleep(1000); GetNextTaskResponse ret = null; System.Net.Http.HttpResponseMessage response; //Don't wait reply. It might that DB server is not up yet. if (ínfo != null) { using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/reader/AddReader", new AddReader() { Reader = ínfo as GXReaderInfo })) { Helpers.CheckStatus(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; GXDLMSReader reader; //Read frame counter from the meter. if (dev.Security != 0) { cl = new GXDLMSSecureClient(dev.UseLogicalNameReferencing, 16, dev.PhysicalAddress, Authentication.None, null, (InterfaceType)dev.InterfaceType); reader = new GXDLMSReader(cl, media, _logger); 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, dev.PhysicalAddress, (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 = (Security)dev.Security; reader = new GXDLMSReader(cl, media, _logger); 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.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, media, 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 ex) { 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); } } }