TrafficController.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //#define USE_ACTORMODEL
  2. /*
  3. This controller contains 2 implementations of the TrafficControl functionality: a basic
  4. implementation and an actor-model based implementation.
  5. The code for the basic implementation is in this controller. The actor-model implementation
  6. resides in the Vehicle actor (./Actors/VehicleActor.cs).
  7. To switch between the two implementations, you need to use the USE_ACTORMODEL symbol at
  8. the top of this file. If you comment the #define USE_ACTORMODEL statement, the basic
  9. implementation is used. Uncomment this statement to use the Actormodel implementation.
  10. */
  11. namespace TrafficControlService.Controllers;
  12. [ApiController]
  13. [Route("")]
  14. public class TrafficController : ControllerBase
  15. {
  16. private readonly ILogger<TrafficController> _logger;
  17. private readonly IVehicleStateRepository _vehicleStateRepository;
  18. private readonly ISpeedingViolationCalculator _speedingViolationCalculator;
  19. private readonly string _roadId;
  20. public TrafficController(
  21. ILogger<TrafficController> logger,
  22. IVehicleStateRepository vehicleStateRepository,
  23. ISpeedingViolationCalculator speedingViolationCalculator)
  24. {
  25. _logger = logger;
  26. _vehicleStateRepository = vehicleStateRepository;
  27. _speedingViolationCalculator = speedingViolationCalculator;
  28. _roadId = speedingViolationCalculator.GetRoadId();
  29. }
  30. #if !USE_ACTORMODEL
  31. [HttpGet("weatherforecast")]
  32. public async Task<ActionResult> VehicleEntry()
  33. {
  34. try
  35. {
  36. return Ok();
  37. }
  38. catch (Exception ex)
  39. {
  40. _logger.LogError(ex, "Error occurred while processing ENTRY");
  41. return StatusCode(500);
  42. }
  43. }
  44. [HttpPost("entrycam")]
  45. public async Task<ActionResult> VehicleEntryAsync(VehicleRegistered msg)
  46. {
  47. try
  48. {
  49. // log entry
  50. _logger.LogInformation($"ENTRY detected in lane {msg.Lane} at {msg.Timestamp.ToString("hh:mm:ss")} " +
  51. $"of vehicle with license-number {msg.LicenseNumber}.");
  52. // store vehicle state
  53. var vehicleState = new VehicleState(msg.LicenseNumber, msg.Timestamp, null);
  54. await _vehicleStateRepository.SaveVehicleStateAsync(vehicleState);
  55. return Ok();
  56. }
  57. catch (Exception ex)
  58. {
  59. _logger.LogError(ex, "Error occurred while processing ENTRY");
  60. return StatusCode(500);
  61. }
  62. }
  63. [HttpPost("exitcam")]
  64. public async Task<ActionResult> VehicleExitAsync(VehicleRegistered msg, [FromServices] DaprClient daprClient)
  65. {
  66. try
  67. {
  68. // get vehicle state
  69. var state = await _vehicleStateRepository.GetVehicleStateAsync(msg.LicenseNumber);
  70. if (state == default(VehicleState))
  71. {
  72. return NotFound();
  73. }
  74. // log exit
  75. _logger.LogInformation($"EXIT detected in lane {msg.Lane} at {msg.Timestamp.ToString("hh:mm:ss")} " +
  76. $"of vehicle with license-number {msg.LicenseNumber}.");
  77. // update state
  78. var exitState = state.Value with { ExitTimestamp = msg.Timestamp };
  79. await _vehicleStateRepository.SaveVehicleStateAsync(exitState);
  80. // handle possible speeding violation
  81. int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(exitState.EntryTimestamp, exitState.ExitTimestamp.Value);
  82. if (violation > 0)
  83. {
  84. _logger.LogInformation($"Speeding violation detected ({violation} KMh) of vehicle" +
  85. $"with license-number {state.Value.LicenseNumber}.");
  86. var speedingViolation = new SpeedingViolation
  87. {
  88. VehicleId = msg.LicenseNumber,
  89. RoadId = _roadId,
  90. ViolationInKmh = violation,
  91. Timestamp = msg.Timestamp
  92. };
  93. // publish speedingviolation (Dapr publish / subscribe)
  94. await daprClient.PublishEventAsync("pubsub", "speedingviolations", speedingViolation);
  95. }
  96. return Ok();
  97. }
  98. catch (Exception ex)
  99. {
  100. _logger.LogError(ex, "Error occurred while processing EXIT");
  101. return StatusCode(500);
  102. }
  103. }
  104. #else
  105. [HttpPost("entrycam")]
  106. public async Task<ActionResult> VehicleEntryAsync(VehicleRegistered msg)
  107. {
  108. try
  109. {
  110. var actorId = new ActorId(msg.LicenseNumber);
  111. var proxy = ActorProxy.Create<IVehicleActor>(actorId, nameof(VehicleActor));
  112. await proxy.RegisterEntryAsync(msg);
  113. return Ok();
  114. }
  115. catch
  116. {
  117. return StatusCode(500);
  118. }
  119. }
  120. [HttpPost("exitcam")]
  121. public async Task<ActionResult> VehicleExitAsync(VehicleRegistered msg)
  122. {
  123. try
  124. {
  125. var actorId = new ActorId(msg.LicenseNumber);
  126. var proxy = ActorProxy.Create<IVehicleActor>(actorId, nameof(VehicleActor));
  127. await proxy.RegisterExitAsync(msg);
  128. return Ok();
  129. }
  130. catch
  131. {
  132. return StatusCode(500);
  133. }
  134. }
  135. #endif
  136. }