diff --git a/PARR.API/Contracts/V1/ApiRoutes.cs b/PARR.API/Contracts/V1/ApiRoutes.cs
index fea903f7..daf87d89 100644
--- a/PARR.API/Contracts/V1/ApiRoutes.cs
+++ b/PARR.API/Contracts/V1/ApiRoutes.cs
@@ -218,6 +218,12 @@
public const string GetConnectionStats = BaseStat + "/rabbitmq-connections/";
}
+ public static class StatRobotState
+ {
+ public const string Get = BaseStat + "/robot-states/";
+ public const string Send = BaseStat + "/robot-states/";
+ }
+
#endregion
#region Наряды
diff --git a/PARR.API/Contracts/V1/Requests/RobotStateRequest.cs b/PARR.API/Contracts/V1/Requests/RobotStateRequest.cs
new file mode 100644
index 00000000..b0978c73
--- /dev/null
+++ b/PARR.API/Contracts/V1/Requests/RobotStateRequest.cs
@@ -0,0 +1,9 @@
+using PARR.Constants;
+
+namespace PARR.API.Contracts.V1.Requests
+{
+ public class RobotStateRequest
+ {
+ public RobotsAllEnum Robot { get; set; }
+ }
+}
diff --git a/PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs b/PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs
new file mode 100644
index 00000000..b6532576
--- /dev/null
+++ b/PARR.API/Controllers/V1/Statistics/StatRobotStateController.cs
@@ -0,0 +1,67 @@
+using FluentValidation;
+using InfluxDB.Client.Api.Domain;
+using InfluxDB.Client.Writes;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using PARR.API.Contracts.V1;
+using PARR.API.Contracts.V1.Requests;
+using PARR.API.Contracts.V1.Responses.Base;
+using PARR.API.Controllers.V1.Base;
+using PARR.Constants;
+using PARR.DAL.InfluxDbServices;
+using PARR.DAL.Settings;
+
+namespace PARR.API.Controllers.V1.Statistics
+{
+ ///
+ /// Статистика доступности роботов
+ ///
+ [Authorize(Roles = ParrRoles.EsppRobot.RoleOrAdmin)]
+ public class StatRobotStateController : BaseApiController
+ {
+ private readonly IInfluxDbService influxDbService;
+ private readonly IValidator validator;
+ private readonly InfluxDbSettings influxDbSettings;
+
+ public StatRobotStateController(
+ IInfluxDbService influxDbService,
+ IValidator validator,
+ InfluxDbSettings influxDbSettings
+ )
+ {
+ this.influxDbService = influxDbService;
+ this.validator = validator;
+ this.influxDbSettings = influxDbSettings;
+ }
+
+
+ ///
+ /// Статистика доступности роботов. Передать инф-у о доступности
+ ///
+ ///
+ ///
+ [HttpPost(ApiRoutes.StatRobotState.Send)]
+ public async Task Send([FromBody] RobotStateRequest request)
+ {
+ var resultValidate = await validator.ValidateAsync(request);
+ if (!resultValidate.IsValid)
+ return BadRequest(new Response(resultValidate.Errors));
+
+ var result = influxDbService.Write(write =>
+ {
+ var point = PointData.Measurement("robots")
+ .Tag("robot", request.Robot.ToString())
+ //.Field("robot", (int)request.Robot)
+ .Field("isUp", 1)
+ .Timestamp(DateTime.UtcNow, WritePrecision.Ns);
+
+ write.WritePoint(point, bucket: influxDbSettings.Robots!.Bucket, org: influxDbSettings.Organization);
+ }, influxDbSettings.Robots!.Token);
+
+ if (!result)
+ return BadRequest($"Ошибка при отправке данных");
+
+ return Ok(new Response("", true));
+ }
+ }
+}
diff --git a/PARR.API/Validators/RobotStateRequestValidator.cs b/PARR.API/Validators/RobotStateRequestValidator.cs
new file mode 100644
index 00000000..d17f979f
--- /dev/null
+++ b/PARR.API/Validators/RobotStateRequestValidator.cs
@@ -0,0 +1,17 @@
+using FluentValidation;
+using PARR.API.Contracts.V1.Requests;
+using PARR.Constants;
+
+namespace PARR.API.Validators
+{
+ public class RobotStateRequestValidator : AbstractValidator
+ {
+ public RobotStateRequestValidator()
+ {
+ RuleFor(t => t.Robot).NotNull().IsInEnum().WithMessage($"Допустимые значения: {(int)RobotsAllEnum.TemplateOrder} ({RobotsAllEnum.TemplateOrder})," +
+ $"{(int)RobotsAllEnum.ScheduleOrder} ({RobotsAllEnum.ScheduleOrder})," +
+ $"{(int)RobotsAllEnum.TemplatesExport} ({RobotsAllEnum.TemplatesExport})," +
+ $"{(int)RobotsAllEnum.ScheduleExport} ({RobotsAllEnum.ScheduleExport})");
+ }
+ }
+}
diff --git a/PARR.API/appsettings.Development.json b/PARR.API/appsettings.Development.json
index 98dc9f58..56f9d92b 100644
--- a/PARR.API/appsettings.Development.json
+++ b/PARR.API/appsettings.Development.json
@@ -30,5 +30,8 @@
}
}
+ },
+ "InfluxDbSettings": {
+ "Url": "http://10.99.253.216:8086"
}
}
diff --git a/PARR.API/appsettings.json b/PARR.API/appsettings.json
index 89b3f95a..d20a9840 100644
--- a/PARR.API/appsettings.json
+++ b/PARR.API/appsettings.json
@@ -56,5 +56,17 @@
"UserCacheSettings": {
"UserCacheTtl": "00:05:00",
"UserBlockTtl": "00:03:00"
+ },
+ "InfluxDbSettings": {
+ "Url": "http://parr-influxdb:8086",
+ "Organization": "parr",
+ "Robots": {
+ "Bucket": "robots",
+ "Token": "jgEigdAYLlX6_Ey8FsleCyjfGnh-sdieQDs6JtA_XNweINMUhjPKWD-ibALyo4MG6oDBFAUfFNNpwoiUR0HwQA=="
+ },
+ "Logons": {
+ "Bucket": "logons",
+ "Token": "hjhOqZMAOm3UsAJURcROBvNqCRdR1Tp3jGYTdzduLXC4uSVrysjvEzLtM-n8jotdwuD7y0rxa2FzzOZKRGzKLg=="
+ }
}
}
diff --git a/PARR.Constants/RobotsAllEnum.cs b/PARR.Constants/RobotsAllEnum.cs
new file mode 100644
index 00000000..9846eecf
--- /dev/null
+++ b/PARR.Constants/RobotsAllEnum.cs
@@ -0,0 +1,28 @@
+namespace PARR.Constants
+{
+ ///
+ /// Список всех роботов (в бд нет 3, 4)
+ ///
+ public enum RobotsAllEnum //: RobotsEnum
+ {
+ ///
+ /// Робот по созданию/изменению шаблона наряда ЕСПП
+ ///
+ TemplateOrder = 1,
+
+ ///
+ /// Робот по созданию/изменению расписания шаблона наряда в ЕСПП
+ ///
+ ScheduleOrder = 2,
+
+ ///
+ /// Робот экспорта шаблонов из ЕСПП в ПАРР
+ ///
+ TemplatesExport = 3,
+
+ ///
+ /// Робот экспорта расписаний из ЕСПП в ПАРР
+ ///
+ ScheduleExport = 4
+ }
+}
diff --git a/PARR.DAL/InfluxDbServices/IInfluxDbService.cs b/PARR.DAL/InfluxDbServices/IInfluxDbService.cs
new file mode 100644
index 00000000..2a2611be
--- /dev/null
+++ b/PARR.DAL/InfluxDbServices/IInfluxDbService.cs
@@ -0,0 +1,10 @@
+using InfluxDB.Client;
+
+namespace PARR.DAL.InfluxDbServices
+{
+ public interface IInfluxDbService
+ {
+ Task QueryAsync(Func> action, string token);
+ bool Write(Action action, string token);
+ }
+}
diff --git a/PARR.DAL/InfluxDbServices/InfluxDbService.cs b/PARR.DAL/InfluxDbServices/InfluxDbService.cs
new file mode 100644
index 00000000..1235863e
--- /dev/null
+++ b/PARR.DAL/InfluxDbServices/InfluxDbService.cs
@@ -0,0 +1,59 @@
+using InfluxDB.Client;
+using Microsoft.Extensions.Logging;
+using PARR.DAL.Settings;
+
+namespace PARR.DAL.InfluxDbServices
+{
+ internal class InfluxDbService : IInfluxDbService
+ {
+ private readonly InfluxDbSettings settings;
+ private readonly ILogger logger;
+
+ public InfluxDbService(InfluxDbSettings settings, ILogger logger)
+ {
+ this.settings = settings;
+ this.logger = logger;
+ }
+
+ public bool Write(Action action, string token)
+ {
+ try
+ {
+ //using var client = new InfluxDBClient(settings.Url, token);
+ //using var write = client.GetWriteApi();
+
+ using var client = new InfluxDBClient(settings.Url, token);
+ using (var write = client.GetWriteApi())
+ {
+ action(write);
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, "Ошибка при записи в БД, InfluxDb");
+ return false;
+ }
+ }
+
+ public async Task QueryAsync(Func> action, string token)
+ {
+ //TODO:
+ throw new NotImplementedException();
+ //try
+ //{
+ using var client = InfluxDBClientFactory.Create(settings.Url, token);
+ var query = client.GetQueryApi();
+
+ return await action(query);
+ //}
+ //catch (Exception ex)
+ //{
+ // logger.LogError(ex, "Ошибка при запросе данных из БД, InfuxDb");
+ // // return Task.FromResult();
+ // return Task.CompletedTask;
+ //}
+ }
+ }
+}
diff --git a/PARR.DAL/PARR.DAL.csproj b/PARR.DAL/PARR.DAL.csproj
index 024ea576..0d944d24 100644
--- a/PARR.DAL/PARR.DAL.csproj
+++ b/PARR.DAL/PARR.DAL.csproj
@@ -7,6 +7,7 @@
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/PARR.DAL/ParrDalInstaller.cs b/PARR.DAL/ParrDalInstaller.cs
index aeb35cb2..c625d27d 100644
--- a/PARR.DAL/ParrDalInstaller.cs
+++ b/PARR.DAL/ParrDalInstaller.cs
@@ -5,6 +5,7 @@ using PARR.DAL.CacheServices;
using PARR.DAL.Configurations.DbSettings;
using PARR.DAL.Context;
using PARR.DAL.Contracts;
+using PARR.DAL.InfluxDbServices;
using PARR.DAL.Services.Implementation;
using PARR.DAL.Services.Implementations;
using PARR.DAL.Services.Interfaces;
@@ -29,6 +30,8 @@ namespace PARR.DAL
.UseNpgsql(configuration.GetConnectionString("DefaultConnection"))
);
+ #region Redis
+
services.AddStackExchangeRedisCache(opt =>
{
opt.Configuration = configuration.GetConnectionString("RedisConnection");
@@ -36,6 +39,19 @@ namespace PARR.DAL
services.AddTransient();
+ #endregion
+
+ #region InfluxDb
+
+ var influxDbSettings = new InfluxDbSettings();
+ configuration.GetSection(nameof(InfluxDbSettings)).Bind(influxDbSettings);
+ services.AddSingleton(influxDbSettings);
+
+ services.AddTransient();
+
+ #endregion
+
+
// Entity services
services.AddTransient();
services.AddTransient();
diff --git a/PARR.DAL/Settings/InfluxDbSettings.cs b/PARR.DAL/Settings/InfluxDbSettings.cs
new file mode 100644
index 00000000..fad300d6
--- /dev/null
+++ b/PARR.DAL/Settings/InfluxDbSettings.cs
@@ -0,0 +1,32 @@
+namespace PARR.DAL.Settings
+{
+ public class InfluxDbSettings
+ {
+ public string Url { get; set; } = string.Empty;
+
+ public string Organization { get; set; } = string.Empty;
+
+ public InfluxDbBucketRobotsSettings? Robots { get; set; }
+
+ public InfluxDbBucketLogonsSettings? Logons { get; set; }
+ }
+
+ public class InfluxDbBucketRobotsSettings : IInfluxDbBucketSettings
+ {
+ public string Bucket { get; set; } = string.Empty;
+ public string Token { get; set; } = string.Empty;
+ }
+
+ public class InfluxDbBucketLogonsSettings : IInfluxDbBucketSettings
+ {
+ public string Bucket { get; set; } = string.Empty;
+ public string Token { get; set; } = string.Empty;
+ }
+
+ public interface IInfluxDbBucketSettings
+ {
+ public string Bucket { get; set; }
+
+ public string Token { get; set; }
+ }
+}