< 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
71%
Covered lines: 215
Uncovered lines: 85
Coverable lines: 300
Total lines: 375
Line coverage: 71.6%
Branch coverage
75%
Covered branches: 18
Total branches: 24
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

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    IMemoryCache memoryCache,
 2038    IRobotCertificateService robotCertificateService,
 2039    LgdxContext context
 2040  ) : IRobotService
 41{
 2042  private readonly IMemoryCache _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
 2043  private readonly IRobotCertificateService _robotCertificateService = robotCertificateService ?? throw new ArgumentNull
 2044  private readonly LgdxContext _context = context ?? throw new ArgumentNullException(nameof(context));
 45
 46  public async Task<(IEnumerable<RobotListBusinessModel>, PaginationHelper)> GetRobotsAsync(int? realmId, string? name, 
 447  {
 448    var query = _context.Robots as IQueryable<Robot>;
 449    if (realmId != null)
 450    {
 451      query = query.Where(r => r.RealmId == realmId);
 452    }
 453    if (!string.IsNullOrWhiteSpace(name))
 354    {
 355      name = name.Trim();
 356      query = query.Where(r => r.Name.ToLower().Contains(name.ToLower()));
 357    }
 458    var itemCount = await query.CountAsync();
 459    var PaginationHelper = new PaginationHelper(itemCount, pageNumber, pageSize);
 460    var robots = await query.AsNoTracking()
 461      .OrderBy(r => r.Id)
 462      .Skip(pageSize * (pageNumber - 1))
 463      .Take(pageSize)
 464      .Select(r => new RobotListBusinessModel {
 465        Id = r.Id,
 466        Name = r.Name,
 467        RealmId = r.RealmId,
 468        RealmName = r.Realm.Name,
 469      })
 470      .AsSplitQuery()
 471      .ToListAsync();
 472    return (robots, PaginationHelper);
 473  }
 74
 75  public async Task<RobotBusinessModel> GetRobotAsync(Guid robotId)
 276  {
 277    return await _context.Robots.AsNoTracking()
 278      .Where(r => r.Id == robotId)
 279      .Select(r => new RobotBusinessModel {
 280        Id = r.Id,
 281        Name = r.Name,
 282        RealmId = r.RealmId,
 283        RealmName = r.Realm.Name,
 284        IsRealtimeExchange = r.IsRealtimeExchange,
 285        IsProtectingHardwareSerialNumber = r.IsProtectingHardwareSerialNumber,
 286        RobotCertificate = new RobotCertificateBusinessModel {
 287          Id = r.RobotCertificate.Id,
 288          RobotId = r.Id,
 289          RobotName = r.Name,
 290          Thumbprint = r.RobotCertificate.Thumbprint,
 291          ThumbprintBackup = r.RobotCertificate.ThumbprintBackup,
 292          NotBefore = r.RobotCertificate.NotBefore,
 293          NotAfter = r.RobotCertificate.NotAfter,
 294        },
 295        RobotSystemInfo = r.RobotSystemInfo == null ? null : new RobotSystemInfoBusinessModel {
 296          Id = r.RobotSystemInfo.Id,
 297          Cpu = r.RobotSystemInfo.Cpu,
 298          IsLittleEndian = r.RobotSystemInfo.IsLittleEndian,
 299          Motherboard = r.RobotSystemInfo.Motherboard,
 2100          MotherboardSerialNumber = r.RobotSystemInfo.MotherboardSerialNumber,
 2101          RamMiB = r.RobotSystemInfo.RamMiB,
 2102          Gpu = r.RobotSystemInfo.Gpu,
 2103          Os = r.RobotSystemInfo.Os,
 2104          Is32Bit = r.RobotSystemInfo.Is32Bit,
 2105          McuSerialNumber = r.RobotSystemInfo.McuSerialNumber,
 2106        },
 2107        RobotChassisInfo = r.RobotChassisInfo == null ? null : new RobotChassisInfoBusinessModel {
 2108          Id = r.RobotChassisInfo.Id,
 2109          RobotTypeId = r.RobotChassisInfo.RobotTypeId,
 2110          ChassisLengthX = r.RobotChassisInfo.ChassisLengthX,
 2111          ChassisLengthY = r.RobotChassisInfo.ChassisLengthY,
 2112          ChassisWheelCount = r.RobotChassisInfo.ChassisWheelCount,
 2113          ChassisWheelRadius = r.RobotChassisInfo.ChassisWheelRadius,
 2114          BatteryCount = r.RobotChassisInfo.BatteryCount,
 2115          BatteryMaxVoltage = r.RobotChassisInfo.BatteryMaxVoltage,
 2116          BatteryMinVoltage = r.RobotChassisInfo.BatteryMinVoltage,
 2117        },
 2118        AssignedTasks = r.AssignedTasks
 2119          .Where(t =>  t.CurrentProgressId != (int)ProgressState.Aborted
 2120                    && t.CurrentProgressId != (int)ProgressState.Completed
 2121                    && t.CurrentProgressId != (int)ProgressState.Template)
 2122          .OrderByDescending(t => t.CurrentProgressId)
 2123          .ThenBy(t => t.Id)
 2124          .Select(t => new AutoTaskListBusinessModel {
 2125          Id = t.Id,
 2126          Name = t.Name,
 2127          Priority = t.Priority,
 2128          FlowId = t.FlowId,
 2129          FlowName = t.Flow!.Name,
 2130          RealmId = r.RealmId,
 2131          RealmName = r.Realm.Name,
 2132          AssignedRobotId = r.Id,
 2133          AssignedRobotName = r.Name,
 2134          CurrentProgressId = t.CurrentProgressId,
 2135          CurrentProgressName = t.CurrentProgress.Name,
 2136        })
 2137        .ToList(),
 2138      })
 2139      .FirstOrDefaultAsync()
 2140        ?? throw new LgdxNotFound404Exception();
 1141  }
 142
 143  public async Task<RobotCreateResponseBusinessModel> CreateRobotAsync(RobotCreateBusinessModel robotCreateBusinessModel
 2144  {
 2145    var realm = await _context.Realms.Where(r => r.Id == robotCreateBusinessModel.RealmId).AnyAsync();
 2146    if (realm == false)
 1147    {
 1148      throw new LgdxValidation400Expection(nameof(robotCreateBusinessModel.RealmId), "Realm does not exist.");
 149    }
 150
 1151    var id = Guid.CreateVersion7();
 1152    var robotCertificate = _robotCertificateService.IssueRobotCertificate(id);
 1153    var robot = new Robot {
 1154      Id = id,
 1155      Name = robotCreateBusinessModel.Name,
 1156      RealmId = robotCreateBusinessModel.RealmId,
 1157      IsRealtimeExchange = robotCreateBusinessModel.IsRealtimeExchange,
 1158      IsProtectingHardwareSerialNumber = robotCreateBusinessModel.IsProtectingHardwareSerialNumber,
 1159      RobotCertificate = new RobotCertificate {
 1160        Thumbprint = robotCertificate.RobotCertificateThumbprint,
 1161        NotBefore = DateTime.SpecifyKind(robotCertificate.RobotCertificateNotBefore, DateTimeKind.Utc),
 1162        NotAfter = DateTime.SpecifyKind(robotCertificate.RobotCertificateNotAfter, DateTimeKind.Utc)
 1163      },
 1164      RobotChassisInfo = new RobotChassisInfo {
 1165        RobotTypeId = robotCreateBusinessModel.RobotChassisInfo.RobotTypeId,
 1166        ChassisLengthX = robotCreateBusinessModel.RobotChassisInfo.ChassisLengthX,
 1167        ChassisLengthY = robotCreateBusinessModel.RobotChassisInfo.ChassisLengthY,
 1168        ChassisWheelCount = robotCreateBusinessModel.RobotChassisInfo.ChassisWheelCount,
 1169        ChassisWheelRadius = robotCreateBusinessModel.RobotChassisInfo.ChassisWheelRadius,
 1170        BatteryCount = robotCreateBusinessModel.RobotChassisInfo.BatteryCount,
 1171        BatteryMaxVoltage = robotCreateBusinessModel.RobotChassisInfo.BatteryMaxVoltage,
 1172        BatteryMinVoltage = robotCreateBusinessModel.RobotChassisInfo.BatteryMinVoltage,
 1173      }
 1174    };
 1175    await _context.Robots.AddAsync(robot);
 1176    await _context.SaveChangesAsync();
 177
 1178    return new RobotCreateResponseBusinessModel {
 1179      RobotId = robot.Id,
 1180      RobotName = robot.Name,
 1181      RootCertificate = robotCertificate.RootCertificate,
 1182      RobotCertificatePrivateKey = robotCertificate.RobotCertificatePrivateKey,
 1183      RobotCertificatePublicKey = robotCertificate.RobotCertificatePublicKey
 1184    };
 1185  }
 186
 187  public async Task<bool> UpdateRobotAsync(Guid id, RobotUpdateBusinessModel robotUpdateDtoBusinessModel)
 0188  {
 0189    return await _context.Robots
 0190      .Where(r => r.Id == id)
 0191      .ExecuteUpdateAsync(setters => setters
 0192        .SetProperty(r => r.Name, robotUpdateDtoBusinessModel.Name)
 0193        .SetProperty(r => r.IsRealtimeExchange, robotUpdateDtoBusinessModel.IsRealtimeExchange)
 0194        .SetProperty(r => r.IsProtectingHardwareSerialNumber, robotUpdateDtoBusinessModel.IsProtectingHardwareSerialNumb
 0195      ) == 1;
 0196  }
 197
 198  public async Task<bool> UpdateRobotChassisInfoAsync(Guid id, RobotChassisInfoUpdateBusinessModel robotChassisInfoUpdat
 0199  {
 0200    return await _context.RobotChassisInfos
 0201      .Where(r => r.RobotId == id)
 0202      .ExecuteUpdateAsync(setters => setters
 0203        .SetProperty(r => r.RobotTypeId, robotChassisInfoUpdateBusinessModel.RobotTypeId)
 0204        .SetProperty(r => r.ChassisLengthX, robotChassisInfoUpdateBusinessModel.ChassisLengthX)
 0205        .SetProperty(r => r.ChassisLengthY, robotChassisInfoUpdateBusinessModel.ChassisLengthY)
 0206        .SetProperty(r => r.ChassisWheelCount, robotChassisInfoUpdateBusinessModel.ChassisWheelCount)
 0207        .SetProperty(r => r.ChassisWheelRadius, robotChassisInfoUpdateBusinessModel.ChassisWheelRadius)
 0208        .SetProperty(r => r.BatteryCount, robotChassisInfoUpdateBusinessModel.BatteryCount)
 0209        .SetProperty(r => r.BatteryMaxVoltage, robotChassisInfoUpdateBusinessModel.BatteryMaxVoltage)
 0210        .SetProperty(r => r.BatteryMinVoltage, robotChassisInfoUpdateBusinessModel.BatteryMinVoltage)
 0211      ) == 1;
 0212  }
 213
 214  public async Task<RobotChassisInfoBusinessModel?> GetRobotChassisInfoAsync(Guid robotId)
 0215  {
 0216    return await _context.RobotChassisInfos.AsNoTracking()
 0217      .Where(r => r.RobotId == robotId)
 0218      .Select(r => new RobotChassisInfoBusinessModel {
 0219        Id = r.Id,
 0220        RobotTypeId = r.RobotTypeId,
 0221        ChassisLengthX = r.ChassisLengthX,
 0222        ChassisLengthY = r.ChassisLengthY,
 0223        ChassisWheelCount = r.ChassisWheelCount,
 0224        ChassisWheelRadius = r.ChassisWheelRadius,
 0225        BatteryCount = r.BatteryCount,
 0226        BatteryMaxVoltage = r.BatteryMaxVoltage,
 0227        BatteryMinVoltage = r.BatteryMinVoltage,
 0228      }).FirstOrDefaultAsync();
 0229  }
 230
 231  public async Task<bool> TestDeleteRobotAsync(Guid id)
 2232  {
 2233    var depeendencies = await _context.AutoTasks
 2234      .Where(t => t.AssignedRobotId == id)
 2235      .Where(t => t.CurrentProgressId != (int)ProgressState.Completed && t.CurrentProgressId != (int)ProgressState.Abort
 2236      .CountAsync();
 2237    if (depeendencies > 0)
 1238    {
 1239      throw new LgdxValidation400Expection(nameof(id), $"This robot has been used by {depeendencies} running/waiting/tem
 240    }
 1241    return true;
 1242  }
 243
 244  public async Task<bool> DeleteRobotAsync(Guid id)
 0245  {
 0246    return await _context.Robots.Where(r => r.Id == id)
 0247      .ExecuteDeleteAsync() >= 1;
 0248  }
 249
 250  public async Task<RobotSystemInfoBusinessModel?> GetRobotSystemInfoAsync(Guid robotId)
 1251  {
 1252    return await _context.RobotSystemInfos.AsNoTracking()
 1253      .Where(r => r.RobotId == robotId)
 1254      .Select(r => new RobotSystemInfoBusinessModel {
 1255        Id = r.Id,
 1256        Cpu = r.Cpu,
 1257        IsLittleEndian = r.IsLittleEndian,
 1258        Motherboard = r.Motherboard,
 1259        MotherboardSerialNumber = r.MotherboardSerialNumber,
 1260        RamMiB = r.RamMiB,
 1261        Gpu = r.Gpu,
 1262        Os = r.Os,
 1263        Is32Bit = r.Is32Bit,
 1264        McuSerialNumber = r.McuSerialNumber,
 1265      })
 1266      .FirstOrDefaultAsync();
 1267  }
 268
 269  public async Task<bool> CreateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoCreateBusinessModel robotSystemInfoCre
 1270  {
 1271    var robotSystemInfo = new RobotSystemInfo {
 1272      Cpu = robotSystemInfoCreateBusinessModel.Cpu,
 1273      IsLittleEndian = robotSystemInfoCreateBusinessModel.IsLittleEndian,
 1274      Motherboard = robotSystemInfoCreateBusinessModel.Motherboard,
 1275      MotherboardSerialNumber = robotSystemInfoCreateBusinessModel.MotherboardSerialNumber,
 1276      RamMiB = robotSystemInfoCreateBusinessModel.RamMiB,
 1277      Gpu = robotSystemInfoCreateBusinessModel.Gpu,
 1278      Os = robotSystemInfoCreateBusinessModel.Os,
 1279      Is32Bit = robotSystemInfoCreateBusinessModel.Is32Bit,
 1280      McuSerialNumber = robotSystemInfoCreateBusinessModel.McuSerialNumber,
 1281      RobotId = robotId
 1282    };
 1283    _context.RobotSystemInfos.Add(robotSystemInfo);
 1284    return await _context.SaveChangesAsync() >= 1;
 1285  }
 286
 287  public async Task<bool> UpdateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoUpdateBusinessModel robotSystemInfoUpd
 0288  {
 0289    return await _context.RobotSystemInfos
 0290      .Where(r => r.RobotId == robotId)
 0291      .ExecuteUpdateAsync(setters => setters
 0292        .SetProperty(r => r.Cpu, robotSystemInfoUpdateBusinessModel.Cpu)
 0293        .SetProperty(r => r.IsLittleEndian, robotSystemInfoUpdateBusinessModel.IsLittleEndian)
 0294        .SetProperty(r => r.Motherboard, robotSystemInfoUpdateBusinessModel.Motherboard)
 0295        .SetProperty(r => r.MotherboardSerialNumber, robotSystemInfoUpdateBusinessModel.MotherboardSerialNumber)
 0296        .SetProperty(r => r.RamMiB, robotSystemInfoUpdateBusinessModel.RamMiB)
 0297        .SetProperty(r => r.Gpu, robotSystemInfoUpdateBusinessModel.Gpu)
 0298        .SetProperty(r => r.Os, robotSystemInfoUpdateBusinessModel.Os)
 0299        .SetProperty(r => r.Is32Bit, robotSystemInfoUpdateBusinessModel.Is32Bit)
 0300        .SetProperty(r => r.McuSerialNumber, robotSystemInfoUpdateBusinessModel.McuSerialNumber)
 0301      ) == 1;
 0302  }
 303
 304  public async Task UpsertRobotChassisInfoAsync(Guid robotId, RobotChassisInfoBusinessModel robotChassisInfo)
 0305  {
 0306    var robotChassisInfoEntity = await _context.RobotChassisInfos.Where(r => r.RobotId == robotId).FirstOrDefaultAsync()
 0307    if (robotChassisInfoEntity == null)
 0308    {
 0309      _context.RobotChassisInfos.Add(new RobotChassisInfo {
 0310        RobotId = robotId,
 0311        RobotTypeId = robotChassisInfo.RobotTypeId,
 0312        ChassisLengthX = robotChassisInfo.ChassisLengthX,
 0313        ChassisLengthY = robotChassisInfo.ChassisLengthY,
 0314        ChassisWheelCount = robotChassisInfo.ChassisWheelCount,
 0315        ChassisWheelRadius = robotChassisInfo.ChassisWheelRadius,
 0316        BatteryCount = robotChassisInfo.BatteryCount,
 0317        BatteryMaxVoltage = robotChassisInfo.BatteryMaxVoltage,
 0318        BatteryMinVoltage = robotChassisInfo.BatteryMinVoltage,
 0319      });
 0320    }
 321    else
 0322    {
 0323      robotChassisInfoEntity.RobotTypeId = robotChassisInfo.RobotTypeId;
 0324      robotChassisInfoEntity.ChassisLengthX = robotChassisInfo.ChassisLengthX;
 0325      robotChassisInfoEntity.ChassisLengthY = robotChassisInfo.ChassisLengthY;
 0326      robotChassisInfoEntity.ChassisWheelCount = robotChassisInfo.ChassisWheelCount;
 0327      robotChassisInfoEntity.ChassisWheelRadius = robotChassisInfo.ChassisWheelRadius;
 0328      robotChassisInfoEntity.BatteryCount = robotChassisInfo.BatteryCount;
 0329      robotChassisInfoEntity.BatteryMaxVoltage = robotChassisInfo.BatteryMaxVoltage;
 0330      robotChassisInfoEntity.BatteryMinVoltage = robotChassisInfo.BatteryMinVoltage;
 0331    }
 0332    await _context.SaveChangesAsync();
 0333  }
 334
 335  public async Task<IEnumerable<RobotSearchBusinessModel>> SearchRobotsAsync(int realmId, string? name, Guid? robotId)
 4336  {
 4337    var n = name ?? string.Empty;
 4338    return await _context.Robots.AsNoTracking()
 4339      .Where(r => r.RealmId == realmId)
 4340      .Where(t => t.Name.ToLower().Contains(n.ToLower()))
 4341      .Where(r => robotId == null || r.Id == robotId)
 4342      .Take(10)
 4343      .Select(m => new RobotSearchBusinessModel {
 4344        Id = m.Id,
 4345        Name = m.Name,
 4346      })
 4347      .ToListAsync();
 4348  }
 349
 350  public async Task<int?> GetRobotRealmIdAsync(Guid robotId)
 3351  {
 3352    if (_memoryCache.TryGetValue<int>($"RobotService_GetRobotRealmIdAsync_{robotId}", out var RealmId))
 1353    {
 1354      return RealmId;
 355    }
 356
 2357    var robot = await _context.Robots.AsNoTracking()
 2358      .Where(m => m.Id == robotId)
 2359      .Select(m => new { m.Id, m.RealmId })
 2360      .FirstOrDefaultAsync();
 2361    if (robot == null)
 1362      return null;
 363
 1364    _memoryCache.Set($"RobotService_GetRobotRealmIdAsync_{robotId}", robot!.RealmId, TimeSpan.FromDays(1));
 1365    return robot.RealmId;
 3366  }
 367
 368  public async Task<bool> GetRobotIsRealtimeExchange(Guid robotId)
 1369  {
 1370    return await _context.Robots.AsNoTracking()
 1371      .Where(r => r.Id == robotId)
 1372      .Select(r => r.IsRealtimeExchange)
 1373      .FirstOrDefaultAsync();
 1374  }
 375}