HiveMind PoC + P1, P3 fixes
This commit is contained in:
committed by
Kirill
parent
1744425d5f
commit
9f6c1f5135
+101
@@ -0,0 +1,101 @@
|
||||
using DevOpsProject.HiveMind.Logic.Services.Interfaces;
|
||||
using DevOpsProject.HiveMind.Logic.State;
|
||||
using DevOpsProject.Shared.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace DevOpsProject.HiveMind.Logic.Services
|
||||
{
|
||||
public class HiveMindMovingService : IHiveMindMovingService
|
||||
{
|
||||
private readonly ILogger<HiveMindMovingService> _logger;
|
||||
private Timer _movementTimer;
|
||||
public HiveMindMovingService(ILogger<HiveMindMovingService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void MoveToLocation(Location destination)
|
||||
{
|
||||
lock (typeof(HiveInMemoryState))
|
||||
{
|
||||
if (HiveInMemoryState.OperationalArea == null || HiveInMemoryState.CurrentLocation == null)
|
||||
{
|
||||
_logger.LogWarning("Cannot start moving: OperationalArea or CurrentLocation is not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// If already moving - stop movement
|
||||
if (HiveInMemoryState.IsMoving)
|
||||
{
|
||||
StopMovement();
|
||||
}
|
||||
|
||||
HiveInMemoryState.Destination = destination;
|
||||
HiveInMemoryState.IsMoving = true;
|
||||
|
||||
_logger.LogInformation($"Received move command: Moving towards {destination}");
|
||||
|
||||
// Start the movement timer if not already running
|
||||
if (_movementTimer == null)
|
||||
{
|
||||
// TODO: Recalculating position each N seconds
|
||||
_movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
|
||||
_logger.LogInformation("Movement timer started.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMovement(object state)
|
||||
{
|
||||
lock (typeof(HiveInMemoryState))
|
||||
{
|
||||
var currentLocation = HiveInMemoryState.CurrentLocation;
|
||||
var destination = HiveInMemoryState.Destination;
|
||||
|
||||
if (currentLocation == null || destination == null)
|
||||
{
|
||||
StopMovement();
|
||||
return;
|
||||
}
|
||||
|
||||
if (AreLocationsEqual(currentLocation.Value, destination.Value))
|
||||
{
|
||||
StopMovement();
|
||||
return;
|
||||
}
|
||||
|
||||
Location newLocation = CalculateNextPosition(currentLocation.Value, destination.Value, 0.1f);
|
||||
HiveInMemoryState.CurrentLocation = newLocation;
|
||||
|
||||
_logger.LogInformation($"Moved closer: {newLocation}");
|
||||
}
|
||||
}
|
||||
|
||||
private void StopMovement()
|
||||
{
|
||||
_movementTimer?.Dispose();
|
||||
_movementTimer = null;
|
||||
HiveInMemoryState.IsMoving = false;
|
||||
HiveInMemoryState.Destination = null;
|
||||
_logger.LogInformation("Movement stopped: Reached destination.");
|
||||
}
|
||||
|
||||
private static bool AreLocationsEqual(Location loc1, Location loc2)
|
||||
{
|
||||
const float tolerance = 0.000001f;
|
||||
return Math.Abs(loc1.Latitude - loc2.Latitude) < tolerance &&
|
||||
Math.Abs(loc1.Longitude - loc2.Longitude) < tolerance;
|
||||
}
|
||||
|
||||
private static Location CalculateNextPosition(Location current, Location destination, float stepSize)
|
||||
{
|
||||
float newLat = current.Latitude + (destination.Latitude - current.Latitude) * stepSize;
|
||||
float newLon = current.Longitude + (destination.Longitude - current.Longitude) * stepSize;
|
||||
return new Location
|
||||
{
|
||||
Latitude = newLat,
|
||||
Longitude = newLon
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using DevOpsProject.HiveMind.Logic.Services.Interfaces;
|
||||
using DevOpsProject.Shared.Clients;
|
||||
using DevOpsProject.Shared.Models;
|
||||
using DevOpsProject.Shared.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Text.Json;
|
||||
using DevOpsProject.HiveMind.Logic.State;
|
||||
|
||||
namespace DevOpsProject.HiveMind.Logic.Services
|
||||
{
|
||||
public class HiveMindService : IHiveMindService
|
||||
{
|
||||
private readonly HiveMindHttpClient _httpClient;
|
||||
private readonly ILogger<HiveMindService> _logger;
|
||||
private readonly HiveCommunicationConfig _communicationConfigurationOptions;
|
||||
private Timer _telemetryTimer;
|
||||
|
||||
public HiveMindService(HiveMindHttpClient httpClient, ILogger<HiveMindService> logger, IOptionsSnapshot<HiveCommunicationConfig> communicationConfigurationOptions)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_logger = logger;
|
||||
_communicationConfigurationOptions = communicationConfigurationOptions.Value;
|
||||
}
|
||||
|
||||
public async Task ConnectHive()
|
||||
{
|
||||
var request = new HiveConnectRequest
|
||||
{
|
||||
HiveIP = _communicationConfigurationOptions.HiveIP,
|
||||
HivePort = _communicationConfigurationOptions.HivePort,
|
||||
HiveID = _communicationConfigurationOptions.HiveID
|
||||
};
|
||||
|
||||
var connectResult = await _httpClient.SendCommunicationControlConnectAsync(_communicationConfigurationOptions.RequestSchema,
|
||||
_communicationConfigurationOptions.CommunicationControlIP, _communicationConfigurationOptions.CommunicationControlPort,
|
||||
_communicationConfigurationOptions.CommunicationControlPath, request);
|
||||
|
||||
_logger.LogInformation($"Connect result for HiveID: {request.HiveID}: {connectResult}");
|
||||
|
||||
if (connectResult != null)
|
||||
{
|
||||
var hiveConnectResponse = JsonSerializer.Deserialize<HiveConnectResponse>(connectResult);
|
||||
|
||||
if (hiveConnectResponse != null && hiveConnectResponse.ConnectResult)
|
||||
{
|
||||
HiveInMemoryState.OperationalArea = hiveConnectResponse.OperationalArea;
|
||||
HiveInMemoryState.CurrentLocation = _communicationConfigurationOptions.InitialLocation;
|
||||
|
||||
// HERE - we are starting to send telemetry
|
||||
StartTelemetry();
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation($"Connecting hive failed for ID: {request.HiveID}");
|
||||
throw new Exception($"Failed to connect HiveID: {request.HiveID}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError($"Unable to connect Hive with ID: {request.HiveID}, Port: {request.HivePort}, IP: {request.HiveIP} to Communication Control. \n" +
|
||||
$"Requested IP: {_communicationConfigurationOptions.CommunicationControlIP}, Port: {_communicationConfigurationOptions.HivePort}");
|
||||
throw new Exception($"Failed to connect hive for HiveID: {request.HiveID}");
|
||||
}
|
||||
}
|
||||
|
||||
public void StopAllTelemetry()
|
||||
{
|
||||
StopTelemetry();
|
||||
}
|
||||
|
||||
#region private methods
|
||||
private void StartTelemetry()
|
||||
{
|
||||
if (HiveInMemoryState.IsTelemetryRunning) return;
|
||||
// TODO: Sending telemetry each N seconds
|
||||
_telemetryTimer = new Timer(SendTelemetry, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
|
||||
|
||||
_logger.LogInformation("Telemetry timer started.");
|
||||
}
|
||||
|
||||
private void StopTelemetry()
|
||||
{
|
||||
_telemetryTimer?.Dispose();
|
||||
HiveInMemoryState.IsTelemetryRunning = false;
|
||||
|
||||
_logger.LogInformation("Telemetry timer stopped.");
|
||||
}
|
||||
|
||||
private async void SendTelemetry(object state)
|
||||
{
|
||||
var currentLocation = HiveInMemoryState.CurrentLocation;
|
||||
|
||||
try
|
||||
{
|
||||
var request = new HiveTelemetryRequest
|
||||
{
|
||||
HiveID = _communicationConfigurationOptions.HiveID,
|
||||
Location = HiveInMemoryState.CurrentLocation ?? default,
|
||||
// TODO: MOCKED FOR NOW
|
||||
Height = 5,
|
||||
Speed = 15,
|
||||
State = Shared.Enums.State.Move
|
||||
};
|
||||
|
||||
var connectResult = await _httpClient.SendCommunicationControlTelemetryAsync(_communicationConfigurationOptions.RequestSchema,
|
||||
_communicationConfigurationOptions.CommunicationControlIP, _communicationConfigurationOptions.CommunicationControlPort,
|
||||
_communicationConfigurationOptions.CommunicationControlPath, request);
|
||||
|
||||
_logger.LogInformation($"Telemetry sent for HiveID: {request.HiveID}: {connectResult}");
|
||||
|
||||
if (connectResult != null)
|
||||
{
|
||||
// TODO: Store timestamp
|
||||
var hiveConnectResponse = JsonSerializer.Deserialize<HiveTelemetryResponse>(connectResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError($"Unable to send Hive telemetry for HiveID: {request.HiveID}.");
|
||||
throw new Exception($"Failed to send telemetry for HiveID: {request.HiveID}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error sending telemetry: {Message}", ex.Message);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
using DevOpsProject.Shared.Models;
|
||||
|
||||
namespace DevOpsProject.HiveMind.Logic.Services.Interfaces
|
||||
{
|
||||
public interface IHiveMindMovingService
|
||||
{
|
||||
void MoveToLocation(Location destination);
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using DevOpsProject.Shared.Models;
|
||||
|
||||
namespace DevOpsProject.HiveMind.Logic.Services.Interfaces
|
||||
{
|
||||
public interface IHiveMindService
|
||||
{
|
||||
Task ConnectHive();
|
||||
void StopAllTelemetry();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user