Skip to content

Commit 6688950

Browse files
authored
support websocket snapshot (#157)
1 parent 8a62b3c commit 6688950

28 files changed

Lines changed: 1257 additions & 53 deletions

OpenAlprWebhookProcessor.Server/Features/ImageRelay/ImageRelayController.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using OpenAlprWebhookProcessor.Features.ImageRelay.GetCropImage;
55
using OpenAlprWebhookProcessor.Features.ImageRelay.GetImage;
66
using OpenAlprWebhookProcessor.Features.ImageRelay.SnapshotRelay;
7+
using OpenAlprWebhookProcessor.Features.ImageRelay.WebsocketSnapshotRelay;
78
using System;
89
using System.Threading;
910
using System.Threading.Tasks;
@@ -75,5 +76,24 @@ public async Task<IActionResult> GetSnapshot(
7576
return NotFound();
7677
}
7778
}
79+
80+
[HttpGet("websocket/{agentId}/{cameraId}/snapshot")]
81+
public async Task<IActionResult> GetWebsocketSnapshot(
82+
string agentId,
83+
long cameraId,
84+
CancellationToken cancellationToken)
85+
{
86+
try
87+
{
88+
var query = new GetWebsocketSnapshotQuery(agentId, cameraId);
89+
var snapshot = await _mediator.Send(query, cancellationToken);
90+
91+
return File(snapshot, "image/jpeg");
92+
}
93+
catch
94+
{
95+
return NotFound();
96+
}
97+
}
7898
}
7999
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using Mediator;
2+
using System;
3+
using System.IO;
4+
5+
namespace OpenAlprWebhookProcessor.Features.ImageRelay.WebsocketSnapshotRelay
6+
{
7+
public class GetWebsocketSnapshotQuery : IQuery<Stream>
8+
{
9+
public string AgentId { get; set; }
10+
11+
public long CameraId { get; set; }
12+
13+
public GetWebsocketSnapshotQuery(string agentId, long cameraId)
14+
{
15+
AgentId = agentId;
16+
CameraId = cameraId;
17+
}
18+
}
19+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using Mediator;
2+
using OpenAlprWebhookProcessor.Features.Webhooks.WebhookProcessor.OpenAlprWebsocket;
3+
using System;
4+
using System.IO;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
8+
namespace OpenAlprWebhookProcessor.Features.ImageRelay.WebsocketSnapshotRelay
9+
{
10+
public class GetWebsocketSnapshotQueryHandler : IQueryHandler<GetWebsocketSnapshotQuery, Stream>
11+
{
12+
private readonly IWebsocketClientOrganizer _websocketClientOrganizer;
13+
14+
public GetWebsocketSnapshotQueryHandler(IWebsocketClientOrganizer websocketClientOrganizer)
15+
{
16+
_websocketClientOrganizer = websocketClientOrganizer ?? throw new ArgumentNullException(nameof(websocketClientOrganizer));
17+
}
18+
19+
public async ValueTask<Stream> Handle(GetWebsocketSnapshotQuery request, CancellationToken cancellationToken)
20+
{
21+
var response = await _websocketClientOrganizer.GetCameraSnapshotAsync(
22+
request.AgentId,
23+
request.CameraId,
24+
cancellationToken);
25+
26+
if (response == null)
27+
{
28+
throw new InvalidOperationException("Failed to get snapshot from agent");
29+
}
30+
31+
if (string.IsNullOrWhiteSpace(response.Image))
32+
{
33+
throw new InvalidOperationException("Agent returned empty image data");
34+
}
35+
36+
try
37+
{
38+
var imageBytes = Convert.FromBase64String(response.Image);
39+
return new MemoryStream(imageBytes);
40+
}
41+
catch (FormatException ex)
42+
{
43+
throw new InvalidOperationException("Invalid image data received from agent", ex);
44+
}
45+
}
46+
}
47+
}

OpenAlprWebhookProcessor.Server/Features/LicensePlates/Commands/UpdatePlateNumber/UpdatePlateNumberCommand.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ public class UpdatePlateNumberCommand : ICommand
99

1010
public string PlateNumber { get; set; }
1111
}
12+
13+

OpenAlprWebhookProcessor.Server/Features/LicensePlates/Commands/UpdatePlateNumber/UpdatePlateNumberCommandHandler.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ public async ValueTask<Unit> Handle(UpdatePlateNumberCommand request, Cancellati
3232
return Unit.Value;
3333
}
3434
}
35+
36+

OpenAlprWebhookProcessor.Server/Features/Webhooks/WebhookProcessor/OpenAlprWebsocket/IOpenAlprWebsocketClient.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ Task SendGetAgentStatusRequestAsync(
2323

2424
Task SendGetImageRequestAsync(
2525
Guid transactionId,
26-
long cameraId,
26+
long cameraId,
27+
string imageUuid,
2728
CancellationToken cancellationToken = default);
2829

2930
Task SendSaveMaskRequestAsync(

OpenAlprWebhookProcessor.Server/Features/Webhooks/WebhookProcessor/OpenAlprWebsocket/IWebsocketClientOrganizer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.IO;
12
using System.Threading;
23
using System.Threading.Tasks;
34

@@ -29,6 +30,11 @@ Task<bool> UpsertCameraMaskAsync(
2930
string openAlprName,
3031
CancellationToken cancellationToken = default);
3132

33+
Task<ImageDownloadResponse> GetCameraSnapshotAsync(
34+
string agentId,
35+
long cameraId,
36+
CancellationToken cancellationToken = default);
37+
3238
Task DisconnectAllClientsAsync(CancellationToken cancellationToken = default);
3339
}
3440
}

OpenAlprWebhookProcessor.Server/Features/Webhooks/WebhookProcessor/OpenAlprWebsocket/ImageDownloadRequest.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,20 @@ public class ImageDownloadRequest
77
{
88
public ImageDownloadRequest() { }
99

10-
1110
[JsonPropertyName("type")]
1211
public string RequestType { get; set; }
12+
13+
[JsonPropertyName("uuid")]
14+
public string Uuid { get; set; }
1315

1416
[JsonPropertyName("direction")]
1517
public string Direction { get; set; }
1618

1719
[JsonPropertyName("camera_id")]
1820
public long CameraId { get; set; }
21+
22+
[JsonPropertyName("size")]
23+
public ImageDownloadRequestSize Size { get; set; }
1924

2025
[JsonPropertyName("transaction_id")]
2126
public Guid TransactionId { get; set; }
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace OpenAlprWebhookProcessor.Features.Webhooks.WebhookProcessor.OpenAlprWebsocket
4+
{
5+
public class ImageDownloadRequestSize
6+
{
7+
public ImageDownloadRequestSize() { }
8+
9+
[JsonPropertyName("type")]
10+
public string X { get; set; }
11+
12+
[JsonPropertyName("uuid")]
13+
public string Y { get; set; }
14+
15+
[JsonPropertyName("direction")]
16+
public int Width { get; set; }
17+
18+
[JsonPropertyName("camera_id")]
19+
public int Height { get; set; }
20+
}
21+
}

OpenAlprWebhookProcessor.Server/Features/Webhooks/WebhookProcessor/OpenAlprWebsocket/OpenAlprWebsocketClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public async Task ConsumeMessagesAsync(CancellationToken cancellationToken = def
8282
public async Task SendGetImageRequestAsync(
8383
Guid transactionId,
8484
long cameraId,
85+
string imageUuid = null,
8586
CancellationToken cancellationToken = default)
8687
{
8788
var imageRequest = new ImageDownloadRequest()
@@ -90,6 +91,7 @@ public async Task SendGetImageRequestAsync(
9091
Direction = "request",
9192
RequestType = RequestType.GetRequestType(OpenAlprRequestType.ImageDownload),
9293
TransactionId = transactionId,
94+
Uuid = imageUuid,
9395
};
9496

9597
var message = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(imageRequest));

0 commit comments

Comments
 (0)