diff --git a/AsbCloudApp/Data/WellMapInfoDto.cs b/AsbCloudApp/Data/WellMapInfoDto.cs
index 242ecb6c..8b0bdb58 100644
--- a/AsbCloudApp/Data/WellMapInfoDto.cs
+++ b/AsbCloudApp/Data/WellMapInfoDto.cs
@@ -50,6 +50,11 @@ namespace AsbCloudApp.Data
/// 2 - завершена
///
public int IdState { get; set; }
+
+ ///
+ /// Название текущей секции
+ ///
+ public string? Section { get; set; }
///
/// Коэф-т использования автоподачи долота (суммарный ротор + слайд)
@@ -89,6 +94,31 @@ namespace AsbCloudApp.Data
///
public PlanFactDto ROP { get; set; } = null!;
+ ///
+ /// Нагрузка на долота, Т
+ ///
+ public PlanFactDto AxialLoad { get; set; } = null!;
+
+ ///
+ /// Обороты ротора
+ ///
+ public PlanFactDto TopDriveSpeed { get; set; } = null!;
+
+ ///
+ /// Момент ротора кн/м
+ ///
+ public PlanFactDto TopDriveTorque { get; set; } = null!;
+
+ ///
+ /// Перепад давления
+ ///
+ public PlanFactDto Pressure { get; set; } = null!;
+
+ ///
+ /// Действующее задание давления, атм
+ ///
+ public double? PressureSp { get; set; }
+
///
/// Плановая и текущая глубина
///
diff --git a/AsbCloudApp/IntegrationEvents/Interfaces/IIntegrationEvent.cs b/AsbCloudApp/IntegrationEvents/Interfaces/IIntegrationEvent.cs
new file mode 100644
index 00000000..a80dfdee
--- /dev/null
+++ b/AsbCloudApp/IntegrationEvents/Interfaces/IIntegrationEvent.cs
@@ -0,0 +1,6 @@
+namespace AsbCloudApp.IntegrationEvents.Interfaces;
+
+///
+/// Интерфейс маркер для доменных событий
+///
+public interface IIntegrationEvent { }
\ No newline at end of file
diff --git a/AsbCloudApp/IntegrationEvents/Interfaces/IIntegrationEventHandler.cs b/AsbCloudApp/IntegrationEvents/Interfaces/IIntegrationEventHandler.cs
new file mode 100644
index 00000000..18695f07
--- /dev/null
+++ b/AsbCloudApp/IntegrationEvents/Interfaces/IIntegrationEventHandler.cs
@@ -0,0 +1,19 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.IntegrationEvents.Interfaces;
+
+///
+/// Обработчик событий
+///
+///
+public interface IIntegrationEventHandler where T: IIntegrationEvent
+{
+ ///
+ /// Метод обработки события
+ ///
+ ///
+ ///
+ ///
+ Task HandleAsync(T integrationEvent, CancellationToken cancellationToken);
+}
\ No newline at end of file
diff --git a/AsbCloudApp/IntegrationEvents/UpdateWellInfoEvent.cs b/AsbCloudApp/IntegrationEvents/UpdateWellInfoEvent.cs
new file mode 100644
index 00000000..4ae75a19
--- /dev/null
+++ b/AsbCloudApp/IntegrationEvents/UpdateWellInfoEvent.cs
@@ -0,0 +1,9 @@
+using AsbCloudApp.IntegrationEvents.Interfaces;
+
+namespace AsbCloudApp.IntegrationEvents;
+
+///
+/// Обновление показателей бурения
+///
+///
+public record UpdateWellInfoEvent(int IdWell) : IIntegrationEvent;
\ No newline at end of file
diff --git a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs
index 1faa769f..a971116e 100644
--- a/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs
+++ b/AsbCloudInfrastructure/Services/Subsystems/SubsystemOperationTimeService.cs
@@ -230,11 +230,15 @@ namespace AsbCloudInfrastructure.Services.Subsystems
var beginUTC = gtDate.HasValue
? gtDate.Value.ToUtcDateTimeOffset(hoursOffset)
- : DateTime.Today.AddDays(-1).ToUtcDateTimeOffset(hoursOffset);
+ : db.SubsystemOperationTimes.Min(s => s.DateStart)
+ .DateTime
+ .ToUtcDateTimeOffset(hoursOffset);
var endUTC = ltDate.HasValue
? ltDate.Value.ToUtcDateTimeOffset(hoursOffset)
- : DateTime.Today.ToUtcDateTimeOffset(hoursOffset);
+ : db.SubsystemOperationTimes.Max(s => s.DateEnd)
+ .DateTime
+ .ToUtcDateTimeOffset(hoursOffset);
var telemetryIds = wells
.Where(w => w.IdTelemetry is not null)
diff --git a/AsbCloudInfrastructure/Services/WellInfoService.cs b/AsbCloudInfrastructure/Services/WellInfoService.cs
index 7066ef22..efcfd54d 100644
--- a/AsbCloudInfrastructure/Services/WellInfoService.cs
+++ b/AsbCloudInfrastructure/Services/WellInfoService.cs
@@ -6,7 +6,6 @@ using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudApp.Services.Subsystems;
-using AsbCloudDb.Model;
using AsbCloudInfrastructure.Background;
using AsbCloudInfrastructure.Services.SAUB;
using Mapster;
@@ -16,6 +15,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using AsbCloudApp.IntegrationEvents;
+using AsbCloudApp.IntegrationEvents.Interfaces;
namespace AsbCloudInfrastructure.Services
{
@@ -36,7 +37,7 @@ namespace AsbCloudInfrastructure.Services
private readonly IWitsRecordRepository witsRecord1Repository;
private readonly IGtrRepository gtrRepository;
private static IEnumerable WellMapInfo = Enumerable.Empty();
-
+
public WellInfoService(
TelemetryDataCache telemetryDataSaubCache,
TelemetryDataCache telemetryDataSpinCache,
@@ -63,23 +64,18 @@ namespace AsbCloudInfrastructure.Services
private static async Task WorkAction(string workName, IServiceProvider serviceProvider, CancellationToken token)
{
- var db = serviceProvider.GetRequiredService();
var wellService = serviceProvider.GetRequiredService();
var operationsStatService = serviceProvider.GetRequiredService();
var processMapRepository = serviceProvider.GetRequiredService();
var subsystemOperationTimeService = serviceProvider.GetRequiredService();
var telemetryDataSaubCache = serviceProvider.GetRequiredService>();
+ var messageHub = serviceProvider.GetRequiredService>();
- var activeWells = await wellService.GetAsync(new() {IdState = 1}, token);
+ var wells = await wellService.GetAllAsync(token);
- IEnumerable activeWellsIds = activeWells
- .Select(w => w.Id);
+ var wellsIds = wells.Select(w => w.Id);
- var idTelemetries = activeWells
- .Where(w => w.IdTelemetry != null)
- .Select(t => t.IdTelemetry);
-
- var processMapRequests = activeWellsIds.Select(id => new ProcessMapRequest { IdWell = id });
+ var processMapRequests = wellsIds.Select(id => new ProcessMapRequest { IdWell = id });
var processMaps = await processMapRepository.GetProcessMapAsync(processMapRequests, token);
var wellDepthByProcessMap = processMaps
@@ -90,20 +86,23 @@ namespace AsbCloudInfrastructure.Services
DepthEnd = g.Max(p => p.DepthEnd)
});
- var operationsStat = await operationsStatService.GetWellsStatAsync(activeWellsIds, token);
+ var operationsStat = await operationsStatService.GetWellsStatAsync(wellsIds, token);
- var subsystemStat = await subsystemOperationTimeService.GetStatByActiveWells(activeWellsIds, token);
+ var subsystemStat = await subsystemOperationTimeService
+ .GetStatByActiveWells(wellsIds, token);
- WellMapInfo = activeWells.Select(well => {
+ WellMapInfo = wells.Select(well => {
var wellMapInfo = well.Adapt();
wellMapInfo.IdState = well.IdState;
double? currentDepth = null;
+ TelemetryDataSaubDto? lastSaubTelemetry = null;
+
if (well.IdTelemetry.HasValue)
{
wellMapInfo.IdTelemetry = well.IdTelemetry.Value;
- var lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value);
+ lastSaubTelemetry = telemetryDataSaubCache.GetLastOrDefault(well.IdTelemetry.Value);
if(lastSaubTelemetry is not null)
{
currentDepth = lastSaubTelemetry.WellDepth;
@@ -119,27 +118,54 @@ namespace AsbCloudInfrastructure.Services
.OrderBy(p => p.DepthEnd);
int? idSection = wellLastFactSection?.Id;
- ProcessMapPlanDto? welllProcessMap = null;
+ ProcessMapPlanDto? wellProcessMap = null;
if (idSection.HasValue)
{
- welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
+ wellProcessMap = wellProcessMaps.FirstOrDefault(p => p.IdWellSectionType == idSection);
}
else if(currentDepth.HasValue)
{
- welllProcessMap = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth.Value && p.DepthEnd >= currentDepth.Value);
- idSection ??= welllProcessMap?.IdWellSectionType;
+ wellProcessMap = wellProcessMaps.FirstOrDefault(p => p.DepthStart <= currentDepth.Value && p.DepthEnd >= currentDepth.Value);
}
double? planTotalDepth = null;
planTotalDepth = wellDepthByProcessMap.FirstOrDefault(p => p.Id == well.Id)?.DepthEnd;
planTotalDepth ??= wellOperationsStat?.Total.Plan?.WellDepthEnd;
+ wellMapInfo.Section = wellLastFactSection?.Caption;
+
wellMapInfo.FirstFactOperationDateStart = wellOperationsStat?.Total.Fact?.Start
?? wellOperationsStat?.Total.Plan?.Start;
wellMapInfo.LastPredictOperationDateEnd = wellOperationsStat?.Total.Plan?.End;
+ wellMapInfo.AxialLoad = new()
+ {
+ Plan = wellProcessMap?.AxialLoad.Plan,
+ Fact = lastSaubTelemetry?.AxialLoad
+ };
+
+ wellMapInfo.TopDriveSpeed = new()
+ {
+ Plan = wellProcessMap?.TopDriveSpeed.Plan,
+ Fact = lastSaubTelemetry?.RotorSpeed
+ };
+
+ wellMapInfo.TopDriveTorque = new()
+ {
+ Plan = wellProcessMap?.TopDriveTorque.Plan,
+ Fact = lastSaubTelemetry?.RotorTorque
+ };
+
+ wellMapInfo.Pressure = new()
+ {
+ Plan = wellProcessMap?.Pressure.Plan,
+ Fact = lastSaubTelemetry?.Pressure
+ };
+
+ wellMapInfo.PressureSp = lastSaubTelemetry?.PressureSp;
+
wellMapInfo.WellDepth = new()
{
Plan = planTotalDepth,
@@ -148,7 +174,7 @@ namespace AsbCloudInfrastructure.Services
wellMapInfo.ROP = new()
{
- Plan = welllProcessMap?.RopPlan,
+ Plan = wellProcessMap?.RopPlan,
Fact = wellOperationsStat?.Total.Fact?.Rop,
};
@@ -167,6 +193,11 @@ namespace AsbCloudInfrastructure.Services
return wellMapInfo;
}).ToArray();
+
+ var updateWellInfoEventTasks = wellsIds.Select(idWell =>
+ messageHub.HandleAsync(new UpdateWellInfoEvent(idWell), token));
+
+ await Task.WhenAll(updateWellInfoEventTasks);
}
private WellMapInfoWithTelemetryStat Convert(WellMapInfoWithComanies wellInfo)
diff --git a/AsbCloudInfrastructure/Services/WellService.cs b/AsbCloudInfrastructure/Services/WellService.cs
index c47dd204..4973baf0 100644
--- a/AsbCloudInfrastructure/Services/WellService.cs
+++ b/AsbCloudInfrastructure/Services/WellService.cs
@@ -92,7 +92,7 @@ namespace AsbCloudInfrastructure.Services
Longitude = gCluster.Key.Longitude ?? gDeposit.Key.Longitude,
Wells = gCluster.Select(well =>
{
- var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id);
+ var dto = wellInfoService.FirstOrDefault(w => w.Id == well.Id && well.IdState == 1);
dto ??= well.Adapt();
dto.Latitude ??= gCluster.Key.Latitude ?? gDeposit.Key.Latitude;
dto.Longitude ??= gCluster.Key.Longitude ?? gDeposit.Key.Longitude;
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index d2a619c4..13abc59a 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -32,7 +32,7 @@ namespace AsbCloudWebApi.Controllers
IWellOperationImportService wellOperationImportService,
IUserRepository userRepository)
{
- this.operationRepository = operationService;
+ this.operationRepository = operationRepository;
this.wellService = wellService;
this.wellOperationImportService = wellOperationImportService;
this.userRepository = userRepository;
@@ -218,7 +218,7 @@ namespace AsbCloudWebApi.Controllers
var result = await operationRepository.InsertRangeAsync(values, token)
.ConfigureAwait(false);
-
+
return Ok(result);
}
diff --git a/AsbCloudWebApi/DependencyInjection.cs b/AsbCloudWebApi/DependencyInjection.cs
index 7477f745..09922854 100644
--- a/AsbCloudWebApi/DependencyInjection.cs
+++ b/AsbCloudWebApi/DependencyInjection.cs
@@ -3,7 +3,6 @@ using AsbCloudApp.Repositories;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
-using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
@@ -12,8 +11,12 @@ using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
+using AsbCloudApp.IntegrationEvents;
+using AsbCloudApp.IntegrationEvents.Interfaces;
using AsbCloudApp.Services.Notifications;
+using AsbCloudWebApi.SignalR;
using AsbCloudWebApi.SignalR.Services;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Any;
namespace AsbCloudWebApi
@@ -140,5 +143,8 @@ namespace AsbCloudWebApi
{
services.AddTransient();
}
+
+ public static void AddIntegrationEvents(this IServiceCollection services) => services
+ .AddTransient, WellInfoHub>();
}
}
diff --git a/AsbCloudWebApi/SignalR/WellInfoHub.cs b/AsbCloudWebApi/SignalR/WellInfoHub.cs
new file mode 100644
index 00000000..677b4f64
--- /dev/null
+++ b/AsbCloudWebApi/SignalR/WellInfoHub.cs
@@ -0,0 +1,53 @@
+using System.Threading;
+using System.Threading.Tasks;
+using AsbCloudApp.IntegrationEvents;
+using AsbCloudApp.IntegrationEvents.Interfaces;
+using AsbCloudApp.Services;
+using AsbCloudInfrastructure.Services;
+using Microsoft.AspNetCore.SignalR;
+
+namespace AsbCloudWebApi.SignalR;
+
+public class WellInfoHub : BaseHub, IIntegrationEventHandler
+{
+ private readonly IHubContext hubContext;
+ private readonly IWellService wellService;
+ private readonly WellInfoService wellInfoService;
+
+ public WellInfoHub(IHubContext hubContext,
+ IWellService wellService,
+ WellInfoService wellInfoService)
+ {
+ this.hubContext = hubContext;
+ this.wellService = wellService;
+ this.wellInfoService = wellInfoService;
+ }
+
+ public override async Task AddToGroup(string groupName)
+ {
+ var idWell = int.Parse(groupName.Split('_')[2]);
+
+ await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
+
+ await HandleAsync(new UpdateWellInfoEvent(idWell), CancellationToken.None);
+ }
+
+ public async Task HandleAsync(UpdateWellInfoEvent integrationEvent, CancellationToken cancellationToken)
+ {
+ const string method = "update_well_info";
+
+ var well = await wellService.GetOrDefaultAsync(integrationEvent.IdWell, cancellationToken);
+
+ if(well is null)
+ return;
+
+ var wellInfo = wellInfoService.FirstOrDefault(w => w.Id == well.Id);
+
+ await hubContext.Clients.Group($"well_info_{integrationEvent.IdWell}")
+ .SendAsync(method, new
+ {
+ Well = well,
+ WellInfo = wellInfo
+ }, cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/AsbCloudWebApi/Startup.cs b/AsbCloudWebApi/Startup.cs
index 0fb3ba87..f04a53d1 100644
--- a/AsbCloudWebApi/Startup.cs
+++ b/AsbCloudWebApi/Startup.cs
@@ -45,6 +45,8 @@ namespace AsbCloudWebApi
services.AddNotificationTransportServices();
+ services.AddIntegrationEvents();
+
services.AddJWTAuthentication();
services.AddSignalR()
@@ -151,6 +153,7 @@ namespace AsbCloudWebApi
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
+ endpoints.MapHub("/hubs/wellInfo");
endpoints.MapHub("/hubs/notifications");
endpoints.MapHub("/hubs/telemetry");
endpoints.MapHub("/hubs/reports");
diff --git a/SignalRTestClient/Program.cs b/SignalRTestClient/Program.cs
index 487f1253..9ae72e04 100644
--- a/SignalRTestClient/Program.cs
+++ b/SignalRTestClient/Program.cs
@@ -10,7 +10,7 @@ internal class Program
{
var connectionBuilder = new HubConnectionBuilder();
var connection = connectionBuilder
- .WithUrl("http://localhost:5000/hubs/notifications", connectionOptions => {
+ .WithUrl("http://localhost:5000/hubs/limitingParameters", connectionOptions => {
connectionOptions.AccessTokenProvider = AccessTokenProvider;
})
.WithAutomaticReconnect()
@@ -26,9 +26,9 @@ internal class Program
connection.StartAsync().Wait();
//Console.WriteLine("OnConnected");
- //connection.SendCoreAsync("OnConnected", new object[] { }, CancellationToken.None).Wait();
+ connection.SendCoreAsync("OnConnectedAsync", new object[] { 1 }, CancellationToken.None).Wait();
- var subsction = connection.On