forked from ddrilling/AsbCloudServer
Форматирование TelemetryDataSaubService
This commit is contained in:
parent
7dd92be567
commit
bb107c8f5b
@ -1,176 +1,172 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudApp.Data.SAUB;
|
|
||||||
using AsbCloudApp.Exceptions;
|
using AsbCloudApp.Exceptions;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Org.BouncyCastle.Asn1.Pkcs;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Csv;
|
using System.Text.Csv;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.SAUB
|
namespace AsbCloudInfrastructure.Services.SAUB;
|
||||||
|
|
||||||
|
public class TelemetryDataSaubService : TelemetryDataBaseService<TelemetryDataSaubDto, TelemetryDataSaub>, ITelemetryDataSaubService
|
||||||
{
|
{
|
||||||
|
private readonly ITelemetryUserService telemetryUserService;
|
||||||
|
|
||||||
public class TelemetryDataSaubService : TelemetryDataBaseService<TelemetryDataSaubDto, TelemetryDataSaub>, ITelemetryDataSaubService
|
public TelemetryDataSaubService(
|
||||||
|
IAsbCloudDbContext db,
|
||||||
|
ITelemetryService telemetryService,
|
||||||
|
ITelemetryUserService telemetryUserService,
|
||||||
|
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
||||||
|
: base(db, telemetryService, telemetryDataCache)
|
||||||
{
|
{
|
||||||
private readonly ITelemetryUserService telemetryUserService;
|
this.telemetryUserService = telemetryUserService;
|
||||||
|
|
||||||
public TelemetryDataSaubService(
|
|
||||||
IAsbCloudDbContext db,
|
|
||||||
ITelemetryService telemetryService,
|
|
||||||
ITelemetryUserService telemetryUserService,
|
|
||||||
ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
|
|
||||||
: base(db, telemetryService, telemetryDataCache)
|
|
||||||
{
|
|
||||||
this.telemetryUserService = telemetryUserService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<TelemetryDataSaubDto>> Get(int idTelemetry, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token)
|
|
||||||
{
|
|
||||||
var offset = telemetryService.GetTimezone(idTelemetry).Offset;
|
|
||||||
var geDateUtc = geDate.ToUniversalTime();
|
|
||||||
var leDateUtc = leDate.ToUniversalTime();
|
|
||||||
|
|
||||||
var query = db.Set<TelemetryDataSaub>()
|
|
||||||
.Where(t => t.IdTelemetry == idTelemetry)
|
|
||||||
.Where(t => t.DateTime >= geDateUtc)
|
|
||||||
.Where(t => t.DateTime <= leDateUtc);
|
|
||||||
|
|
||||||
if (isBitOnBottom)
|
|
||||||
query = query.Where(t => Math.Abs(t.BitDepth - t.WellDepth) < 0.0001);
|
|
||||||
|
|
||||||
query = query
|
|
||||||
.OrderBy(t => t.DateTime)
|
|
||||||
.Take(take);
|
|
||||||
|
|
||||||
var entities = await query.ToArrayAsync(token);
|
|
||||||
var dtos = entities.Select(e => Convert(e, offset.TotalHours));
|
|
||||||
return dtos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<TelemetryDataSaubStatDto>> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token)
|
|
||||||
{
|
|
||||||
var timezone = telemetryService.GetTimezone(idTelemetry);
|
|
||||||
var timezoneOffset = TimeSpan.FromHours(timezone.Hours);
|
|
||||||
int[] modes = new int[] { 0, 1, 3 };
|
|
||||||
|
|
||||||
db.Database.SetCommandTimeout(TimeSpan.FromMinutes(1.5));
|
|
||||||
|
|
||||||
var query = db.Set<TelemetryDataSaub>()
|
|
||||||
.Where(t => t.IdTelemetry == idTelemetry)
|
|
||||||
.Where(t => t.BlockPosition > 0.0001)
|
|
||||||
.Where(t => t.WellDepth > 0.0001)
|
|
||||||
.Where(t => modes.Contains(t.Mode))
|
|
||||||
.Where(t => t.WellDepth - t.BitDepth < 0.01)
|
|
||||||
.GroupBy(t => new {
|
|
||||||
t.DateTime.Hour,
|
|
||||||
WellDepthX10 = Math.Truncate(t.WellDepth * 10),
|
|
||||||
t.Mode,
|
|
||||||
t.IdFeedRegulator})
|
|
||||||
.Select(g => new TelemetryDataSaubStatDto
|
|
||||||
{
|
|
||||||
Count = g.Count(),
|
|
||||||
IdMode = g.Key.Mode,
|
|
||||||
IdFeedRegulator = g.Key.IdFeedRegulator,
|
|
||||||
|
|
||||||
DateMin = DateTime.SpecifyKind(g.Min(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified),
|
|
||||||
DateMax = DateTime.SpecifyKind(g.Max(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified),
|
|
||||||
|
|
||||||
WellDepthMin = g.Min(t => t.WellDepth),
|
|
||||||
WellDepthMax = g.Max(t => t.WellDepth),
|
|
||||||
|
|
||||||
Pressure = g.Average(t => t.Pressure),
|
|
||||||
PressureSp = g.Average(t => t.PressureSp!.Value),
|
|
||||||
PressureIdle = g.Average(t => t.PressureIdle!.Value),
|
|
||||||
PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value),
|
|
||||||
PressureDelta = g.Average(t => t.Pressure - t.PressureIdle!.Value),
|
|
||||||
PressureSpDelta = g.Average(t => t.PressureSp!.Value - t.PressureIdle!.Value),
|
|
||||||
|
|
||||||
AxialLoad = g.Average(t => t.AxialLoad),
|
|
||||||
AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value),
|
|
||||||
AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value),
|
|
||||||
|
|
||||||
RotorTorque = g.Average(t => t.RotorTorque),
|
|
||||||
RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value),
|
|
||||||
RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value),
|
|
||||||
|
|
||||||
BlockSpeed = g.Average(t => t.BlockSpeed!.Value),
|
|
||||||
BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value),
|
|
||||||
})
|
|
||||||
.Where(s => s.WellDepthMin != s.WellDepthMax)
|
|
||||||
.Where(s => s.Count > 3)
|
|
||||||
.OrderBy(t => t.DateMin);
|
|
||||||
|
|
||||||
return await query.ToArrayAsync(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
|
|
||||||
{
|
|
||||||
var entity = src.Adapt<TelemetryDataSaub>();
|
|
||||||
var telemetryUser = telemetryUserService
|
|
||||||
.GetUsers(src.IdTelemetry, u => (u.Name == src.User || u.Surname == src.User))
|
|
||||||
.FirstOrDefault();
|
|
||||||
entity.IdUser = telemetryUser?.Id;
|
|
||||||
entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset);
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TelemetryDataSaubDto Convert(TelemetryDataSaub src, double timezoneOffset)
|
|
||||||
{
|
|
||||||
var dto = src.Adapt<TelemetryDataSaubDto>();
|
|
||||||
var telemetryUser = telemetryUserService.GetOrDefault(src.IdTelemetry, src.IdUser??int.MinValue);
|
|
||||||
dto.User = telemetryUser?.MakeDisplayName();
|
|
||||||
dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset);
|
|
||||||
dto.BitDepth = src.BitDepth <= src.WellDepth
|
|
||||||
? src.BitDepth
|
|
||||||
: src.WellDepth;
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Stream> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token)
|
|
||||||
{
|
|
||||||
double intervalSec = (endDate - beginDate).TotalSeconds;
|
|
||||||
if (intervalSec > 60*60*24*3)
|
|
||||||
throw new ArgumentInvalidException(nameof(endDate), "Слишком большой диапазон");
|
|
||||||
|
|
||||||
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell)
|
|
||||||
?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина id:{idWell} не содержит телеметрии");
|
|
||||||
|
|
||||||
var approxPointsCount = intervalSec switch
|
|
||||||
{
|
|
||||||
< 2048 => 2048,
|
|
||||||
< 8_192 => 4_096,
|
|
||||||
< 131_072 => 16_384,
|
|
||||||
_ => 32_768
|
|
||||||
};
|
|
||||||
|
|
||||||
var data = await GetAsync(idWell, beginDate, intervalSec, approxPointsCount, token );
|
|
||||||
|
|
||||||
var fileName = $"DataSaub idWell{idWell}";
|
|
||||||
if (telemetry.Info is not null)
|
|
||||||
fileName += $" {telemetry.Info?.Cluster}, {telemetry.Info?.Well}";
|
|
||||||
fileName += $" {beginDate:yyyy-MM-DDTHH-mm} - {endDate:yyyy-MM-DDTHH-mm}.csv";
|
|
||||||
|
|
||||||
var outStream = new MemoryStream();
|
|
||||||
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
|
|
||||||
{
|
|
||||||
var entryFile = archive.CreateEntry(fileName, CompressionLevel.Optimal);
|
|
||||||
using var entryStream = entryFile.Open();
|
|
||||||
var serializer = new CsvSerializer<TelemetryDataSaubDto>();
|
|
||||||
serializer.Serialize(data, entryStream);
|
|
||||||
}
|
|
||||||
outStream.Seek(0, SeekOrigin.Begin);
|
|
||||||
return outStream;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TelemetryDataSaubDto>> Get(int idTelemetry, bool isBitOnBottom, DateTimeOffset geDate, DateTimeOffset leDate, int take, CancellationToken token)
|
||||||
|
{
|
||||||
|
var offset = telemetryService.GetTimezone(idTelemetry).Offset;
|
||||||
|
var geDateUtc = geDate.ToUniversalTime();
|
||||||
|
var leDateUtc = leDate.ToUniversalTime();
|
||||||
|
|
||||||
|
var query = db.Set<TelemetryDataSaub>()
|
||||||
|
.Where(t => t.IdTelemetry == idTelemetry)
|
||||||
|
.Where(t => t.DateTime >= geDateUtc)
|
||||||
|
.Where(t => t.DateTime <= leDateUtc);
|
||||||
|
|
||||||
|
if (isBitOnBottom)
|
||||||
|
query = query.Where(t => Math.Abs(t.BitDepth - t.WellDepth) < 0.0001);
|
||||||
|
|
||||||
|
query = query
|
||||||
|
.OrderBy(t => t.DateTime)
|
||||||
|
.Take(take);
|
||||||
|
|
||||||
|
var entities = await query.ToArrayAsync(token);
|
||||||
|
var dtos = entities.Select(e => Convert(e, offset.TotalHours));
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TelemetryDataSaubStatDto>> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token)
|
||||||
|
{
|
||||||
|
var timezone = telemetryService.GetTimezone(idTelemetry);
|
||||||
|
var timezoneOffset = TimeSpan.FromHours(timezone.Hours);
|
||||||
|
int[] modes = new int[] { 0, 1, 3 };
|
||||||
|
|
||||||
|
db.Database.SetCommandTimeout(TimeSpan.FromMinutes(1.5));
|
||||||
|
|
||||||
|
var query = db.Set<TelemetryDataSaub>()
|
||||||
|
.Where(t => t.IdTelemetry == idTelemetry)
|
||||||
|
.Where(t => t.BlockPosition > 0.0001)
|
||||||
|
.Where(t => t.WellDepth > 0.0001)
|
||||||
|
.Where(t => modes.Contains(t.Mode))
|
||||||
|
.Where(t => t.WellDepth - t.BitDepth < 0.01)
|
||||||
|
.GroupBy(t => new
|
||||||
|
{
|
||||||
|
t.DateTime.Hour,
|
||||||
|
WellDepthX10 = Math.Truncate(t.WellDepth * 10),
|
||||||
|
t.Mode,
|
||||||
|
t.IdFeedRegulator
|
||||||
|
})
|
||||||
|
.Select(g => new TelemetryDataSaubStatDto
|
||||||
|
{
|
||||||
|
Count = g.Count(),
|
||||||
|
IdMode = g.Key.Mode,
|
||||||
|
IdFeedRegulator = g.Key.IdFeedRegulator,
|
||||||
|
|
||||||
|
DateMin = DateTime.SpecifyKind(g.Min(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified),
|
||||||
|
DateMax = DateTime.SpecifyKind(g.Max(t => t.DateTime.UtcDateTime) + timezoneOffset, DateTimeKind.Unspecified),
|
||||||
|
|
||||||
|
WellDepthMin = g.Min(t => t.WellDepth),
|
||||||
|
WellDepthMax = g.Max(t => t.WellDepth),
|
||||||
|
|
||||||
|
Pressure = g.Average(t => t.Pressure),
|
||||||
|
PressureSp = g.Average(t => t.PressureSp!.Value),
|
||||||
|
PressureIdle = g.Average(t => t.PressureIdle!.Value),
|
||||||
|
PressureDeltaLimitMax = g.Average(t => t.PressureDeltaLimitMax!.Value),
|
||||||
|
PressureDelta = g.Average(t => t.Pressure - t.PressureIdle!.Value),
|
||||||
|
PressureSpDelta = g.Average(t => t.PressureSp!.Value - t.PressureIdle!.Value),
|
||||||
|
|
||||||
|
AxialLoad = g.Average(t => t.AxialLoad),
|
||||||
|
AxialLoadSp = g.Average(t => t.AxialLoadSp!.Value),
|
||||||
|
AxialLoadLimitMax = g.Average(t => t.AxialLoadLimitMax!.Value),
|
||||||
|
|
||||||
|
RotorTorque = g.Average(t => t.RotorTorque),
|
||||||
|
RotorTorqueSp = g.Average(t => t.RotorTorqueSp!.Value),
|
||||||
|
RotorTorqueLimitMax = g.Average(t => t.RotorTorqueLimitMax!.Value),
|
||||||
|
|
||||||
|
BlockSpeed = g.Average(t => t.BlockSpeed!.Value),
|
||||||
|
BlockSpeedSp = g.Average(t => t.BlockSpeedSp!.Value),
|
||||||
|
})
|
||||||
|
.Where(s => s.WellDepthMin != s.WellDepthMax)
|
||||||
|
.Where(s => s.Count > 3)
|
||||||
|
.OrderBy(t => t.DateMin);
|
||||||
|
|
||||||
|
return await query.ToArrayAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TelemetryDataSaub Convert(TelemetryDataSaubDto src, double timezoneOffset)
|
||||||
|
{
|
||||||
|
var entity = src.Adapt<TelemetryDataSaub>();
|
||||||
|
var telemetryUser = telemetryUserService
|
||||||
|
.GetUsers(src.IdTelemetry, u => (u.Name == src.User || u.Surname == src.User))
|
||||||
|
.FirstOrDefault();
|
||||||
|
entity.IdUser = telemetryUser?.Id;
|
||||||
|
entity.DateTime = src.DateTime.ToUtcDateTimeOffset(timezoneOffset);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TelemetryDataSaubDto Convert(TelemetryDataSaub src, double timezoneOffset)
|
||||||
|
{
|
||||||
|
var dto = src.Adapt<TelemetryDataSaubDto>();
|
||||||
|
var telemetryUser = telemetryUserService.GetOrDefault(src.IdTelemetry, src.IdUser ?? int.MinValue);
|
||||||
|
dto.User = telemetryUser?.MakeDisplayName();
|
||||||
|
dto.DateTime = src.DateTime.ToRemoteDateTime(timezoneOffset);
|
||||||
|
dto.BitDepth = src.BitDepth <= src.WellDepth
|
||||||
|
? src.BitDepth
|
||||||
|
: src.WellDepth;
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Stream> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token)
|
||||||
|
{
|
||||||
|
double intervalSec = (endDate - beginDate).TotalSeconds;
|
||||||
|
if (intervalSec > 60 * 60 * 24 * 3)
|
||||||
|
throw new ArgumentInvalidException(nameof(endDate), "Слишком большой диапазон");
|
||||||
|
|
||||||
|
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell)
|
||||||
|
?? throw new ArgumentInvalidException(nameof(idWell), $"Скважина id:{idWell} не содержит телеметрии");
|
||||||
|
|
||||||
|
var approxPointsCount = intervalSec switch
|
||||||
|
{
|
||||||
|
< 2048 => 2048,
|
||||||
|
< 8_192 => 4_096,
|
||||||
|
< 131_072 => 16_384,
|
||||||
|
_ => 32_768
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = await GetAsync(idWell, beginDate, intervalSec, approxPointsCount, token);
|
||||||
|
|
||||||
|
var fileName = $"DataSaub idWell{idWell}";
|
||||||
|
if (telemetry.Info is not null)
|
||||||
|
fileName += $" {telemetry.Info?.Cluster}, {telemetry.Info?.Well}";
|
||||||
|
fileName += $" {beginDate:yyyy-MM-DDTHH-mm} - {endDate:yyyy-MM-DDTHH-mm}.csv";
|
||||||
|
|
||||||
|
var outStream = new MemoryStream();
|
||||||
|
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
|
||||||
|
{
|
||||||
|
var entryFile = archive.CreateEntry(fileName, CompressionLevel.Optimal);
|
||||||
|
using var entryStream = entryFile.Open();
|
||||||
|
var serializer = new CsvSerializer<TelemetryDataSaubDto>();
|
||||||
|
serializer.Serialize(data, entryStream);
|
||||||
|
}
|
||||||
|
outStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
return outStream;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user