forked from ddrilling/AsbCloudServer
среда:)
This commit is contained in:
parent
31a2e1e878
commit
ef9bb8f39f
@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "ConsoleApp1\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudDb", "AsbCloudDb\AsbCloudDb.csproj", "{40FBD29B-724B-4496-B5D9-1A5D14102456}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsbCloudDb", "AsbCloudDb\AsbCloudDb.csproj", "{40FBD29B-724B-4496-B5D9-1A5D14102456}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaubPanelOnlineSender", "SaubPanelOnlineSender\SaubPanelOnlineSender.csproj", "{B156D582-4D32-4368-A103-687D15B9846C}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -39,6 +41,10 @@ Global
|
|||||||
{40FBD29B-724B-4496-B5D9-1A5D14102456}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{40FBD29B-724B-4496-B5D9-1A5D14102456}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{40FBD29B-724B-4496-B5D9-1A5D14102456}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{40FBD29B-724B-4496-B5D9-1A5D14102456}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{40FBD29B-724B-4496-B5D9-1A5D14102456}.Release|Any CPU.Build.0 = Release|Any CPU
|
{40FBD29B-724B-4496-B5D9-1A5D14102456}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B156D582-4D32-4368-A103-687D15B9846C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B156D582-4D32-4368-A103-687D15B9846C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B156D582-4D32-4368-A103-687D15B9846C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B156D582-4D32-4368-A103-687D15B9846C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -1,25 +1,58 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace AsbCloudApp.Data
|
namespace AsbCloudApp.Data
|
||||||
{
|
{
|
||||||
public class DataSaubBaseDto
|
public class DataSaubBaseDto
|
||||||
{
|
{
|
||||||
|
//[JsonPropertyName("date")]
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Режим работы САУБ:
|
||||||
|
/// 0 - "РУЧНОЙ"
|
||||||
|
/// 1 - "БУРЕНИЕ В РОТОРЕ"
|
||||||
|
/// 2 - "ПРОРАБОТКА"
|
||||||
|
/// 3 - "БУРЕНИЕ В СЛАЙДЕ"
|
||||||
|
/// 4 - "СПУСК СПО"
|
||||||
|
/// 5 - "ПОДЪЕМ СПО"
|
||||||
|
/// 6 - "ПОДЪЕМ С ПРОРАБОТКОЙ"
|
||||||
|
/// 10 - "БЛОКИРОВКА"
|
||||||
|
/// </summary>
|
||||||
public int? Mode { get; set; }
|
public int? Mode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Глубина забоя
|
||||||
|
/// </summary>
|
||||||
public double? WellDepth { get; set; }
|
public double? WellDepth { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Глубина долта
|
||||||
|
/// </summary>
|
||||||
public double? BitDepth { get; set; }
|
public double? BitDepth { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Талевый блок. Высота
|
||||||
|
/// </summary>
|
||||||
public double? BlockHeight { get; set; }
|
public double? BlockHeight { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Талевый блок. Скорость
|
||||||
|
/// </summary>
|
||||||
public double? BlockSpeed { get; set; }
|
public double? BlockSpeed { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Талевый блок. Задание скорости
|
||||||
|
/// </summary>
|
||||||
public double? BlockSpeedSp { get; set; }
|
public double? BlockSpeedSp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Давтение
|
||||||
|
/// </summary>
|
||||||
public double? Pressure { get; set; }
|
public double? Pressure { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Давтение при холостом ходе.
|
||||||
|
/// </summary>
|
||||||
public double? PressureIdle { get; set; }
|
public double? PressureIdle { get; set; }
|
||||||
|
|
||||||
public double? PressureSp { get; set; }
|
public double? PressureSp { get; set; }
|
||||||
|
28
AsbCloudApp/Data/TelemetryDataDto.cs
Normal file
28
AsbCloudApp/Data/TelemetryDataDto.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Формат посылки от панели к облаку.
|
||||||
|
/// Панель копит у себя данные и при удачной отправке помечает как отправленные.
|
||||||
|
/// </summary>
|
||||||
|
public class TelemetryDataDto
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Версия ПО панели.
|
||||||
|
/// Нужна будет для разбора информации
|
||||||
|
/// </summary>
|
||||||
|
public string HmiVersion { get; set; }
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public List<DataSaubBaseDto> DataSaub { get; set; }
|
||||||
|
|
||||||
|
/// TODO:
|
||||||
|
//public List<EventDto> EventsDictiotary { get; set; }
|
||||||
|
|
||||||
|
//public List<MessageDto> Messages { get; set; }
|
||||||
|
}
|
||||||
|
}
|
13
AsbCloudApp/Data/TelemetryInfoDto.cs
Normal file
13
AsbCloudApp/Data/TelemetryInfoDto.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Data
|
||||||
|
{
|
||||||
|
public class TelemetryInfoDto
|
||||||
|
{
|
||||||
|
public string Caption { get; set; }
|
||||||
|
public string Cluster { get; set; }
|
||||||
|
public string Deposit { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,8 @@
|
|||||||
namespace AsbCloudApp.Data
|
namespace AsbCloudApp.Data
|
||||||
{
|
{
|
||||||
public class WellDto
|
public class WellDto : WellInfoDto
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Caption { get; set; }
|
|
||||||
public string Cluster { get; set; }
|
|
||||||
public string Deposit { get; set; }
|
|
||||||
public object LastData { get; set; }//DataSaubBaseDto
|
public object LastData { get; set; }//DataSaubBaseDto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
AsbCloudApp/Data/WellInfoDto.cs
Normal file
9
AsbCloudApp/Data/WellInfoDto.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace AsbCloudApp.Data
|
||||||
|
{
|
||||||
|
public class WellInfoDto
|
||||||
|
{
|
||||||
|
public string Caption { get; set; }
|
||||||
|
public string Cluster { get; set; }
|
||||||
|
public string Deposit { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
AsbCloudApp/Services/ITelemetryDataService.cs
Normal file
11
AsbCloudApp/Services/ITelemetryDataService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services
|
||||||
|
{
|
||||||
|
public interface ITelemetryDataService
|
||||||
|
{
|
||||||
|
IEnumerable<DataSaubBaseDto> Get(int wellId, DateTime dateBegin = default, double intervalSec = 600d, int approxPointsCount = 1024);
|
||||||
|
}
|
||||||
|
}
|
15
AsbCloudApp/Services/ITelemetryService.cs
Normal file
15
AsbCloudApp/Services/ITelemetryService.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudApp.Services
|
||||||
|
{
|
||||||
|
public interface ITelemetryService
|
||||||
|
{
|
||||||
|
void UpdateData(string uid, TelemetryDataDto data);
|
||||||
|
void UpdateInfo(string uid, TelemetryInfoDto info);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
@ -156,5 +158,20 @@ namespace AsbCloudDb.Model
|
|||||||
.Include(e => e.Role)
|
.Include(e => e.Role)
|
||||||
.Include(e => e.Customer)
|
.Include(e => e.Customer)
|
||||||
.Where(e => e.Login == login);
|
.Where(e => e.Login == login);
|
||||||
|
|
||||||
|
public async Task<int> CreatePartitionAsync<TEntity>(string propertyName, int id, CancellationToken token = default)
|
||||||
|
where TEntity: class
|
||||||
|
{
|
||||||
|
var dbSet = Set<TEntity>();
|
||||||
|
var baseTableName = dbSet.EntityType.GetTableName();
|
||||||
|
var schema = dbSet.EntityType.GetSchema();
|
||||||
|
var tableObject = Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier.Table(baseTableName, schema);
|
||||||
|
var tableName = baseTableName.Replace("_base", "");
|
||||||
|
var property = dbSet.EntityType.GetProperty(propertyName).GetColumnName(tableObject);
|
||||||
|
|
||||||
|
var query = $"CREATE TABLE {tableName}_{id} (like {baseTableName} including all, constraint partitioning_check check ({property} = 1)) INHERITS ({baseTableName});";
|
||||||
|
|
||||||
|
return await Database.ExecuteSqlRawAsync(query, token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_cluster"), Comment("Кусты")]
|
[Table("t_cluster"), Comment("Кусты")]
|
||||||
public partial class Cluster
|
public partial class Cluster: IId
|
||||||
{
|
{
|
||||||
public Cluster()
|
public Cluster()
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_customer")]
|
[Table("t_customer")]
|
||||||
public partial class Customer
|
public partial class Customer: IId
|
||||||
{
|
{
|
||||||
public Customer()
|
public Customer()
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_data_saub_base"), Comment("набор основных данных по SAUB")]
|
[Table("t_data_saub_base"), Comment("набор основных данных по SAUB")]
|
||||||
public partial class DataSaubBase
|
public partial class DataSaubBase: IId
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
|
@ -8,7 +8,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_deposit"), Comment("Месторождение")]
|
[Table("t_deposit"), Comment("Месторождение")]
|
||||||
public partial class Deposit
|
public partial class Deposit: IId
|
||||||
{
|
{
|
||||||
public Deposit()
|
public Deposit()
|
||||||
{
|
{
|
||||||
|
@ -25,5 +25,6 @@ namespace AsbCloudDb.Model
|
|||||||
|
|
||||||
IQueryable<Well> GetWellsByCustomer(int idCustomer);
|
IQueryable<Well> GetWellsByCustomer(int idCustomer);
|
||||||
IQueryable<User> GetUsersByLogin(string login);
|
IQueryable<User> GetUsersByLogin(string login);
|
||||||
|
Task<int> CreatePartitionAsync<TEntity>(string propertyName, int id, CancellationToken token = default) where TEntity : class;
|
||||||
}
|
}
|
||||||
}
|
}
|
11
AsbCloudDb/Model/IId.cs
Normal file
11
AsbCloudDb/Model/IId.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AsbCloudDb.Model
|
||||||
|
{
|
||||||
|
public interface IId
|
||||||
|
{
|
||||||
|
public int Id { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_message"), Comment("Сообщения на буровых")]
|
[Table("t_message"), Comment("Сообщения на буровых")]
|
||||||
public partial class Message
|
public partial class Message: IId
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
|
@ -11,7 +11,7 @@ namespace AsbCloudDb.Model
|
|||||||
[Table("t_telemetry"), Comment("таблица привязки телеметрии от комплектов к конкретной скважине.")]
|
[Table("t_telemetry"), Comment("таблица привязки телеметрии от комплектов к конкретной скважине.")]
|
||||||
[Index(nameof(RemoteUid), Name = "t_telemetry_remote_uid_index")]
|
[Index(nameof(RemoteUid), Name = "t_telemetry_remote_uid_index")]
|
||||||
[Index(nameof(Version), Name = "t_telemetry_version_index")]
|
[Index(nameof(Version), Name = "t_telemetry_version_index")]
|
||||||
public partial class Telemetry
|
public partial class Telemetry: IId
|
||||||
{
|
{
|
||||||
public Telemetry()
|
public Telemetry()
|
||||||
{
|
{
|
||||||
@ -26,7 +26,7 @@ namespace AsbCloudDb.Model
|
|||||||
[Column("remote_uid"), Comment("Идентификатор передающего устройства. Может посторяться в списке, так как комплекты оборудования переезжают от скв. к скв.")]
|
[Column("remote_uid"), Comment("Идентификатор передающего устройства. Может посторяться в списке, так как комплекты оборудования переезжают от скв. к скв.")]
|
||||||
public string RemoteUid { get; set; }
|
public string RemoteUid { get; set; }
|
||||||
|
|
||||||
[Column("info", TypeName = "json"), Comment("Информация с панели о скважине")]
|
[Column("info", TypeName = "jsonb"), Comment("Информация с панели о скважине")]
|
||||||
public string Info { get; set; }
|
public string Info { get; set; }
|
||||||
|
|
||||||
[Column("data", TypeName = "json"), Comment("последние пришедшие данные со скважины в сыром виде")]
|
[Column("data", TypeName = "json"), Comment("последние пришедшие данные со скважины в сыром виде")]
|
||||||
@ -39,6 +39,9 @@ namespace AsbCloudDb.Model
|
|||||||
[StringLength(64)]
|
[StringLength(64)]
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
//[Column("time_zone", TypeName = "json"), Comment("Временная зона панели САУБ.")]
|
||||||
|
//public TimeZoneInfo TimeZone { get; set; }
|
||||||
|
|
||||||
[InverseProperty(nameof(Model.Well.Telemetry))]
|
[InverseProperty(nameof(Model.Well.Telemetry))]
|
||||||
public virtual Well Well { get; set; }
|
public virtual Well Well { get; set; }
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_user"), Comment("Пользователи облака")]
|
[Table("t_user"), Comment("Пользователи облака")]
|
||||||
public partial class User
|
public partial class User: IId
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
|
@ -7,7 +7,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_user_role"), Comment("Роли пользователей в системе")]
|
[Table("t_user_role"), Comment("Роли пользователей в системе")]
|
||||||
public class UserRole
|
public class UserRole : IId
|
||||||
{
|
{
|
||||||
public UserRole()
|
public UserRole()
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@ using System.ComponentModel.DataAnnotations.Schema;
|
|||||||
namespace AsbCloudDb.Model
|
namespace AsbCloudDb.Model
|
||||||
{
|
{
|
||||||
[Table("t_well"), Comment("скважины")]
|
[Table("t_well"), Comment("скважины")]
|
||||||
public partial class Well
|
public partial class Well: IId
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
[Column("id")]
|
[Column("id")]
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoMapper" Version="10.1.1" />
|
<PackageReference Include="AutoMapper" Version="10.1.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.8.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services;
|
||||||
|
using AsbCloudInfrastructure.Services.Cache;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
@ -19,18 +20,20 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetService<AsbCloudDbContext>());
|
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetService<AsbCloudDbContext>());
|
||||||
|
|
||||||
services.AddSingleton(new MapperConfiguration(AutoMapperConfig));
|
services.AddSingleton(new MapperConfiguration(AutoMapperConfig));
|
||||||
|
services.AddSingleton(new CacheDb());
|
||||||
|
|
||||||
services.AddTransient<IAuthService, AuthService>();
|
services.AddTransient<IAuthService, AuthService>();
|
||||||
services.AddTransient<IWellService, WellService>();
|
services.AddTransient<IWellService, WellService>();
|
||||||
|
services.AddTransient<ITelemetryService, TelemetryService>();
|
||||||
|
services.AddTransient<ITelemetryDataService, TelemetryDataService>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void AutoMapperConfig(IMapperConfigurationExpression cfg)
|
private static void AutoMapperConfig(IMapperConfigurationExpression cfg)
|
||||||
{
|
{
|
||||||
cfg.CreateMap<DataSaubBase, DataSaubBaseDto>();
|
cfg.CreateMap<DataSaubBase, DataSaubBaseDto>();
|
||||||
|
cfg.CreateMap<DataSaubBaseDto, DataSaubBase>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
AsbCloudInfrastructure/Services/Cache/CacheDb.cs
Normal file
25
AsbCloudInfrastructure/Services/Cache/CacheDb.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.Cache
|
||||||
|
{
|
||||||
|
|
||||||
|
public class CacheDb
|
||||||
|
{
|
||||||
|
private Dictionary<Type, IEnumerable<object>> cache = new Dictionary<Type, IEnumerable<object>>();
|
||||||
|
|
||||||
|
public ICacheTable<TEntity> GetCachedTable<TEntity>(DbContext context)
|
||||||
|
where TEntity : class
|
||||||
|
{
|
||||||
|
var entityType = typeof(TEntity);
|
||||||
|
if (!cache.ContainsKey(entityType))
|
||||||
|
cache[entityType] = new List<TEntity>(8);
|
||||||
|
|
||||||
|
var tableCache = new CacheTable<TEntity>(context, (List<TEntity>)cache[entityType]);
|
||||||
|
return tableCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
272
AsbCloudInfrastructure/Services/Cache/CacheTable.cs
Normal file
272
AsbCloudInfrastructure/Services/Cache/CacheTable.cs
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.Cache
|
||||||
|
{
|
||||||
|
class CacheTable<TEntity> : ICacheTable<TEntity> where TEntity : class
|
||||||
|
{
|
||||||
|
private readonly DbContext context;
|
||||||
|
private List<TEntity> entities;
|
||||||
|
|
||||||
|
internal CacheTable(DbContext context, List<TEntity> entities)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.entities = entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TEntity this[int index] { get => entities.ElementAt(index); }
|
||||||
|
|
||||||
|
|
||||||
|
public int Refresh()
|
||||||
|
{
|
||||||
|
entities.Clear();
|
||||||
|
var dbEntities = context.Set<TEntity>().ToList();
|
||||||
|
entities.AddRange(dbEntities);
|
||||||
|
return entities.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> RefreshAsync(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
entities.Clear();
|
||||||
|
var dbEntities = await context.Set<TEntity>().ToListAsync(token).ConfigureAwait(false);
|
||||||
|
entities.AddRange(dbEntities);
|
||||||
|
return entities.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckRefresh(RefreshMode refreshMode)
|
||||||
|
{
|
||||||
|
if (refreshMode == RefreshMode.Force)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!entities.Any()) && (refreshMode == RefreshMode.IfResultEmpty))
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> CheckRefreshAsync(RefreshMode refreshMode, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (refreshMode == RefreshMode.Force)
|
||||||
|
{
|
||||||
|
await RefreshAsync(token);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!entities.Any()) && (refreshMode == RefreshMode.IfResultEmpty))
|
||||||
|
{
|
||||||
|
await RefreshAsync(token);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty)
|
||||||
|
=> FirstOrDefault(predicate, refreshMode) != default;
|
||||||
|
|
||||||
|
public Task<bool> ContainsAsync(Func<TEntity, bool> predicate, CancellationToken token = default)
|
||||||
|
=> ContainsAsync(predicate, RefreshMode.IfResultEmpty, token);
|
||||||
|
|
||||||
|
public async Task<bool> ContainsAsync(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default)
|
||||||
|
=> await FirstOrDefaultAsync(predicate, refreshMode, token) != default;
|
||||||
|
|
||||||
|
public Task<TEntity> FirstOrDefaultAsync(CancellationToken token = default)
|
||||||
|
=> FirstOrDefaultAsync(RefreshMode.IfResultEmpty, token);
|
||||||
|
|
||||||
|
public TEntity FirstOrDefault(RefreshMode refreshMode = RefreshMode.IfResultEmpty)
|
||||||
|
{
|
||||||
|
bool isUpdated = CheckRefresh(refreshMode);
|
||||||
|
|
||||||
|
var result = entities.FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == default && refreshMode == RefreshMode.IfResultEmpty && !isUpdated)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
return entities.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TEntity> FirstOrDefaultAsync(RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
bool isUpdated = await CheckRefreshAsync(refreshMode, token);
|
||||||
|
|
||||||
|
var result = entities.FirstOrDefault();
|
||||||
|
|
||||||
|
if (result == default && refreshMode == RefreshMode.IfResultEmpty && !isUpdated)
|
||||||
|
{
|
||||||
|
await RefreshAsync(token);
|
||||||
|
return entities.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<TEntity> FirstOrDefaultAsync(Func<TEntity, bool> predicate, CancellationToken token = default)
|
||||||
|
=> FirstOrDefaultAsync(predicate, RefreshMode.IfResultEmpty, token);
|
||||||
|
|
||||||
|
public TEntity FirstOrDefault(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty)
|
||||||
|
{
|
||||||
|
bool isUpdated = CheckRefresh(refreshMode);
|
||||||
|
|
||||||
|
var result = entities.FirstOrDefault(predicate);
|
||||||
|
|
||||||
|
if (result == default && refreshMode == RefreshMode.IfResultEmpty && !isUpdated)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
return entities.FirstOrDefault(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TEntity> FirstOrDefaultAsync(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
bool isUpdated = await CheckRefreshAsync(refreshMode, token);
|
||||||
|
|
||||||
|
var result = entities.FirstOrDefault(predicate);
|
||||||
|
|
||||||
|
if (result == default && refreshMode == RefreshMode.IfResultEmpty && !isUpdated)
|
||||||
|
{
|
||||||
|
await RefreshAsync(token);
|
||||||
|
return entities.FirstOrDefault(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IEnumerable<TEntity>> SelectAsync(Func<TEntity, bool> predicate, CancellationToken token = default)
|
||||||
|
=> SelectAsync(predicate, RefreshMode.IfResultEmpty, token);
|
||||||
|
|
||||||
|
public IEnumerable<TEntity> Select(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty)
|
||||||
|
{
|
||||||
|
bool isUpdated = CheckRefresh(refreshMode);
|
||||||
|
|
||||||
|
var result = entities.Where(predicate);
|
||||||
|
|
||||||
|
if (!result.Any() && refreshMode == RefreshMode.IfResultEmpty && !isUpdated)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
return entities.Where(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TEntity>> SelectAsync(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
bool isUpdated = await CheckRefreshAsync(refreshMode, token);
|
||||||
|
|
||||||
|
var result = entities.Where(predicate);
|
||||||
|
|
||||||
|
if (!result.Any() && refreshMode == RefreshMode.IfResultEmpty && !isUpdated)
|
||||||
|
{
|
||||||
|
await RefreshAsync(token);
|
||||||
|
return entities.Where(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TEntity> Update(Func<TEntity, bool> predicate, Action<TEntity> mutation)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var dbEntities = dbSet.Where(predicate);
|
||||||
|
if (dbEntities.Any())
|
||||||
|
{
|
||||||
|
foreach (var dbEntity in dbEntities)
|
||||||
|
mutation(dbEntity);
|
||||||
|
context.SaveChanges();
|
||||||
|
}
|
||||||
|
entities.RemoveAll(e => predicate(e));
|
||||||
|
entities.AddRange(dbEntities);
|
||||||
|
return dbEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TEntity>> UpdateAsync(Func<TEntity, bool> predicate, Action<TEntity> mutation, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var dbEntities = dbSet.Where(predicate);
|
||||||
|
if (dbEntities.Any())
|
||||||
|
{
|
||||||
|
foreach (var dbEntity in dbEntities)
|
||||||
|
mutation(dbEntity);
|
||||||
|
await context.SaveChangesAsync(token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
entities.RemoveAll(e => predicate(e));
|
||||||
|
entities.AddRange(dbEntities);
|
||||||
|
return dbEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Func<TEntity, bool> predicate)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
entities.RemoveAll(e => predicate(e));
|
||||||
|
dbSet.RemoveRange(dbSet.Where(predicate));
|
||||||
|
context.SaveChanges();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveAsync(Func<TEntity, bool> predicate, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
entities.RemoveAll(e => predicate(e));
|
||||||
|
dbSet.RemoveRange(dbSet.Where(predicate));
|
||||||
|
await context.SaveChangesAsync(token).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TEntity Insert(TEntity entity)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var dbEntity = dbSet.Add(entity).Entity;
|
||||||
|
context.SaveChanges();
|
||||||
|
entities.Add(dbEntity);
|
||||||
|
return dbEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TEntity> InsertAsync(TEntity entity, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var dbEntity = dbSet.Add(entity).Entity;
|
||||||
|
await context.SaveChangesAsync(token).ConfigureAwait(false);
|
||||||
|
entities.Add(dbEntity);
|
||||||
|
return dbEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TEntity> Insert(IEnumerable<TEntity> newEntities)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var dbEntities = new List<TEntity>(newEntities.Count());
|
||||||
|
foreach (var item in newEntities)
|
||||||
|
dbEntities.Add(dbSet.Add(item).Entity);
|
||||||
|
context.SaveChanges();
|
||||||
|
entities.AddRange(dbEntities);
|
||||||
|
return dbEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TEntity>> InsertAsync(IEnumerable<TEntity> newEntities, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
var dbSet = context.Set<TEntity>();
|
||||||
|
var dbEntities = new List<TEntity>(newEntities.Count());
|
||||||
|
foreach (var item in newEntities)
|
||||||
|
dbEntities.Add(dbSet.Add(item).Entity);
|
||||||
|
await context.SaveChangesAsync(token).ConfigureAwait(false);
|
||||||
|
entities.AddRange(dbEntities);
|
||||||
|
return dbEntities;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
37
AsbCloudInfrastructure/Services/Cache/ICacheTable.cs
Normal file
37
AsbCloudInfrastructure/Services/Cache/ICacheTable.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.Cache
|
||||||
|
{
|
||||||
|
public interface ICacheTable<TEntity> where TEntity : class
|
||||||
|
{
|
||||||
|
TEntity this[int index] { get; }
|
||||||
|
int Refresh();
|
||||||
|
bool Contains(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty);
|
||||||
|
TEntity FirstOrDefault(RefreshMode refreshMode = RefreshMode.IfResultEmpty);
|
||||||
|
TEntity FirstOrDefault(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty);
|
||||||
|
IEnumerable<TEntity> Insert(IEnumerable<TEntity> newEntities);
|
||||||
|
TEntity Insert(TEntity entity);
|
||||||
|
void Remove(Func<TEntity, bool> predicate);
|
||||||
|
IEnumerable<TEntity> Select(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty);
|
||||||
|
IEnumerable<TEntity> Update(Func<TEntity, bool> predicate, Action<TEntity> mutation);
|
||||||
|
|
||||||
|
//----- ASYNC ------
|
||||||
|
|
||||||
|
Task<int> RefreshAsync(CancellationToken token = default);
|
||||||
|
Task<bool> ContainsAsync(Func<TEntity, bool> predicate, CancellationToken token = default);
|
||||||
|
Task<bool> ContainsAsync(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default);
|
||||||
|
Task<TEntity> FirstOrDefaultAsync(CancellationToken token = default);
|
||||||
|
Task<TEntity> FirstOrDefaultAsync(RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default);
|
||||||
|
Task<TEntity> FirstOrDefaultAsync(Func<TEntity, bool> predicate, CancellationToken token = default);
|
||||||
|
Task<TEntity> FirstOrDefaultAsync(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default);
|
||||||
|
Task<IEnumerable<TEntity>> InsertAsync(IEnumerable<TEntity> newEntities, CancellationToken token = default);
|
||||||
|
Task<TEntity> InsertAsync(TEntity entity, CancellationToken token = default);
|
||||||
|
Task RemoveAsync(Func<TEntity, bool> predicate, CancellationToken token = default);
|
||||||
|
Task<IEnumerable<TEntity>> SelectAsync(Func<TEntity, bool> predicate, CancellationToken token = default);
|
||||||
|
Task<IEnumerable<TEntity>> SelectAsync(Func<TEntity, bool> predicate, RefreshMode refreshMode = RefreshMode.IfResultEmpty, CancellationToken token = default);
|
||||||
|
Task<IEnumerable<TEntity>> UpdateAsync(Func<TEntity, bool> predicate, Action<TEntity> mutation, CancellationToken token = default);
|
||||||
|
}
|
||||||
|
}
|
4
AsbCloudInfrastructure/Services/Cache/RefreshMode.cs
Normal file
4
AsbCloudInfrastructure/Services/Cache/RefreshMode.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
namespace AsbCloudInfrastructure.Services.Cache
|
||||||
|
{
|
||||||
|
public enum RefreshMode { None, IfResultEmpty, Force, }
|
||||||
|
}
|
68
AsbCloudInfrastructure/Services/TelemetryDataService.cs
Normal file
68
AsbCloudInfrastructure/Services/TelemetryDataService.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Services.Cache;
|
||||||
|
using AutoMapper;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services
|
||||||
|
{
|
||||||
|
public class TelemetryDataService : ITelemetryDataService
|
||||||
|
{
|
||||||
|
private IAsbCloudDbContext db;
|
||||||
|
private IMapper mapper;
|
||||||
|
private ICacheTable<Telemetry> cacheTelemetry;
|
||||||
|
private ICacheTable<Well> cacheWells;
|
||||||
|
|
||||||
|
public TelemetryDataService(IAsbCloudDbContext db, CacheDb cacheDb, MapperConfiguration mapperConfiguration)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
mapper = mapperConfiguration.CreateMapper();
|
||||||
|
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
|
||||||
|
cacheWells = cacheDb.GetCachedTable<Well>((AsbCloudDbContext)db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DataSaubBaseDto> Get(int wellId, DateTime dateBegin = default, double intervalSec = 600d, int approxPointsCount = 1024)
|
||||||
|
{
|
||||||
|
var well = cacheWells.FirstOrDefault(w => w.Id == wellId);
|
||||||
|
if (well is null)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
var telemetry = cacheTelemetry.FirstOrDefault(t => t.Id == well.IdTelemetry);
|
||||||
|
if (telemetry is null)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
if(dateBegin == default)
|
||||||
|
dateBegin = DateTime.Now.AddSeconds(-intervalSec);
|
||||||
|
|
||||||
|
var datEnd = dateBegin.AddSeconds(intervalSec);
|
||||||
|
|
||||||
|
var fullData = from data in db.DataSaubBases
|
||||||
|
where data.IdTelemetry == telemetry.Id
|
||||||
|
&& data.Date >= dateBegin && data.Date < datEnd
|
||||||
|
select data;
|
||||||
|
|
||||||
|
var fullDataCount = fullData.Count();
|
||||||
|
|
||||||
|
if (fullDataCount == 0)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
if (fullDataCount > 1.2 * approxPointsCount)
|
||||||
|
{
|
||||||
|
var m = approxPointsCount / fullDataCount;
|
||||||
|
fullData = fullData.Where(d => d.Id % m == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbData = fullData.ToList();
|
||||||
|
var result = new List<DataSaubBaseDto>(dbData.Count);
|
||||||
|
|
||||||
|
foreach (var item in dbData)
|
||||||
|
result.Add(mapper.Map<DataSaubBaseDto>(item));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
AsbCloudInfrastructure/Services/TelemetryService.cs
Normal file
71
AsbCloudInfrastructure/Services/TelemetryService.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Services.Cache;
|
||||||
|
using AutoMapper;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services
|
||||||
|
{
|
||||||
|
public class TelemetryService : ITelemetryService
|
||||||
|
{
|
||||||
|
private readonly IAsbCloudDbContext db;
|
||||||
|
private readonly IMapper mapper;
|
||||||
|
private readonly ICacheTable<Telemetry> cacheTelemetry;
|
||||||
|
|
||||||
|
public TelemetryService(IAsbCloudDbContext db, CacheDb cacheDb, MapperConfiguration mapperConfiguration)
|
||||||
|
{
|
||||||
|
this.db = db;
|
||||||
|
mapper = mapperConfiguration.CreateMapper();
|
||||||
|
cacheTelemetry = cacheDb.GetCachedTable<Telemetry>((AsbCloudDbContext)db);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateData(string uid, TelemetryDataDto data)
|
||||||
|
{
|
||||||
|
var telemetry = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid, RefreshMode.IfResultEmpty);
|
||||||
|
|
||||||
|
if(telemetry is null)
|
||||||
|
{
|
||||||
|
var newTelemetry = new Telemetry
|
||||||
|
{
|
||||||
|
RemoteUid = uid,
|
||||||
|
Version = data.HmiVersion,
|
||||||
|
Data = JsonSerializer.Serialize(data),
|
||||||
|
LastDataSaub = JsonSerializer.Serialize(data.DataSaub),
|
||||||
|
};
|
||||||
|
telemetry = cacheTelemetry.Insert(newTelemetry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.DataSaub != default)
|
||||||
|
{
|
||||||
|
foreach (var item in data.DataSaub)
|
||||||
|
{
|
||||||
|
var dataSaub = mapper.Map<DataSaubBase>(item);
|
||||||
|
dataSaub.IdTelemetry = telemetry.Id;
|
||||||
|
db.DataSaubBases.Add(dataSaub);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateInfo(string uid, TelemetryInfoDto info)
|
||||||
|
{
|
||||||
|
var telemetry = cacheTelemetry.FirstOrDefault(t => t.RemoteUid == uid);
|
||||||
|
if (telemetry is null)
|
||||||
|
{
|
||||||
|
var newTelemetry = new Telemetry
|
||||||
|
{
|
||||||
|
RemoteUid = uid,
|
||||||
|
Info = JsonSerializer.Serialize(info),
|
||||||
|
};
|
||||||
|
telemetry = cacheTelemetry.Insert(newTelemetry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace AsbCloudApp
|
|
||||||
{
|
|
||||||
public class TinyMapper<Tout, Tin>
|
|
||||||
where Tout: new()
|
|
||||||
{
|
|
||||||
private ConstructorInfo[] ctors;
|
|
||||||
|
|
||||||
public TinyMapper()
|
|
||||||
{
|
|
||||||
ctors = typeof(Tin).GetConstructors();
|
|
||||||
typeof(Tin).GetProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
//public Tout Map(Tin original, params object?[]? ctorParameters)
|
|
||||||
//{
|
|
||||||
// var result = new Tout();
|
|
||||||
// var convertion
|
|
||||||
// return result;
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
41
AsbCloudWebApi/Controllers/DataController.cs
Normal file
41
AsbCloudWebApi/Controllers/DataController.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Контроллер сбора данных от буровых
|
||||||
|
/// </summary>
|
||||||
|
[Route("api/well")]
|
||||||
|
[ApiController]
|
||||||
|
[Authorize]
|
||||||
|
public class DataController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ITelemetryDataService telemetryDataService;
|
||||||
|
|
||||||
|
public DataController(ITelemetryDataService telemetryDataService)
|
||||||
|
{
|
||||||
|
this.telemetryDataService = telemetryDataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Возвращает данные САУБ по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wellId"></param>
|
||||||
|
/// <param name=""></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[Route("{wellId}/data")]
|
||||||
|
[ProducesResponseType(typeof(IEnumerable<DataSaubBaseDto>), (int)System.Net.HttpStatusCode.OK)]
|
||||||
|
public IActionResult Get(int wellId)
|
||||||
|
{
|
||||||
|
return Ok(telemetryDataService.Get(wellId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
AsbCloudWebApi/Controllers/TelemetryController.cs
Normal file
51
AsbCloudWebApi/Controllers/TelemetryController.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Controllers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Контроллер сбора данных от буровых
|
||||||
|
/// </summary>
|
||||||
|
[Route("api/telemetry")]
|
||||||
|
[ApiController]
|
||||||
|
public class TelemetryController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly ITelemetryService telemetryService;
|
||||||
|
|
||||||
|
public TelemetryController(ITelemetryService telemetryService)
|
||||||
|
{
|
||||||
|
this.telemetryService = telemetryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Принимает общую информацию по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
[Route("{uid}/info")]
|
||||||
|
public IActionResult Info(string uid, [FromBody] TelemetryInfoDto info)
|
||||||
|
{
|
||||||
|
telemetryService.UpdateInfo(uid, info);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Принимает данные от разных систем по скважине
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost]
|
||||||
|
[Route("{uid}/data")]
|
||||||
|
public IActionResult Data(string uid, [FromBody] TelemetryDataDto data)
|
||||||
|
{
|
||||||
|
telemetryService.UpdateData(uid, data);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers
|
namespace AsbCloudWebApi.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/[controller]")]
|
[Route("api/well")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class WellController : ControllerBase
|
public class WellController : ControllerBase
|
||||||
@ -34,21 +34,5 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
return Ok(wells);
|
return Ok(wells);
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Route("{id}")]
|
|
||||||
//[HttpGet]
|
|
||||||
//[ProducesResponseType(typeof(IEnumerable<WellDto>), (int)System.Net.HttpStatusCode.OK)]
|
|
||||||
//public IActionResult GetByCustomer(int id)
|
|
||||||
//{
|
|
||||||
// var claimIdCustomer = User.FindFirst("IdCustomer");
|
|
||||||
|
|
||||||
// if (claimIdCustomer is null)
|
|
||||||
// return NoContent();
|
|
||||||
|
|
||||||
// var idCustomer = int.Parse(claimIdCustomer.Value);
|
|
||||||
|
|
||||||
// var wells = wellService.GetWellsByCustomer(idCustomer);
|
|
||||||
|
|
||||||
// return Ok(wells);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
ConsoleApp1/Header.cs
Normal file
8
ConsoleApp1/Header.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace ConsoleApp1
|
||||||
|
{
|
||||||
|
public class Header
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public System.Type PropertyType { get; set; } = typeof(object);
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,60 @@
|
|||||||
using AsbCloudDb.Model;
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudInfrastructure.Services.Cache;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using BenchmarkDotNet.Attributes;
|
using BenchmarkDotNet.Attributes;
|
||||||
using BenchmarkDotNet.Running;
|
using BenchmarkDotNet.Running;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace ConsoleApp1
|
namespace ConsoleApp1
|
||||||
{
|
{
|
||||||
|
public class A {
|
||||||
|
public int P1 { get; set; }
|
||||||
|
public int P2 { get; set; }
|
||||||
|
};
|
||||||
|
|
||||||
|
public class B
|
||||||
|
{
|
||||||
|
public int P1 { get; set; }
|
||||||
|
public int P3 { get; set; }
|
||||||
|
};
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
//var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
|
||||||
|
// .UseNpgsql("Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True")
|
||||||
|
// .Options;
|
||||||
|
//var context = new AsbCloudDbContext(options);
|
||||||
|
|
||||||
|
var table = new Table
|
||||||
|
{
|
||||||
|
Headers = new List<Header>
|
||||||
|
{
|
||||||
|
new Header {Name = "P1", PropertyType = typeof(int) },
|
||||||
|
new Header {Name = "P2", PropertyType = typeof(int) },
|
||||||
|
new Header {Name = "P3", PropertyType = typeof(int) },
|
||||||
|
},
|
||||||
|
|
||||||
|
Rows = new List<object[]>
|
||||||
|
{
|
||||||
|
new object[] {1,2,3 },
|
||||||
|
new object[] {4,5,6 },
|
||||||
|
new object[] {7,8,9 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var mapper = new TableMapper<B>();
|
||||||
|
|
||||||
|
var b = new B();
|
||||||
|
mapper.UpdateObjectFromTable(ref b, table, 1);
|
||||||
|
|
||||||
Console.WriteLine("Done");
|
Console.WriteLine("Done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
ConsoleApp1/Table.cs
Normal file
17
ConsoleApp1/Table.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ConsoleApp1
|
||||||
|
{
|
||||||
|
public class Table
|
||||||
|
{
|
||||||
|
public IEnumerable<Header> Headers { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<IEnumerable<object>> Rows { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
97
ConsoleApp1/TableMapper.cs
Normal file
97
ConsoleApp1/TableMapper.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ConsoleApp1
|
||||||
|
{
|
||||||
|
// для работы с таблицами
|
||||||
|
public class TableMapper<T>
|
||||||
|
{
|
||||||
|
Dictionary<string, PropertyHelper> props;
|
||||||
|
|
||||||
|
public TableMapper()
|
||||||
|
{
|
||||||
|
var props = typeof(T).GetProperties();
|
||||||
|
this.props = new Dictionary<string, PropertyHelper>(props.Length);
|
||||||
|
foreach (var prop in props)
|
||||||
|
{
|
||||||
|
var helper = new PropertyHelper(prop);
|
||||||
|
this.props.Add(helper.Id, helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int UpdateObjectFromTable(ref T obj, Table table, int rowIndex)
|
||||||
|
{
|
||||||
|
var updatesCount = 0;
|
||||||
|
if (table.Rows.Count() <= rowIndex)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var row = table.Rows.ElementAt(rowIndex);
|
||||||
|
var headerIndex = 0;
|
||||||
|
|
||||||
|
foreach (var header in table.Headers)
|
||||||
|
{
|
||||||
|
var headerId = PropertyHelper.MakeIdentity(header.PropertyType.Name, header.Name);
|
||||||
|
if (props.ContainsKey(headerId))
|
||||||
|
{
|
||||||
|
props[headerId].Set(obj, row.ElementAt(headerIndex));
|
||||||
|
updatesCount++;
|
||||||
|
}
|
||||||
|
headerIndex++;
|
||||||
|
}
|
||||||
|
return updatesCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ускоренный обработчик свойства
|
||||||
|
/// </summary>
|
||||||
|
class PropertyHelper
|
||||||
|
{
|
||||||
|
public PropertyHelper(PropertyInfo property)
|
||||||
|
{
|
||||||
|
PropertyName = property.Name;
|
||||||
|
PropertyType = property.PropertyType;
|
||||||
|
Id = MakeIdentity(property.PropertyType.Name, property.Name);
|
||||||
|
|
||||||
|
var setter = property.SetMethod;
|
||||||
|
var getter = property.GetMethod;
|
||||||
|
|
||||||
|
var instanceExpression = Expression.Parameter(typeof(object), "instance");
|
||||||
|
var argumentsExpression = Expression.Parameter(typeof(object[]), "arguments");
|
||||||
|
var argumentExpressions = new List<Expression> { Expression.Convert(Expression.ArrayIndex(argumentsExpression, Expression.Constant(0)), PropertyType) };
|
||||||
|
var callExpression = Expression.Call(Expression.Convert(instanceExpression, setter.ReflectedType), setter, argumentExpressions);
|
||||||
|
Setter = Expression.Lambda<SetterDelegate>(callExpression, instanceExpression, argumentsExpression).Compile();
|
||||||
|
|
||||||
|
callExpression = Expression.Call(Expression.Convert(instanceExpression, getter.ReflectedType), getter);
|
||||||
|
Getter = Expression.Lambda<GetterDelegate>(Expression.Convert(callExpression, typeof(object)), instanceExpression).Compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PropertyName { get;}
|
||||||
|
public Type PropertyType { get; }
|
||||||
|
public string Id { get; }
|
||||||
|
|
||||||
|
delegate void SetterDelegate(object instanse, object[] values);
|
||||||
|
|
||||||
|
delegate object GetterDelegate(object instanse);
|
||||||
|
|
||||||
|
SetterDelegate Setter { get; }
|
||||||
|
GetterDelegate Getter { get; }
|
||||||
|
|
||||||
|
void SetValues(object instance, params object[] values)
|
||||||
|
=> Setter(instance, values);
|
||||||
|
|
||||||
|
public void Set(object instance, object value)
|
||||||
|
=> SetValues(instance, value);
|
||||||
|
|
||||||
|
public object Get(object instance)
|
||||||
|
=> Getter(instance);
|
||||||
|
|
||||||
|
public static string MakeIdentity(string propertyTypeName, string propertyName) => $"{propertyTypeName}_{propertyName}".ToLower();
|
||||||
|
}
|
||||||
|
}
|
51
SaubPanelOnlineSender/CloudDataSender.cs
Normal file
51
SaubPanelOnlineSender/CloudDataSender.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SaubPanelOnlineSender
|
||||||
|
{
|
||||||
|
public class CloudDataSender
|
||||||
|
{
|
||||||
|
public CloudDataSender() { }
|
||||||
|
|
||||||
|
public string OnlineUrl => "http://localhost:5000/api/telemetry/0A:00:27:00:11:12/data";
|
||||||
|
|
||||||
|
public void Send(DataSaubBaseDto data)
|
||||||
|
{
|
||||||
|
var request = MakeRequest();
|
||||||
|
using var streamWriter = request.GetRequestStream();
|
||||||
|
var requestBodyJson = MakeRequestBody(data);
|
||||||
|
var dataBytes = Encoding.UTF8.GetBytes(requestBodyJson);
|
||||||
|
streamWriter.Write(dataBytes, 0, dataBytes.Length);
|
||||||
|
var response = request.GetResponse();
|
||||||
|
streamWriter.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpWebRequest MakeRequest()
|
||||||
|
{
|
||||||
|
var request = WebRequest.CreateHttp(OnlineUrl);
|
||||||
|
request.Method = "POST";
|
||||||
|
request.Timeout = 4900;
|
||||||
|
request.ContentType = "application/json";
|
||||||
|
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
|
||||||
|
request.ServicePoint.Expect100Continue = false;
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MakeRequestBody(DataSaubBaseDto dataSaub)
|
||||||
|
{
|
||||||
|
var telemetry = new TelemetryDataDto
|
||||||
|
{
|
||||||
|
Date = DateTime.Now,
|
||||||
|
DataSaub = new List<DataSaubBaseDto> { dataSaub },
|
||||||
|
HmiVersion = "3.1",
|
||||||
|
UserName = "online sender",
|
||||||
|
};
|
||||||
|
|
||||||
|
return Newtonsoft.Json.JsonConvert.SerializeObject(telemetry);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
140
SaubPanelOnlineSender/DbPlayerService.cs
Normal file
140
SaubPanelOnlineSender/DbPlayerService.cs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SaubPanelOnlineSender
|
||||||
|
{
|
||||||
|
public enum DbPlayerServiceState
|
||||||
|
{
|
||||||
|
Unaviable,
|
||||||
|
Stopped,
|
||||||
|
Paused,
|
||||||
|
Working
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DbPlayerService
|
||||||
|
{
|
||||||
|
public DbPlayerServiceState State
|
||||||
|
{
|
||||||
|
get => state;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (state == value)
|
||||||
|
return;
|
||||||
|
state = value;
|
||||||
|
OnStateUpdate?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime LastSentDate { get; private set; }
|
||||||
|
|
||||||
|
public EventHandler<double> OnProcessUpdate;
|
||||||
|
public EventHandler<Exception> OnError;
|
||||||
|
public EventHandler OnStateUpdate;
|
||||||
|
|
||||||
|
private CancellationTokenSource cancellationTokenSource;
|
||||||
|
private DbPlayerServiceState state;
|
||||||
|
|
||||||
|
private static readonly Random rnd = new Random((int)DateTime.Now.Ticks);
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
State = DbPlayerServiceState.Working;
|
||||||
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
//dataSender = new ModbusDataSender(Host);
|
||||||
|
Task.Run(async () => await Work(cancellationTokenSource.Token));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
State = State == DbPlayerServiceState.Paused
|
||||||
|
? DbPlayerServiceState.Working
|
||||||
|
: DbPlayerServiceState.Paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
State = DbPlayerServiceState.Stopped;
|
||||||
|
cancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task Work(CancellationToken token)
|
||||||
|
{
|
||||||
|
var period = TimeSpan.FromSeconds(1);
|
||||||
|
DateTime nextTime;
|
||||||
|
var dataSender = new CloudDataSender();
|
||||||
|
|
||||||
|
while (!token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
nextTime = DateTime.Now + period;
|
||||||
|
if ((State != DbPlayerServiceState.Working)
|
||||||
|
&& ((State != DbPlayerServiceState.Paused)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (State == DbPlayerServiceState.Paused)
|
||||||
|
{
|
||||||
|
await Task.Delay(100, token).ConfigureAwait(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (State == DbPlayerServiceState.Working)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dataSender.Send(MakeDataSaubBaseDto());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
OnError?.Invoke(this, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
OnProcessUpdate?.Invoke(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var waitTime = nextTime - DateTime.Now;
|
||||||
|
if (waitTime.TotalMilliseconds > 0)
|
||||||
|
await Task.Delay(waitTime, token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static DataSaubBaseDto MakeDataSaubBaseDto()
|
||||||
|
{
|
||||||
|
return new DataSaubBaseDto
|
||||||
|
{
|
||||||
|
Date = DateTime.Now,
|
||||||
|
AxialLoad = rnd.NextDouble()*100d,
|
||||||
|
AxialLoadLimitMax = rnd.NextDouble()*100d,
|
||||||
|
AxialLoadSp = rnd.NextDouble()*100d,
|
||||||
|
BitDepth = rnd.NextDouble()*100d,
|
||||||
|
BlockHeight = rnd.NextDouble()*100d,
|
||||||
|
BlockSpeed = rnd.NextDouble()*100d,
|
||||||
|
WellDepth = rnd.NextDouble()*100d,
|
||||||
|
BlockSpeedSp = rnd.NextDouble()*100d,
|
||||||
|
Flow = rnd.NextDouble()*100d,
|
||||||
|
FlowDeltaLimitMax = rnd.NextDouble()*100d,
|
||||||
|
FlowIdle = rnd.NextDouble()*100d,
|
||||||
|
HookWeight = rnd.NextDouble()*100d,
|
||||||
|
HookWeightIdle = rnd.NextDouble()*100d,
|
||||||
|
HookWeightLimitMax = rnd.NextDouble()*100d,
|
||||||
|
HookWeightLimitMin= rnd.NextDouble() * 100d,
|
||||||
|
Mode= 1,
|
||||||
|
Pressure= rnd.NextDouble() * 100d,
|
||||||
|
PressureDeltaLimitMax= rnd.NextDouble() * 100d,
|
||||||
|
PressureIdle= rnd.NextDouble() * 100d,
|
||||||
|
PressureSp= rnd.NextDouble() * 100d,
|
||||||
|
RotorSpeed= rnd.NextDouble() * 100d,
|
||||||
|
RotorTorque= rnd.NextDouble() * 100d,
|
||||||
|
RotorTorqueIdle= rnd.NextDouble() * 100d,
|
||||||
|
RotorTorqueLimitMax= rnd.NextDouble() * 100d,
|
||||||
|
RotorTorqueSp= rnd.NextDouble() * 100d,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
SaubPanelOnlineSender/Program.cs
Normal file
88
SaubPanelOnlineSender/Program.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace SaubPanelOnlineSender
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(/*string[] args*/)
|
||||||
|
{
|
||||||
|
Console.Write("player starting\n");
|
||||||
|
Console.Write("press `Esc` or `Q` to quit\n");
|
||||||
|
Console.Write("press `p` to pause/unpause\n");
|
||||||
|
Console.Write("press `s` to stop/start\n");
|
||||||
|
|
||||||
|
var playerService = new DbPlayerService();
|
||||||
|
|
||||||
|
playerService.OnProcessUpdate =
|
||||||
|
(s, a) => Console.Write($"Sent: {playerService.LastSentDate:G}\n");
|
||||||
|
playerService.OnStateUpdate =
|
||||||
|
(s, a) => Console.Write($"\nState: {playerService.State}\n");
|
||||||
|
playerService.OnError =
|
||||||
|
(s, a) =>
|
||||||
|
{
|
||||||
|
var color = Console.ForegroundColor;
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.Write($"ERROR: {a.Message}");
|
||||||
|
Console.ForegroundColor = color;
|
||||||
|
Console.Write("\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
playerService.Start();
|
||||||
|
|
||||||
|
if (Console.IsInputRedirected)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (Console.KeyAvailable)
|
||||||
|
{
|
||||||
|
var key = Console.ReadKey().Key;
|
||||||
|
if ((key == ConsoleKey.Escape) ||
|
||||||
|
(key == ConsoleKey.Q))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (key == ConsoleKey.P)
|
||||||
|
{
|
||||||
|
switch (playerService.State)
|
||||||
|
{
|
||||||
|
case DbPlayerServiceState.Paused:
|
||||||
|
case DbPlayerServiceState.Working:
|
||||||
|
playerService.Pause();
|
||||||
|
break;
|
||||||
|
case DbPlayerServiceState.Unaviable:
|
||||||
|
case DbPlayerServiceState.Stopped:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == ConsoleKey.S)
|
||||||
|
{
|
||||||
|
switch (playerService.State)
|
||||||
|
{
|
||||||
|
case DbPlayerServiceState.Working:
|
||||||
|
playerService.Stop();
|
||||||
|
break;
|
||||||
|
case DbPlayerServiceState.Stopped:
|
||||||
|
playerService.Start();
|
||||||
|
break;
|
||||||
|
case DbPlayerServiceState.Unaviable:
|
||||||
|
case DbPlayerServiceState.Paused:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playerService.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
SaubPanelOnlineSender/REAMDE.md
Normal file
2
SaubPanelOnlineSender/REAMDE.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
* Назначение
|
||||||
|
проект предназначен для иммитации работы панели САУБ для НОВОГО облака.
|
12
SaubPanelOnlineSender/SaubPanelOnlineSender.csproj
Normal file
12
SaubPanelOnlineSender/SaubPanelOnlineSender.csproj
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AsbCloudApp\AsbCloudApp.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
Loading…
Reference in New Issue
Block a user