diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.html b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.html index f17974cf..9ef3950b 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.html +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.html @@ -10,4 +10,4 @@

Edit Plate

-
\ No newline at end of file + \ No newline at end of file diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.ts b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.ts index 9f9197bd..71db1e41 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.ts +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/edit-plate/edit-plate.component.ts @@ -18,5 +18,4 @@ export class EditPlateComponent implements OnInit { ngOnInit(): void { this.plate = this.data.plate; } - } diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plate.service.ts b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plate.service.ts index 25e370a6..0dc9a3d8 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plate.service.ts +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plate.service.ts @@ -16,6 +16,7 @@ export class PlateService { private hydrateDatabaseUrl = "hydration/start"; private getFiltersUrl = 'licenseplates/filters'; private getStatistics = 'licenseplates/statistics'; + private enrichPlateUrl = 'licenseplates/enrich'; constructor(private http: HttpClient) { } @@ -46,6 +47,10 @@ export class PlateService { getPlateStatistics(plateNumber: string): Observable { return this.http.get(`/${this.getStatistics}/${plateNumber}`) } + + enrichPlate(plateId: string): Observable { + return this.http.post(`/${this.enrichPlateUrl}/${plateId}`, null); + } } export class PlateRequest { diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.html b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.html index 5646b46b..1340e3cf 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.html +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.html @@ -32,6 +32,7 @@ (searchPlatesEvent)="searchPlates($event)"> + diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.ts b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.ts index 6c1e46e2..45f942bc 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.ts +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/plates/plates.component.ts @@ -17,6 +17,7 @@ import { VehicleFilters } from './vehicleFilters'; import { MatDialog } from '@angular/material/dialog'; import { EditPlateComponent } from './edit-plate/edit-plate.component'; import { LocalStorageService } from '@app/_services/local-storage.service'; +import { EnrichersService } from '@app/settings/enrichers/enrichers.service'; @Component({ selector: 'app-plates', @@ -80,6 +81,8 @@ export class PlatesComponent implements OnInit, OnDestroy, AfterViewInit { public vehicleFilters: VehicleFilters = {} as VehicleFilters; public isDeletingPlate: boolean; + public isEnrichingPlate: boolean; + public isAddingToIgnoreList: boolean; public isAddingToAlertList: boolean; @@ -95,6 +98,7 @@ export class PlatesComponent implements OnInit, OnDestroy, AfterViewInit { @ViewChild(MatPaginator) paginator: MatPaginator; constructor( + private enricherService: EnrichersService, private plateService: PlateService, private signalRHub: SignalrService, private snackbarService: SnackbarService, @@ -279,7 +283,19 @@ export class PlatesComponent implements OnInit, OnDestroy, AfterViewInit { this.validateSearchPlateNumber(); } - openEditDialog(plateId: string): void { + public enrichPlate(plateId: string) { + this.isEnrichingPlate = true; + this.plateService.enrichPlate(plateId).subscribe(_ => { + this.isEnrichingPlate = false; + this.snackbarService.create("Plate successfully enriched.", SnackBarType.Saved); + }, + _ => { + this.isEnrichingPlate = false; + this.snackbarService.create("Failed to enrich plate, check the logs.", SnackBarType.Error); + }) + } + + public openEditDialog(plateId: string): void { var plateToEdit = this.plates.find(x => x.id == plateId); const dialogRef = this.dialog.open(EditPlateComponent, { diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enricher.ts b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enricher.ts index 65deab29..8886f0e8 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enricher.ts +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enricher.ts @@ -1,10 +1,10 @@ +import { EnrichmentType } from "./enrichmentType"; + export class Enricher { id: string; isEnabled: boolean; apiKey: string; - enrichAlways: boolean; - enrichInNightMode: boolean; - enrichManually: boolean; + enrichmentType: EnrichmentType; constructor(init?:Partial) { Object.assign(this, init); diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichers.component.html b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichers.component.html index f8065aac..9a1781ce 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichers.component.html +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichers.component.html @@ -15,15 +15,11 @@ help_center -
- Enrich every plate -
-
- Enrich plates during night mode -
-
- Only enrich manually -
+ + Enrich every plate + Enrich plates during night mode + Only enrich manually + diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichmentType.ts b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichmentType.ts new file mode 100644 index 00000000..6df9e88f --- /dev/null +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/enrichers/enrichmentType.ts @@ -0,0 +1,6 @@ +export enum EnrichmentType { + Unknown = 0, + Always = "Always", + OnlyAtNight = "OnlyAtNight", + Manually = "Manually", +} \ No newline at end of file diff --git a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/settings.module.ts b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/settings.module.ts index 21f37562..d09497d9 100644 --- a/OpenAlprWebhookProcessor/ClientApp/src/app/settings/settings.module.ts +++ b/OpenAlprWebhookProcessor/ClientApp/src/app/settings/settings.module.ts @@ -34,6 +34,7 @@ import { SystemLogsComponent } from './systemLogs/systemLogs.component'; import { HighlightModule } from 'ngx-highlightjs'; import { PushoverComponent } from './alerts/pushover/pushover.component'; import { EnrichersComponent } from './enrichers/enrichers.component'; +import { MatRadioModule } from '@angular/material/radio'; @NgModule({ declarations: [ @@ -75,6 +76,7 @@ import { EnrichersComponent } from './enrichers/enrichers.component'; FlexLayoutModule, MatSlideToggleModule, MatCheckboxModule, + MatRadioModule, HighlightModule, ] }) diff --git a/OpenAlprWebhookProcessor/Data/Enricher.cs b/OpenAlprWebhookProcessor/Data/Enricher.cs index 79558c51..b7c2d68e 100644 --- a/OpenAlprWebhookProcessor/Data/Enricher.cs +++ b/OpenAlprWebhookProcessor/Data/Enricher.cs @@ -1,4 +1,5 @@ using OpenAlprWebhookProcessor.LicensePlates.Enricher; +using OpenAlprWebhookProcessor.Settings.Enrichers; using System; namespace OpenAlprWebhookProcessor.Data @@ -13,10 +14,6 @@ public class Enricher public string ApiKey { get; set; } - public bool RunAlways { get; set; } - - public bool RunAtNight { get; set; } - - public bool RunManually { get; set; } + public EnrichmentType EnrichmentType { get; set; } } } diff --git a/OpenAlprWebhookProcessor/Data/Migrations/20210721024525_enricherEnum.Designer.cs b/OpenAlprWebhookProcessor/Data/Migrations/20210721024525_enricherEnum.Designer.cs new file mode 100644 index 00000000..5adff815 --- /dev/null +++ b/OpenAlprWebhookProcessor/Data/Migrations/20210721024525_enricherEnum.Designer.cs @@ -0,0 +1,336 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using OpenAlprWebhookProcessor.Data; + +namespace OpenAlprWebhookProcessor.Migrations +{ + [DbContext(typeof(ProcessorContext))] + [Migration("20210721024525_enricherEnum")] + partial class enricherEnum + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.0-preview.4.21253.1"); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.Agent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("EndpointUrl") + .HasColumnType("TEXT"); + + b.Property("Hostname") + .HasColumnType("TEXT"); + + b.Property("LastSuccessfulScrapeEpoch") + .HasColumnType("INTEGER"); + + b.Property("Latitude") + .HasColumnType("REAL"); + + b.Property("Longitude") + .HasColumnType("REAL"); + + b.Property("OpenAlprWebServerApiKey") + .HasColumnType("TEXT"); + + b.Property("OpenAlprWebServerUrl") + .HasColumnType("TEXT"); + + b.Property("SunriseOffset") + .HasColumnType("INTEGER"); + + b.Property("SunsetOffset") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneOffset") + .HasColumnType("REAL"); + + b.Property("Uid") + .HasColumnType("TEXT"); + + b.Property("Version") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Agents"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.Alert", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsStrictMatch") + .HasColumnType("INTEGER"); + + b.Property("PlateNumber") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Alerts"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.Camera", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CameraPassword") + .HasColumnType("TEXT"); + + b.Property("CameraUsername") + .HasColumnType("TEXT"); + + b.Property("DayFocus") + .HasColumnType("TEXT"); + + b.Property("DayZoom") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasColumnType("TEXT"); + + b.Property("LatestProcessedPlateUuid") + .HasColumnType("TEXT"); + + b.Property("Latitude") + .HasColumnType("REAL"); + + b.Property("Longitude") + .HasColumnType("REAL"); + + b.Property("Manufacturer") + .HasColumnType("INTEGER"); + + b.Property("ModelNumber") + .HasColumnType("TEXT"); + + b.Property("NextClearOverlayScheduleId") + .HasColumnType("TEXT"); + + b.Property("NextDayNightScheduleId") + .HasColumnType("TEXT"); + + b.Property("NightFocus") + .HasColumnType("TEXT"); + + b.Property("NightZoom") + .HasColumnType("TEXT"); + + b.Property("OpenAlprCameraId") + .HasColumnType("INTEGER"); + + b.Property("OpenAlprEnabled") + .HasColumnType("INTEGER"); + + b.Property("OpenAlprName") + .HasColumnType("TEXT"); + + b.Property("PlatesSeen") + .HasColumnType("INTEGER"); + + b.Property("SunriseOffset") + .HasColumnType("INTEGER"); + + b.Property("SunsetOffset") + .HasColumnType("INTEGER"); + + b.Property("TimezoneOffset") + .HasColumnType("REAL"); + + b.Property("UpdateDayNightModeEnabled") + .HasColumnType("INTEGER"); + + b.Property("UpdateDayNightModeUrl") + .HasColumnType("TEXT"); + + b.Property("UpdateOverlayEnabled") + .HasColumnType("INTEGER"); + + b.Property("UpdateOverlayTextUrl") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Cameras"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.Enricher", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .HasColumnType("TEXT"); + + b.Property("EnricherType") + .HasColumnType("INTEGER"); + + b.Property("EnrichmentType") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Enrichers"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.Ignore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IsStrictMatch") + .HasColumnType("INTEGER"); + + b.Property("PlateNumber") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Ignores"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.PlateGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AlertDescription") + .HasColumnType("TEXT"); + + b.Property("BestNumber") + .HasColumnType("TEXT"); + + b.Property("Confidence") + .HasColumnType("REAL"); + + b.Property("Direction") + .HasColumnType("REAL"); + + b.Property("IsAlert") + .HasColumnType("INTEGER"); + + b.Property("Jpeg") + .HasColumnType("TEXT"); + + b.Property("Notes") + .HasColumnType("TEXT"); + + b.Property("OpenAlprCameraId") + .HasColumnType("INTEGER"); + + b.Property("OpenAlprProcessingTimeMs") + .HasColumnType("REAL"); + + b.Property("OpenAlprUuid") + .HasColumnType("TEXT"); + + b.Property("PlateCoordinates") + .HasColumnType("TEXT"); + + b.Property("PossibleNumbers") + .HasColumnType("TEXT"); + + b.Property("ReceivedOnEpoch") + .HasColumnType("INTEGER"); + + b.Property("VehicleColor") + .HasColumnType("TEXT"); + + b.Property("VehicleMake") + .HasColumnType("TEXT"); + + b.Property("VehicleMakeModel") + .HasColumnType("TEXT"); + + b.Property("VehicleRegion") + .HasColumnType("TEXT"); + + b.Property("VehicleType") + .HasColumnType("TEXT"); + + b.Property("VehicleYear") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PlateGroups"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.Pushover", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApiToken") + .HasColumnType("TEXT"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("SendPlatePreview") + .HasColumnType("INTEGER"); + + b.Property("UserKey") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("PushoverAlertClients"); + }); + + modelBuilder.Entity("OpenAlprWebhookProcessor.Data.WebhookForward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ForwardGroupPreviews") + .HasColumnType("INTEGER"); + + b.Property("ForwardGroups") + .HasColumnType("INTEGER"); + + b.Property("ForwardSinglePlates") + .HasColumnType("INTEGER"); + + b.Property("FowardingDestination") + .HasColumnType("TEXT"); + + b.Property("IgnoreSslErrors") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("WebhookForwards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/OpenAlprWebhookProcessor/Data/Migrations/20210721024525_enricherEnum.cs b/OpenAlprWebhookProcessor/Data/Migrations/20210721024525_enricherEnum.cs new file mode 100644 index 00000000..59c361c0 --- /dev/null +++ b/OpenAlprWebhookProcessor/Data/Migrations/20210721024525_enricherEnum.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace OpenAlprWebhookProcessor.Migrations +{ + public partial class enricherEnum : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RunAlways", + table: "Enrichers"); + + migrationBuilder.DropColumn( + name: "RunAtNight", + table: "Enrichers"); + + migrationBuilder.RenameColumn( + name: "RunManually", + table: "Enrichers", + newName: "EnrichmentType"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "EnrichmentType", + table: "Enrichers", + newName: "RunManually"); + + migrationBuilder.AddColumn( + name: "RunAlways", + table: "Enrichers", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "RunAtNight", + table: "Enrichers", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + } +} diff --git a/OpenAlprWebhookProcessor/Data/Migrations/ProcessorContextModelSnapshot.cs b/OpenAlprWebhookProcessor/Data/Migrations/ProcessorContextModelSnapshot.cs index 10405c39..015453d4 100644 --- a/OpenAlprWebhookProcessor/Data/Migrations/ProcessorContextModelSnapshot.cs +++ b/OpenAlprWebhookProcessor/Data/Migrations/ProcessorContextModelSnapshot.cs @@ -181,16 +181,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("EnricherType") .HasColumnType("INTEGER"); - b.Property("IsEnabled") - .HasColumnType("INTEGER"); - - b.Property("RunAlways") + b.Property("EnrichmentType") .HasColumnType("INTEGER"); - b.Property("RunAtNight") - .HasColumnType("INTEGER"); - - b.Property("RunManually") + b.Property("IsEnabled") .HasColumnType("INTEGER"); b.HasKey("Id"); diff --git a/OpenAlprWebhookProcessor/LicensePlates/Enricher/EnrichLicensePlateRequestHandler.cs b/OpenAlprWebhookProcessor/LicensePlates/Enricher/EnrichLicensePlateRequestHandler.cs new file mode 100644 index 00000000..39b95e72 --- /dev/null +++ b/OpenAlprWebhookProcessor/LicensePlates/Enricher/EnrichLicensePlateRequestHandler.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore; +using OpenAlprWebhookProcessor.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenAlprWebhookProcessor.LicensePlates.Enricher +{ + public class EnrichLicensePlateRequestHandler + { + private readonly ProcessorContext _processorContext; + + private readonly ILicensePlateEnricherClient _licensePlateEnricherClient; + public EnrichLicensePlateRequestHandler( + ILicensePlateEnricherClient licensePlateEnricherClient, + ProcessorContext processorContext) + { + _licensePlateEnricherClient = licensePlateEnricherClient; + _processorContext = processorContext; + } + + public async Task HandleAsync(Guid plateId) + { + var plateGroup = await _processorContext.PlateGroups + .Where(x => x.Id == plateId) + .FirstOrDefaultAsync(); + + if (plateGroup == null) + { + throw new ArgumentException("Plate Id not found."); + } + + if (!plateGroup.VehicleRegion.StartsWith("us-")) + { + throw new ArgumentException("Plate must be United States region."); + } + + var enrichResult = await _licensePlateEnricherClient.GetLicenseInformationAsync( + plateGroup.BestNumber, + plateGroup.VehicleRegion.Replace("us-", "").ToUpper(), + default); + + plateGroup.VehicleType = enrichResult.Style; + plateGroup.VehicleMake = enrichResult.Make; + plateGroup.VehicleMakeModel = enrichResult.Make + " " + enrichResult.Model; + plateGroup.VehicleYear = enrichResult.Year; + + await _processorContext.SaveChangesAsync(); + } + } +} diff --git a/OpenAlprWebhookProcessor/LicensePlates/Enricher/LicensePlateData/LicensePlateDataClient.cs b/OpenAlprWebhookProcessor/LicensePlates/Enricher/LicensePlateData/LicensePlateDataClient.cs index 3a4db6d2..46995e27 100644 --- a/OpenAlprWebhookProcessor/LicensePlates/Enricher/LicensePlateData/LicensePlateDataClient.cs +++ b/OpenAlprWebhookProcessor/LicensePlates/Enricher/LicensePlateData/LicensePlateDataClient.cs @@ -37,8 +37,6 @@ public async Task GetLicenseInformationAsync( string state, CancellationToken cancellationToken) { - - var response = await _httpClient.GetAsync( LicensePlateDataApiUrl .Replace("$key", await GetApiKeyAsync(cancellationToken)) @@ -88,7 +86,7 @@ public async Task TestAsync(CancellationToken cancellationToken) if (!response.IsSuccessStatusCode) { - _logger.LogError("An error occurred while enriching with LicensePlateData API: " + await response.Content.ReadAsStringAsync(cancellationToken)); + _logger.LogError("An error occurred while testing LicensePlateData API: " + await response.Content.ReadAsStringAsync(cancellationToken)); return false; } @@ -98,7 +96,7 @@ await response.Content.ReadAsStreamAsync(cancellationToken), if (parsed.Error) { - _logger.LogError("An error occurred while testing: " + parsed.Message); + _logger.LogError("An error occurred while testing LicensePlateData API: " + parsed.Message); return false; } diff --git a/OpenAlprWebhookProcessor/LicensePlates/LicensePlatesController.cs b/OpenAlprWebhookProcessor/LicensePlates/LicensePlatesController.cs index 2c6f14c8..00208e2e 100644 --- a/OpenAlprWebhookProcessor/LicensePlates/LicensePlatesController.cs +++ b/OpenAlprWebhookProcessor/LicensePlates/LicensePlatesController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using OpenAlprWebhookProcessor.LicensePlates.DeletePlate; +using OpenAlprWebhookProcessor.LicensePlates.Enricher; using OpenAlprWebhookProcessor.LicensePlates.GetLicensePlateCounts; using OpenAlprWebhookProcessor.LicensePlates.GetPlateFilters; using OpenAlprWebhookProcessor.LicensePlates.GetStatistics; @@ -29,13 +30,16 @@ public class LicensePlatesController : ControllerBase private readonly UpsertPlateRequestHandler _upsertPlateRequestHandler; + private readonly EnrichLicensePlateRequestHandler _enrichLicensePlateRequestHandler; + public LicensePlatesController( SearchLicensePlateHandler searchLicensePlateHandler, GetLicensePlateCountsHandler getLicensePlateCountsHandler, DeleteLicensePlateGroupRequestHandler deleteLicensePlateGroupHandler, GetLicensePlateFiltersHandler getLicensePlateFiltersHandler, GetStatisticsHandler getStatisticsHandler, - UpsertPlateRequestHandler upsertPlateRequestHandler) + UpsertPlateRequestHandler upsertPlateRequestHandler, + EnrichLicensePlateRequestHandler enrichLicensePlateRequestHandler) { _searchLicensePlateHandler = searchLicensePlateHandler; _getLicensePlateCountsHandler = getLicensePlateCountsHandler; @@ -43,6 +47,7 @@ public LicensePlatesController( _getLicensePlateFiltersHandler = getLicensePlateFiltersHandler; _getStatisticsHandler = getStatisticsHandler; _upsertPlateRequestHandler = upsertPlateRequestHandler; + _enrichLicensePlateRequestHandler = enrichLicensePlateRequestHandler; } [HttpPost("search")] @@ -100,5 +105,11 @@ public async Task GetPlateStatistics( plateNumber, cancellationToken); } + + [HttpPost("enrich/{plateId}")] + public async Task EnrichPlate(Guid plateId) + { + await _enrichLicensePlateRequestHandler.HandleAsync(plateId); + } } } diff --git a/OpenAlprWebhookProcessor/Settings/Enrichers/Enricher.cs b/OpenAlprWebhookProcessor/Settings/Enrichers/Enricher.cs index e55a3f2f..3a09afb7 100644 --- a/OpenAlprWebhookProcessor/Settings/Enrichers/Enricher.cs +++ b/OpenAlprWebhookProcessor/Settings/Enrichers/Enricher.cs @@ -1,5 +1,6 @@ using OpenAlprWebhookProcessor.LicensePlates.Enricher; using System; +using System.Text.Json.Serialization; namespace OpenAlprWebhookProcessor.Settings.Enrichers { @@ -13,10 +14,6 @@ public class Enricher public string ApiKey { get; set; } - public bool RunAlways { get; set; } - - public bool RunAtNight { get; set; } - - public bool RunManually { get; set; } + public EnrichmentType EnrichmentType { get; set; } } } diff --git a/OpenAlprWebhookProcessor/Settings/Enrichers/EnrichmentType.cs b/OpenAlprWebhookProcessor/Settings/Enrichers/EnrichmentType.cs new file mode 100644 index 00000000..d313557d --- /dev/null +++ b/OpenAlprWebhookProcessor/Settings/Enrichers/EnrichmentType.cs @@ -0,0 +1,13 @@ +namespace OpenAlprWebhookProcessor.Settings.Enrichers +{ + public enum EnrichmentType + { + Unknown = 0, + + Always = 1, + + OnlyAtNight = 2, + + Manually = 3, + } +} diff --git a/OpenAlprWebhookProcessor/Settings/Enrichers/GetEnrichersRequestHandler.cs b/OpenAlprWebhookProcessor/Settings/Enrichers/GetEnrichersRequestHandler.cs index 951b398c..6cd9f0e9 100644 --- a/OpenAlprWebhookProcessor/Settings/Enrichers/GetEnrichersRequestHandler.cs +++ b/OpenAlprWebhookProcessor/Settings/Enrichers/GetEnrichersRequestHandler.cs @@ -29,9 +29,7 @@ public async Task HandleAsync(CancellationToken cancellationToken) EnricherType = enricher.EnricherType, IsEnabled = enricher.IsEnabled, Id = enricher.Id, - RunAlways = enricher.RunAlways, - RunAtNight = enricher.RunAtNight, - RunManually = enricher.RunManually, + EnrichmentType = enricher.EnrichmentType, }; } } diff --git a/OpenAlprWebhookProcessor/Settings/Enrichers/TestEnricherRequestHandler.cs b/OpenAlprWebhookProcessor/Settings/Enrichers/TestEnricherRequestHandler.cs index a35fcda7..42d77421 100644 --- a/OpenAlprWebhookProcessor/Settings/Enrichers/TestEnricherRequestHandler.cs +++ b/OpenAlprWebhookProcessor/Settings/Enrichers/TestEnricherRequestHandler.cs @@ -1,7 +1,4 @@ -using Microsoft.EntityFrameworkCore; -using OpenAlprWebhookProcessor.Data; -using OpenAlprWebhookProcessor.LicensePlates.Enricher; -using System; +using OpenAlprWebhookProcessor.LicensePlates.Enricher; using System.Threading; using System.Threading.Tasks; @@ -11,12 +8,8 @@ public class TestEnricherRequestHandler { private readonly ILicensePlateEnricherClient _licensePlateEnricherClient; - private readonly ProcessorContext _processorContext; - public TestEnricherRequestHandler( - ProcessorContext processorContext, - ILicensePlateEnricherClient licensePlateEnricherClient) + public TestEnricherRequestHandler(ILicensePlateEnricherClient licensePlateEnricherClient) { - _processorContext = processorContext; _licensePlateEnricherClient = licensePlateEnricherClient; } diff --git a/OpenAlprWebhookProcessor/Settings/Enrichers/UpsertEnricherRequestHandler.cs b/OpenAlprWebhookProcessor/Settings/Enrichers/UpsertEnricherRequestHandler.cs index 1b7c3adf..a4c108f1 100644 --- a/OpenAlprWebhookProcessor/Settings/Enrichers/UpsertEnricherRequestHandler.cs +++ b/OpenAlprWebhookProcessor/Settings/Enrichers/UpsertEnricherRequestHandler.cs @@ -27,9 +27,7 @@ public async Task HandleAsync(Enricher enricher) ApiKey = enricher.ApiKey, EnricherType = enricher.EnricherType, IsEnabled = enricher.IsEnabled, - RunAlways = enricher.RunAlways, - RunAtNight = enricher.RunAtNight, - RunManually = enricher.RunManually, + EnrichmentType = enricher.EnrichmentType, }; _processorContext.Add(dbEnricher); @@ -39,9 +37,7 @@ public async Task HandleAsync(Enricher enricher) dbEnricher.ApiKey = enricher.ApiKey; dbEnricher.EnricherType = enricher.EnricherType; dbEnricher.IsEnabled = enricher.IsEnabled; - dbEnricher.RunAlways = enricher.RunAlways; - dbEnricher.RunAtNight = enricher.RunAtNight; - dbEnricher.RunManually = enricher.RunManually; + dbEnricher.EnrichmentType = enricher.EnrichmentType; } await _processorContext.SaveChangesAsync(); diff --git a/OpenAlprWebhookProcessor/Startup.cs b/OpenAlprWebhookProcessor/Startup.cs index 40b7a2c9..90aedb7d 100644 --- a/OpenAlprWebhookProcessor/Startup.cs +++ b/OpenAlprWebhookProcessor/Startup.cs @@ -45,6 +45,7 @@ using OpenAlprWebhookProcessor.Settings.Enrichers; using OpenAlprWebhookProcessor.LicensePlates.Enricher; using OpenAlprWebhookProcessor.LicensePlates.Enricher.LicensePlateData; +using System.Text.Json.Serialization; namespace OpenAlprWebhookProcessor { @@ -66,7 +67,13 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddCors(); - services.AddControllersWithViews(); + services + .AddControllersWithViews() + .AddJsonOptions(options => + { + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + services.AddSignalR(); var processorOptionsBuilder = new DbContextOptionsBuilder(); @@ -176,6 +183,7 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped();