296 lines
12 KiB
C#
296 lines
12 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using NLog;
|
|
using OpenCvSharp;
|
|
using OpenCvSharp.Extensions;
|
|
|
|
namespace AIParkingApplication
|
|
{
|
|
public partial class LaneOut : UserControl, ILane
|
|
{
|
|
private Camera overviewCamera;
|
|
private Camera plateCamera;
|
|
private PlateProcessor plateProcessor;
|
|
public int DoorId { get; set; }
|
|
private string cameraId;
|
|
private bool isSupportSquarePlate;
|
|
private bool isSupportLongPlate;
|
|
private bool isAutoOpenDoor;
|
|
private bool isRetryMode;
|
|
private IDoorControlAccess doorControlAccess;
|
|
private ApiController apiController;
|
|
private Printer printer;
|
|
private Logger appLogger;
|
|
|
|
public LaneOut(int doorId,
|
|
string cameraId,
|
|
string plateStream,
|
|
string overviewStream,
|
|
IDoorControlAccess doorControlAccess,
|
|
ApiController apiController,
|
|
EngineApiController engineApiController,
|
|
Logger appLogger,
|
|
bool isSupportSquarePlate = true,
|
|
bool isSupportLongPlate = false,
|
|
bool isAutoOpenDoor = true,
|
|
bool isRetryMode = false)
|
|
{
|
|
InitializeComponent();
|
|
this.appLogger = appLogger;
|
|
DoorId = doorId;
|
|
this.cameraId = cameraId;
|
|
this.isSupportSquarePlate = isSupportSquarePlate;
|
|
this.isSupportLongPlate = isSupportLongPlate;
|
|
this.isAutoOpenDoor = isAutoOpenDoor;
|
|
this.isRetryMode = isRetryMode;
|
|
overviewCamera = new Camera(overviewStream);
|
|
plateCamera = new Camera(plateStream);
|
|
this.apiController = apiController;
|
|
this.doorControlAccess = doorControlAccess;
|
|
printer = new Printer(appLogger);
|
|
plateProcessor = new PlateProcessor(engineApiController, this.isSupportSquarePlate, this.isSupportLongPlate);
|
|
}
|
|
|
|
private async void C3Device_OnNewCardReceived(int doorId, string cardNumber)
|
|
{
|
|
if (DoorId != doorId)
|
|
{
|
|
return;
|
|
}
|
|
ClearPlateAndOverviewImage();
|
|
ClearPlateAndOverviewImageIn();
|
|
var cardInfoResult = await apiController.GetCardInformation(cardNumber);
|
|
if (cardInfoResult == null)
|
|
{
|
|
lblStatusInfo.UpdateLabel("KHÔNG THỂ KẾT NỐI SERVER", Color.Purple);
|
|
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: KHÔNG THỂ KẾT NỐI TỚI SERVER");
|
|
return;
|
|
}
|
|
if (!cardInfoResult.IsValid)
|
|
{
|
|
lblStatusInfo.UpdateLabel("THẺ KHÔNG HỢP LỆ", Color.Purple);
|
|
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: THẺ KHÔNG HỢP LỆ");
|
|
return;
|
|
}
|
|
|
|
if (cardInfoResult.Direction != "out")
|
|
{
|
|
lblStatusInfo.UpdateLabel("CHƯA NHẬN THẺ VÀO", Color.Red);
|
|
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: XE ĐÃ Ở TRONG BÃI");
|
|
return;
|
|
}
|
|
|
|
Bitmap plateImageIn = Util.ConvertFromBase64Image(cardInfoResult.PlateImageBase64);
|
|
Bitmap overviewImageIn = Util.ConvertFromBase64Image(cardInfoResult.FrameImageBase64);
|
|
|
|
pictureBoxPlateImageIn.UpdateImage(plateImageIn);
|
|
pictureBoxOverviewImageIn.UpdateImage(overviewImageIn);
|
|
|
|
plateCamera.RequestCaptureOneFrame();
|
|
overviewCamera.RequestCaptureOneFrame();
|
|
await Task.Delay(200);
|
|
appLogger.Log(LogLevel.Info, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | Chụp ảnh camera");
|
|
|
|
var plateVideoFrame = plateCamera.CurrentFrame;
|
|
FinalPlateResult result = await ProcessFrameImage(plateProcessor, plateVideoFrame, isRetryMode);
|
|
pictureBoxPlateImage.UpdateImage(result.PlateImage.ToBitmap());
|
|
|
|
var overviewVideoFrame = overviewCamera.CurrentFrame;
|
|
pictureBoxOverviewImage.UpdateImage(overviewVideoFrame.ToBitmap());
|
|
|
|
var cardInformation = await apiController.GetCardInformation(cardNumber);
|
|
|
|
var saveLogResult = await apiController.SaveLog(LaneDirection.Out, cardInformation.CardRealID.ToString(), cameraId, result.PlateType, DateTime.Now.GetTimeFormatted(), result.PlateString, result.PlateImage, result.PlateImage, result.PlateImage, overviewVideoFrame, cardInformation.LogID.ToString());
|
|
|
|
if (saveLogResult == null)
|
|
{
|
|
lblStatusInfo.UpdateLabel("KHÔNG CÓ KẾT NỐI ĐẾN MÁY CHỦ", Color.Red);
|
|
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: KHÔNG CÓ KẾT NỐI ĐẾN MÁY CHỦ - KHÔNG LƯU ĐƯỢC LOG");
|
|
return;
|
|
}
|
|
|
|
ShowCardInfoOnUI(cardNumber, result.PlateString, cardInformation.PlateString, cardInformation.CardType, cardInformation.TimeIn, DateTime.Now.GetTimeFormatted(), saveLogResult.Cost);
|
|
|
|
if (saveLogResult.Status)
|
|
{
|
|
if (isAutoOpenDoor)
|
|
{
|
|
OpenDoor(doorId);
|
|
appLogger.Log(LogLevel.Info, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | biển số: {result.PlateString} | Đã mở cửa");
|
|
}
|
|
PrinterData printerData = new PrinterData
|
|
{
|
|
PlateString = result.PlateString,
|
|
MoneyAmount = saveLogResult.Cost,
|
|
TimeParkingIn = cardInformation.TimeIn,
|
|
TimeParkingOut = DateTime.Now.GetTimeFormatted()
|
|
};
|
|
printer.DoPrint(printerData);
|
|
}
|
|
else
|
|
{
|
|
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: LƯU BẢN GHI LỖI");
|
|
lblStatusInfo.UpdateLabel("LƯU BẢN GHI LỖI", Color.Red);
|
|
}
|
|
}
|
|
|
|
private void PlateCamera_OnOpenVideoStreamFailed(Mat videoFrame)
|
|
{
|
|
pictureBoxPlateVideo.UpdateImage(videoFrame.ToBitmap());
|
|
}
|
|
|
|
private void OverviewCamera_OnOpenVideoStreamFailed(Mat videoFrame)
|
|
{
|
|
pictureBoxOverviewVideo.UpdateImage(videoFrame.ToBitmap());
|
|
}
|
|
|
|
private void ClearPlateAndOverviewImage()
|
|
{
|
|
pictureBoxPlateImage.UpdateImage(null);
|
|
pictureBoxOverviewImage.UpdateImage(null);
|
|
}
|
|
|
|
private void ClearPlateAndOverviewImageIn()
|
|
{
|
|
pictureBoxPlateImageIn.UpdateImage(null);
|
|
pictureBoxOverviewImageIn.UpdateImage(null);
|
|
}
|
|
|
|
private void OpenDoor(int doorId)
|
|
{
|
|
if (doorControlAccess.OpenDoor(doorId).HasError)
|
|
{
|
|
lblStatusInfo.UpdateLabel("KHÔNG THỂ MỞ CỬA", Color.Red);
|
|
}
|
|
}
|
|
|
|
private async Task<FinalPlateResult> ProcessFrameImage(PlateProcessor plateProcessor, Mat frame, bool isRetryMode)
|
|
{
|
|
try
|
|
{
|
|
Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
|
|
FinalPlateResult finalPlateResult = await plateProcessor.ProcessPlate(frame);
|
|
|
|
if (isRetryMode && !plateProcessor.IsPlateStringValid(finalPlateResult.PlateString))
|
|
{
|
|
Console.WriteLine("ProcessFrameImage Retry Mode");
|
|
Thread.Sleep(1000);
|
|
overviewCamera.RequestCaptureOneFrame();
|
|
finalPlateResult = await plateProcessor.ProcessPlate(frame);
|
|
}
|
|
return finalPlateResult;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"ProcessFrameImage\texMessage: {ex.Message}");
|
|
return new FinalPlateResult
|
|
{
|
|
PlateImage = frame,
|
|
PlateString = string.Empty,
|
|
PlateType = PlateType.Square
|
|
};
|
|
}
|
|
}
|
|
|
|
public void Stop()
|
|
{
|
|
plateCamera.Stop();
|
|
overviewCamera.Stop();
|
|
|
|
pictureBoxPlateImage.UpdateImage(null);
|
|
pictureBoxPlateVideo.UpdateImage(null);
|
|
|
|
pictureBoxOverviewImage.UpdateImage(null);
|
|
pictureBoxOverviewVideo.UpdateImage(null);
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
plateCamera.Start();
|
|
overviewCamera.Start();
|
|
}
|
|
|
|
private void ShowCardInfoOnUI(string cardNumber, string plateStringEngine, string plateInString, string cardType, string cardTimeIn, string cardTimeOut, string money)
|
|
{
|
|
lblCardNumber.UpdateLabel($"Số thẻ: {cardNumber}");
|
|
lblPlateString.UpdateLabel($"Biển số: {plateStringEngine}");
|
|
lblCardType.UpdateLabel($"Loại thẻ: {cardType}");
|
|
lblCardTime.UpdateLabel($"Vào: {cardTimeIn}");
|
|
lblCardTimeOut.UpdateLabel($"Ra: {cardTimeOut}");
|
|
|
|
int.TryParse(money, out int moneyAmount);
|
|
lblMoneyAmount.UpdateLabel($"Số tiền: {string.Format("{0:n0}", moneyAmount)} vnđ");
|
|
|
|
if (string.IsNullOrEmpty(plateStringEngine))
|
|
{
|
|
lblStatusInfo.UpdateLabel("KHÔNG NHẬN DIỆN ĐƯỢC BIỂN SỐ", Color.Red);
|
|
}
|
|
else
|
|
{
|
|
if (plateStringEngine != plateInString)
|
|
{
|
|
lblStatusInfo.UpdateLabel("SO KHỚP BIỂN SỐ KHÔNG CHÍNH XÁC", Color.Red);
|
|
}
|
|
else
|
|
{
|
|
lblStatusInfo.UpdateLabel($"MỜI XE {plateStringEngine} QUA", Color.Green);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OverviewCameraOnVideoFrameReceived(Mat videoFrame)
|
|
{
|
|
try
|
|
{
|
|
pictureBoxOverviewVideo.UpdateImage(videoFrame.ToBitmap());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"{Util.GetCurrentMethodName()}\texMessage: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void PlateCameraOnVideoFrameReceived(Mat videoFrame)
|
|
{
|
|
try
|
|
{
|
|
pictureBoxPlateVideo.UpdateImage(videoFrame.ToBitmap());
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"{Util.GetCurrentMethodName()}\texMessage: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void ConnectToDoorAccessControl()
|
|
{
|
|
if (!doorControlAccess.Connect().HasError)
|
|
{
|
|
_ = doorControlAccess.GetLogToReceiveNewCard();
|
|
}
|
|
else
|
|
{
|
|
lblStatusInfo.UpdateLabel("KHÔNG THỂ KẾT NỐI TỚI C3200", Color.Purple);
|
|
}
|
|
}
|
|
|
|
private void LaneIn_Load(object sender, EventArgs e)
|
|
{
|
|
ConnectToDoorAccessControl();
|
|
}
|
|
|
|
private void LaneOut_Load(object sender, EventArgs e)
|
|
{
|
|
doorControlAccess.OnNewCardReceived += C3Device_OnNewCardReceived;
|
|
plateCamera.OnVideoFrameReceived += PlateCameraOnVideoFrameReceived;
|
|
plateCamera.OnOpenVideoStreamFailed += PlateCamera_OnOpenVideoStreamFailed;
|
|
|
|
overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived;
|
|
overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed;
|
|
}
|
|
}
|
|
}
|