< Summary

Information
Class: LGDXRobotCloud.API.Services.Navigation.RobotService
Assembly: LGDXRobotCloud.API
File(s): /builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Navigation/RobotService.cs
Line coverage
72%
Covered lines: 224
Uncovered lines: 87
Coverable lines: 311
Total lines: 387
Line coverage: 72%
Branch coverage
63%
Covered branches: 19
Total branches: 30
Branch coverage: 63.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%88100%
GetRobotsAsync()100%44100%
GetRobotAsync()100%22100%
CreateRobotAsync()100%22100%
UpdateRobotAsync()0%620%
UpdateRobotChassisInfoAsync()0%620%
GetRobotChassisInfoAsync()100%210%
TestDeleteRobotAsync()100%22100%
DeleteRobotAsync()0%620%
GetRobotSystemInfoAsync()100%11100%
CreateRobotSystemInfoAsync()100%11100%
UpdateRobotSystemInfoAsync()100%210%
SearchRobotsAsync()50%22100%
GetRobotRealmIdAsync()100%44100%
GetRobotIsRealtimeExchange()100%11100%

File(s)

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

#LineLine coverage
 1using LGDXRobotCloud.API.Exceptions;
 2using LGDXRobotCloud.API.Services.Administration;
 3using LGDXRobotCloud.Data.DbContexts;
 4using LGDXRobotCloud.Data.Entities;
 5using LGDXRobotCloud.Data.Models.Business.Administration;
 6using LGDXRobotCloud.Data.Models.Business.Automation;
 7using LGDXRobotCloud.Data.Models.Business.Navigation;
 8using LGDXRobotCloud.Utilities.Enums;
 9using LGDXRobotCloud.Utilities.Helpers;
 10using Microsoft.EntityFrameworkCore;
 11using Microsoft.Extensions.Caching.Memory;
 12
 13namespace LGDXRobotCloud.API.Services.Navigation;
 14
 15public interface IRobotService
 16{
 17  Task<(IEnumerable<RobotListBusinessModel>, PaginationHelper)> GetRobotsAsync(int? realmId, string? name, int pageNumbe
 18  Task<RobotBusinessModel> GetRobotAsync(Guid robotId);
 19  Task<RobotCreateResponseBusinessModel> CreateRobotAsync(RobotCreateBusinessModel robotCreateBusinessModel);
 20  Task<bool> UpdateRobotAsync(Guid id, RobotUpdateBusinessModel robotUpdateDtoBusinessModel);
 21  Task<RobotChassisInfoBusinessModel?> GetRobotChassisInfoAsync(Guid robotId);
 22  Task<bool> UpdateRobotChassisInfoAsync(Guid id, RobotChassisInfoUpdateBusinessModel robotChassisInfoUpdateBusinessMode
 23  Task<bool> TestDeleteRobotAsync(Guid id);
 24  Task<bool> DeleteRobotAsync(Guid id);
 25
 26  Task<RobotSystemInfoBusinessModel?> GetRobotSystemInfoAsync(Guid robotId);
 27  Task<bool> CreateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoCreateBusinessModel robotSystemInfoCreateBusinessMo
 28  Task<bool> UpdateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoUpdateBusinessModel robotSystemInfoUpdateBusinessMo
 29
 30  Task<IEnumerable<RobotSearchBusinessModel>> SearchRobotsAsync(int realmId, string? name, Guid? robotId);
 31
 32  Task<int?> GetRobotRealmIdAsync(Guid robotId);
 33  Task<bool> GetRobotIsRealtimeExchange(Guid robotId);
 34}
 35
 2036public class RobotService(
 2037    IActivityLogService activityLogService,
 2038    IMemoryCache memoryCache,
 2039    IRobotCertificateService robotCertificateService,
 2040    LgdxContext context
 2041  ) : IRobotService
 42{
 2043  private readonly IActivityLogService _activityLogService = activityLogService ?? throw new ArgumentNullException(nameo
 2044  private readonly IMemoryCache _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
 2045  private readonly IRobotCertificateService _robotCertificateService = robotCertificateService ?? throw new ArgumentNull
 2046  private readonly LgdxContext _context = context ?? throw new ArgumentNullException(nameof(context));
 47
 48  public async Task<(IEnumerable<RobotListBusinessModel>, PaginationHelper)> GetRobotsAsync(int? realmId, string? name, 
 449  {
 450    var query = _context.Robots as IQueryable<Robot>;
 451    if (realmId != null)
 452    {
 453      query = query.Where(r => r.RealmId == realmId);
 454    }
 455    if (!string.IsNullOrWhiteSpace(name))
 356    {
 357      name = name.Trim();
 358      query = query.Where(r => r.Name.ToLower().Contains(name.ToLower()));
 359    }
 460    var itemCount = await query.CountAsync();
 461    var PaginationHelper = new PaginationHelper(itemCount, pageNumber, pageSize);
 462    var robots = await query.AsNoTracking()
 463      .OrderBy(r => r.Id)
 464      .Skip(pageSize * (pageNumber - 1))
 465      .Take(pageSize)
 466      .Select(r => new RobotListBusinessModel {
 467        Id = r.Id,
 468        Name = r.Name,
 469        RealmId = r.RealmId,
 470        RealmName = r.Realm.Name,
 471      })
 472      .AsSplitQuery()
 473      .ToListAsync();
 474    return (robots, PaginationHelper);
 475  }
 76
 77  public async Task<RobotBusinessModel> GetRobotAsync(Guid robotId)
 278  {
 279    return await _context.Robots.AsNoTracking()
 280      .Where(r => r.Id == robotId)
 281      .Select(r => new RobotBusinessModel {
 282        Id = r.Id,
 283        Name = r.Name,
 284        RealmId = r.RealmId,
 285        RealmName = r.Realm.Name,
 286        IsRealtimeExchange = r.IsRealtimeExchange,
 287        IsProtectingHardwareSerialNumber = r.IsProtectingHardwareSerialNumber,
 288        RobotCertificate = new RobotCertificateBusinessModel {
 289          Id = r.RobotCertificate.Id,
 290          RobotId = r.Id,
 291          RobotName = r.Name,
 292          Thumbprint = r.RobotCertificate.Thumbprint,
 293          ThumbprintBackup = r.RobotCertificate.ThumbprintBackup,
 294          NotBefore = r.RobotCertificate.NotBefore,
 295          NotAfter = r.RobotCertificate.NotAfter,
 296        },
 297        RobotSystemInfo = r.RobotSystemInfo == null ? null : new RobotSystemInfoBusinessModel {
 298          Id = r.RobotSystemInfo.Id,
 299          Cpu = r.RobotSystemInfo.Cpu,
 2100          IsLittleEndian = r.RobotSystemInfo.IsLittleEndian,
 2101          Motherboard = r.RobotSystemInfo.Motherboard,
 2102          MotherboardSerialNumber = r.RobotSystemInfo.MotherboardSerialNumber,
 2103          RamMiB = r.RobotSystemInfo.RamMiB,
 2104          Gpu = r.RobotSystemInfo.Gpu,
 2105          Os = r.RobotSystemInfo.Os,
 2106          Is32Bit = r.RobotSystemInfo.Is32Bit,
 2107          McuSerialNumber = r.RobotSystemInfo.McuSerialNumber,
 2108        },
 2109        RobotChassisInfo = r.RobotChassisInfo == null ? null : new RobotChassisInfoBusinessModel {
 2110          Id = r.RobotChassisInfo.Id,
 2111          RobotTypeId = r.RobotChassisInfo.RobotTypeId,
 2112          ChassisLengthX = r.RobotChassisInfo.ChassisLengthX,
 2113          ChassisLengthY = r.RobotChassisInfo.ChassisLengthY,
 2114          ChassisWheelCount = r.RobotChassisInfo.ChassisWheelCount,
 2115          ChassisWheelRadius = r.RobotChassisInfo.ChassisWheelRadius,
 2116          BatteryCount = r.RobotChassisInfo.BatteryCount,
 2117          BatteryMaxVoltage = r.RobotChassisInfo.BatteryMaxVoltage,
 2118          BatteryMinVoltage = r.RobotChassisInfo.BatteryMinVoltage,
 2119        },
 2120        AssignedTasks = r.AssignedTasks
 2121          .Where(t =>  t.CurrentProgressId != (int)ProgressState.Aborted
 2122                    && t.CurrentProgressId != (int)ProgressState.Completed
 2123                    && t.CurrentProgressId != (int)ProgressState.Template)
 2124          .OrderByDescending(t => t.CurrentProgressId)
 2125          .ThenBy(t => t.Id)
 2126          .Select(t => new AutoTaskListBusinessModel {
 2127          Id = t.Id,
 2128          Name = t.Name,
 2129          Priority = t.Priority,
 2130          FlowId = t.FlowId,
 2131          FlowName = t.Flow!.Name,
 2132          RealmId = r.RealmId,
 2133          RealmName = r.Realm.Name,
 2134          AssignedRobotId = r.Id,
 2135          AssignedRobotName = r.Name,
 2136          CurrentProgressId = t.CurrentProgressId,
 2137          CurrentProgressName = t.CurrentProgress.Name,
 2138        })
 2139        .ToList(),
 2140      })
 2141      .FirstOrDefaultAsync()
 2142        ?? throw new LgdxNotFound404Exception();
 1143  }
 144
 145  public async Task<RobotCreateResponseBusinessModel> CreateRobotAsync(RobotCreateBusinessModel robotCreateBusinessModel
 2146  {
 2147    var realm = await _context.Realms.Where(r => r.Id == robotCreateBusinessModel.RealmId).AnyAsync();
 2148    if (realm == false)
 1149    {
 1150      throw new LgdxValidation400Expection(nameof(robotCreateBusinessModel.RealmId), "Realm does not exist.");
 151    }
 152
 1153    var id = Guid.CreateVersion7();
 1154    var robotCertificate = await _robotCertificateService.IssueRobotCertificateAsync(id);
 1155    var robot = new Robot {
 1156      Id = id,
 1157      Name = robotCreateBusinessModel.Name,
 1158      RealmId = robotCreateBusinessModel.RealmId,
 1159      IsRealtimeExchange = robotCreateBusinessModel.IsRealtimeExchange,
 1160      IsProtectingHardwareSerialNumber = robotCreateBusinessModel.IsProtectingHardwareSerialNumber,
 1161      RobotCertificate = new RobotCertificate {
 1162        Thumbprint = robotCertificate.RobotCertificateThumbprint,
 1163        NotBefore = DateTime.SpecifyKind(robotCertificate.RobotCertificateNotBefore, DateTimeKind.Utc),
 1164        NotAfter = DateTime.SpecifyKind(robotCertificate.RobotCertificateNotAfter, DateTimeKind.Utc)
 1165      },
 1166      RobotChassisInfo = new RobotChassisInfo {
 1167        RobotTypeId = robotCreateBusinessModel.RobotChassisInfo.RobotTypeId,
 1168        ChassisLengthX = robotCreateBusinessModel.RobotChassisInfo.ChassisLengthX,
 1169        ChassisLengthY = robotCreateBusinessModel.RobotChassisInfo.ChassisLengthY,
 1170        ChassisWheelCount = robotCreateBusinessModel.RobotChassisInfo.ChassisWheelCount,
 1171        ChassisWheelRadius = robotCreateBusinessModel.RobotChassisInfo.ChassisWheelRadius,
 1172        BatteryCount = robotCreateBusinessModel.RobotChassisInfo.BatteryCount,
 1173        BatteryMaxVoltage = robotCreateBusinessModel.RobotChassisInfo.BatteryMaxVoltage,
 1174        BatteryMinVoltage = robotCreateBusinessModel.RobotChassisInfo.BatteryMinVoltage,
 1175      }
 1176    };
 1177    await _context.Robots.AddAsync(robot);
 1178    await _context.SaveChangesAsync();
 179
 1180    await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 1181    {
 1182      EntityName = nameof(Robot),
 1183      EntityId = robot.Id.ToString(),
 1184      Action = ActivityAction.Create,
 1185    });
 186
 1187    return new RobotCreateResponseBusinessModel
 1188    {
 1189      RobotId = robot.Id,
 1190      RobotName = robot.Name,
 1191      RootCertificate = robotCertificate.RootCertificate,
 1192      RobotCertificatePrivateKey = robotCertificate.RobotCertificatePrivateKey,
 1193      RobotCertificatePublicKey = robotCertificate.RobotCertificatePublicKey
 1194    };
 1195  }
 196
 197  public async Task<bool> UpdateRobotAsync(Guid id, RobotUpdateBusinessModel robotUpdateDtoBusinessModel)
 0198  {
 0199    bool result = await _context.Robots
 0200      .Where(r => r.Id == id)
 0201      .ExecuteUpdateAsync(setters => setters
 0202        .SetProperty(r => r.Name, robotUpdateDtoBusinessModel.Name)
 0203        .SetProperty(r => r.IsRealtimeExchange, robotUpdateDtoBusinessModel.IsRealtimeExchange)
 0204        .SetProperty(r => r.IsProtectingHardwareSerialNumber, robotUpdateDtoBusinessModel.IsProtectingHardwareSerialNumb
 0205      ) == 1;
 206
 0207    if (result)
 0208    {
 0209      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0210      {
 0211        EntityName = nameof(Robot),
 0212        EntityId = id.ToString(),
 0213        Action = ActivityAction.Update,
 0214      });
 0215    }
 0216    return result;
 0217  }
 218
 219  public async Task<bool> UpdateRobotChassisInfoAsync(Guid id, RobotChassisInfoUpdateBusinessModel robotChassisInfoUpdat
 0220  {
 0221    bool result = await _context.RobotChassisInfos
 0222      .Where(r => r.RobotId == id)
 0223      .ExecuteUpdateAsync(setters => setters
 0224        .SetProperty(r => r.RobotTypeId, robotChassisInfoUpdateBusinessModel.RobotTypeId)
 0225        .SetProperty(r => r.ChassisLengthX, robotChassisInfoUpdateBusinessModel.ChassisLengthX)
 0226        .SetProperty(r => r.ChassisLengthY, robotChassisInfoUpdateBusinessModel.ChassisLengthY)
 0227        .SetProperty(r => r.ChassisWheelCount, robotChassisInfoUpdateBusinessModel.ChassisWheelCount)
 0228        .SetProperty(r => r.ChassisWheelRadius, robotChassisInfoUpdateBusinessModel.ChassisWheelRadius)
 0229        .SetProperty(r => r.BatteryCount, robotChassisInfoUpdateBusinessModel.BatteryCount)
 0230        .SetProperty(r => r.BatteryMaxVoltage, robotChassisInfoUpdateBusinessModel.BatteryMaxVoltage)
 0231        .SetProperty(r => r.BatteryMinVoltage, robotChassisInfoUpdateBusinessModel.BatteryMinVoltage)
 0232      ) == 1;
 233
 0234    if (result)
 0235    {
 0236      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0237      {
 0238        EntityName = nameof(Robot),
 0239        EntityId = id.ToString(),
 0240        Action = ActivityAction.Update,
 0241      });
 0242    }
 0243    return result;
 0244  }
 245
 246  public async Task<RobotChassisInfoBusinessModel?> GetRobotChassisInfoAsync(Guid robotId)
 0247  {
 0248    return await _context.RobotChassisInfos.AsNoTracking()
 0249      .Where(r => r.RobotId == robotId)
 0250      .Select(r => new RobotChassisInfoBusinessModel {
 0251        Id = r.Id,
 0252        RobotTypeId = r.RobotTypeId,
 0253        ChassisLengthX = r.ChassisLengthX,
 0254        ChassisLengthY = r.ChassisLengthY,
 0255        ChassisWheelCount = r.ChassisWheelCount,
 0256        ChassisWheelRadius = r.ChassisWheelRadius,
 0257        BatteryCount = r.BatteryCount,
 0258        BatteryMaxVoltage = r.BatteryMaxVoltage,
 0259        BatteryMinVoltage = r.BatteryMinVoltage,
 0260      }).FirstOrDefaultAsync();
 0261  }
 262
 263  public async Task<bool> TestDeleteRobotAsync(Guid id)
 2264  {
 2265    var dependencies = await _context.AutoTasks
 2266      .Where(t => t.AssignedRobotId == id)
 2267      .Where(t => t.CurrentProgressId != (int)ProgressState.Completed && t.CurrentProgressId != (int)ProgressState.Abort
 2268      .CountAsync();
 2269    if (dependencies > 0)
 1270    {
 1271      throw new LgdxValidation400Expection(nameof(id), $"This robot has been used by {dependencies} running/waiting/temp
 272    }
 1273    return true;
 1274  }
 275
 276  public async Task<bool> DeleteRobotAsync(Guid id)
 0277  {
 0278    bool result = await _context.Robots.Where(r => r.Id == id)
 0279      .ExecuteDeleteAsync() == 1;
 280
 0281    if (result)
 0282    {
 0283      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0284      {
 0285        EntityName = nameof(Robot),
 0286        EntityId = id.ToString(),
 0287        Action = ActivityAction.Delete,
 0288      });
 0289    }
 0290    return result;
 0291  }
 292
 293  public async Task<RobotSystemInfoBusinessModel?> GetRobotSystemInfoAsync(Guid robotId)
 1294  {
 1295    return await _context.RobotSystemInfos.AsNoTracking()
 1296      .Where(r => r.RobotId == robotId)
 1297      .Select(r => new RobotSystemInfoBusinessModel {
 1298        Id = r.Id,
 1299        Cpu = r.Cpu,
 1300        IsLittleEndian = r.IsLittleEndian,
 1301        Motherboard = r.Motherboard,
 1302        MotherboardSerialNumber = r.MotherboardSerialNumber,
 1303        RamMiB = r.RamMiB,
 1304        Gpu = r.Gpu,
 1305        Os = r.Os,
 1306        Is32Bit = r.Is32Bit,
 1307        McuSerialNumber = r.McuSerialNumber,
 1308      })
 1309      .FirstOrDefaultAsync();
 1310  }
 311
 312  public async Task<bool> CreateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoCreateBusinessModel robotSystemInfoCre
 1313  {
 1314    var robotSystemInfo = new RobotSystemInfo {
 1315      Cpu = robotSystemInfoCreateBusinessModel.Cpu,
 1316      IsLittleEndian = robotSystemInfoCreateBusinessModel.IsLittleEndian,
 1317      Motherboard = robotSystemInfoCreateBusinessModel.Motherboard,
 1318      MotherboardSerialNumber = robotSystemInfoCreateBusinessModel.MotherboardSerialNumber,
 1319      RamMiB = robotSystemInfoCreateBusinessModel.RamMiB,
 1320      Gpu = robotSystemInfoCreateBusinessModel.Gpu,
 1321      Os = robotSystemInfoCreateBusinessModel.Os,
 1322      Is32Bit = robotSystemInfoCreateBusinessModel.Is32Bit,
 1323      McuSerialNumber = robotSystemInfoCreateBusinessModel.McuSerialNumber,
 1324      RobotId = robotId
 1325    };
 1326    _context.RobotSystemInfos.Add(robotSystemInfo);
 1327    return await _context.SaveChangesAsync() >= 1;
 1328  }
 329
 330  public async Task<bool> UpdateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoUpdateBusinessModel robotSystemInfoUpd
 0331  {
 0332    return await _context.RobotSystemInfos
 0333      .Where(r => r.RobotId == robotId)
 0334      .ExecuteUpdateAsync(setters => setters
 0335        .SetProperty(r => r.Cpu, robotSystemInfoUpdateBusinessModel.Cpu)
 0336        .SetProperty(r => r.IsLittleEndian, robotSystemInfoUpdateBusinessModel.IsLittleEndian)
 0337        .SetProperty(r => r.Motherboard, robotSystemInfoUpdateBusinessModel.Motherboard)
 0338        .SetProperty(r => r.MotherboardSerialNumber, robotSystemInfoUpdateBusinessModel.MotherboardSerialNumber)
 0339        .SetProperty(r => r.RamMiB, robotSystemInfoUpdateBusinessModel.RamMiB)
 0340        .SetProperty(r => r.Gpu, robotSystemInfoUpdateBusinessModel.Gpu)
 0341        .SetProperty(r => r.Os, robotSystemInfoUpdateBusinessModel.Os)
 0342        .SetProperty(r => r.Is32Bit, robotSystemInfoUpdateBusinessModel.Is32Bit)
 0343        .SetProperty(r => r.McuSerialNumber, robotSystemInfoUpdateBusinessModel.McuSerialNumber)
 0344      ) == 1;
 0345  }
 346
 347  public async Task<IEnumerable<RobotSearchBusinessModel>> SearchRobotsAsync(int realmId, string? name, Guid? robotId)
 4348  {
 4349    var n = name ?? string.Empty;
 4350    return await _context.Robots.AsNoTracking()
 4351      .Where(r => r.RealmId == realmId)
 4352      .Where(t => t.Name.ToLower().Contains(n.ToLower()))
 4353      .Where(r => robotId == null || r.Id == robotId)
 4354      .Take(10)
 4355      .Select(m => new RobotSearchBusinessModel {
 4356        Id = m.Id,
 4357        Name = m.Name,
 4358      })
 4359      .ToListAsync();
 4360  }
 361
 362  public async Task<int?> GetRobotRealmIdAsync(Guid robotId)
 3363  {
 3364    if (_memoryCache.TryGetValue<int>($"RobotService_GetRobotRealmIdAsync_{robotId}", out var RealmId))
 1365    {
 1366      return RealmId;
 367    }
 368
 2369    var robot = await _context.Robots.AsNoTracking()
 2370      .Where(m => m.Id == robotId)
 2371      .Select(m => new { m.Id, m.RealmId })
 2372      .FirstOrDefaultAsync();
 2373    if (robot == null)
 1374      return null;
 375
 1376    _memoryCache.Set($"RobotService_GetRobotRealmIdAsync_{robotId}", robot!.RealmId, TimeSpan.FromDays(1));
 1377    return robot.RealmId;
 3378  }
 379
 380  public async Task<bool> GetRobotIsRealtimeExchange(Guid robotId)
 1381  {
 1382    return await _context.Robots.AsNoTracking()
 1383      .Where(r => r.Id == robotId)
 1384      .Select(r => r.IsRealtimeExchange)
 1385      .FirstOrDefaultAsync();
 1386  }
 387}