< Summary

Information
Class: LGDXRobotCloud.API.Services.Navigation.OnlineRobotsService
Assembly: LGDXRobotCloud.API
File(s): /builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Navigation/OnlineRobotsService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 121
Coverable lines: 121
Total lines: 177
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 32
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)0%110100%
AddRobotAsync()100%210%
RemoveRobotAsync()100%210%
UpdateRobotDataAsync()0%4260%
SetAbortTaskAsync()0%620%
SetSoftwareEmergencyStopAsync()0%4260%
SetPauseTaskAssignmentAsync()0%4260%
GetPauseAutoTaskAssignmentAsync()0%620%

File(s)

/builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Navigation/OnlineRobotsService.cs

#LineLine coverage
 1using LGDXRobotCloud.API.Repositories;
 2using LGDXRobotCloud.API.Services.Administration;
 3using LGDXRobotCloud.API.Services.Common;
 4using LGDXRobotCloud.Data.Entities;
 5using LGDXRobotCloud.Data.Models.Business.Administration;
 6using LGDXRobotCloud.Data.Models.Redis;
 7using LGDXRobotCloud.Protos;
 8using LGDXRobotCloud.Utilities.Enums;
 9using Microsoft.Extensions.Caching.Distributed;
 10using Microsoft.Extensions.Caching.Memory;
 11
 12namespace LGDXRobotCloud.API.Services.Navigation;
 13
 14public interface IOnlineRobotsService
 15{
 16  Task AddRobotAsync(Guid robotId);
 17  Task RemoveRobotAsync(Guid robotId);
 18  Task UpdateRobotDataAsync(Guid robotId, RobotClientsData data);
 19
 20  Task<bool> SetAbortTaskAsync(Guid robotId);
 21  Task<bool> SetSoftwareEmergencyStopAsync(Guid robotId, bool enable);
 22  Task<bool> SetPauseTaskAssignmentAsync(Guid robotId, bool enable);
 23  Task<bool> GetPauseAutoTaskAssignmentAsync(Guid robotId);
 24}
 25
 026public class OnlineRobotsService(
 027    IActivityLogService activityLogService,
 028    IEmailService emailService,
 029    IMemoryCache memoryCache,
 030    IRobotDataRepository robotDataRepository,
 031    IRobotService robotService
 032  ) : IOnlineRobotsService
 33{
 034  private readonly IActivityLogService _activityLogService = activityLogService ?? throw new ArgumentNullException(nameo
 035  private readonly IEmailService _emailService = emailService ?? throw new ArgumentNullException(nameof(emailService));
 036  private readonly IMemoryCache _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
 037  private readonly IRobotDataRepository _robotDataRepository = robotDataRepository ?? throw new ArgumentNullException(na
 038  private readonly IRobotService _robotService = robotService ?? throw new ArgumentNullException(nameof(robotService));
 39
 40  public async Task AddRobotAsync(Guid robotId)
 041  {
 042    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 043    await _robotDataRepository.StartExchangeAsync(realmId, robotId);
 044  }
 45
 46  public async Task RemoveRobotAsync(Guid robotId)
 047  {
 048    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 049    await _robotDataRepository.StopExchangeAsync(realmId, robotId);
 050  }
 51
 52  public async Task UpdateRobotDataAsync(Guid robotId, RobotClientsData data)
 053  {
 054    if (_memoryCache.TryGetValue<bool>($"OnlineRobotsService_RobotData_Pause_{robotId}", out var _))
 055    {
 56      // Blocking too much data to rabbitmq
 057      return;
 58    }
 059    _memoryCache.Set($"OnlineRobotsService_RobotData_Pause_{robotId}", true, TimeSpan.FromMilliseconds(100));
 60
 061    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 062    await _robotDataRepository.SetRobotDataAsync(realmId, robotId, new RobotData
 063    {
 064      RobotStatus = (RobotStatus)data.RobotStatus,
 065      CriticalStatus = new RobotCriticalStatus
 066      {
 067        SoftwareEmergencyStop = data.CriticalStatus.SoftwareEmergencyStop,
 068        HardwareEmergencyStop = data.CriticalStatus.HardwareEmergencyStop,
 069        BatteryLow = [.. data.CriticalStatus.BatteryLow],
 070        MotorDamaged = [.. data.CriticalStatus.MotorDamaged]
 071      },
 072      Batteries = [.. data.Batteries],
 073      Position = new RobotDof
 074      {
 075        X = data.Position.X,
 076        Y = data.Position.Y,
 077        Rotation = data.Position.Rotation
 078      },
 079      NavProgress = new AutoTaskNavProgress
 080      {
 081        Eta = data.NavProgress.Eta,
 082        Recoveries = data.NavProgress.Recoveries,
 083        DistanceRemaining = data.NavProgress.DistanceRemaining,
 084        WaypointsRemaining = data.NavProgress.WaypointsRemaining,
 085        Plan = [.. data.NavProgress.Plan.Select(x => new Robot2Dof { X = x.X, Y = x.Y })]
 086      },
 087      PauseTaskAssignment = data.PauseTaskAssignment
 088    });
 89
 090    var robotStatus = (RobotStatus)data.RobotStatus;
 091    if (robotStatus == RobotStatus.Stuck)
 092    {
 093      if (!_memoryCache.TryGetValue<bool>($"OnlineRobotsService_RobotStuck_{robotId}", out var _))
 094      {
 95        // First stuck in 5 minutes, sending email
 096        await _emailService.SendRobotStuckEmailAsync(robotId, data.Position.X, data.Position.Y);
 097      }
 098      _memoryCache.Set($"OnlineRobotsService_RobotStuck_{robotId}", true, TimeSpan.FromMinutes(5));
 099    }
 0100  }
 101
 102  public async Task<bool> SetAbortTaskAsync(Guid robotId)
 0103  {
 0104    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 0105    if (await _robotDataRepository.AddRobotCommandAsync(realmId, robotId, new RobotClientsRobotCommands { AbortTask = tr
 0106    {
 0107      return true;
 108    }
 109    else
 0110    {
 0111      return false;
 112    }
 0113  }
 114
 115  public async Task<bool> SetSoftwareEmergencyStopAsync(Guid robotId, bool enable)
 0116  {
 0117    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 0118    bool result = false;
 119
 0120    if (enable)
 0121    {
 0122      result = await _robotDataRepository.AddRobotCommandAsync(realmId, robotId, new RobotClientsRobotCommands { Softwar
 0123    }
 124    else
 0125    {
 0126      result = await _robotDataRepository.AddRobotCommandAsync(realmId, robotId, new RobotClientsRobotCommands { Softwar
 0127    }
 128
 0129    if (result)
 0130    {
 0131      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0132      {
 0133        EntityName = nameof(Robot),
 0134        EntityId = robotId.ToString(),
 0135        Action = enable ? ActivityAction.RobotSoftwareEmergencyStopEnabled : ActivityAction.RobotSoftwareEmergencyStopDi
 0136      });
 0137    }
 0138    return result;
 0139  }
 140
 141  public async Task<bool> SetPauseTaskAssignmentAsync(Guid robotId, bool enable)
 0142  {
 0143    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 0144    bool result = false;
 145
 0146    if (enable)
 0147    {
 0148      result = await _robotDataRepository.AddRobotCommandAsync(realmId, robotId, new RobotClientsRobotCommands { PauseTa
 0149    }
 150    else
 0151    {
 0152      result = await _robotDataRepository.AddRobotCommandAsync(realmId, robotId, new RobotClientsRobotCommands { PauseTa
 0153    }
 154
 0155    if (result)
 0156    {
 0157      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0158      {
 0159        EntityName = nameof(Robot),
 0160        EntityId = robotId.ToString(),
 0161        Action = enable ? ActivityAction.RobotPauseTaskAssignmentEnabled : ActivityAction.RobotPauseTaskAssignmentDisabl
 0162      });
 0163    }
 0164    return result;
 0165  }
 166
 167  public async Task<bool> GetPauseAutoTaskAssignmentAsync(Guid robotId)
 0168  {
 0169    var realmId = await _robotService.GetRobotRealmIdAsync(robotId) ?? 0;
 0170    var robotData = await _robotDataRepository.GetRobotDataAsync(realmId, robotId);
 0171    if (robotData != null)
 0172    {
 0173      return robotData.PauseTaskAssignment;
 174    }
 0175    return false;
 0176  }
 177}