Compare commits
10 Commits
21a6a22a9e
...
d4b830096f
Author | SHA1 | Date | |
---|---|---|---|
d4b830096f | |||
8ca9a1c385 | |||
cbe236f220 | |||
|
17ceed960e | ||
|
b0bdf686d2 | ||
|
4390a523c7 | ||
|
26c4c8e00c | ||
|
a0e70bd3c4 | ||
|
08f30fc7fc | ||
|
9329d76ab6 |
69
Dockerfile
Normal file
69
Dockerfile
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# dotnet build environment
|
||||||
|
FROM alpine:latest as dotnet
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
RUN apk add dotnet8-sdk git
|
||||||
|
RUN git clone https://gitlab.com/kzotkin/hiveemulator
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/CommunicationControl/
|
||||||
|
RUN dotnet build DevOpsProject/DevOpsProject.CommunicationControl.API.csproj
|
||||||
|
RUN dotnet build DevOpsProject.HiveMind.API/DevOpsProject.HiveMind.API.csproj
|
||||||
|
|
||||||
|
|
||||||
|
# nodejs build environment
|
||||||
|
#FROM alpine:latest as nodejs
|
||||||
|
#WORKDIR /
|
||||||
|
|
||||||
|
#RUN apk add git npm
|
||||||
|
#RUN git clone https://gitlab.com/kzotkin/hiveemulator
|
||||||
|
|
||||||
|
#WORKDIR /hiveemulator/src/MapClient/
|
||||||
|
#RUN npm install
|
||||||
|
#RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
# production environment
|
||||||
|
FROM alpine:latest
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
#RUN apk add dotnet8-sdk redis openrc lighttpd npm
|
||||||
|
#RUN apk add git dotnet8-sdk redis openrc npm
|
||||||
|
#RUN apk add git aspnetcore8-runtime redis openrc npm
|
||||||
|
RUN apk add aspnetcore8-runtime redis openrc npm
|
||||||
|
|
||||||
|
#RUN git clone https://gitlab.com/kzotkin/hiveemulator
|
||||||
|
#COPY --from=nodejs /hiveemulator/ /hiveemulator/
|
||||||
|
COPY --from=dotnet /hiveemulator/ /hiveemulator/
|
||||||
|
#COPY --from=nodejs /hiveemulator/src/MapClient/dist/* /var/www/localhost/htdocs/
|
||||||
|
|
||||||
|
#RUN mkdir /hive-cc
|
||||||
|
#COPY --from=0 /hiveemulator/src/CommunicationControl/DevOpsProject/* /hive-cc/
|
||||||
|
#COPY --from=dotnet /hiveemulator/src/CommunicationControl/DevOpsProject/* /hiveemulator/src/CommunicationControl/DevOpsProject/
|
||||||
|
#COPY --from=dotnet /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/* /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/
|
||||||
|
|
||||||
|
#RUN mkdir /hive-hm
|
||||||
|
#COPY --from=0 /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/* /hive-hm/
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/MapClient/
|
||||||
|
RUN npm install
|
||||||
|
RUN sed -i 's/localhost/10\.1\.1\.2/' public/config.json
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
COPY ./daemon-files/hive-cc /etc/init.d/hive-cc
|
||||||
|
COPY ./daemon-files/hive-hm /etc/init.d/hive-hm
|
||||||
|
COPY ./daemon-files/hive-map /etc/init.d/hive-map
|
||||||
|
RUN chmod u+x /etc/init.d/hive-hm /etc/init.d/hive-cc /etc/init.d/hive-map
|
||||||
|
|
||||||
|
#RUN mkdir /etc/rulevels/{stage-redis,stage-cc,stage-hm,stage-map}
|
||||||
|
|
||||||
|
#RUN rc-update add redis default
|
||||||
|
#RUN rc-update add hive-hm default
|
||||||
|
#RUN rc-update add hive-cc default
|
||||||
|
#RUN rc-update add hive-map default
|
||||||
|
|
||||||
|
CMD sh -c "openrc default ; \
|
||||||
|
rc-service redis start ; \
|
||||||
|
rc-service hive-cc start ; \
|
||||||
|
rc-service hive-hm start ; \
|
||||||
|
rc-service hive-map start ; \
|
||||||
|
exec sh"
|
24
Dockerfile-cc
Normal file
24
Dockerfile-cc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# dotnet build environment
|
||||||
|
FROM alpine:latest as dotnet
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
RUN apk add git
|
||||||
|
RUN git clone https://gitlab.com/kzotkin/hiveemulator
|
||||||
|
|
||||||
|
RUN apk add dotnet8-sdk
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/CommunicationControl/
|
||||||
|
RUN dotnet publish DevOpsProject/DevOpsProject.CommunicationControl.API.csproj
|
||||||
|
|
||||||
|
# production environment
|
||||||
|
#FROM mcr.microsoft.com/dotnet/aspnet:8.0 as prod
|
||||||
|
FROM alpine:latest as prod
|
||||||
|
#COPY --from=dotnet /hiveemulator/src/CommunicationControl/DevOpsProject/bin/Release/net8.0/ /app/
|
||||||
|
RUN apk add aspnetcore8-runtime
|
||||||
|
RUN mkdir -p /hiveemulator/src/CommunicationControl/DevOpsProject/bin/Release/net8.0/
|
||||||
|
COPY --from=dotnet /hiveemulator/src/CommunicationControl/DevOpsProject/bin/Release/net8.0/ /hiveemulator/src/CommunicationControl/DevOpsProject/bin/Release/net8.0/
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/CommunicationControl/DevOpsProject/bin/Release/net8.0/
|
||||||
|
ENTRYPOINT ["./DevOpsProject.CommunicationControl.API"]
|
23
Dockerfile-hm
Normal file
23
Dockerfile-hm
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# dotnet build environment
|
||||||
|
FROM alpine:latest as dotnet
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
RUN apk add git
|
||||||
|
RUN git clone https://gitlab.com/kzotkin/hiveemulator
|
||||||
|
|
||||||
|
RUN apk add dotnet8-sdk
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/CommunicationControl/
|
||||||
|
RUN dotnet publish DevOpsProject.HiveMind.API/DevOpsProject.HiveMind.API.csproj
|
||||||
|
|
||||||
|
|
||||||
|
# production environment
|
||||||
|
#FROM mcr.microsoft.com/dotnet/aspnet:8.0 as prod
|
||||||
|
FROM alpine:latest as prod
|
||||||
|
RUN apk add aspnetcore8-runtime
|
||||||
|
RUN mkdir -p /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/bin/Release/net8.0/
|
||||||
|
#COPY --from=dotnet /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/bin/Release/net8.0/ /app/
|
||||||
|
COPY --from=dotnet /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/bin/Release/net8.0/ /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/bin/Release/net8.0/
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/bin/Release/net8.0/
|
||||||
|
ENTRYPOINT ["./DevOpsProject.HiveMind.API"]
|
22
Dockerfile-map
Normal file
22
Dockerfile-map
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# nodejs build environment
|
||||||
|
FROM alpine:latest as nodejs
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
RUN apk add git
|
||||||
|
RUN git clone https://gitlab.com/kzotkin/hiveemulator
|
||||||
|
|
||||||
|
RUN apk add npm
|
||||||
|
|
||||||
|
WORKDIR /hiveemulator/src/MapClient/
|
||||||
|
RUN npm install
|
||||||
|
RUN npm run build
|
||||||
|
RUN rm public/config.json
|
||||||
|
|
||||||
|
|
||||||
|
# production environment
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY --from=nodejs /hiveemulator/src/MapClient/dist/ /usr/share/nginx/html/
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
ENTRYPOINT ["nginx", "-g", "daemon off;"]
|
14
daemon-files/hive-cc
Normal file
14
daemon-files/hive-cc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
command="./DevOpsProject.CommunicationControl.API"
|
||||||
|
command_args=""
|
||||||
|
pidfile="/run/hive-cc.pid"
|
||||||
|
supervisor="supervise-daemon"
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
cd /hiveemulator/src/CommunicationControl/DevOpsProject/bin/Debug/net8.0/
|
||||||
|
}
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need redis
|
||||||
|
}
|
14
daemon-files/hive-hm
Normal file
14
daemon-files/hive-hm
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
command="./DevOpsProject.HiveMind.API"
|
||||||
|
command_args=""
|
||||||
|
pidfile="/run/hive-hm.pid"
|
||||||
|
supervisor="supervise-daemon"
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
cd /hiveemulator/src/CommunicationControl/DevOpsProject.HiveMind.API/bin/Debug/net8.0/
|
||||||
|
}
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need hive-cc
|
||||||
|
}
|
14
daemon-files/hive-map
Normal file
14
daemon-files/hive-map
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
command="npm"
|
||||||
|
command_args="run dev"
|
||||||
|
pidfile="/run/hive-map.pid"
|
||||||
|
supervisor="supervise-daemon"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need hive-cc
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
cd /hiveemulator/src/MapClient/
|
||||||
|
}
|
50
docker-compose.yaml
Normal file
50
docker-compose.yaml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:7
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- sys
|
||||||
|
|
||||||
|
cc:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile-cc
|
||||||
|
#image: registry.digitalocean.com/duke-listings/cc
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
Redis__ConnectionString: "redis:6379"
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
networks:
|
||||||
|
- sys
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
|
||||||
|
hm:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile-hm
|
||||||
|
#image: registry.digitalocean.com/duke-listings/hm
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
CommunicationConfiguration__CommunicationControlIP: "cc"
|
||||||
|
networks:
|
||||||
|
- sys
|
||||||
|
depends_on:
|
||||||
|
- cc
|
||||||
|
|
||||||
|
map:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile-map
|
||||||
|
#image: registry.digitalocean.com/duke-listings/map
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./map/config.json:/usr/share/nginx/html/config.json:ro
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
networks:
|
||||||
|
- sys
|
||||||
|
|
||||||
|
networks:
|
||||||
|
sys:
|
3
map/config.json
Normal file
3
map/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"API": "http://10.1.1.2:8080/api/v1/client"
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
using DevOpsProject.CommunicationControl.Logic.Services.Interfaces;
|
using DevOpsProject.CommunicationControl.Logic.Services.Interfaces;
|
||||||
using DevOpsProject.Shared.Clients;
|
using DevOpsProject.Shared.Clients;
|
||||||
using DevOpsProject.Shared.Configuration;
|
using DevOpsProject.Shared.Configuration;
|
||||||
using DevOpsProject.Shared.Enums;
|
using DevOpsProject.Shared.Enums;
|
||||||
@ -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,18 +65,29 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
|||||||
|
|
||||||
public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
|
public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
|
||||||
{
|
{
|
||||||
|
bool isHiveAlreadyConnected = await IsHiveConnected(model.HiveID);
|
||||||
|
if (isHiveAlreadyConnected)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Reconnect Hive request: {@model}", model);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_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
|
if (isHiveAlreadyConnected)
|
||||||
|
{
|
||||||
|
await _messageBus.Publish(new HiveReconnectedMessage
|
||||||
{
|
{
|
||||||
HiveID = model.HiveID,
|
HiveID = model.HiveID,
|
||||||
Hive = model,
|
Hive = model,
|
||||||
InitialOperationalArea = operationalArea,
|
InitialOperationalArea = operationalArea,
|
||||||
IsSuccessfullyConnected = result
|
IsSuccessfullyReconnected = result
|
||||||
});
|
});
|
||||||
return operationalArea;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -84,23 +95,42 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
|||||||
{
|
{
|
||||||
HiveID = model.HiveID,
|
HiveID = model.HiveID,
|
||||||
Hive = model,
|
Hive = model,
|
||||||
|
InitialOperationalArea = operationalArea,
|
||||||
IsSuccessfullyConnected = result
|
IsSuccessfullyConnected = result
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
return operationalArea;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("Failed to connect Hive: {@model}", model);
|
||||||
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 +139,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(hive.HiveSchema, 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 +174,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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -48,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,
|
||||||
|
@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,16 @@
|
|||||||
|
using DevOpsProject.Shared.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DevOpsProject.Shared.Messages
|
||||||
|
{
|
||||||
|
public class HiveReconnectedMessage : BaseMessage
|
||||||
|
{
|
||||||
|
public bool IsSuccessfullyReconnected { get; set; }
|
||||||
|
public HiveModel Hive { get; set; }
|
||||||
|
public HiveOperationalArea InitialOperationalArea { 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")]
|
||||||
@ -36,6 +38,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
|||||||
};
|
};
|
||||||
|
|
||||||
return Ok(connectResponse);
|
return Ok(connectResponse);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("telemetry")]
|
[HttpPost("telemetry")]
|
||||||
@ -51,6 +54,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
|
||||||
{
|
{
|
||||||
@ -59,6 +65,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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,5 @@ namespace DevOpsProject.CommunicationControl.API.DI
|
|||||||
|
|
||||||
return serviceCollection;
|
return serviceCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
src/MapClient/public/config.json
Normal file
3
src/MapClient/public/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"API": "http://localhost:8080/api/v1/client"
|
||||||
|
}
|
@ -3,9 +3,9 @@ import axios from "axios";
|
|||||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
||||||
|
|
||||||
// Fetch the center coordinates for the initial map load
|
// Fetch the center coordinates for the initial map load
|
||||||
export const fetchCenterCoordinates = async () => {
|
export const fetchCenterCoordinates = async (apiUrl) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${API_BASE_URL}/area`);
|
const response = await axios.get(`${apiUrl}/area`);
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching center coordinates:", error);
|
console.error("Error fetching center coordinates:", error);
|
||||||
@ -14,9 +14,9 @@ export const fetchCenterCoordinates = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Fetch all hives and extract their latitude/longitude
|
// Fetch all hives and extract their latitude/longitude
|
||||||
export const fetchHives = async () => {
|
export const fetchHives = async (apiUrl) => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`${API_BASE_URL}/hive`);
|
const response = await axios.get(`${apiUrl}/hive`);
|
||||||
|
|
||||||
return response.data.map(hive => ({
|
return response.data.map(hive => ({
|
||||||
id: hive.HiveID,
|
id: hive.HiveID,
|
||||||
@ -31,9 +31,9 @@ export const fetchHives = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Move all hives to a new location
|
// Move all hives to a new location
|
||||||
export const moveHives = async (lat, lon, ids) => {
|
export const moveHives = async (apiUrl, lat, lon, ids) => {
|
||||||
try {
|
try {
|
||||||
await axios.patch(`${API_BASE_URL}/hive`, {
|
await axios.patch(`${apiUrl}/hive`, {
|
||||||
Hives: ids,
|
Hives: ids,
|
||||||
Destination: {
|
Destination: {
|
||||||
Latitude: lat,
|
Latitude: lat,
|
||||||
|
@ -21,6 +21,7 @@ const MapView = () => {
|
|||||||
const mapRef = useRef(null);
|
const mapRef = useRef(null);
|
||||||
const vectorLayerRef = useRef(null);
|
const vectorLayerRef = useRef(null);
|
||||||
const initialized = useRef(false);
|
const initialized = useRef(false);
|
||||||
|
const apiUrl = useRef(null)
|
||||||
const [hives, setHives] = useState([]);
|
const [hives, setHives] = useState([]);
|
||||||
const [popup, setPopup] = useState({ visible: false, coords: null });
|
const [popup, setPopup] = useState({ visible: false, coords: null });
|
||||||
const [mouseCoords, setMouseCoords] = useState({ lat: "", lon: "" });
|
const [mouseCoords, setMouseCoords] = useState({ lat: "", lon: "" });
|
||||||
@ -28,11 +29,17 @@ const MapView = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeMap = async () => {
|
const initializeMap = async () => {
|
||||||
|
|
||||||
|
const res = await fetch('/config.json')
|
||||||
|
const data = await res.json()
|
||||||
|
|
||||||
|
apiUrl.current = data.API
|
||||||
|
|
||||||
if (initialized.current) return;
|
if (initialized.current) return;
|
||||||
initialized.current = true;
|
initialized.current = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const center = await fetchCenterCoordinates();
|
const center = await fetchCenterCoordinates(apiUrl.current);
|
||||||
if (center) {
|
if (center) {
|
||||||
initMap(center.Latitude, center.Longitude);
|
initMap(center.Latitude, center.Longitude);
|
||||||
await fetchAndDrawHives();
|
await fetchAndDrawHives();
|
||||||
@ -66,7 +73,7 @@ const MapView = () => {
|
|||||||
// Fetch hives and draw them on the map
|
// Fetch hives and draw them on the map
|
||||||
const fetchAndDrawHives = async () => {
|
const fetchAndDrawHives = async () => {
|
||||||
try {
|
try {
|
||||||
const data = await fetchHives();
|
const data = await fetchHives(apiUrl.current);
|
||||||
setHives(data);
|
setHives(data);
|
||||||
drawHives(data);
|
drawHives(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -174,7 +181,7 @@ const MapView = () => {
|
|||||||
<Popup
|
<Popup
|
||||||
isVisible={popup.visible}
|
isVisible={popup.visible}
|
||||||
coords={popup.coords}
|
coords={popup.coords}
|
||||||
onConfirm={() => moveHives(popup.coords.lat, popup.coords.lon, hives.map(h => h.id))}
|
onConfirm={() => moveHives(apiUrl.current, popup.coords.lat, popup.coords.lon, hives.map(h => h.id))}
|
||||||
onCancel={() => setPopup({ visible: false })}
|
onCancel={() => setPopup({ visible: false })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user