Add TelemetryDataSaubController.GetZippedCsv(..)

This commit is contained in:
ngfrolov 2023-03-09 12:32:09 +05:00
parent cff9fe3fe7
commit db1bd49d60
Signed by: ng.frolov
GPG Key ID: E99907A0357B29A7
8 changed files with 186 additions and 24 deletions

View File

@ -19,6 +19,11 @@ namespace AsbCloudApp.Data
/// информация о бурении, панели оператора и контроллерах
/// </summary>
public TelemetryInfoDto? Info { get; set; }
/// <summary>
/// Смещение часового пояса от UTC
/// </summary>
public SimpleTimezoneDto? TimeZone { get; set; }
}
/// <summary>

View File

@ -1,5 +1,7 @@
using AsbCloudApp.Data.SAUB;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@ -20,5 +22,15 @@ namespace AsbCloudApp.Services
/// <param name="token"></param>
/// <returns></returns>
Task<IEnumerable<TelemetryDataSaubStatDto>> GetTelemetryDataStatAsync(int idTelemetry, CancellationToken token);
/// <summary>
/// Получить упакованый csv файл
/// </summary>
/// <param name="idWell"></param>
/// <param name="beginDate"></param>
/// <param name="endDate"></param>
/// <param name="token"></param>
/// <returns></returns>
Task<Stream> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token);
}
}

View File

@ -0,0 +1,85 @@
using DocumentFormat.OpenXml.Drawing.Diagrams;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
namespace System.Text.Csv
{
#nullable enable
public class CsvSerializer<T>
{
private readonly PropertyInfo[] props;
private readonly static Regex numbers = new Regex(@"^[0-9\-\+\.]+$");
public string Separator { get; set; } = ";";
public string NewLine { get; set; } = "\r\n";
public string Quot { get; set; } = "\"";
public Encoding Encoding { get; set; } = Encoding.UTF8;
public string FloatingPointFormat { get; set; } = "#0.000#";
public string DateTimeFormat { get; set; } = "yyyy-MM-dd HH:mm:ss";
public string objDateTimeOffsetFormat { get; set; } = "yyyy-MM-dd HH:mm:ss zzz";
public string TimeOnlyFormat { get; set; } = "HH:mm:ss";
public string DateOnlyFormat { get; set; } = "yyyy-MM-dd";
public CsvSerializer()
{
props = typeof(T).GetProperties();
}
public void Serialize(IEnumerable<T> data, Stream toStream)
{
if (!data.Any())
return;
if(!props.Any())
return;
void HandleRow(IEnumerable<object?> rowData)
{
var row = string.Join(Separator, rowData);
var bytes = Encoding.GetBytes(row + NewLine);
toStream.Write(bytes);
}
HandleRow(props.Select(p => p.Name));
foreach ( var item in data)
HandleRow(props.Select(p => CsvSerializer<T>.Escape(Fromat(p.GetValue(item)))));
}
private string Fromat(object? obj)
{
if (obj is double objDouble)
return objDouble.ToString(FloatingPointFormat);
if (obj is float objfloat)
return objfloat.ToString(FloatingPointFormat);
if (obj is DateTime objDateTime)
return objDateTime.ToString(DateTimeFormat);
if (obj is DateTimeOffset objDateTimeOffset)
return objDateTimeOffset.ToString(objDateTimeOffsetFormat);
if (obj is DateOnly objDateOnly)
return objDateOnly.ToString(DateOnlyFormat);
if (obj is TimeOnly objTimeOnly)
return objTimeOnly.ToString(TimeOnlyFormat);
return obj?.ToString() ?? string.Empty;
}
private static string Escape(string inString)
{
if (numbers.IsMatch(inString))
return inString;
return $"\"{inString}\"";
}
}
#nullable disable
}

View File

@ -1,4 +1,6 @@
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Data;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
@ -6,7 +8,10 @@ using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.Csv;
using System.Threading;
using System.Threading.Tasks;
@ -99,10 +104,40 @@ namespace AsbCloudInfrastructure.Services.SAUB
return dto;
}
public Stream GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate)
public async Task<Stream> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token)
{
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
return null;
double intervalSec = (endDate - beginDate).TotalSeconds;
if (intervalSec > 60*60*24*3)
throw new ArgumentInvalidException("Слишком большой диапазон", nameof(endDate));
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell)
?? throw new ArgumentInvalidException($"Скважина id:{idWell} не содержит телеметрии", nameof(idWell));
var approxPointsCount = intervalSec switch
{
< 2048 => 2048,
< 8_192 => 4_096,
< 131_072 => 16_384,
_ => 32_768
};
var data = await GetOrDefaultAsync(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;
}
}
#nullable disable

View File

@ -47,7 +47,7 @@ namespace AsbCloudInfrastructure.Services.SAUB
.Options;
var db = new AsbCloudDbContext(contextOptions);
var cacheTelemetry = memoryCache.GetOrCreateBasic(db.Set<Telemetry>());
var cacheTelemetry = memoryCache.GetOrCreateBasic(db.Set<Telemetry>().Include(t=>t.Well));
var keyValuePairs = new Dictionary<string, TrackerStat>(cacheTelemetry.Count());
foreach (var telemetry in cacheTelemetry)
{

View File

@ -18,9 +18,9 @@ namespace AsbCloudWebApi.Controllers.SAUB
public abstract class TelemetryDataBaseController<TDto> : ControllerBase
where TDto : ITelemetryData
{
protected readonly IWellService wellService;
private readonly ITelemetryService telemetryService;
private readonly ITelemetryDataService<TDto> telemetryDataService;
private readonly IWellService wellService;
private readonly IHubContext<TelemetryHub> telemetryHubContext;
public string SirnalRMethodGetDataName { get; protected set; } = "ReceiveData";

View File

@ -3,6 +3,11 @@ using AsbCloudApp.Services;
using AsbCloudWebApi.SignalR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using AsbCloudInfrastructure.Services;
using System;
namespace AsbCloudWebApi.Controllers.SAUB
{
@ -13,6 +18,8 @@ namespace AsbCloudWebApi.Controllers.SAUB
[ApiController]
public class TelemetryDataSaubController : TelemetryDataBaseController<TelemetryDataSaubDto>
{
private readonly ITelemetryDataSaubService telemetryDataSaubService;
public TelemetryDataSaubController(
ITelemetryService telemetryService,
ITelemetryDataSaubService telemetryDataService,
@ -25,6 +32,35 @@ namespace AsbCloudWebApi.Controllers.SAUB
telemetryHubContext)
{
SirnalRMethodGetDataName = "ReceiveDataSaub";
telemetryDataSaubService = telemetryDataService;
}
/// <summary>
/// Выгрузка архива. Не более 3-х суток. Формат даты строгий.
/// </summary>
/// <param name="idWell">id скважины (из адресной строки)</param>
/// <param name="beginDate">начало интервала в формате: yyyy-MM-DD HH:mm</param>
/// <param name="endDate">конец интервала в формате: yyyy-MM-DD HH:mm</param>
/// <param name="token"></param>
/// <returns></returns>
[HttpGet("{idWell}/export/csv")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
public async Task<IActionResult> GetZippedCsv(int idWell, DateTime beginDate, DateTime endDate, CancellationToken token)
{
int? idCompany = User.GetCompanyId();
if (idCompany is null)
return Forbid();
bool isCompanyOwnsWell = await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false);
if (!isCompanyOwnsWell)
return Forbid();
var stream = await telemetryDataSaubService.GetZippedCsv(idWell, beginDate, endDate, token).ConfigureAwait(false);
var fileName = $"DataSaub idWell{idWell} {beginDate:yyyy-MM-DDTHH-mm} - {endDate:yyyy-MM-DDTHH-mm}.zip";
return File(stream, "application/octet-stream", fileName);
}
}
}

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
@ -19,20 +17,11 @@ namespace ConsoleApp1
{
static void Main(/*string[] args*/)
{
var db = ServiceFactory.Context;
var q = db.TelemetryDataSaub
.Select(t => new {
t.IdTelemetry,
t.DateTime,
t.WellDepth,
})
.GroupBy(t => t.IdTelemetry)
.Select(g => new {
Id = g.Key,
First = g.OrderBy(t => t.DateTime).FirstOrDefault(),
Last = g.OrderBy(t => t.DateTime).LastOrDefault(),
});
var d = q.AsNoTracking().ToArray();
var n = "-159.99";
var s = "159.99s";
var r1 = reg.IsMatch( n );
var r2 = reg.IsMatch( s );
}
}
}