Merge branch 'Cleanup' into 'main'
Program.cs cleanup, HiveModel change, log level change See merge request kzotkin/hiveemulator!3
This commit is contained in:
		
						commit
						08f30fc7fc
					
				@ -37,7 +37,7 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
 | 
				
			|||||||
            bool isSuccessfullyDisconnected = false;
 | 
					            bool isSuccessfullyDisconnected = false;
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var result = await _redisService.DeleteAsync(hiveId);
 | 
					                var result = await _redisService.DeleteAsync(GetHiveKey(hiveId));
 | 
				
			||||||
                isSuccessfullyDisconnected = result;
 | 
					                isSuccessfullyDisconnected = result;
 | 
				
			||||||
                return result;
 | 
					                return result;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -65,9 +65,11 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
 | 
					        public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            _logger.LogInformation("Trying to connect Hive: {@model}", model);
 | 
				
			||||||
            bool result = await _redisService.SetAsync(GetHiveKey(model.HiveID), model);
 | 
					            bool result = await _redisService.SetAsync(GetHiveKey(model.HiveID), model);
 | 
				
			||||||
            if (result)
 | 
					            if (result)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogInformation("Successfully connected Hive: {@model}", model);
 | 
				
			||||||
                var operationalArea = _spatialService.GetHiveOperationalArea(model);
 | 
					                var operationalArea = _spatialService.GetHiveOperationalArea(model);
 | 
				
			||||||
                await _messageBus.Publish(new HiveConnectedMessage
 | 
					                await _messageBus.Publish(new HiveConnectedMessage
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -80,27 +82,34 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                await _messageBus.Publish(new HiveConnectedMessage
 | 
					                _logger.LogError("Failed to connect Hive: {@model}", model);
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    HiveID = model.HiveID,
 | 
					 | 
				
			||||||
                    Hive = model,
 | 
					 | 
				
			||||||
                    IsSuccessfullyConnected = result
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                throw new HiveConnectionException($"Failed to connect hive for HiveId: {model.HiveID}");
 | 
					                throw new HiveConnectionException($"Failed to connect hive for HiveId: {model.HiveID}");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public async Task<bool> IsHiveConnected(string hiveId)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            string hiveKey = GetHiveKey(hiveId);
 | 
				
			||||||
 | 
					            return await _redisService.CheckIfKeyExists(hiveKey);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<DateTime> AddTelemetry(HiveTelemetryModel model)
 | 
					        public async Task<DateTime> AddTelemetry(HiveTelemetryModel model)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            string hiveKey = GetHiveKey(model.HiveID);
 | 
					            string hiveKey = GetHiveKey(model.HiveID);
 | 
				
			||||||
            bool hiveExists = await _redisService.CheckIfKeyExists(hiveKey);
 | 
					 | 
				
			||||||
            if (hiveExists)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) =>
 | 
					            bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                hive.Telemetry = model;
 | 
					                hive.Telemetry = model;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (result)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogInformation("Telemetry updated for HiveID: {hiveId}. Updated telemetry timestamp: {timestamp}", model.HiveID, model.Timestamp);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogError("Failed to update Telemetry - Redis update issue. HiveID: {hiveId}, Telemetry model: {@telemetry}", model.HiveID, model);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await _messageBus.Publish(new TelemetrySentMessage
 | 
					            await _messageBus.Publish(new TelemetrySentMessage
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                HiveID = model.HiveID,
 | 
					                HiveID = model.HiveID,
 | 
				
			||||||
@ -109,44 +118,33 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
            return model.Timestamp;
 | 
					            return model.Timestamp;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                await _messageBus.Publish(new TelemetrySentMessage
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    HiveID = model.HiveID,
 | 
					 | 
				
			||||||
                    Telemetry = model,
 | 
					 | 
				
			||||||
                    IsSuccessfullySent = false
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                throw new HiveNotFoundException($"Hive not found for id: {model.HiveID}");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public async Task<string> SendHiveControlSignal(string hiveId, Location destination)
 | 
					        public async Task<string> SendHiveControlSignal(string hiveId, Location destination)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var hive = await GetHiveModel(hiveId);
 | 
					            var hive = await GetHiveModel(hiveId);
 | 
				
			||||||
            if (hive == null)
 | 
					            if (hive == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                throw new Exception($"Hive control signal error: cannot find hive with id: {hiveId}");
 | 
					                _logger.LogError("Sending Hive Control signal: Hive not found for HiveID: {hiveId}", hiveId);
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bool isSuccessfullySent = false;
 | 
					            bool isSuccessfullySent = false;
 | 
				
			||||||
 | 
					            string hiveMindPath = _communicationControlConfiguration.CurrentValue.HiveMindPath;
 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            var command = new MoveHiveMindCommand
 | 
					            var command = new MoveHiveMindCommand
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                CommandType = State.Move,
 | 
					                CommandType = State.Move,
 | 
				
			||||||
                Location = destination,
 | 
					                Location = destination,
 | 
				
			||||||
                Timestamp = DateTime.Now
 | 
					                Timestamp = DateTime.Now
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
                var result = await _hiveHttpClient.SendHiveControlCommandAsync(_communicationControlConfiguration.CurrentValue.RequestScheme,
 | 
					            {
 | 
				
			||||||
                    hive.HiveIP, hive.HivePort, _communicationControlConfiguration.CurrentValue.HiveMindPath, command);
 | 
					                var result = await _hiveHttpClient.SendHiveControlCommandAsync(hive.HiveSchema, hive.HiveIP, hive.HivePort, hiveMindPath, command);
 | 
				
			||||||
                isSuccessfullySent = true;
 | 
					                isSuccessfullySent = true;
 | 
				
			||||||
                return result;
 | 
					                return result;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (isSuccessfullySent)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    await _messageBus.Publish(new MoveHiveMessage
 | 
					                    await _messageBus.Publish(new MoveHiveMessage
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -155,6 +153,12 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
 | 
				
			|||||||
                        HiveID = hiveId
 | 
					                        HiveID = hiveId
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    _logger.LogError("Failed to send control command for Hive: {@hive}, path: {path}, \n Command: {@command}", hive, hiveMindPath, command);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private string GetHiveKey(string hiveId)
 | 
					        private string GetHiveKey(string hiveId)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces
 | 
				
			|||||||
        Task<HiveModel> GetHiveModel(string hiveId);
 | 
					        Task<HiveModel> GetHiveModel(string hiveId);
 | 
				
			||||||
        Task<List<HiveModel>> GetAllHives();
 | 
					        Task<List<HiveModel>> GetAllHives();
 | 
				
			||||||
        Task<HiveOperationalArea> ConnectHive(HiveModel model);
 | 
					        Task<HiveOperationalArea> ConnectHive(HiveModel model);
 | 
				
			||||||
 | 
					        Task<bool> IsHiveConnected(string hiveId);
 | 
				
			||||||
        Task<DateTime> AddTelemetry(HiveTelemetryModel model);
 | 
					        Task<DateTime> AddTelemetry(HiveTelemetryModel model);
 | 
				
			||||||
        Task<string> SendHiveControlSignal(string hiveId, Location destination);
 | 
					        Task<string> SendHiveControlSignal(string hiveId, Location destination);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					using DevOpsProject.HiveMind.Logic.Services.Interfaces;
 | 
				
			||||||
 | 
					using DevOpsProject.HiveMind.Logic.Services;
 | 
				
			||||||
 | 
					using Asp.Versioning;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DevOpsProject.HiveMind.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class ApiVersioningConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddApiVersioningConfiguration(this IServiceCollection serviceCollection)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.AddApiVersioning(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.DefaultApiVersion = new ApiVersion(1, 0);
 | 
				
			||||||
 | 
					                options.AssumeDefaultVersionWhenUnspecified = true;
 | 
				
			||||||
 | 
					                options.ReportApiVersions = true;
 | 
				
			||||||
 | 
					                options.ApiVersionReader = ApiVersionReader.Combine(
 | 
				
			||||||
 | 
					                    new UrlSegmentApiVersionReader(),
 | 
				
			||||||
 | 
					                    new HeaderApiVersionReader("X-Api-Version")
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }).AddApiExplorer(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.GroupNameFormat = "'v'VVV";
 | 
				
			||||||
 | 
					                options.SubstituteApiVersionInUrl = true;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					namespace DevOpsProject.HiveMind.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class CorsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCorsConfiguration(this IServiceCollection serviceCollection, string corsPolicyName)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.AddCors(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.AddPolicy(name: corsPolicyName,
 | 
				
			||||||
 | 
					                    policy =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
 | 
				
			||||||
 | 
					                            .AllowAnyMethod()
 | 
				
			||||||
 | 
					                            .AllowAnyHeader();
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					using DevOpsProject.Shared.Clients;
 | 
				
			||||||
 | 
					using Polly.Extensions.Http;
 | 
				
			||||||
 | 
					using Polly;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DevOpsProject.HiveMind.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class HttpClientsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddHttpClientsConfiguration(this IServiceCollection serviceCollection)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var communicationControlTelemetryPolicy = HttpPolicyExtensions
 | 
				
			||||||
 | 
					                .HandleTransientHttpError()
 | 
				
			||||||
 | 
					                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
 | 
				
			||||||
 | 
					            serviceCollection.AddHttpClient<HiveMindHttpClient>()
 | 
				
			||||||
 | 
					                .AddPolicyHandler(communicationControlTelemetryPolicy);
 | 
				
			||||||
 | 
					            serviceCollection.AddHttpClient("HiveConnectClient");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using DevOpsProject.Shared.Configuration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DevOpsProject.HiveMind.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class OptionsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddOptionsConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.Configure<HiveCommunicationConfig>(configuration.GetSection("CommunicationConfiguration"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -3,13 +3,10 @@ using Asp.Versioning.Builder;
 | 
				
			|||||||
using DevOpsProject.HiveMind.API.DI;
 | 
					using DevOpsProject.HiveMind.API.DI;
 | 
				
			||||||
using DevOpsProject.HiveMind.API.Middleware;
 | 
					using DevOpsProject.HiveMind.API.Middleware;
 | 
				
			||||||
using DevOpsProject.HiveMind.Logic.Services.Interfaces;
 | 
					using DevOpsProject.HiveMind.Logic.Services.Interfaces;
 | 
				
			||||||
using DevOpsProject.Shared.Clients;
 | 
					 | 
				
			||||||
using DevOpsProject.Shared.Configuration;
 | 
					using DevOpsProject.Shared.Configuration;
 | 
				
			||||||
using DevOpsProject.Shared.Models;
 | 
					using DevOpsProject.Shared.Models;
 | 
				
			||||||
using Microsoft.Extensions.Options;
 | 
					using Microsoft.Extensions.Options;
 | 
				
			||||||
using Microsoft.OpenApi.Models;
 | 
					using Microsoft.OpenApi.Models;
 | 
				
			||||||
using Polly;
 | 
					 | 
				
			||||||
using Polly.Extensions.Http;
 | 
					 | 
				
			||||||
using Serilog;
 | 
					using Serilog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var builder = WebApplication.CreateBuilder(args);
 | 
					var builder = WebApplication.CreateBuilder(args);
 | 
				
			||||||
@ -19,52 +16,23 @@ builder.Host.UseSerilog((context, services, loggerConfig) =>
 | 
				
			|||||||
                .ReadFrom.Services(services)
 | 
					                .ReadFrom.Services(services)
 | 
				
			||||||
                .Enrich.FromLogContext());
 | 
					                .Enrich.FromLogContext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
builder.Services.AddApiVersioning(options =>
 | 
					builder.Services.AddApiVersioningConfiguration();
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    options.DefaultApiVersion = new ApiVersion(1, 0);
 | 
					 | 
				
			||||||
    options.AssumeDefaultVersionWhenUnspecified = true;
 | 
					 | 
				
			||||||
    options.ReportApiVersions = true;
 | 
					 | 
				
			||||||
    options.ApiVersionReader = ApiVersionReader.Combine(
 | 
					 | 
				
			||||||
        new UrlSegmentApiVersionReader(),
 | 
					 | 
				
			||||||
        new HeaderApiVersionReader("X-Api-Version")
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
}).AddApiExplorer(options =>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    options.GroupNameFormat = "'v'VVV";
 | 
					 | 
				
			||||||
    options.SubstituteApiVersionInUrl = true;
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 | 
					 | 
				
			||||||
builder.Services.AddEndpointsApiExplorer();
 | 
					builder.Services.AddEndpointsApiExplorer();
 | 
				
			||||||
builder.Services.AddAuthorization();
 | 
					builder.Services.AddAuthorization();
 | 
				
			||||||
builder.Services.AddSwaggerGen(c =>
 | 
					builder.Services.AddSwaggerGen(c =>
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "HiveMind - V1", Version = "v1.0" });
 | 
					    c.SwaggerDoc("v1", new OpenApiInfo { Title = "HiveMind - V1", Version = "v1.0" });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					builder.Services.AddOptionsConfiguration(builder.Configuration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
builder.Services.AddHiveMindLogic();
 | 
					builder.Services.AddHiveMindLogic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
builder.Services.Configure<HiveCommunicationConfig>(builder.Configuration.GetSection("CommunicationConfiguration"));
 | 
					builder.Services.AddHttpClientsConfiguration();
 | 
				
			||||||
 | 
					 | 
				
			||||||
var communicationControlTelemetryPolicy = HttpPolicyExtensions
 | 
					 | 
				
			||||||
    .HandleTransientHttpError()
 | 
					 | 
				
			||||||
    .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
 | 
					 | 
				
			||||||
builder.Services.AddHttpClient<HiveMindHttpClient>()
 | 
					 | 
				
			||||||
    .AddPolicyHandler(communicationControlTelemetryPolicy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// register NAMED client for connect request
 | 
					 | 
				
			||||||
builder.Services.AddHttpClient("HiveConnectClient");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
string corsPolicyName = "HiveMindCorsPolicy";
 | 
					string corsPolicyName = "HiveMindCorsPolicy";
 | 
				
			||||||
builder.Services.AddCors(options =>
 | 
					builder.Services.AddCorsConfiguration(corsPolicyName);
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    options.AddPolicy(name: corsPolicyName,
 | 
					 | 
				
			||||||
        policy =>
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
 | 
					 | 
				
			||||||
                .AllowAnyMethod()
 | 
					 | 
				
			||||||
                .AllowAnyHeader();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
builder.Services.AddExceptionHandler<ExceptionHandlingMiddleware>();
 | 
					builder.Services.AddExceptionHandler<ExceptionHandlingMiddleware>();
 | 
				
			||||||
builder.Services.AddProblemDetails();
 | 
					builder.Services.AddProblemDetails();
 | 
				
			||||||
@ -82,7 +50,7 @@ using (var scope = app.Services.CreateScope())
 | 
				
			|||||||
    catch (Exception ex)
 | 
					    catch (Exception ex)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        logger.LogError($"Error occured while connecting Hive to Communication Control. \nException text: {ex.Message}");
 | 
					        logger.LogError($"Error occured while connecting Hive to Communication Control. \nException text: {ex.Message}");
 | 
				
			||||||
        System.Diagnostics.Process.GetCurrentProcess().Kill();
 | 
					        Environment.Exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -105,7 +73,6 @@ ApiVersionSet apiVersionSet = app.NewApiVersionSet()
 | 
				
			|||||||
    .HasApiVersion(new ApiVersion(1))
 | 
					    .HasApiVersion(new ApiVersion(1))
 | 
				
			||||||
    .ReportApiVersions()
 | 
					    .ReportApiVersions()
 | 
				
			||||||
    .Build();
 | 
					    .Build();
 | 
				
			||||||
 | 
					 | 
				
			||||||
RouteGroupBuilder groupBuilder = app.MapGroup("api/v{apiVersion:apiVersion}").WithApiVersionSet(apiVersionSet);
 | 
					RouteGroupBuilder groupBuilder = app.MapGroup("api/v{apiVersion:apiVersion}").WithApiVersionSet(apiVersionSet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
groupBuilder.MapGet("ping", (IOptionsSnapshot<HiveCommunicationConfig> config) =>
 | 
					groupBuilder.MapGet("ping", (IOptionsSnapshot<HiveCommunicationConfig> config) =>
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@
 | 
				
			|||||||
          "rollingInterval": "Day",
 | 
					          "rollingInterval": "Day",
 | 
				
			||||||
          "rollOnFileSizeLimit": true,
 | 
					          "rollOnFileSizeLimit": true,
 | 
				
			||||||
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
 | 
					          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
 | 
				
			||||||
          "restrictedToMinimumLevel": "Warning"
 | 
					          "restrictedToMinimumLevel": "Information"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
                // If already moving - stop movement
 | 
					                // If already moving - stop movement
 | 
				
			||||||
                if (HiveInMemoryState.IsMoving)
 | 
					                if (HiveInMemoryState.IsMoving)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
					                    _logger.LogWarning("Previous movement command terminated. Previous destination: {@destination}, Current Location: {@current}, new destination: {@destination}", HiveInMemoryState.Destination, HiveInMemoryState.CurrentLocation, destination);
 | 
				
			||||||
                    StopMovement();
 | 
					                    StopMovement();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,8 +40,9 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
                if (_movementTimer == null)
 | 
					                if (_movementTimer == null)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // TODO: Recalculating position each N seconds
 | 
					                    // TODO: Recalculating position each N seconds
 | 
				
			||||||
                    _movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
 | 
					                    int intervalFromSeconds = 3;
 | 
				
			||||||
                    _logger.LogInformation("Movement timer started.");
 | 
					                    _movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(intervalFromSeconds));
 | 
				
			||||||
 | 
					                    _logger.LogInformation("Movement timer started. Destination: {@destination}, recalculation interval: {interval}", destination, intervalFromSeconds);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -60,14 +62,13 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (AreLocationsEqual(currentLocation.Value, destination.Value))
 | 
					                if (AreLocationsEqual(currentLocation.Value, destination.Value))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
					                    _logger.LogInformation("Reached destination. Current location: {@currentLocation}, Destination: {@destination}", currentLocation, destination);
 | 
				
			||||||
                    StopMovement();
 | 
					                    StopMovement();
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Location newLocation = CalculateNextPosition(currentLocation.Value, destination.Value, 0.1f);
 | 
					                Location newLocation = CalculateNextPosition(currentLocation.Value, destination.Value, 0.1f);
 | 
				
			||||||
                HiveInMemoryState.CurrentLocation = newLocation;
 | 
					                HiveInMemoryState.CurrentLocation = newLocation;
 | 
				
			||||||
 | 
					 | 
				
			||||||
                _logger.LogInformation($"Moved closer: {newLocation}");
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,7 +78,6 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
            _movementTimer = null;
 | 
					            _movementTimer = null;
 | 
				
			||||||
            HiveInMemoryState.IsMoving = false;
 | 
					            HiveInMemoryState.IsMoving = false;
 | 
				
			||||||
            HiveInMemoryState.Destination = null;
 | 
					            HiveInMemoryState.Destination = null;
 | 
				
			||||||
            _logger.LogInformation("Movement stopped: Reached destination.");
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static bool AreLocationsEqual(Location loc1, Location loc2)
 | 
					        private static bool AreLocationsEqual(Location loc1, Location loc2)
 | 
				
			||||||
 | 
				
			|||||||
@ -31,6 +31,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var request = new HiveConnectRequest
 | 
					            var request = new HiveConnectRequest
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                HiveSchema = _communicationConfigurationOptions.RequestSchema,
 | 
				
			||||||
                HiveIP = _communicationConfigurationOptions.HiveIP,
 | 
					                HiveIP = _communicationConfigurationOptions.HiveIP,
 | 
				
			||||||
                HivePort = _communicationConfigurationOptions.HivePort,
 | 
					                HivePort = _communicationConfigurationOptions.HivePort,
 | 
				
			||||||
                HiveID = _communicationConfigurationOptions.HiveID
 | 
					                HiveID = _communicationConfigurationOptions.HiveID
 | 
				
			||||||
@ -47,6 +48,8 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
            var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
 | 
					            var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _logger.LogInformation("Attempting to connect Hive. Request: {@request}, URI: {uri}", request, uriBuilder.Uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var retryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
 | 
					            var retryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
 | 
				
			||||||
                .WaitAndRetryAsync(
 | 
					                .WaitAndRetryAsync(
 | 
				
			||||||
                    10,
 | 
					                    10,
 | 
				
			||||||
@ -68,7 +71,6 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
                    HiveInMemoryState.OperationalArea = hiveConnectResponse.OperationalArea;
 | 
					                    HiveInMemoryState.OperationalArea = hiveConnectResponse.OperationalArea;
 | 
				
			||||||
                    HiveInMemoryState.CurrentLocation = _communicationConfigurationOptions.InitialLocation;
 | 
					                    HiveInMemoryState.CurrentLocation = _communicationConfigurationOptions.InitialLocation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // HERE - we are starting to send telemetry
 | 
					 | 
				
			||||||
                    StartTelemetry();
 | 
					                    StartTelemetry();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
@ -80,7 +82,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _logger.LogError($"Failed to connect hive, terminating process");
 | 
					                _logger.LogError($"Failed to connect hive, terminating process");
 | 
				
			||||||
                System.Diagnostics.Process.GetCurrentProcess().Kill();
 | 
					                Environment.Exit(1);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class ComControlCommunicationConfiguration
 | 
					    public class ComControlCommunicationConfiguration
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public string RequestScheme { get; set; }
 | 
					 | 
				
			||||||
        public string HiveMindPath { get; set; }
 | 
					        public string HiveMindPath { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +0,0 @@
 | 
				
			|||||||
namespace DevOpsProject.Shared.Exceptions
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public class HiveNotFoundException : Exception
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public HiveNotFoundException()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public HiveNotFoundException(string message)
 | 
					 | 
				
			||||||
            : base(message)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public HiveNotFoundException(string message, Exception inner)
 | 
					 | 
				
			||||||
            : base(message, inner)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,13 +1,8 @@
 | 
				
			|||||||
using System;
 | 
					namespace DevOpsProject.Shared.Models
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using System.Threading.Tasks;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace DevOpsProject.Shared.Models
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public class HiveConnectRequest
 | 
					    public class HiveConnectRequest
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        public string HiveSchema { get; set; }
 | 
				
			||||||
        public string HiveIP { get; set; }
 | 
					        public string HiveIP { get; set; }
 | 
				
			||||||
        public int HivePort { get; set; }
 | 
					        public int HivePort { get; set; }
 | 
				
			||||||
        public string HiveID { get; set; }
 | 
					        public string HiveID { get; set; }
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@
 | 
				
			|||||||
        public string HiveID { get; set; }
 | 
					        public string HiveID { get; set; }
 | 
				
			||||||
        public string HiveIP { get; set; }
 | 
					        public string HiveIP { get; set; }
 | 
				
			||||||
        public int HivePort { get; set; }
 | 
					        public int HivePort { get; set; }
 | 
				
			||||||
 | 
					        public string HiveSchema { get; set; }
 | 
				
			||||||
        public HiveTelemetryModel Telemetry { get; set; }
 | 
					        public HiveTelemetryModel Telemetry { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -32,17 +32,21 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
        [HttpGet("hive/{hiveId}")]
 | 
					        [HttpGet("hive/{hiveId}")]
 | 
				
			||||||
        public async Task<IActionResult> GetHive(string hiveId)
 | 
					        public async Task<IActionResult> GetHive(string hiveId)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var hiveModel = await _communicationControlService.GetHiveModel(hiveId);
 | 
					            var hiveExists = await _communicationControlService.IsHiveConnected(hiveId);
 | 
				
			||||||
 | 
					            if (!hiveExists)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogWarning("Failed to get Hive for HiveID: {hiveId}", hiveId);
 | 
				
			||||||
 | 
					                return NotFound($"Hive with HiveID: {hiveId} is not found");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var hiveModel = await _communicationControlService.GetHiveModel(hiveId);
 | 
				
			||||||
            return Ok(hiveModel);
 | 
					            return Ok(hiveModel);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpGet("hive")]
 | 
					        [HttpGet("hive")]
 | 
				
			||||||
        public async Task<IActionResult> GetHives()
 | 
					        public async Task<IActionResult> GetHives()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					 | 
				
			||||||
            var hives = await _communicationControlService.GetAllHives();
 | 
					            var hives = await _communicationControlService.GetAllHives();
 | 
				
			||||||
 | 
					 | 
				
			||||||
            return Ok(hives);
 | 
					            return Ok(hives);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -59,6 +63,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
            if (request?.Hives == null || !request.Hives.Any())
 | 
					            if (request?.Hives == null || !request.Hives.Any())
 | 
				
			||||||
                return BadRequest("No hive IDs provided.");
 | 
					                return BadRequest("No hive IDs provided.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _logger.LogInformation("Hive moving request accepted by enpdoint. Request: {@request}", request);
 | 
				
			||||||
            foreach (var id in request.Hives)
 | 
					            foreach (var id in request.Hives)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                _ = Task.Run(async () =>
 | 
					                _ = Task.Run(async () =>
 | 
				
			||||||
@ -69,7 +74,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    catch (Exception ex)
 | 
					                    catch (Exception ex)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        _logger.LogError(ex, $"Failed to send control signal for HiveID: {id}");
 | 
					                        _logger.LogError(ex, "Failed to send control signal for HiveID: {id} \n Request: {@request}", id, request);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,10 +11,12 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
    public class HiveController : Controller
 | 
					    public class HiveController : Controller
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private readonly ICommunicationControlService _communicationControlService;
 | 
					        private readonly ICommunicationControlService _communicationControlService;
 | 
				
			||||||
 | 
					        private readonly ILogger<HiveController> _logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public HiveController(ICommunicationControlService communicationControlService)
 | 
					        public HiveController(ICommunicationControlService communicationControlService, ILogger<HiveController> logger)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _communicationControlService = communicationControlService;
 | 
					            _communicationControlService = communicationControlService;
 | 
				
			||||||
 | 
					            _logger = logger;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpPost("connect")]
 | 
					        [HttpPost("connect")]
 | 
				
			||||||
@ -25,8 +27,16 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
                HiveID = request.HiveID,
 | 
					                HiveID = request.HiveID,
 | 
				
			||||||
                HiveIP = request.HiveIP,
 | 
					                HiveIP = request.HiveIP,
 | 
				
			||||||
                HivePort = request.HivePort,
 | 
					                HivePort = request.HivePort,
 | 
				
			||||||
 | 
					                HiveSchema = request.HiveSchema
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool isConnected = await _communicationControlService.IsHiveConnected(request.HiveID);
 | 
				
			||||||
 | 
					            if (isConnected)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogError("Hive with HiveID: {hiveId} already connected. Request: {@request}", request.HiveID, request);
 | 
				
			||||||
 | 
					                return BadRequest($"Hive with HiveID: {request.HiveID} already connected");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel);
 | 
					            var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel);
 | 
				
			||||||
            var connectResponse = new HiveConnectResponse
 | 
					            var connectResponse = new HiveConnectResponse
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -35,6 +45,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return Ok(connectResponse);
 | 
					            return Ok(connectResponse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [HttpPost("telemetry")]
 | 
					        [HttpPost("telemetry")]
 | 
				
			||||||
@ -50,6 +61,9 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
                Timestamp = DateTime.Now
 | 
					                Timestamp = DateTime.Now
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool isHiveConnected = await _communicationControlService.IsHiveConnected(request.HiveID);
 | 
				
			||||||
 | 
					            if (isHiveConnected)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel);
 | 
					                var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel);
 | 
				
			||||||
                var telemetryResponse = new HiveTelemetryResponse
 | 
					                var telemetryResponse = new HiveTelemetryResponse
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -58,6 +72,12 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                return Ok(telemetryResponse);
 | 
					                return Ok(telemetryResponse);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _logger.LogWarning("Failed to write telemetry. Hive with HiveID: {hiveId} is not connected. Request: {@request}", request.HiveID, request);
 | 
				
			||||||
 | 
					                return NotFound($"Failed to write telemetry. Hive with HiveID: {request.HiveID} is not connected");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					using Asp.Versioning;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DevOpsProject.CommunicationControl.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class ApiVersioningConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddApiVersioningConfiguration(this IServiceCollection serviceCollection)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.AddApiVersioning(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.DefaultApiVersion = new ApiVersion(1, 0);
 | 
				
			||||||
 | 
					                options.AssumeDefaultVersionWhenUnspecified = true;
 | 
				
			||||||
 | 
					                options.ReportApiVersions = true;
 | 
				
			||||||
 | 
					                options.ApiVersionReader = ApiVersionReader.Combine(
 | 
				
			||||||
 | 
					                    new UrlSegmentApiVersionReader(),
 | 
				
			||||||
 | 
					                    new HeaderApiVersionReader("X-Api-Version")
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }).AddApiExplorer(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.GroupNameFormat = "'v'VVV";
 | 
				
			||||||
 | 
					                options.SubstituteApiVersionInUrl = true;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					namespace DevOpsProject.CommunicationControl.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class CorsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddCorsConfiguration(this IServiceCollection serviceCollection, string corsPolicyName)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.AddCors(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.AddPolicy(name: corsPolicyName,
 | 
				
			||||||
 | 
					                    policy =>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
 | 
				
			||||||
 | 
					                            .AllowAnyMethod()
 | 
				
			||||||
 | 
					                            .AllowAnyHeader();
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					using DevOpsProject.Shared.Clients;
 | 
				
			||||||
 | 
					using Polly;
 | 
				
			||||||
 | 
					using Polly.Extensions.Http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DevOpsProject.CommunicationControl.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class HttpClientsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddHttpClientsConfiguration(this IServiceCollection serviceCollection)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var hiveRetryPolicy = HttpPolicyExtensions
 | 
				
			||||||
 | 
					            .HandleTransientHttpError()
 | 
				
			||||||
 | 
					            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
 | 
				
			||||||
 | 
					            serviceCollection.AddHttpClient<CommunicationControlHttpClient>()
 | 
				
			||||||
 | 
					                .AddPolicyHandler(hiveRetryPolicy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					namespace DevOpsProject.CommunicationControl.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class JsonControllerOptionsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddJsonControllerOptionsConfiguration(this IServiceCollection serviceCollection)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.AddControllers().AddJsonOptions(options =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                options.JsonSerializerOptions.PropertyNamingPolicy = null;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -12,7 +12,5 @@ namespace DevOpsProject.CommunicationControl.API.DI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            return serviceCollection;
 | 
					            return serviceCollection;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					using DevOpsProject.Shared.Configuration;
 | 
				
			||||||
 | 
					using DevOpsProject.Shared.Models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace DevOpsProject.CommunicationControl.API.DI
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class OptionsConfiguration
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static IServiceCollection AddOptionsConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            serviceCollection.Configure<OperationalAreaConfig>(configuration.GetSection("OperationalArea"));
 | 
				
			||||||
 | 
					            serviceCollection.Configure<ComControlCommunicationConfiguration>(configuration.GetSection("CommunicationConfiguration"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return serviceCollection;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,13 +1,6 @@
 | 
				
			|||||||
using Asp.Versioning;
 | 
					 | 
				
			||||||
using DevOpsProject.CommunicationControl.API.DI;
 | 
					using DevOpsProject.CommunicationControl.API.DI;
 | 
				
			||||||
using DevOpsProject.CommunicationControl.API.Middleware;
 | 
					using DevOpsProject.CommunicationControl.API.Middleware;
 | 
				
			||||||
using DevOpsProject.Shared.Clients;
 | 
					 | 
				
			||||||
using DevOpsProject.Shared.Configuration;
 | 
					 | 
				
			||||||
using DevOpsProject.Shared.Models;
 | 
					 | 
				
			||||||
using Microsoft.Extensions.Options;
 | 
					 | 
				
			||||||
using Microsoft.OpenApi.Models;
 | 
					using Microsoft.OpenApi.Models;
 | 
				
			||||||
using Polly;
 | 
					 | 
				
			||||||
using Polly.Extensions.Http;
 | 
					 | 
				
			||||||
using Serilog;
 | 
					using Serilog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
internal class Program
 | 
					internal class Program
 | 
				
			||||||
@ -21,26 +14,11 @@ internal class Program
 | 
				
			|||||||
                        .ReadFrom.Services(services)
 | 
					                        .ReadFrom.Services(services)
 | 
				
			||||||
                        .Enrich.FromLogContext());
 | 
					                        .Enrich.FromLogContext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        builder.Services.AddApiVersioning(options =>
 | 
					        builder.Services.AddApiVersioningConfiguration();
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            options.DefaultApiVersion = new ApiVersion(1, 0);
 | 
					 | 
				
			||||||
            options.AssumeDefaultVersionWhenUnspecified = true;
 | 
					 | 
				
			||||||
            options.ReportApiVersions = true;
 | 
					 | 
				
			||||||
            options.ApiVersionReader = ApiVersionReader.Combine(
 | 
					 | 
				
			||||||
                new UrlSegmentApiVersionReader(),
 | 
					 | 
				
			||||||
                new HeaderApiVersionReader("X-Api-Version")
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }).AddApiExplorer(options =>
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            options.GroupNameFormat = "'v'VVV";
 | 
					 | 
				
			||||||
            options.SubstituteApiVersionInUrl = true;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO: consider this approach
 | 
					        // TODO: consider this approach
 | 
				
			||||||
        builder.Services.AddControllers().AddJsonOptions(options =>
 | 
					        builder.Services.AddJsonControllerOptionsConfiguration();
 | 
				
			||||||
        {
 | 
					
 | 
				
			||||||
            options.JsonSerializerOptions.PropertyNamingPolicy = null;
 | 
					 | 
				
			||||||
        });        // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 | 
					 | 
				
			||||||
        builder.Services.AddEndpointsApiExplorer();
 | 
					        builder.Services.AddEndpointsApiExplorer();
 | 
				
			||||||
        builder.Services.AddSwaggerGen(c =>
 | 
					        builder.Services.AddSwaggerGen(c =>
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -52,36 +30,12 @@ internal class Program
 | 
				
			|||||||
        builder.Services.AddRedis(builder.Configuration);
 | 
					        builder.Services.AddRedis(builder.Configuration);
 | 
				
			||||||
        builder.Services.AddCommunicationControlLogic();
 | 
					        builder.Services.AddCommunicationControlLogic();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        builder.Services.Configure<OperationalAreaConfig>(builder.Configuration.GetSection("OperationalArea"));
 | 
					        builder.Services.AddOptionsConfiguration(builder.Configuration);
 | 
				
			||||||
        builder.Services.Configure<ComControlCommunicationConfiguration>(builder.Configuration.GetSection("CommunicationConfiguration"));
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        var hiveRetryPolicy = HttpPolicyExtensions
 | 
					 | 
				
			||||||
            .HandleTransientHttpError()
 | 
					 | 
				
			||||||
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
 | 
					 | 
				
			||||||
        builder.Services.AddHttpClient<CommunicationControlHttpClient>()
 | 
					 | 
				
			||||||
            .AddPolicyHandler(hiveRetryPolicy);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        builder.Services.AddHttpClientsConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var corsPolicyName = "AllowReactApp";
 | 
					        var corsPolicyName = "AllowReactApp";
 | 
				
			||||||
        var localCorsPolicyName = "AllowLocalHtml";
 | 
					        builder.Services.AddCorsConfiguration(corsPolicyName);
 | 
				
			||||||
        builder.Services.AddCors(options =>
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            options.AddPolicy(name: corsPolicyName,
 | 
					 | 
				
			||||||
                policy =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
 | 
					 | 
				
			||||||
                        .AllowAnyMethod()
 | 
					 | 
				
			||||||
                        .AllowAnyHeader();
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            options.AddPolicy(name: localCorsPolicyName,
 | 
					 | 
				
			||||||
                policy =>
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    policy.AllowAnyOrigin() //SECURITY WARNING ! Never allow all origins
 | 
					 | 
				
			||||||
                        .AllowAnyMethod()
 | 
					 | 
				
			||||||
                        .AllowAnyHeader();
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        builder.Services.AddExceptionHandler<ExceptionHandlingMiddleware>();
 | 
					        builder.Services.AddExceptionHandler<ExceptionHandlingMiddleware>();
 | 
				
			||||||
        builder.Services.AddProblemDetails();
 | 
					        builder.Services.AddProblemDetails();
 | 
				
			||||||
@ -97,7 +51,6 @@ internal class Program
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app.UseCors(corsPolicyName);
 | 
					        app.UseCors(corsPolicyName);
 | 
				
			||||||
        //app.UseCors(localCorsPolicyName);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        app.UseAuthorization();
 | 
					        app.UseAuthorization();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,10 +14,8 @@
 | 
				
			|||||||
    "InitialSpeed_KM": 5,
 | 
					    "InitialSpeed_KM": 5,
 | 
				
			||||||
    "TelemetryInterval_MS": 30000,
 | 
					    "TelemetryInterval_MS": 30000,
 | 
				
			||||||
    "PingInterval_MS": 15000
 | 
					    "PingInterval_MS": 15000
 | 
				
			||||||
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "CommunicationConfiguration": {
 | 
					  "CommunicationConfiguration": {
 | 
				
			||||||
    "RequestScheme": "http",
 | 
					 | 
				
			||||||
    "HiveMindPath": "api/v1"
 | 
					    "HiveMindPath": "api/v1"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "AllowedHosts": "*",
 | 
					  "AllowedHosts": "*",
 | 
				
			||||||
@ -45,7 +43,7 @@
 | 
				
			|||||||
          "rollingInterval": "Day",
 | 
					          "rollingInterval": "Day",
 | 
				
			||||||
          "rollOnFileSizeLimit": true,
 | 
					          "rollOnFileSizeLimit": true,
 | 
				
			||||||
          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
 | 
					          "formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
 | 
				
			||||||
          "restrictedToMinimumLevel": "Warning"
 | 
					          "restrictedToMinimumLevel": "Information"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user