forked from ddrilling/AsbCloudServer
Merge pull request 'gtr_wits' (#39) from gtr into dev
Reviewed-on: http://test.digitaldrilling.ru:8080/DDrilling/AsbCloudServer/pulls/39
This commit is contained in:
commit
66ac06c1fe
14
AsbCloudApp/Data/GTR/JsonValue.cs
Normal file
14
AsbCloudApp/Data/GTR/JsonValue.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace AsbCloudApp.Data.GTR
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Класс позволяющий хранить значение неопределенного типа.
|
||||||
|
/// Все возможные типы должны быть описаны в JsonValueJsonConverter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Value"></param>
|
||||||
|
public record JsonValue(object Value)
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override string ToString()
|
||||||
|
=> Value.ToString() ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
26
AsbCloudApp/Data/GTR/WitsRecordDto.cs
Normal file
26
AsbCloudApp/Data/GTR/WitsRecordDto.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data.GTR
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Запись WITS
|
||||||
|
/// </summary>
|
||||||
|
public class WitsRecordDto
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id записи
|
||||||
|
/// </summary>
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Дата создания записи
|
||||||
|
/// </summary>
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Параметры. Ключ - id_item. ValueContainer содержит значение.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<int, JsonValue> Items { get; set; } = new();
|
||||||
|
}
|
||||||
|
}
|
39
AsbCloudApp/Repositories/IGtrRepository.cs
Normal file
39
AsbCloudApp/Repositories/IGtrRepository.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using AsbCloudApp.Data.GTR;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Repositories
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
/// <summary>
|
||||||
|
/// данные ГТИ
|
||||||
|
/// </summary>
|
||||||
|
public interface IGtrRepository
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// добавить данные (для панели бурильщика)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idTelemetry"></param>
|
||||||
|
/// <param name="dto"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SaveDataAsync(int idTelemetry, WitsRecordDto dto, CancellationToken token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// получить данные для клиента
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="idWell"></param>
|
||||||
|
/// <param name="dateBegin"></param>
|
||||||
|
/// <param name="intervalSec"></param>
|
||||||
|
/// <param name="approxPointsCount">кол-во элементов до которых эти данные прореживаются</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<IEnumerable<WitsRecordDto>> GetAsync(int idWell,
|
||||||
|
DateTime? dateBegin, double intervalSec = 600d,
|
||||||
|
int approxPointsCount = 1024, CancellationToken token = default);
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
}
|
7960
AsbCloudDb/Migrations/20230418055848_Add_GTR.Designer.cs
generated
Normal file
7960
AsbCloudDb/Migrations/20230418055848_Add_GTR.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
97
AsbCloudDb/Migrations/20230418055848_Add_GTR.cs
Normal file
97
AsbCloudDb/Migrations/20230418055848_Add_GTR.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Migrations
|
||||||
|
{
|
||||||
|
public partial class Add_GTR : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "t_wits_float",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id_telemetry = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
id_record = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
id_item = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||||
|
value = table.Column<float>(type: "real", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_t_wits_float", x => new { x.id_telemetry, x.id_record, x.id_item, x.date });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_t_wits_float_t_telemetry_id_telemetry",
|
||||||
|
column: x => x.id_telemetry,
|
||||||
|
principalTable: "t_telemetry",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
},
|
||||||
|
comment: "таблица данных ГТИ с типом значения float");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "t_wits_int",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id_telemetry = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
id_record = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
id_item = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||||
|
value = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_t_wits_int", x => new { x.id_telemetry, x.id_record, x.id_item, x.date });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_t_wits_int_t_telemetry_id_telemetry",
|
||||||
|
column: x => x.id_telemetry,
|
||||||
|
principalTable: "t_telemetry",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
},
|
||||||
|
comment: "таблица данных ГТИ с типом значения int");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "t_wits_string",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id_telemetry = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
id_record = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
id_item = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||||
|
value = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_t_wits_string", x => new { x.id_telemetry, x.id_record, x.id_item, x.date });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_t_wits_string_t_telemetry_id_telemetry",
|
||||||
|
column: x => x.id_telemetry,
|
||||||
|
principalTable: "t_telemetry",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
},
|
||||||
|
comment: "таблица данных ГТИ с типом значения string");
|
||||||
|
|
||||||
|
migrationBuilder.Sql
|
||||||
|
("SELECT create_hypertable('t_wits_string','date','id_telemetry',2,chunk_time_interval => INTERVAL '5 day'); " +
|
||||||
|
"SELECT create_hypertable('t_wits_float','date','id_telemetry',2,chunk_time_interval => INTERVAL '5 day'); " +
|
||||||
|
"SELECT create_hypertable('t_wits_int','date','id_telemetry',2,chunk_time_interval => INTERVAL '5 day'); ");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "t_wits_float");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "t_wits_int");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "t_wits_string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -801,6 +801,94 @@ namespace AsbCloudDb.Migrations
|
|||||||
b.HasComment("Действия с файлами.");
|
b.HasComment("Действия с файлами.");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemFloat", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("IdTelemetry")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_telemetry");
|
||||||
|
|
||||||
|
b.Property<int>("IdRecord")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_record");
|
||||||
|
|
||||||
|
b.Property<int>("IdItem")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_item");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("DateTime")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date");
|
||||||
|
|
||||||
|
b.Property<float>("Value")
|
||||||
|
.HasColumnType("real")
|
||||||
|
.HasColumnName("value");
|
||||||
|
|
||||||
|
b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime");
|
||||||
|
|
||||||
|
b.ToTable("t_wits_float");
|
||||||
|
|
||||||
|
b.HasComment("таблица данных ГТИ с типом значения float");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemInt", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("IdTelemetry")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_telemetry");
|
||||||
|
|
||||||
|
b.Property<int>("IdRecord")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_record");
|
||||||
|
|
||||||
|
b.Property<int>("IdItem")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_item");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("DateTime")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date");
|
||||||
|
|
||||||
|
b.Property<int>("Value")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("value");
|
||||||
|
|
||||||
|
b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime");
|
||||||
|
|
||||||
|
b.ToTable("t_wits_int");
|
||||||
|
|
||||||
|
b.HasComment("таблица данных ГТИ с типом значения int");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemString", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("IdTelemetry")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_telemetry");
|
||||||
|
|
||||||
|
b.Property<int>("IdRecord")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_record");
|
||||||
|
|
||||||
|
b.Property<int>("IdItem")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id_item");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("DateTime")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("date");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("value");
|
||||||
|
|
||||||
|
b.HasKey("IdTelemetry", "IdRecord", "IdItem", "DateTime");
|
||||||
|
|
||||||
|
b.ToTable("t_wits_string");
|
||||||
|
|
||||||
|
b.HasComment("таблица данных ГТИ с типом значения string");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b =>
|
modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -7164,6 +7252,39 @@ namespace AsbCloudDb.Migrations
|
|||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemFloat", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IdTelemetry")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Telemetry");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemInt", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IdTelemetry")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Telemetry");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("AsbCloudDb.Model.GTR.WitsItemString", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IdTelemetry")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Telemetry");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b =>
|
modelBuilder.Entity("AsbCloudDb.Model.LimitingParameter", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
b.HasOne("AsbCloudDb.Model.Telemetry", "Telemetry")
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudDb.Model.Subsystems;
|
using AsbCloudDb.Model.GTR;
|
||||||
|
using AsbCloudDb.Model.Subsystems;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -55,6 +56,11 @@ namespace AsbCloudDb.Model
|
|||||||
|
|
||||||
public virtual DbSet<TelemetryWirelineRunOut> TelemetryWirelineRunOut => Set<TelemetryWirelineRunOut>();
|
public virtual DbSet<TelemetryWirelineRunOut> TelemetryWirelineRunOut => Set<TelemetryWirelineRunOut>();
|
||||||
|
|
||||||
|
// GTR WITS
|
||||||
|
public DbSet<WitsItemFloat> WitsItemFloat => Set<WitsItemFloat>();
|
||||||
|
public DbSet<WitsItemInt> WitsItemInt => Set<WitsItemInt>();
|
||||||
|
public DbSet<WitsItemString> WitsItemString => Set<WitsItemString>();
|
||||||
|
|
||||||
// WITS
|
// WITS
|
||||||
public DbSet<WITS.Record1> Record1 => Set<WITS.Record1>();
|
public DbSet<WITS.Record1> Record1 => Set<WITS.Record1>();
|
||||||
public DbSet<WITS.Record7> Record7 => Set<WITS.Record7>();
|
public DbSet<WITS.Record7> Record7 => Set<WITS.Record7>();
|
||||||
@ -334,6 +340,31 @@ namespace AsbCloudDb.Model
|
|||||||
.HasJsonConversion();
|
.HasJsonConversion();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<WitsItemFloat>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(
|
||||||
|
nameof(ITelemetryData.IdTelemetry),
|
||||||
|
nameof(WitsItemBase<float>.IdRecord),
|
||||||
|
nameof(WitsItemBase<float>.IdItem),
|
||||||
|
nameof(WitsItemBase<float>.DateTime));
|
||||||
|
});
|
||||||
|
modelBuilder.Entity<WitsItemInt>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(
|
||||||
|
nameof(ITelemetryData.IdTelemetry),
|
||||||
|
nameof(WitsItemBase<int>.IdRecord),
|
||||||
|
nameof(WitsItemBase<int>.IdItem),
|
||||||
|
nameof(WitsItemBase<int>.DateTime));
|
||||||
|
});
|
||||||
|
modelBuilder.Entity<WitsItemString>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(
|
||||||
|
nameof(ITelemetryData.IdTelemetry),
|
||||||
|
nameof(WitsItemBase<string>.IdRecord),
|
||||||
|
nameof(WitsItemBase<string>.IdItem),
|
||||||
|
nameof(WitsItemBase<string>.DateTime));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
modelBuilder.Entity<UserSetting>(entity =>
|
modelBuilder.Entity<UserSetting>(entity =>
|
||||||
{
|
{
|
||||||
|
37
AsbCloudDb/Model/GTR/WitsItemBase.cs
Normal file
37
AsbCloudDb/Model/GTR/WitsItemBase.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Model.GTR
|
||||||
|
{
|
||||||
|
public class WitsItemBase<T> : ITelemetryData
|
||||||
|
where T: notnull
|
||||||
|
{
|
||||||
|
[Column("id_telemetry")]
|
||||||
|
public int IdTelemetry { get; set; }
|
||||||
|
|
||||||
|
[Column("id_record")]
|
||||||
|
public int IdRecord { get; set; }
|
||||||
|
|
||||||
|
[Column("id_item")]
|
||||||
|
public int IdItem { get; set; }
|
||||||
|
|
||||||
|
[Column("date", TypeName = "timestamp with time zone")]
|
||||||
|
public DateTimeOffset DateTime { get; set; }
|
||||||
|
|
||||||
|
[Column("value")]
|
||||||
|
public T Value { get; set; } = default!;
|
||||||
|
|
||||||
|
[ForeignKey(nameof(IdTelemetry))]
|
||||||
|
public virtual Telemetry? Telemetry { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Table("t_wits_string"), Comment("таблица данных ГТИ с типом значения string")]
|
||||||
|
public class WitsItemString : WitsItemBase<string> { }
|
||||||
|
|
||||||
|
[Table("t_wits_float"), Comment("таблица данных ГТИ с типом значения float")]
|
||||||
|
public class WitsItemFloat : WitsItemBase<float> { }
|
||||||
|
|
||||||
|
[Table("t_wits_int"), Comment("таблица данных ГТИ с типом значения int")]
|
||||||
|
public class WitsItemInt : WitsItemBase<int> { }
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using AsbCloudDb.Model.Subsystems;
|
using AsbCloudDb.Model.GTR;
|
||||||
|
using AsbCloudDb.Model.Subsystems;
|
||||||
using AsbCloudDb.Model.WITS;
|
using AsbCloudDb.Model.WITS;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
@ -47,6 +48,9 @@ namespace AsbCloudDb.Model
|
|||||||
DbSet<WellOperationCategory> WellOperationCategories { get; }
|
DbSet<WellOperationCategory> WellOperationCategories { get; }
|
||||||
DbSet<WellSectionType> WellSectionTypes { get; }
|
DbSet<WellSectionType> WellSectionTypes { get; }
|
||||||
DbSet<WellType> WellTypes { get; }
|
DbSet<WellType> WellTypes { get; }
|
||||||
|
DbSet<WitsItemFloat> WitsItemFloat { get; }
|
||||||
|
DbSet<WitsItemInt> WitsItemInt { get; }
|
||||||
|
DbSet<WitsItemString> WitsItemString { get; }
|
||||||
DbSet<Driller> Drillers { get; }
|
DbSet<Driller> Drillers { get; }
|
||||||
DbSet<Schedule> Schedule { get; }
|
DbSet<Schedule> Schedule { get; }
|
||||||
DbSet<OperationValue> OperationValues { get; }
|
DbSet<OperationValue> OperationValues { get; }
|
||||||
|
@ -17,10 +17,9 @@ dotnet ef migrations add <MigrationName> --project AsbCloudDb
|
|||||||
```
|
```
|
||||||
## Откатить миграцию
|
## Откатить миграцию
|
||||||
```
|
```
|
||||||
dotnet ef migrations remove <MigrationName> --project AsbCloudDb
|
dotnet ef migrations remove --project AsbCloudDb
|
||||||
```
|
```
|
||||||
\<MigrationName> - Name of migration class.
|
Удаляется последняя созданная миграция.
|
||||||
После создания миграции обязательно прочитать генерированный код.
|
|
||||||
|
|
||||||
## Применить миграции
|
## Применить миграции
|
||||||
При старте проекта применяются автоматически
|
При старте проекта применяются автоматически
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.GTR;
|
||||||
using AsbCloudApp.Data.SAUB;
|
using AsbCloudApp.Data.SAUB;
|
||||||
using AsbCloudApp.Data.Subsystems;
|
using AsbCloudApp.Data.Subsystems;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudApp.Services.Subsystems;
|
using AsbCloudApp.Services.Subsystems;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudDb.Model.GTR;
|
||||||
using AsbCloudDb.Model.Subsystems;
|
using AsbCloudDb.Model.Subsystems;
|
||||||
using AsbCloudInfrastructure.Background;
|
using AsbCloudInfrastructure.Background;
|
||||||
using AsbCloudInfrastructure.Repository;
|
using AsbCloudInfrastructure.Repository;
|
||||||
@ -139,6 +141,7 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<IProcessMapReportMakerService, ProcessMapReportMakerService>();
|
services.AddTransient<IProcessMapReportMakerService, ProcessMapReportMakerService>();
|
||||||
services.AddTransient<IProcessMapReportService, ProcessMapReportService>();
|
services.AddTransient<IProcessMapReportService, ProcessMapReportService>();
|
||||||
services.AddTransient<ITrajectoryVisualizationService, TrajectoryVisualizationService>();
|
services.AddTransient<ITrajectoryVisualizationService, TrajectoryVisualizationService>();
|
||||||
|
services.AddTransient<IGtrRepository, GtrWitsRepository>();
|
||||||
|
|
||||||
// admin crud services:
|
// admin crud services:
|
||||||
services.AddTransient<ICrudRepository<TelemetryDto>, CrudCacheRepositoryBase<TelemetryDto, Telemetry>>(s =>
|
services.AddTransient<ICrudRepository<TelemetryDto>, CrudCacheRepositoryBase<TelemetryDto, Telemetry>>(s =>
|
||||||
|
160
AsbCloudInfrastructure/Repository/GtrWitsRepository.cs
Normal file
160
AsbCloudInfrastructure/Repository/GtrWitsRepository.cs
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
using AsbCloudApp.Data.GTR;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudDb.Model.GTR;
|
||||||
|
using Mapster;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Repository
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
public class GtrWitsRepository : IGtrRepository
|
||||||
|
{
|
||||||
|
private readonly IAsbCloudDbContext db;
|
||||||
|
private readonly ITelemetryService telemetryService;
|
||||||
|
|
||||||
|
public GtrWitsRepository(
|
||||||
|
IAsbCloudDbContext db,
|
||||||
|
ITelemetryService telemetryService)
|
||||||
|
{
|
||||||
|
|
||||||
|
this.db = db;
|
||||||
|
this.telemetryService = telemetryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<WitsRecordDto>> GetAsync(int idWell, DateTime? dateBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var telemetry = telemetryService.GetOrDefaultTelemetryByIdWell(idWell);
|
||||||
|
if (telemetry is null)
|
||||||
|
return Enumerable.Empty<WitsRecordDto>();
|
||||||
|
|
||||||
|
var timezone = telemetryService.GetTimezone(telemetry.Id);
|
||||||
|
|
||||||
|
DateTimeOffset? dateBeginUtc = dateBegin?.ToUtcDateTimeOffset(timezone.Hours);
|
||||||
|
var dateEnd = dateBeginUtc?.AddSeconds(intervalSec);
|
||||||
|
|
||||||
|
var recordAllInt = await GetItemsOrDefaultAsync<WitsItemInt, int>(telemetry.Id, dateBeginUtc, dateEnd, approxPointsCount, timezone.Hours, token);
|
||||||
|
var recordAllFloat = await GetItemsOrDefaultAsync<WitsItemFloat, float>(telemetry.Id, dateBeginUtc, dateEnd, approxPointsCount,timezone.Hours, token);
|
||||||
|
var recordAllString = await GetItemsOrDefaultAsync<WitsItemString, string>(telemetry.Id, dateBeginUtc, dateEnd, approxPointsCount, timezone.Hours, token);
|
||||||
|
|
||||||
|
var dtos = (recordAllFloat.Union(recordAllInt)).Union(recordAllString)
|
||||||
|
.GroupBy(g => new
|
||||||
|
{
|
||||||
|
g.IdRecord,
|
||||||
|
g.Date
|
||||||
|
})
|
||||||
|
.Select(g => new WitsRecordDto
|
||||||
|
{
|
||||||
|
Id = g.Key.IdRecord,
|
||||||
|
Date = g.Key.Date,
|
||||||
|
Items = g.Select(r => new {
|
||||||
|
Key = r.IdItem,
|
||||||
|
Value = r.Item
|
||||||
|
}).ToDictionary(x => x.Key, x => x.Value)
|
||||||
|
});
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IEnumerable<ItemRecord>> GetItemsOrDefaultAsync<TEntity, TValue>(
|
||||||
|
int idTelemetry,
|
||||||
|
DateTimeOffset? dateBegin,
|
||||||
|
DateTimeOffset? dateEnd,
|
||||||
|
int approxPointsCount,
|
||||||
|
double timezoneHours,
|
||||||
|
CancellationToken token)
|
||||||
|
where TEntity: WitsItemBase<TValue>
|
||||||
|
where TValue: notnull
|
||||||
|
{
|
||||||
|
var query = db.Set<TEntity>()
|
||||||
|
.Where(i => i.IdTelemetry == idTelemetry);
|
||||||
|
|
||||||
|
if (dateBegin is not null)
|
||||||
|
query = query
|
||||||
|
.Where(d => d.DateTime >= dateBegin);
|
||||||
|
|
||||||
|
if (dateEnd is not null)
|
||||||
|
query = query
|
||||||
|
.Where(d => d.DateTime <= dateEnd);
|
||||||
|
|
||||||
|
var fullDataCount = await query.CountAsync(token);
|
||||||
|
|
||||||
|
if (fullDataCount == 0)
|
||||||
|
return Enumerable.Empty<ItemRecord>();
|
||||||
|
|
||||||
|
if (fullDataCount > 1.75 * approxPointsCount)
|
||||||
|
{
|
||||||
|
var m = (int)Math.Round(1d * fullDataCount / approxPointsCount);
|
||||||
|
if (m > 1)
|
||||||
|
query = query.Where((d) => (((d.DateTime.DayOfYear * 24 + d.DateTime.Hour) * 60 + d.DateTime.Minute) * 60 + d.DateTime.Second) % m == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var entities = await query
|
||||||
|
.OrderBy(d => d.DateTime)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync(token)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
var items = entities.Select(e => new ItemRecord
|
||||||
|
{
|
||||||
|
IdRecord = e.IdRecord,
|
||||||
|
IdTelemetry = e.IdTelemetry,
|
||||||
|
Date = e.DateTime.ToRemoteDateTime(timezoneHours),
|
||||||
|
IdItem = e.IdItem,
|
||||||
|
Item = new JsonValue(e.Value)
|
||||||
|
});
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveDataAsync(int idTelemetry, WitsRecordDto dto, CancellationToken token)
|
||||||
|
{
|
||||||
|
var timezoneHours = telemetryService.GetTimezone(idTelemetry).Hours;
|
||||||
|
foreach (var item in dto.Items)
|
||||||
|
{
|
||||||
|
var dateTime = dto.Date.ToUtcDateTimeOffset(timezoneHours);
|
||||||
|
if (item.Value.Value is string valueString)
|
||||||
|
{
|
||||||
|
var entity = MakeEntity<WitsItemString, string>( dto.Id, item.Key, idTelemetry, dateTime, valueString);
|
||||||
|
db.WitsItemString.Add(entity);
|
||||||
|
}
|
||||||
|
if (item.Value.Value is float valueFloat)
|
||||||
|
{
|
||||||
|
var entity = MakeEntity<WitsItemFloat, float>(dto.Id, item.Key, idTelemetry, dateTime, valueFloat);
|
||||||
|
db.WitsItemFloat.Add(entity);
|
||||||
|
}
|
||||||
|
if (item.Value.Value is int valueInt)
|
||||||
|
{
|
||||||
|
var entity = MakeEntity<WitsItemInt, int>(dto.Id, item.Key, idTelemetry, dateTime, valueInt);
|
||||||
|
db.WitsItemInt.Add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TEntity MakeEntity<TEntity, TValue>(int idRecord, int idItem, int idTelemetry, DateTimeOffset dateTime, TValue value)
|
||||||
|
where TEntity : WitsItemBase<TValue>, new()
|
||||||
|
where TValue: notnull
|
||||||
|
=> new TEntity() {
|
||||||
|
IdRecord = idRecord,
|
||||||
|
IdItem = idItem,
|
||||||
|
IdTelemetry = idTelemetry,
|
||||||
|
DateTime = dateTime,
|
||||||
|
Value = value,
|
||||||
|
};
|
||||||
|
|
||||||
|
internal class ItemRecord
|
||||||
|
{
|
||||||
|
public int IdRecord { get; set; }
|
||||||
|
public int IdTelemetry { get; set; }
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
public int IdItem { get; set; }
|
||||||
|
public JsonValue Item { get; set; } = default!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
}
|
95
AsbCloudWebApi/Controllers/SAUB/GtrWitsController.cs
Normal file
95
AsbCloudWebApi/Controllers/SAUB/GtrWitsController.cs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
using AsbCloudApp.Data.GTR;
|
||||||
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudWebApi.SignalR;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Controllers.SAUB
|
||||||
|
{
|
||||||
|
#nullable enable
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class GtrWitsController : ControllerBase
|
||||||
|
|
||||||
|
{
|
||||||
|
protected readonly IWellService wellService;
|
||||||
|
private readonly ITelemetryService telemetryService;
|
||||||
|
private readonly IGtrRepository gtrRepository;
|
||||||
|
private readonly IHubContext<TelemetryHub> telemetryHubContext;
|
||||||
|
|
||||||
|
public string SignalRMethodGetDataName { get; protected set; } = "ReceiveData";
|
||||||
|
|
||||||
|
public GtrWitsController(
|
||||||
|
ITelemetryService telemetryService,
|
||||||
|
IGtrRepository gtrRepository,
|
||||||
|
IWellService wellService,
|
||||||
|
IHubContext<TelemetryHub> telemetryHubContext)
|
||||||
|
{
|
||||||
|
this.telemetryService = telemetryService;
|
||||||
|
this.gtrRepository = gtrRepository;
|
||||||
|
this.wellService = wellService;
|
||||||
|
this.telemetryHubContext = telemetryHubContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Получить загруженные данные ГТИ по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <param name = "idWell" > id скважины</param>
|
||||||
|
/// <param name = "begin" > дата начала выборки.По умолчанию: текущее время - intervalSec</param>
|
||||||
|
/// <param name = "intervalSec" > интервал времени даты начала выборки, секунды</param>
|
||||||
|
/// <param name = "approxPointsCount" > желаемое количество точек. Если в выборке точек будет больше, то выборка будет прорежена.</param>
|
||||||
|
/// <param name = "token" > Токен завершения задачи</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("{idWell}")]
|
||||||
|
[Permission]
|
||||||
|
public async Task<ActionResult<IEnumerable<WitsRecordDto>>> GetDataAsync(int idWell, DateTime? begin,
|
||||||
|
int intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
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 content = await gtrRepository.GetAsync(idWell, begin,
|
||||||
|
intervalSec, approxPointsCount, token).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return Ok(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Метод для получения WITS записи от панели оператора.
|
||||||
|
/// Сохраняет в БД.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">уникальный идентификатор телеметрии</param>
|
||||||
|
/// <param name="dto">WITS запись</param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("{uid}")]
|
||||||
|
public async Task<IActionResult> PostDataAsync(
|
||||||
|
string uid,
|
||||||
|
[FromBody] WitsRecordDto dto,
|
||||||
|
CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var idTelemetry = telemetryService.GetOrCreateTelemetryIdByUid(uid);
|
||||||
|
await gtrRepository.SaveDataAsync(idTelemetry, dto, token).ConfigureAwait(false);
|
||||||
|
var idWell = telemetryService.GetIdWellByTelemetryUid(uid);
|
||||||
|
if (idWell is not null && dto is not null)
|
||||||
|
_ = Task.Run(() => telemetryHubContext.Clients.Group($"well_{idWell}_gtr")
|
||||||
|
.SendAsync(SignalRMethodGetDataName, dto), CancellationToken.None);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#nullable disable
|
||||||
|
}
|
74
AsbCloudWebApi/Converters/JsonValueJsonConverter.cs
Normal file
74
AsbCloudWebApi/Converters/JsonValueJsonConverter.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using System.Text.Json;
|
||||||
|
using AsbCloudApp.Data.GTR;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Converters
|
||||||
|
{
|
||||||
|
public class JsonValueJsonConverter : JsonConverter<JsonValue>
|
||||||
|
{
|
||||||
|
public override JsonValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonTokenType.String)
|
||||||
|
{
|
||||||
|
var stringVal = reader.GetString() ?? string.Empty;
|
||||||
|
return new JsonValue(stringVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType == JsonTokenType.Number)
|
||||||
|
{
|
||||||
|
if (reader.TryGetInt32(out int intVal))
|
||||||
|
return new JsonValue(intVal);
|
||||||
|
|
||||||
|
if (reader.TryGetDouble(out double doubleVal))
|
||||||
|
return new JsonValue((float)doubleVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FormatException($"Wrong format at position {reader.Position}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, JsonValue value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
if (value.Value is string strValue)
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(FormatString(strValue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Value is int intValue)
|
||||||
|
{
|
||||||
|
writer.WriteNumberValue(intValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Value is short shortValue)
|
||||||
|
{
|
||||||
|
writer.WriteNumberValue(shortValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Value is float floatValue)
|
||||||
|
{
|
||||||
|
writer.WriteRawValue(floatValue.ToString("#0.0##", CultureInfo.InvariantCulture), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.Value is double doubleValue)
|
||||||
|
{
|
||||||
|
writer.WriteRawValue(doubleValue.ToString("#0.0##", CultureInfo.InvariantCulture), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeName = value.Value.GetType().Name;
|
||||||
|
throw new NotImplementedException($"{typeName} is not supported type for WITS value");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatString(string value)
|
||||||
|
=> value
|
||||||
|
.Replace("\"", "")
|
||||||
|
.Trim()
|
||||||
|
.Replace("\r", "")
|
||||||
|
.Replace("\n", "");
|
||||||
|
}
|
||||||
|
}
|
31
AsbCloudWebApi/Rest/Gtr.http
Normal file
31
AsbCloudWebApi/Rest/Gtr.http
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
@baseUrl = http://127.0.0.1:5000
|
||||||
|
@contentType = application/json
|
||||||
|
@auth = Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCJ9.eyJpZCI6IjEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiZGV2IiwiaWRDb21wYW55IjoiMSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6InJvb3QiLCJuYmYiOjE2NjI1NDgxNjIsImV4cCI6MTY5NDEwNTc2MiwiaXNzIjoiYSIsImF1ZCI6ImEifQ.OEAlNzxi7Jat6pzDBTAjTbChskc-tdJthJexyWwwUKE
|
||||||
|
|
||||||
|
@uid = 20210910_012752700
|
||||||
|
@idCluster = 1
|
||||||
|
@idWell = 1
|
||||||
|
|
||||||
|
# https://marketplace.visualstudio.com/items?itemName=humao.rest-client
|
||||||
|
|
||||||
|
###
|
||||||
|
GET {{baseUrl}}/api/GtrWits/{{idWell}}
|
||||||
|
Content-Type: {{contentType}}
|
||||||
|
accept: */*
|
||||||
|
Authorization: {{auth}}
|
||||||
|
|
||||||
|
### Post
|
||||||
|
POST {{baseUrl}}/api/GtrWits/{{uid}}
|
||||||
|
Content-Type: {{contentType}}
|
||||||
|
accept: */*
|
||||||
|
Authorization: {{auth}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"date": "2023-04-18T08:41:49.332Z",
|
||||||
|
"items": {
|
||||||
|
"1": 1,
|
||||||
|
"2": 1.1,
|
||||||
|
"3": "string1"
|
||||||
|
}
|
||||||
|
}
|
@ -22,13 +22,14 @@ namespace AsbCloudWebApi
|
|||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddControllers()
|
services.AddControllers()
|
||||||
.AddJsonOptions(new System.Action<Microsoft.AspNetCore.Mvc.JsonOptions>(options =>
|
.AddJsonOptions(new System.Action<JsonOptions>(options =>
|
||||||
{
|
{
|
||||||
options.JsonSerializerOptions.NumberHandling =
|
options.JsonSerializerOptions.NumberHandling =
|
||||||
System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals |
|
System.Text.Json.Serialization.JsonNumberHandling.AllowNamedFloatingPointLiterals |
|
||||||
System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString;
|
System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString;
|
||||||
|
|
||||||
options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
|
options.JsonSerializerOptions.Converters.Add(new DateOnlyJsonConverter());
|
||||||
|
options.JsonSerializerOptions.Converters.Add(new JsonValueJsonConverter());
|
||||||
}))
|
}))
|
||||||
.AddProtoBufNet();
|
.AddProtoBufNet();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user