Compare commits

..

51 Commits

Author SHA1 Message Date
DucDangAnh
d97908a22b ConfigurationForm - Add Event For btnCheckDoorDeviceControlAccessIP_Click 2020-07-21 16:02:38 +07:00
DucDangAnh
9400402141 AppConstant - add App.config key 2020-07-21 15:52:47 +07:00
DucDangAnh
59208674e0 App.config - add Key AUTO_RUN_AT_STARTUP. ConfigurationForm - add features: auto startup with Windows. 2020-07-21 14:05:39 +07:00
DucDangAnh
aa73bf8129 ConfigurationForm - btnSaveSettings_Click: fix typo 2020-07-20 15:38:37 +07:00
DucDangAnh
aa1aae8c6c ConfigurationForm - add toolStripStatusLabelSavedSettingStatus to show saved settings status. 2020-07-20 15:36:31 +07:00
DucDangAnh
1671d3b456 ConfigurationForm - add chkAllowAutoLogin 2020-07-20 15:22:10 +07:00
DucDangAnh
a3543084b7 ConfigurationForm - add appLogger into constructor. Add LoadConfiguration() 2020-07-20 15:18:19 +07:00
DucDangAnh
89e766714a ConfigurationForm - allow user use Printer 2020-07-20 14:48:48 +07:00
DucDangAnh
fd96643412 Add ConfigurationForm. AIParkingApplicationForm - add ConfigurationForm 2020-07-20 14:39:16 +07:00
Le Chau
1418b1077e Merge branch 'master' of http://gitea.beetai.com/ducda/AIParkingApplication 2020-07-20 11:55:53 +07:00
Le Chau
53aa3e31ea Thêm tính năng lưu ROI lên Server và Vẽ lại ROI 2020-07-20 11:53:43 +07:00
Le Chau
076290e141 Thêm tính năng Cascade trong vùng ROI 2020-07-17 15:19:12 +07:00
DucDangAnh
6284909fd8 Util - Rename AddOrUpdateAppSettings to UpsertAppSettings 2020-07-17 15:01:16 +07:00
DucDangAnh
68d84387b8 App.config - add DEFAULT_WEB_SERVER key. LoginForm - update DEFAULT_WEB_SERVER 2020-07-17 15:00:13 +07:00
Le Chau
c0c8b325d0 Thêm tính năng vẽ ROI vào khung cam bắt biển 2020-07-17 14:03:14 +07:00
DucDangAnh
2c6e326008 LoginForm - Add UI check status auto login 2020-07-16 16:23:43 +07:00
DucDangAnh
01098b4597 LaneOut - Fix message type 2020-07-16 16:07:40 +07:00
DucDangAnh
61f6be6093 LaneOut - fix typo 2020-07-16 15:58:19 +07:00
DucDangAnh
d3a47432bb LaneOut - Add exMessage to logger of ReadUsePrinterConfig 2020-07-16 15:57:04 +07:00
DucDangAnh
2c60eebda1 App.config - add USE_PRINTER key. LaneOut - add ReadUsePrinterConfig 2020-07-16 15:55:10 +07:00
DucDangAnh
7c03df5229 LoginForm - Auto Login Feature. 2020-07-16 15:44:27 +07:00
DucDangAnh
c9b65ba883 Update logging message. 2020-07-16 15:30:46 +07:00
DucDangAnh
a835ed626b ApiController - simplified CardModel in GetCardInformation 2020-07-15 16:17:06 +07:00
DucDangAnh
79eca30267 ApiController - retry delay 800ms 2020-07-15 16:06:58 +07:00
DucDangAnh
87e3a7418a ApiController - update appLogger log 2020-07-15 16:04:54 +07:00
DucDangAnh
646449b4ba ApiController - rename applicationLogger -> appLogger 2020-07-15 15:59:21 +07:00
DucDangAnh
e8fae43c1d ApiController - Update Method: SaveLog. LaneIn, LaneOut - Add log 2020-07-15 15:54:46 +07:00
DucDangAnh
153eba219f Add appLogger. 2020-07-15 14:34:13 +07:00
DucDangAnh
b4baa218b4 ApiController - Add Log 2020-07-14 17:06:32 +07:00
DucDangAnh
b020ca2a73 AIParkingApplicationForm - Remove Redundant code. 2020-07-14 17:06:06 +07:00
DucDangAnh
ee590211f8 Move applicationLogger into LoginForm 2020-07-14 15:16:11 +07:00
DucDangAnh
52f71be90b ApiController - Update numberOfRetry 2020-07-14 14:48:53 +07:00
DucDangAnh
08c6ed210e NLog.config - Update Log Layout 2020-07-14 14:43:07 +07:00
DucDangAnh
2a8a1ff1a5 AIParkingApplicationForm - Update Loglevel when exit app. 2020-07-14 14:40:01 +07:00
DucDangAnh
8778a976db AIParkingApplicationForm - add applicationLogger 2020-07-14 14:30:58 +07:00
DucDangAnh
e1f1320671 NLog.config - Update logger configuration. 2020-07-14 14:27:43 +07:00
DucDangAnh
0af35e015a AIParkingApplicationForm - use serverIPAddress param instead of hardcoded string. 2020-07-14 11:38:11 +07:00
DucDangAnh
7d2f05a2f8 AIParkingApplication.csproj - Add NLog Lib. 2020-07-14 11:35:53 +07:00
DucDangAnh
d6d87b2ec8 AIParkingApplication.csproj - add class ExtensitionMethods. Util - Remove extensition methods. 2020-07-14 11:14:56 +07:00
DucDangAnh
740858693e AIParkingApplicationForm - hardcoded to const CURRENT_LANE_SETTING_KEY. Util - Add extensition method: DisableSelected 2020-07-14 11:07:53 +07:00
DucDangAnh
0375eac88d AIParkingApplicationForm - Remove Exit Dialog Confirmation. 2020-07-13 16:18:50 +07:00
DucDangAnh
daf755949a AIParkingApplicationForm - Add method: InitLaneFirstTime, save lanes configuration. 2020-07-13 16:02:50 +07:00
DucDangAnh
92d95236c8 LoginForm - Catch Execption: Set default text input for username, password 2020-07-13 15:41:04 +07:00
DucDangAnh
06dc6957ce Util - Update Method: AddOrUpdateAppSettings 2020-07-13 15:39:58 +07:00
DucDangAnh
5773b6d48e LoginForm - Save username, password to ConfigurationFile. 2020-07-13 15:35:01 +07:00
DucDangAnh
73e353b99e Util - Add Method AddOrUpdateAppSettings 2020-07-13 15:34:23 +07:00
DucDangAnh
9d25ac394b AIParkingApplicationForm - Closing Form Show Confirmation Dialog 2020-07-13 15:11:18 +07:00
DucDangAnh
74855b6467 LoginForm - Check IP Address Input. 2020-07-13 14:51:44 +07:00
DucDangAnh
728f65cd90 StatusBar - Remove updateInterval 2020-07-13 11:04:48 +07:00
DucDangAnh
50301189d8 Update App Title 2020-07-13 10:50:00 +07:00
DucDangAnh
6d7125511c Util - Add IsValidIPAddress 2020-07-13 10:48:20 +07:00
60 changed files with 298875 additions and 178 deletions

View File

@@ -77,6 +77,9 @@
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.7.2\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="OpenCvSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6adad1e807fea099, processorArchitecture=MSIL">
<HintPath>..\packages\OpenCvSharp4.4.3.0.20200524\lib\net461\OpenCvSharp.dll</HintPath>
</Reference>
@@ -89,12 +92,19 @@
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -102,7 +112,6 @@
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
@@ -118,8 +127,15 @@
<Compile Include="AppConstant.cs" />
<Compile Include="C3DeviceController.cs" />
<Compile Include="Camera.cs" />
<Compile Include="ConfigurationForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ConfigurationForm.Designer.cs">
<DependentUpon>ConfigurationForm.cs</DependentUpon>
</Compile>
<Compile Include="EngineApiController.cs" />
<Compile Include="Enums.cs" />
<Compile Include="ExtensitionMethods.cs" />
<Compile Include="IDoorControlAccess.cs" />
<Compile Include="ILane.cs" />
<Compile Include="LaneIn.cs">
@@ -167,6 +183,9 @@
<EmbeddedResource Include="AIParkingApplicationForm.resx">
<DependentUpon>AIParkingApplicationForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ConfigurationForm.resx">
<DependentUpon>ConfigurationForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="LaneIn.resx">
<DependentUpon>LaneIn.cs</DependentUpon>
</EmbeddedResource>
@@ -198,6 +217,12 @@
<None Include="engine.bat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Content Include="NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="NLog.xsd">
<SubType>Designer</SubType>
</None>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>

View File

@@ -35,13 +35,15 @@
this.toolStripMenuItemSwitchLaneInOut = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemSwitchLaneOutOut = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItemSwitchLaneOutIn = new System.Windows.Forms.ToolStripMenuItem();
this.setupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip.SuspendLayout();
this.SuspendLayout();
//
// menuStrip
//
this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItemSwitchLane});
this.toolStripMenuItemSwitchLane,
this.setupToolStripMenuItem});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.Size = new System.Drawing.Size(1366, 24);
@@ -62,31 +64,38 @@
// toolStripMenuItemSwitchLaneInIn
//
this.toolStripMenuItemSwitchLaneInIn.Name = "toolStripMenuItemSwitchLaneInIn";
this.toolStripMenuItemSwitchLaneInIn.Size = new System.Drawing.Size(123, 22);
this.toolStripMenuItemSwitchLaneInIn.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItemSwitchLaneInIn.Text = "Vào - Vào";
this.toolStripMenuItemSwitchLaneInIn.Click += new System.EventHandler(this.toolStripMenuItemSwitchLaneInIn_Click);
//
// toolStripMenuItemSwitchLaneInOut
//
this.toolStripMenuItemSwitchLaneInOut.Name = "toolStripMenuItemSwitchLaneInOut";
this.toolStripMenuItemSwitchLaneInOut.Size = new System.Drawing.Size(123, 22);
this.toolStripMenuItemSwitchLaneInOut.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItemSwitchLaneInOut.Text = "Vào - Ra";
this.toolStripMenuItemSwitchLaneInOut.Click += new System.EventHandler(this.toolStripMenuItemSwitchLaneInOut_Click);
//
// toolStripMenuItemSwitchLaneOutOut
//
this.toolStripMenuItemSwitchLaneOutOut.Name = "toolStripMenuItemSwitchLaneOutOut";
this.toolStripMenuItemSwitchLaneOutOut.Size = new System.Drawing.Size(123, 22);
this.toolStripMenuItemSwitchLaneOutOut.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItemSwitchLaneOutOut.Text = "Ra - Ra";
this.toolStripMenuItemSwitchLaneOutOut.Click += new System.EventHandler(this.toolStripMenuItemSwitchLaneOutOut_Click);
//
// toolStripMenuItemSwitchLaneOutIn
//
this.toolStripMenuItemSwitchLaneOutIn.Name = "toolStripMenuItemSwitchLaneOutIn";
this.toolStripMenuItemSwitchLaneOutIn.Size = new System.Drawing.Size(123, 22);
this.toolStripMenuItemSwitchLaneOutIn.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItemSwitchLaneOutIn.Text = "Ra - Vào";
this.toolStripMenuItemSwitchLaneOutIn.Click += new System.EventHandler(this.toolStripMenuItemSwitchLaneOutIn_Click);
//
// setupToolStripMenuItem
//
this.setupToolStripMenuItem.Name = "setupToolStripMenuItem";
this.setupToolStripMenuItem.Size = new System.Drawing.Size(56, 20);
this.setupToolStripMenuItem.Text = "Cài đặt";
this.setupToolStripMenuItem.Click += new System.EventHandler(this.setupToolStripMenuItem_Click);
//
// AIParkingApplicationForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -116,6 +125,7 @@
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSwitchLaneInOut;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSwitchLaneOutOut;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemSwitchLaneOutIn;
private System.Windows.Forms.ToolStripMenuItem setupToolStripMenuItem;
}
}

View File

@@ -1,4 +1,5 @@
using System;
using NLog;
using System;
using System.Configuration;
using System.Drawing;
using System.Linq;
@@ -19,28 +20,31 @@ namespace AIParkingApplication
private Config configOnWeb;
private EngineApiController engineApiController;
private string doorAccessControlDeviceIP;
private Logger appLogger;
public AIParkingApplicationForm(ApiController apiController, Config configOnWeb)
public AIParkingApplicationForm(ApiController apiController, string serverIPAddress, Config configOnWeb, Logger appLogger)
{
InitializeComponent();
this.apiController = apiController;
this.configOnWeb = configOnWeb;
this.appLogger = appLogger;
ReadAccessControlDeviceIPConfiguration();
if (string.IsNullOrEmpty(doorAccessControlDeviceIP))
ReadAccessControlDeviceIPConfigurationFile();
if (string.IsNullOrEmpty(doorAccessControlDeviceIP) || !Util.IsValidIPAddress(doorAccessControlDeviceIP))
{
appLogger.Log(LogLevel.Error, "Kiểm tra lại cấu hình IP thiết bị mở cửa!");
MessageBox.Show("Kiểm tra lại cấu hình IP thiết bị mở cửa! (C3200)", "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
c3Device = new C3DeviceController(doorAccessControlDeviceIP);
c3Device = new C3DeviceController(appLogger, doorAccessControlDeviceIP);
sidebar = new Sidebar(apiController)
{
Location = new Point(0, 0)
};
Controls.Add(sidebar);
statusBar = new StatusBar("192.168.1.122", doorAccessControlDeviceIP, TimeSpan.FromSeconds(1))
statusBar = new StatusBar(serverIPAddress, doorAccessControlDeviceIP)
{
Location = new Point(0, sidebar.Location.Y + sidebar.Height + 26),
Anchor = AnchorStyles.Bottom | AnchorStyles.Left
@@ -51,33 +55,44 @@ namespace AIParkingApplication
{
engineApiController = new EngineApiController($"http://{this.configOnWeb.APIPath.ApiPlateRecognize.IP}:{this.configOnWeb.APIPath.ApiPlateRecognize.Port}");
}
catch (Exception)
catch (Exception ex)
{
appLogger.Log(LogLevel.Error, $"Cấu hình URL của Engine nhận diện biển số lỗi. exMessage: {ex.Message}");
MessageBox.Show("Cấu hình API Plate Recognize lỗi!", "Cấu hình API Engine lỗi!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
}
private void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
appLogger.Log(LogLevel.Error, $"Application.ThreadException. ex:{e.Exception.Message}");
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
appLogger.Log(LogLevel.Error, $"AppDomain.CurrentDomain.UnhandledException. ex:{(e.ExceptionObject as Exception).Message}");
}
private void InitAllLanes()
{
laneIn12 = new LaneIn(10, configOnWeb.CameraData1.Id.ToString(), configOnWeb.CameraData1.StreamUrl, configOnWeb.CameraData2.StreamUrl, c3Device, apiController, engineApiController, true, false, true);
laneIn12 = new LaneIn(10, configOnWeb.CameraData1.Id.ToString(), configOnWeb.CameraData1.StreamUrl, configOnWeb.CameraData2.StreamUrl, c3Device, apiController, engineApiController, appLogger, configOnWeb.CameraData1.Roi_config, true, false, true);
laneIn12.BorderStyle = BorderStyle.FixedSingle;
laneIn12.Hide();
Controls.Add(laneIn12);
laneOut34 = new LaneOut(20, configOnWeb.CameraData3.Id.ToString(), configOnWeb.CameraData3.StreamUrl, configOnWeb.CameraData4.StreamUrl, c3Device, apiController, engineApiController, true, false, true);
laneOut34 = new LaneOut(20, configOnWeb.CameraData3.Id.ToString(), configOnWeb.CameraData3.StreamUrl, configOnWeb.CameraData4.StreamUrl, c3Device, apiController, engineApiController, appLogger, configOnWeb.CameraData3.Roi_config, true, false, true);
laneOut34.BorderStyle = BorderStyle.FixedSingle;
laneOut34.Hide();
Controls.Add(laneOut34);
laneIn56 = new LaneIn(10, configOnWeb.CameraData5.Id.ToString(), configOnWeb.CameraData5.StreamUrl, configOnWeb.CameraData6.StreamUrl, c3Device, apiController, engineApiController, true, false, true);
laneIn56 = new LaneIn(10, configOnWeb.CameraData5.Id.ToString(), configOnWeb.CameraData5.StreamUrl, configOnWeb.CameraData6.StreamUrl, c3Device, apiController, engineApiController, appLogger, configOnWeb.CameraData5.Roi_config, true, false, true);
laneIn56.BorderStyle = BorderStyle.FixedSingle;
laneIn56.Hide();
Controls.Add(laneIn56);
laneOut78 = new LaneOut(20, configOnWeb.CameraData7.Id.ToString(), configOnWeb.CameraData7.StreamUrl, configOnWeb.CameraData8.StreamUrl, c3Device, apiController, engineApiController, true, false, true);
laneOut78 = new LaneOut(20, configOnWeb.CameraData7.Id.ToString(), configOnWeb.CameraData7.StreamUrl, configOnWeb.CameraData8.StreamUrl, c3Device, apiController, engineApiController, appLogger, configOnWeb.CameraData7.Roi_config, true, false, true);
laneOut78.BorderStyle = BorderStyle.FixedSingle;
laneOut78.Hide();
Controls.Add(laneOut78);
@@ -137,30 +152,38 @@ namespace AIParkingApplication
private void toolStripMenuItemSwitchLaneInIn_Click(object sender, EventArgs e)
{
Util.UpsertAppSettings(AppConstant.CURRENT_LANE_SETTING, "IN-IN");
UpdateMenuStripItemStatus(sender as ToolStripMenuItem);
StopAllLanes();
UpdateLaneInIn();
appLogger.Log(LogLevel.Info, "Chuyển làn: IN-IN");
}
private void toolStripMenuItemSwitchLaneInOut_Click(object sender, EventArgs e)
{
Util.UpsertAppSettings(AppConstant.CURRENT_LANE_SETTING, "IN-OUT");
UpdateMenuStripItemStatus(sender as ToolStripMenuItem);
StopAllLanes();
UpdateLaneInOut();
appLogger.Log(LogLevel.Info, "Chuyển làn: IN-OUT");
}
private void toolStripMenuItemSwitchLaneOutIn_Click(object sender, EventArgs e)
{
Util.UpsertAppSettings(AppConstant.CURRENT_LANE_SETTING, "OUT-IN");
UpdateMenuStripItemStatus(sender as ToolStripMenuItem);
StopAllLanes();
UpdateLaneOutIn();
appLogger.Log(LogLevel.Info, "Chuyển làn: OUT-IN");
}
private void toolStripMenuItemSwitchLaneOutOut_Click(object sender, EventArgs e)
{
Util.UpsertAppSettings(AppConstant.CURRENT_LANE_SETTING, "OUT-OUT");
UpdateMenuStripItemStatus(sender as ToolStripMenuItem);
StopAllLanes();
UpdateLaneOutOut();
appLogger.Log(LogLevel.Info, "Chuyển làn: OUT-OUT");
}
private void UpdateMenuStripItemStatus(ToolStripMenuItem selectedToolStripMenuItem)
@@ -198,27 +221,92 @@ namespace AIParkingApplication
laneOut78?.Hide();
}
private void ReadAccessControlDeviceIPConfiguration()
private void InitLaneFirstTime()
{
try
{
doorAccessControlDeviceIP = ConfigurationManager.AppSettings["DOOR_ACCESS_DEVICE_CONTROL_IP"].Trim();
string lanesConfig = ConfigurationManager.AppSettings[AppConstant.CURRENT_LANE_SETTING];
if (!string.IsNullOrEmpty(lanesConfig))
{
string[] lanes = lanesConfig.Split('-');
if (lanes.Length == 2)
{
string lane0 = lanes[0].ToLower();
string lane1 = lanes[1].ToLower();
if (lane0 == "in" && lane1 == "in")
{
UpdateLaneInIn();
toolStripMenuItemSwitchLaneInIn.DisableSelected();
appLogger.Log(LogLevel.Info, $"Khởi động App sử dụng lane: IN-IN");
}
if (lane0 == "in" && lane1 == "out")
{
UpdateLaneInOut();
toolStripMenuItemSwitchLaneInOut.DisableSelected();
appLogger.Log(LogLevel.Info, $"Khởi động App sử dụng lane: IN-OUT");
}
if (lane0 == "out" && lane1 == "in")
{
UpdateLaneOutIn();
toolStripMenuItemSwitchLaneOutIn.DisableSelected();
appLogger.Log(LogLevel.Info, $"Khởi động App sử dụng lane: OUT-IN");
}
if (lane0 == "out" && lane1 == "out")
{
UpdateLaneOutOut();
toolStripMenuItemSwitchLaneOutOut.DisableSelected();
appLogger.Log(LogLevel.Info, $"Khởi động App sử dụng lane: OUT-OUT");
}
}
else
{
Util.UpsertAppSettings(AppConstant.CURRENT_LANE_SETTING, "IN-OUT");
UpdateLaneInOut();
toolStripMenuItemSwitchLaneInOut.DisableSelected();
appLogger.Log(LogLevel.Info, $"Khởi động App đọc config không đủ 2 param: IN-OUT");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now.GetTimeFormatted()}\tReadAccessControlDeviceIPConfiguration\t{ex.Message}");
doorAccessControlDeviceIP = string.Empty;
Util.UpsertAppSettings(AppConstant.CURRENT_LANE_SETTING, "IN-OUT");
UpdateLaneInOut();
toolStripMenuItemSwitchLaneInOut.DisableSelected();
Console.WriteLine($"{DateTime.Now.GetTimeFormatted()}\tReadLaneSettingFromConfigurationFile\t{ex.Message}");
appLogger.Log(LogLevel.Error, $"Đọc config làn lỗi khi khởi động app!\texMessage: {ex.Message}");
}
}
private void AIParkingApplicationForm_FormClosing(object sender, FormClosingEventArgs e)
private void ReadAccessControlDeviceIPConfigurationFile()
{
Application.Exit();
try
{
doorAccessControlDeviceIP = ConfigurationManager.AppSettings[AppConstant.DOOR_ACCESS_DEVICE_CONTROL_IP].Trim();
}
catch (Exception ex)
{
doorAccessControlDeviceIP = string.Empty;
Console.WriteLine($"{DateTime.Now.GetTimeFormatted()}\tReadAccessControlDeviceIPConfiguration\t{ex.Message}");
appLogger.Log(LogLevel.Error, $"Cấu hình IP thiết bị mở cửa lỗi({AppConstant.DOOR_ACCESS_DEVICE_CONTROL_IP})!\texMessage: {ex.Message}");
}
}
private void AIParkingApplicationForm_Load(object sender, EventArgs e)
{
InitAllLanes();
InitLaneFirstTime();
}
private void AIParkingApplicationForm_FormClosing(object sender, FormClosingEventArgs e)
{
appLogger.Log(LogLevel.Info, $"Đóng ứng dụng");
Application.Exit();
}
private void setupToolStripMenuItem_Click(object sender, EventArgs e)
{
var configurationForm = new ConfigurationForm(appLogger);
configurationForm.ShowDialog(this);
}
}
}

View File

@@ -4,23 +4,28 @@ using System.Threading.Tasks;
using OpenCvSharp;
using Newtonsoft.Json;
using System.Net;
using NLog;
using System.Drawing;
namespace AIParkingApplication
{
public class ApiController : IDisposable
{
private const int MAX_REQUEST = 3;
private HttpClient httpClient;
private bool isHttpClientDisposabled;
private int numberOfRetry;
private Logger appLogger;
public ApiController(string baseAddress, int numberOfRetry = 5)
public ApiController(string serverIPAddress, Logger appLogger, int numberOfRetry = 3)
{
this.appLogger = appLogger;
httpClient = new HttpClient
{
BaseAddress = new Uri(baseAddress),
BaseAddress = new Uri($"http://{serverIPAddress}"),
Timeout = TimeSpan.FromSeconds(5)
};
isHttpClientDisposabled = false;
this.numberOfRetry = numberOfRetry;
}
~ApiController()
@@ -40,6 +45,7 @@ namespace AIParkingApplication
catch (Exception ex)
{
Console.WriteLine($"Login Exception:\t{DateTime.Now.GetTimeFormatted()} \t {ex.Message}");
appLogger.Log(LogLevel.Error, $"Login lỗi. exMessage: {ex.Message}");
return new LoginDataModel
{
IsLoginSuccess = false,
@@ -70,28 +76,25 @@ namespace AIParkingApplication
catch (Exception ex)
{
Console.WriteLine($"GetStatisticInfo Exception:\t{DateTime.Now.GetTimeFormatted()} \t {ex.Message}");
appLogger.Log(LogLevel.Error, $"Query dữ liệu thống kê bãi xe lỗi. exMessage: {ex.Message}");
return null;
}
}
public async Task<CardInformation> GetCardInformation(string cardNumber)
{
int requestCounter = 1;
try
{
var request = new CardModel()
{
CardNumber = cardNumber
};
HttpResponseMessage response;
int requestCounter = 1;
do
{
response = await httpClient.PostAsJsonAsync("/api/check-card", request);
response = await httpClient.PostAsJsonAsync("/api/check-card", new CardModel { CardNumber = cardNumber });
response.EnsureSuccessStatusCode();
requestCounter += 1;
await Task.Delay(100);
await Task.Delay(800);
}
while (response.StatusCode != HttpStatusCode.OK && requestCounter < MAX_REQUEST);
while (response.StatusCode != HttpStatusCode.OK && requestCounter < numberOfRetry);
var cardValication = await response.Content.ReadAsAsync<CardInformation>();
return cardValication;
@@ -99,17 +102,19 @@ namespace AIParkingApplication
catch (Exception ex)
{
Console.WriteLine($"CheckCard Exception:\t{DateTime.Now.GetTimeFormatted()} \t {ex.Message}");
appLogger.Log(LogLevel.Error, $"Query thông tin thẻ lỗi. Thẻ số: {cardNumber} | số lần thử lại: {requestCounter} | exMessage: {ex.Message}");
return null;
}
}
//Neu Dicrection la Out thi logID la logID lay ve khi check the
public async Task<SaveLogRespone> SaveLog(LaneDirection direction, string cardID, string cameraID, PlateType plateType, string timestamp, string plateString, Mat plateImage, Mat plateImageResult, Mat plateFrameImage, Mat frameImage, string logID = "")
{
string plateImageBase64 = Convert.ToBase64String(plateImage.ToBytes());
string plateImageResultBase64 = Convert.ToBase64String(plateImageResult.ToBytes());
string plateFrameImageBase64 = Convert.ToBase64String(plateFrameImage.ToBytes());
string frameImageBase64 = Convert.ToBase64String(frameImage.ToBytes());
int requestCounter = 1;
try
{
var request = new SaveLogModel
@@ -127,21 +132,52 @@ namespace AIParkingApplication
FrameImage = frameImageBase64
};
HttpResponseMessage response;
int requestCounter = 1;
do
{
response = await httpClient.PostAsJsonAsync("/api/save-logs", request);
response.EnsureSuccessStatusCode();
requestCounter += 1;
await Task.Delay(100);
} while (response.StatusCode != HttpStatusCode.OK && requestCounter < MAX_REQUEST);
await Task.Delay(800);
} while (response.StatusCode != HttpStatusCode.OK && requestCounter < numberOfRetry);
SaveLogRespone saveLogRespone = await response.Content.ReadAsAsync<SaveLogRespone>();
return saveLogRespone;
}
catch (Exception ex)
{
Console.WriteLine($"SaveLog Exception:\t{DateTime.Now.GetTimeFormatted()} \t {ex.Message}");
return new SaveLogRespone();
appLogger.Log(LogLevel.Error, string.Format("Không thể lưu log gửi xe. Làn: {0} | Mã thẻ: {1} | cameraID: {2} | Thời gian: {3} | Biển số: {4} | LogID: {5} | exMessage: ", direction == LaneDirection.In ? "IN" : "OUT", cardID, cameraID, timestamp, plateString, logID, ex.Message));
return null;
}
}
public async void SaveRoiToServer(Rectangle roiRegion, string cameraId)
{
int requestCounter = 1;
try
{
var request = new RoiConfig
{
CameraID = cameraId,
X = roiRegion.X,
Y = roiRegion.Y,
Width = roiRegion.Width,
Height = roiRegion.Height
};
HttpResponseMessage response;
do
{
response = await httpClient.PostAsJsonAsync("/api/update-roi", request);
response.EnsureSuccessStatusCode();
requestCounter += 1;
} while (response.StatusCode != HttpStatusCode.OK && requestCounter < numberOfRetry);
SaveLogRespone saveLogRespone = await response.Content.ReadAsAsync<SaveLogRespone>();
}
catch (Exception ex)
{
Console.WriteLine($"SaveRoiConfig Exception:\t{DateTime.Now.GetTimeFormatted()} \t {ex.Message}");
appLogger.Log(LogLevel.Error, string.Format("Không thể lưu ROI Config | exMessage: " + ex.Message));
}
}
@@ -482,6 +518,7 @@ namespace AIParkingApplication
public int Logs { get; set; }
}
#region LaneConfig
public class LaneConfig
{

View File

@@ -2,6 +2,16 @@
<configuration>
<appSettings>
<add key="DOOR_ACCESS_DEVICE_CONTROL_IP" value="192.168.1.200" />
<add key="DEFAULT_USERNAME" value="cong1vao" />
<add key="DEFAULT_PASSWORD" value="123456a@" />
<add key="DEFAULT_WEB_SERVER" value="192.168.1.122:80" />
<add key="CURRENT_LANE_SETTING" value="IN-OUT" />
<add key="AUTO_LOGIN" value="false" />
<add key="USE_PRINTER" value="false" />
<add key="AUTO_OPEN_DOOR_1" value="true" />
<add key="AUTO_OPEN_DOOR_2" value="true" />
<add key="ALLOW_CHANGE_ROI_RECT" value="true" />
<add key="AUTO_RUN_AT_STARTUP" value="false" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
@@ -12,6 +22,10 @@
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.1.1.3" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -2,13 +2,29 @@
{
public static class AppConstant
{
#region Application Messages
public const string APPLICATION_IS_RUNNNING = "AIParkingApplication: Ứng dụng đã chạy!";
public const string ERROR_TITLE = "Lỗi";
public const string DATETIME_FORMAT = "HH:mm:ss dd/MM/yyyy";
#endregion
public const string CAMERA_FAILED_IMAGE_PATH = @"Images\CantConnectCamera.jpg";
public const string CAMERA_FAILED_IMAGE_PATH = @".\Images\CantConnectCamera.jpg";
public const string DEFAULT_LOGO_IMAGE = @".\Images\ApplicationLogo.ico";
public const string APPLICATION_LOGGER_NAME = "ApplicationLogger";
public const string PING_SERVER_LOGGER_NAME = "PingServerLogger";
public const string PING_DOOR_DEVICE_CONTROL_ACCESS_LOGGER_NAME = "PingDoorDeviceControlAccessLogger";
#region App Config Key
public const string DOOR_ACCESS_DEVICE_CONTROL_IP = "DOOR_ACCESS_DEVICE_CONTROL_IP";
public const string DEFAULT_USERNAME = "DEFAULT_USERNAME";
public const string DEFAULT_PASSWORD = "DEFAULT_PASSWORD";
public const string DEFAULT_WEB_SERVER = "DEFAULT_WEB_SERVER";
public const string CURRENT_LANE_SETTING = "CURRENT_LANE_SETTING";
public const string AUTO_LOGIN = "AUTO_LOGIN";
public const string USE_PRINTER = "USE_PRINTER";
public const string AUTO_OPEN_DOOR_1 = "AUTO_OPEN_DOOR_1";
public const string AUTO_OPEN_DOOR_2 = "AUTO_OPEN_DOOR_2";
public const string ALLOW_CHANGE_ROI_RECT = "ALLOW_CHANGE_ROI_RECT";
public const string AUTO_RUN_AT_STARTUP = "AUTO_RUN_AT_STARTUP";
#endregion
}
}

View File

@@ -1,4 +1,5 @@
using System;
using NLog;
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
@@ -15,10 +16,11 @@ namespace AIParkingApplication
private string connectionString;
private bool isReconnected;
private int reconnectCounter;
private Logger appLogger;
public event C3DeviceEvent OnNewCardReceived;
public C3DeviceController(string ipAddress, int port = C3Constant.DEFAULT_C3_PORT)
public C3DeviceController(Logger appLogger, string ipAddress, int port = C3Constant.DEFAULT_C3_PORT)
{
this.ipAddress = ipAddress;
this.port = port;
@@ -26,6 +28,7 @@ namespace AIParkingApplication
oneTimeConnectedParamHandler = IntPtr.Zero;
isReconnected = true;
reconnectCounter = 0;
this.appLogger = appLogger;
}
~C3DeviceController()

View File

@@ -1,5 +1,6 @@
using OpenCvSharp;
using System.Threading;
using System.Windows.Forms;
namespace AIParkingApplication
{
@@ -50,7 +51,7 @@ namespace AIParkingApplication
{
if (!videoCapture.Open(streamUrl))
{
OnOpenVideoStreamFailed?.Invoke(Cv2.ImRead(AppConstant.CAMERA_FAILED_IMAGE_PATH));
OnOpenVideoStreamFailed?.Invoke(Cv2.ImRead(Application.StartupPath + AppConstant.CAMERA_FAILED_IMAGE_PATH));
return;
}
@@ -72,7 +73,7 @@ namespace AIParkingApplication
}
else
{
OnOpenVideoStreamFailed?.Invoke(Cv2.ImRead(AppConstant.CAMERA_FAILED_IMAGE_PATH));
OnOpenVideoStreamFailed?.Invoke(Cv2.ImRead(Application.StartupPath + AppConstant.CAMERA_FAILED_IMAGE_PATH));
}
}
}

View File

@@ -0,0 +1,290 @@
namespace AIParkingApplication
{
partial class ConfigurationForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lblDoorDeviceControlAccessIPStatus = new System.Windows.Forms.Label();
this.btnCheckDoorDeviceControlAccessIP = new System.Windows.Forms.Button();
this.btnClose = new System.Windows.Forms.Button();
this.btnSaveSettings = new System.Windows.Forms.Button();
this.chkAllowChangeROIRect = new System.Windows.Forms.CheckBox();
this.chkAllowAutoDoor2 = new System.Windows.Forms.CheckBox();
this.chkAllowAutoDoor1 = new System.Windows.Forms.CheckBox();
this.lblAllowChangeROIRect = new System.Windows.Forms.Label();
this.lblAllowAutoOpenDoorIn = new System.Windows.Forms.Label();
this.txtDoorDeviceControlAccessIP = new System.Windows.Forms.TextBox();
this.lblDoorDeviceControlAccessIP = new System.Windows.Forms.Label();
this.lblAllowUsePrinter = new System.Windows.Forms.Label();
this.chkAllowUsePrinter = new System.Windows.Forms.CheckBox();
this.lblAllowAutoLogin = new System.Windows.Forms.Label();
this.chkAllowAutoLogin = new System.Windows.Forms.CheckBox();
this.statusStrip = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabelSavedSettingStatus = new System.Windows.Forms.ToolStripStatusLabel();
this.lblAllowAutoRun = new System.Windows.Forms.Label();
this.chkAllowAutoRunAtStartUp = new System.Windows.Forms.CheckBox();
this.statusStrip.SuspendLayout();
this.SuspendLayout();
//
// lblDoorDeviceControlAccessIPStatus
//
this.lblDoorDeviceControlAccessIPStatus.AutoSize = true;
this.lblDoorDeviceControlAccessIPStatus.Location = new System.Drawing.Point(412, 9);
this.lblDoorDeviceControlAccessIPStatus.Name = "lblDoorDeviceControlAccessIPStatus";
this.lblDoorDeviceControlAccessIPStatus.Size = new System.Drawing.Size(58, 13);
this.lblDoorDeviceControlAccessIPStatus.TabIndex = 17;
this.lblDoorDeviceControlAccessIPStatus.Text = "Trạng thái:";
//
// btnCheckDoorDeviceControlAccessIP
//
this.btnCheckDoorDeviceControlAccessIP.Location = new System.Drawing.Point(330, 3);
this.btnCheckDoorDeviceControlAccessIP.Name = "btnCheckDoorDeviceControlAccessIP";
this.btnCheckDoorDeviceControlAccessIP.Size = new System.Drawing.Size(75, 24);
this.btnCheckDoorDeviceControlAccessIP.TabIndex = 2;
this.btnCheckDoorDeviceControlAccessIP.Text = "Kiểm tra";
this.btnCheckDoorDeviceControlAccessIP.UseVisualStyleBackColor = true;
this.btnCheckDoorDeviceControlAccessIP.Click += new System.EventHandler(this.btnCheckDoorDeviceControlAccessIP_Click);
//
// btnClose
//
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnClose.Location = new System.Drawing.Point(528, 207);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(106, 41);
this.btnClose.TabIndex = 7;
this.btnClose.Text = "Đóng";
this.btnClose.UseVisualStyleBackColor = true;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// btnSaveSettings
//
this.btnSaveSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnSaveSettings.Location = new System.Drawing.Point(416, 207);
this.btnSaveSettings.Name = "btnSaveSettings";
this.btnSaveSettings.Size = new System.Drawing.Size(106, 41);
this.btnSaveSettings.TabIndex = 0;
this.btnSaveSettings.Text = "Lưu";
this.btnSaveSettings.UseVisualStyleBackColor = true;
this.btnSaveSettings.Click += new System.EventHandler(this.btnSaveSettings_Click);
//
// chkAllowChangeROIRect
//
this.chkAllowChangeROIRect.AutoSize = true;
this.chkAllowChangeROIRect.Location = new System.Drawing.Point(252, 95);
this.chkAllowChangeROIRect.Name = "chkAllowChangeROIRect";
this.chkAllowChangeROIRect.Size = new System.Drawing.Size(72, 17);
this.chkAllowChangeROIRect.TabIndex = 5;
this.chkAllowChangeROIRect.Text = "Cho phép";
this.chkAllowChangeROIRect.UseVisualStyleBackColor = true;
//
// chkAllowAutoDoor2
//
this.chkAllowAutoDoor2.AutoSize = true;
this.chkAllowAutoDoor2.Location = new System.Drawing.Point(252, 37);
this.chkAllowAutoDoor2.Name = "chkAllowAutoDoor2";
this.chkAllowAutoDoor2.Size = new System.Drawing.Size(68, 17);
this.chkAllowAutoDoor2.TabIndex = 4;
this.chkAllowAutoDoor2.Text = "Cửa số 2";
this.chkAllowAutoDoor2.UseVisualStyleBackColor = true;
//
// chkAllowAutoDoor1
//
this.chkAllowAutoDoor1.AutoSize = true;
this.chkAllowAutoDoor1.Location = new System.Drawing.Point(141, 37);
this.chkAllowAutoDoor1.Name = "chkAllowAutoDoor1";
this.chkAllowAutoDoor1.Size = new System.Drawing.Size(68, 17);
this.chkAllowAutoDoor1.TabIndex = 3;
this.chkAllowAutoDoor1.Text = "Cửa số 1";
this.chkAllowAutoDoor1.UseVisualStyleBackColor = true;
//
// lblAllowChangeROIRect
//
this.lblAllowChangeROIRect.AutoSize = true;
this.lblAllowChangeROIRect.Location = new System.Drawing.Point(11, 96);
this.lblAllowChangeROIRect.Name = "lblAllowChangeROIRect";
this.lblAllowChangeROIRect.Size = new System.Drawing.Size(211, 13);
this.lblAllowChangeROIRect.TabIndex = 9;
this.lblAllowChangeROIRect.Text = "Cho phép thay đổi vùng nhận diện biển số:";
//
// lblAllowAutoOpenDoorIn
//
this.lblAllowAutoOpenDoorIn.AutoSize = true;
this.lblAllowAutoOpenDoorIn.Location = new System.Drawing.Point(11, 39);
this.lblAllowAutoOpenDoorIn.Name = "lblAllowAutoOpenDoorIn";
this.lblAllowAutoOpenDoorIn.Size = new System.Drawing.Size(89, 13);
this.lblAllowAutoOpenDoorIn.TabIndex = 10;
this.lblAllowAutoOpenDoorIn.Text = "Tự động mở cửa:";
//
// txtDoorDeviceControlAccessIP
//
this.txtDoorDeviceControlAccessIP.Location = new System.Drawing.Point(141, 5);
this.txtDoorDeviceControlAccessIP.Name = "txtDoorDeviceControlAccessIP";
this.txtDoorDeviceControlAccessIP.Size = new System.Drawing.Size(183, 20);
this.txtDoorDeviceControlAccessIP.TabIndex = 1;
//
// lblDoorDeviceControlAccessIP
//
this.lblDoorDeviceControlAccessIP.AutoSize = true;
this.lblDoorDeviceControlAccessIP.Location = new System.Drawing.Point(12, 9);
this.lblDoorDeviceControlAccessIP.Name = "lblDoorDeviceControlAccessIP";
this.lblDoorDeviceControlAccessIP.Size = new System.Drawing.Size(96, 13);
this.lblDoorDeviceControlAccessIP.TabIndex = 7;
this.lblDoorDeviceControlAccessIP.Text = "IP Thiết bị mở cửa:";
//
// lblAllowUsePrinter
//
this.lblAllowUsePrinter.AutoSize = true;
this.lblAllowUsePrinter.Location = new System.Drawing.Point(11, 67);
this.lblAllowUsePrinter.Name = "lblAllowUsePrinter";
this.lblAllowUsePrinter.Size = new System.Drawing.Size(83, 13);
this.lblAllowUsePrinter.TabIndex = 9;
this.lblAllowUsePrinter.Text = "Sử dụng máy in:";
//
// chkAllowUsePrinter
//
this.chkAllowUsePrinter.AutoSize = true;
this.chkAllowUsePrinter.Location = new System.Drawing.Point(141, 66);
this.chkAllowUsePrinter.Name = "chkAllowUsePrinter";
this.chkAllowUsePrinter.Size = new System.Drawing.Size(66, 17);
this.chkAllowUsePrinter.TabIndex = 5;
this.chkAllowUsePrinter.Text = "Sử dụng";
this.chkAllowUsePrinter.UseVisualStyleBackColor = true;
//
// lblAllowAutoLogin
//
this.lblAllowAutoLogin.AutoSize = true;
this.lblAllowAutoLogin.Location = new System.Drawing.Point(11, 129);
this.lblAllowAutoLogin.Name = "lblAllowAutoLogin";
this.lblAllowAutoLogin.Size = new System.Drawing.Size(106, 13);
this.lblAllowAutoLogin.TabIndex = 9;
this.lblAllowAutoLogin.Text = "Tự động đăng nhập:";
//
// chkAllowAutoLogin
//
this.chkAllowAutoLogin.AutoSize = true;
this.chkAllowAutoLogin.Location = new System.Drawing.Point(141, 128);
this.chkAllowAutoLogin.Name = "chkAllowAutoLogin";
this.chkAllowAutoLogin.Size = new System.Drawing.Size(66, 17);
this.chkAllowAutoLogin.TabIndex = 5;
this.chkAllowAutoLogin.Text = "Sử dụng";
this.chkAllowAutoLogin.UseVisualStyleBackColor = true;
//
// statusStrip
//
this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabelSavedSettingStatus});
this.statusStrip.Location = new System.Drawing.Point(0, 259);
this.statusStrip.Name = "statusStrip";
this.statusStrip.Size = new System.Drawing.Size(646, 22);
this.statusStrip.TabIndex = 18;
this.statusStrip.Text = "statusStrip";
//
// toolStripStatusLabelSavedSettingStatus
//
this.toolStripStatusLabelSavedSettingStatus.Name = "toolStripStatusLabelSavedSettingStatus";
this.toolStripStatusLabelSavedSettingStatus.Size = new System.Drawing.Size(110, 17);
this.toolStripStatusLabelSavedSettingStatus.Text = "Cấu hình ứng dụng";
//
// lblAllowAutoRun
//
this.lblAllowAutoRun.AutoSize = true;
this.lblAllowAutoRun.Location = new System.Drawing.Point(11, 161);
this.lblAllowAutoRun.Name = "lblAllowAutoRun";
this.lblAllowAutoRun.Size = new System.Drawing.Size(122, 13);
this.lblAllowAutoRun.TabIndex = 9;
this.lblAllowAutoRun.Text = "Tự khởi động ứng dụng:";
//
// chkAllowAutoRunAtStartUp
//
this.chkAllowAutoRunAtStartUp.AutoSize = true;
this.chkAllowAutoRunAtStartUp.Location = new System.Drawing.Point(141, 160);
this.chkAllowAutoRunAtStartUp.Name = "chkAllowAutoRunAtStartUp";
this.chkAllowAutoRunAtStartUp.Size = new System.Drawing.Size(66, 17);
this.chkAllowAutoRunAtStartUp.TabIndex = 5;
this.chkAllowAutoRunAtStartUp.Text = "Sử dụng";
this.chkAllowAutoRunAtStartUp.UseVisualStyleBackColor = true;
//
// ConfigurationForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(646, 281);
this.Controls.Add(this.statusStrip);
this.Controls.Add(this.lblDoorDeviceControlAccessIPStatus);
this.Controls.Add(this.btnCheckDoorDeviceControlAccessIP);
this.Controls.Add(this.btnClose);
this.Controls.Add(this.btnSaveSettings);
this.Controls.Add(this.chkAllowAutoRunAtStartUp);
this.Controls.Add(this.chkAllowAutoLogin);
this.Controls.Add(this.chkAllowUsePrinter);
this.Controls.Add(this.chkAllowChangeROIRect);
this.Controls.Add(this.lblAllowAutoRun);
this.Controls.Add(this.chkAllowAutoDoor2);
this.Controls.Add(this.lblAllowAutoLogin);
this.Controls.Add(this.chkAllowAutoDoor1);
this.Controls.Add(this.lblAllowUsePrinter);
this.Controls.Add(this.lblAllowChangeROIRect);
this.Controls.Add(this.lblAllowAutoOpenDoorIn);
this.Controls.Add(this.txtDoorDeviceControlAccessIP);
this.Controls.Add(this.lblDoorDeviceControlAccessIP);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.MaximumSize = new System.Drawing.Size(662, 320);
this.MinimumSize = new System.Drawing.Size(662, 320);
this.Name = "ConfigurationForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Cấu hình ứng dụng";
this.Load += new System.EventHandler(this.ConfigurationForm_Load);
this.statusStrip.ResumeLayout(false);
this.statusStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblDoorDeviceControlAccessIPStatus;
private System.Windows.Forms.Button btnCheckDoorDeviceControlAccessIP;
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.Button btnSaveSettings;
private System.Windows.Forms.CheckBox chkAllowChangeROIRect;
private System.Windows.Forms.CheckBox chkAllowAutoDoor2;
private System.Windows.Forms.CheckBox chkAllowAutoDoor1;
private System.Windows.Forms.Label lblAllowChangeROIRect;
private System.Windows.Forms.Label lblAllowAutoOpenDoorIn;
private System.Windows.Forms.TextBox txtDoorDeviceControlAccessIP;
private System.Windows.Forms.Label lblDoorDeviceControlAccessIP;
private System.Windows.Forms.Label lblAllowUsePrinter;
private System.Windows.Forms.CheckBox chkAllowUsePrinter;
private System.Windows.Forms.Label lblAllowAutoLogin;
private System.Windows.Forms.CheckBox chkAllowAutoLogin;
private System.Windows.Forms.StatusStrip statusStrip;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelSavedSettingStatus;
private System.Windows.Forms.Label lblAllowAutoRun;
private System.Windows.Forms.CheckBox chkAllowAutoRunAtStartUp;
}
}

View File

@@ -0,0 +1,108 @@
using NLog;
using System;
using System.Configuration;
using System.Windows.Forms;
namespace AIParkingApplication
{
public partial class ConfigurationForm : Form
{
private Logger appLogger;
private string doorAccessControlDeviceIP;
private bool allowAutoOpenDoor1;
private bool allowAutoOpenDoor2;
private bool allowUsePrinter;
private bool allowChangeROIRect;
private bool allowAutoLogin;
private bool allowAutoRunAtStartUp;
public ConfigurationForm(Logger appLogger)
{
InitializeComponent();
this.appLogger = appLogger;
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void btnSaveSettings_Click(object sender, EventArgs e)
{
bool isValidIPAddress = Util.IsValidIPAddress(txtDoorDeviceControlAccessIP.Text);
if (!isValidIPAddress)
{
MessageBox.Show("Nhập đúng IP thiết bị mở cửa!");
return;
}
Util.UpsertAppSettings(AppConstant.DOOR_ACCESS_DEVICE_CONTROL_IP, txtDoorDeviceControlAccessIP.Text);
Util.UpsertAppSettings(AppConstant.AUTO_OPEN_DOOR_1, chkAllowAutoDoor1.Checked.ToString().ToLower());
Util.UpsertAppSettings(AppConstant.AUTO_OPEN_DOOR_2, chkAllowAutoDoor2.Checked.ToString().ToLower());
Util.UpsertAppSettings(AppConstant.USE_PRINTER, chkAllowUsePrinter.Checked.ToString().ToLower());
Util.UpsertAppSettings(AppConstant.ALLOW_CHANGE_ROI_RECT, chkAllowChangeROIRect.Checked.ToString().ToLower());
Util.UpsertAppSettings(AppConstant.AUTO_LOGIN, chkAllowAutoLogin.Checked.ToString().ToLower());
Util.UpsertAppSettings(AppConstant.AUTO_RUN_AT_STARTUP, chkAllowAutoRunAtStartUp.Checked.ToString().ToLower());
if (chkAllowAutoRunAtStartUp.Checked)
{
Util.AddApplicationToStartup();
}
else
{
Util.RemoveApplicationFromStartup();
}
toolStripStatusLabelSavedSettingStatus.Text = $"{DateTime.Now.GetTimeFormatted()} Đã lưu cài đặt";
}
private void ConfigurationForm_Load(object sender, EventArgs e)
{
LoadConfiguration();
txtDoorDeviceControlAccessIP.Text = doorAccessControlDeviceIP;
chkAllowAutoDoor1.Checked = allowAutoOpenDoor1;
chkAllowAutoDoor2.Checked = allowAutoOpenDoor2;
chkAllowUsePrinter.Checked = allowUsePrinter;
chkAllowChangeROIRect.Checked = allowChangeROIRect;
chkAllowAutoLogin.Checked = allowAutoLogin;
chkAllowAutoRunAtStartUp.Checked = allowAutoRunAtStartUp;
}
private void LoadConfiguration()
{
doorAccessControlDeviceIP = ReadConfigurationFromAppSettings(AppConstant.DOOR_ACCESS_DEVICE_CONTROL_IP, string.Empty);
bool.TryParse(ReadConfigurationFromAppSettings(AppConstant.AUTO_OPEN_DOOR_1, "false"), out allowAutoOpenDoor1);
bool.TryParse(ReadConfigurationFromAppSettings(AppConstant.AUTO_OPEN_DOOR_2, "false"), out allowAutoOpenDoor2);
bool.TryParse(ReadConfigurationFromAppSettings(AppConstant.USE_PRINTER, "false"), out allowUsePrinter);
bool.TryParse(ReadConfigurationFromAppSettings(AppConstant.ALLOW_CHANGE_ROI_RECT, "false"), out allowChangeROIRect);
bool.TryParse(ReadConfigurationFromAppSettings(AppConstant.AUTO_LOGIN, "false"), out allowAutoLogin);
bool.TryParse(ReadConfigurationFromAppSettings(AppConstant.AUTO_RUN_AT_STARTUP, "false"), out allowAutoRunAtStartUp);
}
private string ReadConfigurationFromAppSettings(string configurationKey, string defaultValueIfReadFailed)
{
try
{
return ConfigurationManager.AppSettings[configurationKey].Trim();
}
catch (Exception ex)
{
Util.UpsertAppSettings(configurationKey, defaultValueIfReadFailed);
Console.WriteLine($"ReadDoorDeviceControlAccessConfiguration. ex: {ex.Message}");
appLogger.Log(LogLevel.Info, $"ConfigurationForm - ReadConfigurationFromAppSettings. Key: {configurationKey} - DefaultValue: {defaultValueIfReadFailed}. ex: {ex.Message}");
return defaultValueIfReadFailed;
}
}
private void btnCheckDoorDeviceControlAccessIP_Click(object sender, EventArgs e)
{
lblDoorDeviceControlAccessIPStatus.Text = string.Empty;
bool isValidIPAddress = Util.IsValidIPAddress(txtDoorDeviceControlAccessIP.Text);
if (!isValidIPAddress)
{
lblDoorDeviceControlAccessIPStatus.Text = "Không đúng định dạng IP";
}
else
{
lblDoorDeviceControlAccessIPStatus.Text = "OK";
}
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,76 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace AIParkingApplication
{
public static class ExtensitionMethods
{
public static void DisableSelected(this ToolStripMenuItem toolStripMenuItem)
{
toolStripMenuItem.Checked = true;
toolStripMenuItem.Enabled = false;
}
public static string GetTimeFormatted(this DateTime dateTime)
{
return dateTime.ToString(AppConstant.DATETIME_FORMAT);
}
public static void UpdateImage(this PictureBox pictureBox, Bitmap image)
{
if (pictureBox.IsDisposed)
{
return;
}
pictureBox.Invoke(new Action(() =>
{
pictureBox.Image?.Dispose();
pictureBox.Image = image;
}));
}
public static void UpdateLabel(this Label label, string text, Color backColor, Color foreColor)
{
if (label.IsDisposed)
{
return;
}
label.Invoke(new Action(() =>
{
label.Text = text;
label.BackColor = backColor;
label.ForeColor = foreColor;
}));
}
public static void UpdateLabel(this Label label, string text, Color backColor)
{
if (label.IsDisposed)
{
return;
}
label.Invoke(new Action(() =>
{
label.Text = text;
label.BackColor = backColor;
}));
}
public static void UpdateLabel(this Label label, string text)
{
if (label.IsDisposed)
{
return;
}
label.Invoke(new Action(() =>
{
label.Text = text;
}));
}
}
}

View File

@@ -69,6 +69,10 @@
this.pictureBoxPlateVideo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBoxPlateVideo.TabIndex = 0;
this.pictureBoxPlateVideo.TabStop = false;
this.pictureBoxPlateVideo.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBoxPlateVideo_Paint);
this.pictureBoxPlateVideo.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBoxPlateVideo_MouseDown);
this.pictureBoxPlateVideo.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBoxPlateVideo_MouseMove);
this.pictureBoxPlateVideo.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBoxPlateVideo_MouseUp);
//
// grbPlateCamera
//

View File

@@ -1,8 +1,12 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Printing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using NLog;
using OpenCvSharp;
using OpenCvSharp.Extensions;
@@ -21,6 +25,13 @@ namespace AIParkingApplication
private bool isRetryMode;
private IDoorControlAccess doorControlAccess;
private ApiController apiController;
private Logger appLogger;
private System.Drawing.Point StartPoint { get; set; }
private System.Drawing.Point CurrentCursorPosition { get; set; }
private Rectangle pictureBoxRoi;
private bool IsDrawBox { get; set; }
private Rect roiBoxRect;
public LaneIn(int doorId,
string cameraId,
@@ -29,12 +40,15 @@ namespace AIParkingApplication
IDoorControlAccess doorControlAccess,
ApiController apiController,
EngineApiController engineApiController,
Logger appLogger,
string roiConfig,
bool isSupportSquarePlate = true,
bool isSupportLongPlate = false,
bool isAutoOpenDoor = true,
bool isRetryMode = false)
{
InitializeComponent();
this.appLogger = appLogger;
DoorId = doorId;
this.cameraId = cameraId;
this.isSupportSquarePlate = isSupportSquarePlate;
@@ -46,6 +60,7 @@ namespace AIParkingApplication
this.apiController = apiController;
this.doorControlAccess = doorControlAccess;
plateProcessor = new PlateProcessor(engineApiController, this.isSupportSquarePlate, this.isSupportLongPlate);
this.pictureBoxRoi = Util.ConvertStringToRectangle(roiConfig);
}
private async void C3Device_OnNewCardReceived(int doorId, string cardNumber)
@@ -59,23 +74,27 @@ namespace AIParkingApplication
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.Info, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: THẺ KHÔNG HỢP LỆ");
return;
}
if (cardInfoResult.Direction != "in")
{
lblStatusInfo.UpdateLabel("XE ĐÃ Ở TRONG BÃI", Color.Red);
appLogger.Log(LogLevel.Info, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | lỗi: XE ĐÃ Ở TRONG BÃI");
return;
}
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);
@@ -88,6 +107,13 @@ namespace AIParkingApplication
var saveLogResult = await apiController.SaveLog(LaneDirection.In, cardInformation.CardRealID.ToString(), cameraId, result.PlateType, DateTime.Now.GetTimeFormatted(), result.PlateString, result.PlateImage, result.PlateImage, result.PlateImage, overviewVideoFrame);
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.CardType, DateTime.Now.GetTimeFormatted());
if (saveLogResult.Status)
@@ -95,11 +121,13 @@ namespace AIParkingApplication
if (isAutoOpenDoor && DoorId == doorId)
{
OpenDoor(doorId);
appLogger.Log(LogLevel.Info, $"Request thẻ cổng {doorId} vào | số thẻ : {cardNumber} | biển số: {result.PlateString} | Đã mở cửa");
}
}
else
{
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: LƯU BẢN GHI LỖI");
lblStatusInfo.UpdateLabel("LƯU BẢN GHI LỖI", Color.Red);
}
}
@@ -129,26 +157,32 @@ namespace AIParkingApplication
private async Task<FinalPlateResult> ProcessFrameImage(PlateProcessor plateProcessor, Mat frame, bool isRetryMode)
{
var starTime = DateTime.Now;
Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
roiBoxRect = Util.ConvertRectangleToRect(pictureBoxRoi, pictureBoxPlateVideo);
Mat frameRoi = frame[roiBoxRect];
try
{
Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
FinalPlateResult finalPlateResult = await plateProcessor.ProcessPlate(frame);
FinalPlateResult finalPlateResult = await plateProcessor.ProcessPlate(frameRoi);
if (isRetryMode && !plateProcessor.IsPlateStringValid(finalPlateResult.PlateString))
{
Console.WriteLine("ProcessFrameImage Retry Mode");
Thread.Sleep(1000);
overviewCamera.RequestCaptureOneFrame();
finalPlateResult = await plateProcessor.ProcessPlate(frame);
finalPlateResult = await plateProcessor.ProcessPlate(frameRoi);
Console.WriteLine("ProcessFrameImage Retry Mode");
}
appLogger.Log(LogLevel.Info, $"ProcessFrameImage: {(DateTime.Now - starTime).TotalMilliseconds} ms");
return finalPlateResult;
}
catch (Exception ex)
{
Console.WriteLine($"ProcessFrameImage\texMessage: {ex.Message}");
appLogger.Log(LogLevel.Info, $"ProcessFrameImage: ex: {ex.Message}");
return new FinalPlateResult
{
PlateImage = frame,
PlateImage = frameRoi,
PlateString = string.Empty,
PlateType = PlateType.Square
};
@@ -159,6 +193,12 @@ namespace AIParkingApplication
{
plateCamera.Stop();
overviewCamera.Stop();
pictureBoxPlateImage.UpdateImage(null);
pictureBoxPlateVideo.UpdateImage(null);
pictureBoxOverviewImage.UpdateImage(null);
pictureBoxOverviewVideo.UpdateImage(null);
}
public void Start()
@@ -208,5 +248,44 @@ namespace AIParkingApplication
overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed;
ConnectToDoorAccessControl();
}
private void pictureBoxPlateVideo_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
StartPoint = e.Location;
pictureBoxRoi = new Rectangle(StartPoint, new System.Drawing.Size(0, 0));
IsDrawBox = true;
}
}
private void pictureBoxPlateVideo_MouseMove(object sender, MouseEventArgs e)
{
if (IsDrawBox)
{
CurrentCursorPosition = e.Location;
pictureBoxRoi.Width = CurrentCursorPosition.X - StartPoint.X;
pictureBoxRoi.Height = CurrentCursorPosition.Y - StartPoint.Y;
}
Refresh();
}
private void pictureBoxPlateVideo_MouseUp(object sender, MouseEventArgs e)
{
IsDrawBox = false;
if (StartPoint.X + pictureBoxRoi.Width > pictureBoxPlateVideo.Width || StartPoint.Y + pictureBoxRoi.Height > pictureBoxPlateVideo.Height)
{
pictureBoxRoi.X = pictureBoxRoi.Y = 0;
pictureBoxRoi.Width = pictureBoxPlateVideo.Width;
pictureBoxRoi.Height = pictureBoxPlateVideo.Height;
}
apiController.SaveRoiToServer(pictureBoxRoi, cameraId);
}
private void pictureBoxPlateVideo_Paint(object sender, PaintEventArgs e)
{
Pen redPen = new Pen(Color.FromArgb(255, 255, 0, 0), 3);
e.Graphics.DrawRectangle(redPen, pictureBoxRoi);
}
}
}

View File

@@ -153,6 +153,12 @@
<metadata name="lblPlateString.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblCardTime.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblPlateString.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblStatusInfo.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View File

@@ -182,6 +182,10 @@
this.pictureBoxPlateVideo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.pictureBoxPlateVideo.TabIndex = 0;
this.pictureBoxPlateVideo.TabStop = false;
this.pictureBoxPlateVideo.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBoxPlateVideo_Paint);
this.pictureBoxPlateVideo.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBoxPlateVideo_MouseDown);
this.pictureBoxPlateVideo.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBoxPlateVideo_MouseMove);
this.pictureBoxPlateVideo.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBoxPlateVideo_MouseUp);
//
// grbPlateCamera
//

View File

@@ -1,8 +1,10 @@
using System;
using System.Configuration;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using NLog;
using OpenCvSharp;
using OpenCvSharp.Extensions;
@@ -22,6 +24,14 @@ namespace AIParkingApplication
private IDoorControlAccess doorControlAccess;
private ApiController apiController;
private Printer printer;
private Logger appLogger;
private bool isUsePrinter;
private System.Drawing.Point StartPoint { get; set; }
private System.Drawing.Point CurrentCursorPosition { get; set; }
private Rectangle pictureBoxRoi;
private bool IsDrawBox { get; set; }
private Rect roiBoxRect;
public LaneOut(int doorId,
string cameraId,
@@ -30,12 +40,15 @@ namespace AIParkingApplication
IDoorControlAccess doorControlAccess,
ApiController apiController,
EngineApiController engineApiController,
Logger appLogger,
string roiConfig,
bool isSupportSquarePlate = true,
bool isSupportLongPlate = false,
bool isAutoOpenDoor = true,
bool isRetryMode = false)
{
InitializeComponent();
this.appLogger = appLogger;
DoorId = doorId;
this.cameraId = cameraId;
this.isSupportSquarePlate = isSupportSquarePlate;
@@ -46,8 +59,10 @@ namespace AIParkingApplication
plateCamera = new Camera(plateStream);
this.apiController = apiController;
this.doorControlAccess = doorControlAccess;
printer = new Printer();
printer = new Printer(appLogger);
plateProcessor = new PlateProcessor(engineApiController, this.isSupportSquarePlate, this.isSupportLongPlate);
ReadUsePrinterConfig();
this.pictureBoxRoi = Util.ConvertStringToRectangle(roiConfig);
}
private async void C3Device_OnNewCardReceived(int doorId, string cardNumber)
@@ -62,17 +77,20 @@ namespace AIParkingApplication
if (cardInfoResult == null)
{
lblStatusInfo.UpdateLabel("KHÔNG THỂ KẾT NỐI SERVER", Color.Purple);
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} ra | 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.Info, $"Request thẻ cổng {doorId} ra | 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.Info, $"Request thẻ cổng {doorId} ra | số thẻ : {cardNumber} | lỗi: CHƯA NHẬN THẺ VÀO");
return;
}
@@ -85,6 +103,7 @@ namespace AIParkingApplication
plateCamera.RequestCaptureOneFrame();
overviewCamera.RequestCaptureOneFrame();
await Task.Delay(200);
appLogger.Log(LogLevel.Info, $"Request thẻ cổng {doorId} ra | số thẻ : {cardNumber} | Chụp ảnh camera");
var plateVideoFrame = plateCamera.CurrentFrame;
FinalPlateResult result = await ProcessFrameImage(plateProcessor, plateVideoFrame, isRetryMode);
@@ -97,6 +116,13 @@ namespace AIParkingApplication
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} ra | 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)
@@ -104,7 +130,11 @@ namespace AIParkingApplication
if (isAutoOpenDoor)
{
OpenDoor(doorId);
appLogger.Log(LogLevel.Info, $"Request thẻ cổng {doorId} ra | số thẻ : {cardNumber} | biển số: {result.PlateString} | Đã mở cửa");
}
if (isUsePrinter)
{
PrinterData printerData = new PrinterData
{
PlateString = result.PlateString,
@@ -114,9 +144,24 @@ namespace AIParkingApplication
};
printer.DoPrint(printerData);
}
}
else
{
lblStatusInfo.UpdateLabel("KHÔNG CÓ KẾT NỐI ĐẾN MÁY CHỦ", Color.Red);
appLogger.Log(LogLevel.Error, $"Request thẻ cổng {doorId} ra | 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 ReadUsePrinterConfig()
{
try
{
bool.TryParse(ConfigurationManager.AppSettings[AppConstant.USE_PRINTER], out isUsePrinter);
}
catch (Exception ex)
{
Util.UpsertAppSettings(AppConstant.USE_PRINTER, "false");
appLogger.Log(LogLevel.Error, $"Không thể đọc cấu hình: {AppConstant.USE_PRINTER}. ex: {ex.Message }");
}
}
@@ -144,17 +189,23 @@ namespace AIParkingApplication
private void OpenDoor(int doorId)
{
if (doorControlAccess.OpenDoor(doorId).HasError)
var openDoorResult = doorControlAccess.OpenDoor(doorId);
if (openDoorResult.HasError)
{
lblStatusInfo.UpdateLabel("KHÔNG THỂ MỞ CỬA", Color.Red);
appLogger.Log(LogLevel.Error, $"Không thể mở cửa {doorId}. Lỗi: {openDoorResult.Message}");
}
}
private async Task<FinalPlateResult> ProcessFrameImage(PlateProcessor plateProcessor, Mat frame, bool isRetryMode)
{
var starTime = DateTime.Now;
Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
Rect roiBoxRect = Util.ConvertRectangleToRect(pictureBoxRoi, pictureBoxPlateVideo);
Mat frameRoi = frame[roiBoxRect];
try
{
Cv2.Resize(frame, frame, new OpenCvSharp.Size(1280, 720));
FinalPlateResult finalPlateResult = await plateProcessor.ProcessPlate(frame);
if (isRetryMode && !plateProcessor.IsPlateStringValid(finalPlateResult.PlateString))
@@ -164,6 +215,7 @@ namespace AIParkingApplication
overviewCamera.RequestCaptureOneFrame();
finalPlateResult = await plateProcessor.ProcessPlate(frame);
}
appLogger.Log(LogLevel.Info, $"ProcessFrameImage: {(DateTime.Now - starTime).TotalMilliseconds} ms");
return finalPlateResult;
}
catch (Exception ex)
@@ -182,6 +234,12 @@ namespace AIParkingApplication
{
plateCamera.Stop();
overviewCamera.Stop();
pictureBoxPlateImage.UpdateImage(null);
pictureBoxPlateVideo.UpdateImage(null);
pictureBoxOverviewImage.UpdateImage(null);
pictureBoxOverviewVideo.UpdateImage(null);
}
public void Start()
@@ -268,5 +326,44 @@ namespace AIParkingApplication
overviewCamera.OnVideoFrameReceived += OverviewCameraOnVideoFrameReceived;
overviewCamera.OnOpenVideoStreamFailed += OverviewCamera_OnOpenVideoStreamFailed;
}
private void pictureBoxPlateVideo_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
StartPoint = e.Location;
pictureBoxRoi = new Rectangle(StartPoint, new System.Drawing.Size(0, 0));
IsDrawBox = true;
}
}
private void pictureBoxPlateVideo_MouseMove(object sender, MouseEventArgs e)
{
if (IsDrawBox)
{
CurrentCursorPosition = e.Location;
pictureBoxRoi.Width = CurrentCursorPosition.X - StartPoint.X;
pictureBoxRoi.Height = CurrentCursorPosition.Y - StartPoint.Y;
}
Refresh();
}
private void pictureBoxPlateVideo_MouseUp(object sender, MouseEventArgs e)
{
IsDrawBox = false;
if (StartPoint.X + pictureBoxRoi.Width > pictureBoxPlateVideo.Width || StartPoint.Y + pictureBoxRoi.Height > pictureBoxPlateVideo.Height)
{
pictureBoxRoi.X = pictureBoxRoi.Y = 0;
pictureBoxRoi.Width = pictureBoxPlateVideo.Width;
pictureBoxRoi.Height = pictureBoxPlateVideo.Height;
}
apiController.SaveRoiToServer(pictureBoxRoi, cameraId);
}
private void pictureBoxPlateVideo_Paint(object sender, PaintEventArgs e)
{
Pen redPen = new Pen(Color.FromArgb(255, 255, 0, 0), 3);
e.Graphics.DrawRectangle(redPen, pictureBoxRoi);
}
}
}

View File

@@ -126,6 +126,12 @@
<metadata name="pictureBoxPlateImageIn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="pictureBoxOverviewImageIn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="pictureBoxPlateImageIn.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="grbCardInformation.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@@ -147,6 +153,24 @@
<metadata name="lblCardNumber.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblCardType.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblCardTimeOut.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblCardTime.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblMoneyAmount.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblPlateString.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="lblCardNumber.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="pictureBoxPlateImage.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>

View File

@@ -37,8 +37,8 @@
this.txtServerAddress = new System.Windows.Forms.TextBox();
this.lblServerAddress = new System.Windows.Forms.Label();
this.btnLogin = new System.Windows.Forms.Button();
this.btnExit = new System.Windows.Forms.Button();
this.lblLoginStatus = new System.Windows.Forms.Label();
this.chkAutoLogin = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBoxImageLogo)).BeginInit();
this.SuspendLayout();
//
@@ -70,7 +70,7 @@
//
// txtPassword
//
this.txtPassword.Location = new System.Drawing.Point(294, 52);
this.txtPassword.Location = new System.Drawing.Point(294, 45);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '*';
this.txtPassword.Size = new System.Drawing.Size(227, 20);
@@ -80,7 +80,7 @@
// lblPassword
//
this.lblPassword.AutoSize = true;
this.lblPassword.Location = new System.Drawing.Point(214, 55);
this.lblPassword.Location = new System.Drawing.Point(214, 48);
this.lblPassword.Name = "lblPassword";
this.lblPassword.Size = new System.Drawing.Size(52, 13);
this.lblPassword.TabIndex = 2;
@@ -88,16 +88,16 @@
//
// txtServerAddress
//
this.txtServerAddress.Location = new System.Drawing.Point(294, 90);
this.txtServerAddress.Location = new System.Drawing.Point(294, 77);
this.txtServerAddress.Name = "txtServerAddress";
this.txtServerAddress.Size = new System.Drawing.Size(227, 20);
this.txtServerAddress.TabIndex = 1;
this.txtServerAddress.Text = "http://localhost:80/";
this.txtServerAddress.Text = "192.168.1.122:80";
//
// lblServerAddress
//
this.lblServerAddress.AutoSize = true;
this.lblServerAddress.Location = new System.Drawing.Point(214, 93);
this.lblServerAddress.Location = new System.Drawing.Point(214, 80);
this.lblServerAddress.Name = "lblServerAddress";
this.lblServerAddress.Size = new System.Drawing.Size(48, 13);
this.lblServerAddress.TabIndex = 2;
@@ -105,40 +105,44 @@
//
// btnLogin
//
this.btnLogin.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnLogin.Location = new System.Drawing.Point(294, 162);
this.btnLogin.Name = "btnLogin";
this.btnLogin.Size = new System.Drawing.Size(101, 37);
this.btnLogin.Size = new System.Drawing.Size(227, 37);
this.btnLogin.TabIndex = 3;
this.btnLogin.Text = "Đăng nhập";
this.btnLogin.UseVisualStyleBackColor = true;
this.btnLogin.Click += new System.EventHandler(this.btnLogin_Click);
//
// btnExit
//
this.btnExit.Location = new System.Drawing.Point(421, 162);
this.btnExit.Name = "btnExit";
this.btnExit.Size = new System.Drawing.Size(101, 37);
this.btnExit.TabIndex = 3;
this.btnExit.Text = "Thoát";
this.btnExit.UseVisualStyleBackColor = true;
this.btnExit.Click += new System.EventHandler(this.btnExit_Click);
//
// lblLoginStatus
//
this.lblLoginStatus.AutoSize = true;
this.lblLoginStatus.Location = new System.Drawing.Point(294, 117);
this.lblLoginStatus.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblLoginStatus.ForeColor = System.Drawing.SystemColors.ControlLight;
this.lblLoginStatus.Location = new System.Drawing.Point(291, 100);
this.lblLoginStatus.Name = "lblLoginStatus";
this.lblLoginStatus.Size = new System.Drawing.Size(66, 13);
this.lblLoginStatus.Size = new System.Drawing.Size(90, 18);
this.lblLoginStatus.TabIndex = 4;
this.lblLoginStatus.Text = "Login Status";
//
// chkAutoLogin
//
this.chkAutoLogin.AutoSize = true;
this.chkAutoLogin.Location = new System.Drawing.Point(295, 142);
this.chkAutoLogin.Name = "chkAutoLogin";
this.chkAutoLogin.Size = new System.Drawing.Size(122, 17);
this.chkAutoLogin.TabIndex = 5;
this.chkAutoLogin.Text = "Tự động đăng nhập";
this.chkAutoLogin.UseVisualStyleBackColor = true;
this.chkAutoLogin.CheckedChanged += new System.EventHandler(this.chkAutoLogin_CheckedChanged);
//
// LoginForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(534, 211);
this.Controls.Add(this.chkAutoLogin);
this.Controls.Add(this.lblLoginStatus);
this.Controls.Add(this.btnExit);
this.Controls.Add(this.btnLogin);
this.Controls.Add(this.lblServerAddress);
this.Controls.Add(this.lblPassword);
@@ -152,8 +156,9 @@
this.MaximumSize = new System.Drawing.Size(550, 250);
this.Name = "LoginForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "AIParking - Hệ thống quản lý bãi đỗ xe - Đăng nhập hệ thống";
this.Text = "AIParking - Hệ thống quản lý bãi đỗ xe - Đăng nhập";
this.TopMost = true;
this.Load += new System.EventHandler(this.LoginForm_Load);
((System.ComponentModel.ISupportInitialize)(this.pictureBoxImageLogo)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@@ -170,7 +175,7 @@
private System.Windows.Forms.TextBox txtServerAddress;
private System.Windows.Forms.Label lblServerAddress;
private System.Windows.Forms.Button btnLogin;
private System.Windows.Forms.Button btnExit;
private System.Windows.Forms.Label lblLoginStatus;
private System.Windows.Forms.CheckBox chkAutoLogin;
}
}

View File

@@ -1,4 +1,6 @@
using System;
using NLog;
using System;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
@@ -8,13 +10,19 @@ namespace AIParkingApplication
public partial class LoginForm : Form
{
private ApiController apiController;
private Logger applicationLogger;
private bool isAutoLogin;
public LoginForm()
{
InitializeComponent();
if (File.Exists(AppConstant.DEFAULT_LOGO_IMAGE))
applicationLogger = LogManager.GetLogger(AppConstant.APPLICATION_LOGGER_NAME);
applicationLogger.Log(LogLevel.Info, new string('-', 20));
isAutoLogin = false;
string defaultLogoImagePath = Application.StartupPath + AppConstant.DEFAULT_LOGO_IMAGE;
if (File.Exists(defaultLogoImagePath))
{
pictureBoxImageLogo.Image = new Bitmap(AppConstant.DEFAULT_LOGO_IMAGE);
pictureBoxImageLogo.Image = new Bitmap(defaultLogoImagePath);
}
txtUsername.Focus();
lblLoginStatus.Text = string.Empty;
@@ -23,25 +31,35 @@ namespace AIParkingApplication
private async void Login()
{
if (string.IsNullOrEmpty(txtServerAddress.Text))
btnLogin.Enabled = false;
string serverUrl = txtServerAddress.Text;
if (string.IsNullOrEmpty(serverUrl))
{
lblLoginStatus.Text = "Địa chỉ server không được để trống!";
lblLoginStatus.Text = "Địa chỉ server không được để trống! \r\n ví dụ: 192.168.1.2:80";
btnLogin.Enabled = true;
applicationLogger.Log(LogLevel.Info, "Địa chỉ server không được để trống");
return;
}
if (!Util.IsUrlValid(txtServerAddress.Text))
Util.ParseHostString(serverUrl, out string ipAddress, out int port);
if (!Util.IsValidIPAddress(ipAddress))
{
lblLoginStatus.Text = "Địa chỉ server không đúng định dạng: \r\n http://localhost:80 hoặc http://192.168.1.2:80";
lblLoginStatus.Text = "Địa chỉ server không đúng định dạng: \r\n ví dụ: 192.168.1.122:80";
btnLogin.Enabled = true;
applicationLogger.Log(LogLevel.Info, "Địa chỉ server không đúng định dạng");
return;
}
try
{
apiController = new ApiController(txtServerAddress.Text);
apiController = new ApiController(serverUrl, applicationLogger);
}
catch (Exception ex)
{
applicationLogger.Log(LogLevel.Error, $"Cấu máy chủ lỗi - Kiểm tra lại tên máy chủ, kết nối máy chủ! Không thể khởi tạo API Webserver. ex: {ex.Message}");
MessageBox.Show($"Cấu máy chủ lỗi - Kiểm tra lại tên máy chủ, kết nối máy chủ! \r\n {ex.Message}", "Lỗi khởi tạo API!", MessageBoxButtons.OK, MessageBoxIcon.Error);
btnLogin.Enabled = true;
return;
}
@@ -50,32 +68,42 @@ namespace AIParkingApplication
string password = txtPassword.Text;
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
{
lblLoginStatus.Text = "Tên tài khoản hoặc mật khẩu không được để trống!";
lblLoginStatus.Text = "Tên tài khoản hoặc mật khẩu không được để trống";
btnLogin.Enabled = true;
applicationLogger.Log(LogLevel.Info, "Tên tài khoản hoặc mật khẩu không được để trống");
return;
}
var loginResult = await apiController.Login(new LoginModel { Username = username, Password = password });
if (loginResult.Exception != null)
{
btnLogin.Enabled = true;
var execeptioMessage = loginResult.Exception.Message;
if (execeptioMessage.Contains("Error converting value"))
{
lblLoginStatus.UpdateLabel("Tên tài khoản hoặc mật khẩu không đúng!", Color.Red);
lblLoginStatus.UpdateLabel("Sai tên tài khoản hoặc mật khẩu!", Color.Red);
applicationLogger.Log(LogLevel.Info, "Sai tên tài khoản hoặc mật khẩu");
return;
}
if (execeptioMessage.Contains("An error occurred while sending the request"))
{
lblLoginStatus.UpdateLabel("Không có kết nối tới server!\r\nKiểm tra lại kết nối tới server!", Color.Red, Color.White);
applicationLogger.Log(LogLevel.Error, "Không có kết nối tới server!");
return;
}
lblLoginStatus.UpdateLabel("Không có kết nối tới server!\r\nKiểm tra lại kết nối tới server!", Color.Red, Color.White);
applicationLogger.Log(LogLevel.Error, "Không có kết nối tới server!");
}
if (loginResult.IsLoginSuccess)
{
new AIParkingApplicationForm(apiController, loginResult.LoginData).Show();
Util.UpsertAppSettings(AppConstant.DEFAULT_USERNAME, txtUsername.Text);
Util.UpsertAppSettings(AppConstant.DEFAULT_PASSWORD, txtPassword.Text);
Util.UpsertAppSettings(AppConstant.DEFAULT_WEB_SERVER, txtServerAddress.Text);
new AIParkingApplicationForm(apiController, ipAddress, loginResult.LoginData, applicationLogger).Show();
Hide();
applicationLogger.Log(LogLevel.Info, $"Đăng nhập thành công với tài khoản: {txtUsername.Text}");
}
}
@@ -84,12 +112,42 @@ namespace AIParkingApplication
Login();
}
private void btnExit_Click(object sender, EventArgs e)
private void ReadAppConfigurationFromFile()
{
if (DialogResult.OK == MessageBox.Show("AIParking - Bạn muốn thoát ứng dụng?", "Cảnh báo!", MessageBoxButtons.OKCancel, MessageBoxIcon.Question))
try
{
Application.Exit();
txtUsername.Text = ConfigurationManager.AppSettings[AppConstant.DEFAULT_USERNAME];
txtPassword.Text = ConfigurationManager.AppSettings[AppConstant.DEFAULT_PASSWORD];
txtServerAddress.Text = ConfigurationManager.AppSettings[AppConstant.DEFAULT_WEB_SERVER];
bool.TryParse(ConfigurationManager.AppSettings[AppConstant.AUTO_LOGIN], out isAutoLogin);
if (isAutoLogin)
{
chkAutoLogin.Checked = true;
Login();
}
}
catch (Exception ex)
{
txtUsername.Text = string.Empty;
txtPassword.Text = string.Empty;
Util.UpsertAppSettings(AppConstant.DEFAULT_USERNAME, string.Empty);
Util.UpsertAppSettings(AppConstant.DEFAULT_PASSWORD, string.Empty);
Util.UpsertAppSettings(AppConstant.AUTO_LOGIN, "false");
Util.UpsertAppSettings(AppConstant.DEFAULT_WEB_SERVER, "127.0.0.1:80");
chkAutoLogin.Checked = false;
Console.WriteLine($"{DateTime.Now.GetTimeFormatted()}\tReadAccessControlDeviceIPConfiguration\t{ex.Message}");
applicationLogger.Log(LogLevel.Error, $"Không thể đọc cấu hình tài khoản mặc định: {AppConstant.DEFAULT_USERNAME}, {AppConstant.DEFAULT_PASSWORD}");
}
}
private void LoginForm_Load(object sender, EventArgs e)
{
ReadAppConfigurationFromFile();
}
private void chkAutoLogin_CheckedChanged(object sender, EventArgs e)
{
Util.UpsertAppSettings(AppConstant.AUTO_LOGIN, (sender as CheckBox).Checked.ToString().ToLower());
}
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="D:\nlog-internal.log">
<variable name="logDirectory" value="${basedir}/logs"/>
<variable name="logLayout" value="${date:format=HH\:mm\:ss dd-MM-yyyy} ${uppercase:${level}} ${message} ${exception}"/>
<targets>
<target xsi:type="File" name="applicationLogger" fileName="${logDirectory}/${shortdate}_App.log"
layout="${logLayout}" maxArchiveFiles="30" encoding="Unicode" writeBom="true"/>
<target xsi:type="File" name="pingServerLoggingFile" fileName="${logDirectory}/${shortdate}_PingServer.log"
layout="${logLayout}" maxArchiveFiles="30" encoding="Unicode" writeBom="true"/>
<target xsi:type="File" name="pingDoorDeviceControlAccessLoggingFile" fileName="${logDirectory}/${shortdate}_PingDoorDeviceControlAccess.log"
layout="${logLayout}" maxArchiveFiles="30" encoding="Unicode" writeBom="true"/>
</targets>
<rules>
<logger name="ApplicationLogger" minlevel="Trace" writeTo="applicationLogger" />
<logger name="PingServerLogger" minlevel="Trace" writeTo="pingServerLoggingFile" />
<logger name="PingDoorDeviceControlAccessLogger" minlevel="Trace" writeTo="pingDoorDeviceControlAccessLoggingFile" />
</rules>
</nlog>

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
using OpenCvSharp;
using System;
using System.Linq;
using System.Windows.Forms;
namespace AIParkingApplication
{
@@ -20,7 +21,8 @@ namespace AIParkingApplication
this.maxSizePlate = maxSizePlate;
this.scaleFactor = scaleFactor;
this.minNeighbors = minNeighbors;
plateCascadeClassifier = new CascadeClassifier(this.plateType == PlateType.Square ? PlateDetectorConstant.SQUARE_PLATE_WEIGHT_FILENAME : PlateDetectorConstant.LONG_PLATE_WEIGHT_FILENAME);
string plateWeightPath = Application.StartupPath + (this.plateType == PlateType.Square ? PlateDetectorConstant.SQUARE_PLATE_WEIGHT_FILENAME : PlateDetectorConstant.LONG_PLATE_WEIGHT_FILENAME);
plateCascadeClassifier = new CascadeClassifier(plateWeightPath);
}
~PlateDetector()
@@ -87,8 +89,8 @@ namespace AIParkingApplication
public static class PlateDetectorConstant
{
public const string SQUARE_PLATE_WEIGHT_FILENAME = "plate.xml";
public const string LONG_PLATE_WEIGHT_FILENAME = "plateLong.xml";
public const string SQUARE_PLATE_WEIGHT_FILENAME = @".\plate.xml";
public const string LONG_PLATE_WEIGHT_FILENAME = @".\plateLong.xml";
public const double SCALE_FACTOR_DEFAULT_SQUARE_PLATE = 1.03;
public static int MIN_NEIGHBORS_DEFAULT_SQUARE_PLATE = 2;

View File

@@ -1,4 +1,5 @@
using Microsoft.Win32;
using NLog;
using System;
using System.IO;
using System.Windows.Forms;
@@ -7,8 +8,11 @@ namespace AIParkingApplication
{
public class Printer
{
public Printer()
private Logger appLogger;
public Printer(Logger appLogger)
{
this.appLogger = appLogger;
SetupPrinterPageSetting();
}
@@ -43,6 +47,7 @@ namespace AIParkingApplication
catch (Exception ex)
{
Console.WriteLine($"ProcessingString\texMessage:{ex.Message}");
appLogger.Log(LogLevel.Error, $"Lỗi khi In hóa đơn: {ex.Message}");
return string.Empty;
}
}

View File

@@ -4,12 +4,12 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AIParkingApplication")]
[assembly: AssemblyTitle("AIParking - Phần mềm quản lý bãi đỗ xe")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AIParkingApplication")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyCopyright("Copyright © DucDA 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@@ -36,6 +36,7 @@
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "Sidebar";
this.Size = new System.Drawing.Size(192, 692);
this.Load += new System.EventHandler(this.Sidebar_Load);
this.ResumeLayout(false);
}

View File

@@ -8,11 +8,20 @@ namespace AIParkingApplication
public partial class Sidebar : UserControl
{
private Statistic statistic;
private string logoImagePath;
private ApiController apiController;
public Sidebar(ApiController apiController, string logoImagePath = AppConstant.DEFAULT_LOGO_IMAGE)
{
InitializeComponent();
if (File.Exists(logoImagePath))
this.apiController = apiController;
this.logoImagePath = logoImagePath;
}
private void Sidebar_Load(object sender, EventArgs e)
{
string defaultLogoImagePath = Application.StartupPath + logoImagePath;
if (File.Exists(defaultLogoImagePath))
{
PictureBox pictureBoxImageLogo;
pictureBoxImageLogo = new PictureBox();

View File

@@ -11,17 +11,15 @@ namespace AIParkingApplication
{
private string webServerIP;
private string doorAccessControlDeviceIP;
private TimeSpan updateInterval;
private const string engineFilePath = @"\engine.bat";
private Thread updateInfoThread;
public StatusBar(string webServerIP, string doorAccessControlDeviceIP, TimeSpan updateInterval)
public StatusBar(string webServerIP, string doorAccessControlDeviceIP)
{
InitializeComponent();
this.webServerIP = webServerIP;
this.doorAccessControlDeviceIP = doorAccessControlDeviceIP;
this.updateInterval = updateInterval;
updateInfoThread = new Thread(new ThreadStart(UpdateStatus)) { IsBackground = true };
updateInfoThread = new Thread(UpdateStatus) { IsBackground = true };
}
private void UpdateStatus()
@@ -56,7 +54,7 @@ namespace AIParkingApplication
lblEngineStatus.UpdateLabel("ĐANG HOẠT ĐỘNG", Color.Green);
}
}
Thread.Sleep(updateInterval);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}

View File

@@ -1,10 +1,13 @@
using Newtonsoft.Json;
using Microsoft.Win32;
using Newtonsoft.Json;
using OpenCvSharp;
using System;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -52,62 +55,6 @@ namespace AIParkingApplication
return sf.GetMethod().Name;
}
public static void UpdateImage(this PictureBox pictureBox, Bitmap image)
{
if (pictureBox.IsDisposed)
{
return;
}
pictureBox.Invoke(new Action(() =>
{
pictureBox.Image?.Dispose();
pictureBox.Image = image;
}));
}
public static void UpdateLabel(this Label label, string text, Color backColor, Color foreColor)
{
if (label.IsDisposed)
{
return;
}
label.Invoke(new Action(() =>
{
label.Text = text;
label.BackColor = backColor;
label.ForeColor = foreColor;
}));
}
public static void UpdateLabel(this Label label, string text, Color backColor)
{
if (label.IsDisposed)
{
return;
}
label.Invoke(new Action(() =>
{
label.Text = text;
label.BackColor = backColor;
}));
}
public static void UpdateLabel(this Label label, string text)
{
if (label.IsDisposed)
{
return;
}
label.Invoke(new Action(() =>
{
label.Text = text;
}));
}
public static Bitmap ConvertFromBase64Image(string base64ImageString)
{
byte[] imageData = Convert.FromBase64String(base64ImageString);
@@ -118,11 +65,6 @@ namespace AIParkingApplication
}
}
public static string GetTimeFormatted(this DateTime dateTime)
{
return dateTime.ToString(AppConstant.DATETIME_FORMAT);
}
public static void ExecuteCommand(string command)
{
var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
@@ -143,12 +85,98 @@ namespace AIParkingApplication
}
}
public static bool IsUrlValid(string url)
public static bool IsValidIPAddress(string ipAddress)
{
if (string.IsNullOrEmpty(ipAddress))
{
return false;
}
bool isValidIPAddress = IPAddress.TryParse(ipAddress, out IPAddress ip);
return isValidIPAddress;
}
string pattern = @"^(http|https|ftp|)\://|[a-zA-Z0-9\-\.]+\.[a-zA-Z](:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&amp;%\$#\=~])*[^\.\,\)\(\s]$";
Regex reg = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
return reg.IsMatch(url);
public static void ParseHostString(string hostString, out string hostName, out int port)
{
if (!hostString.Contains(":"))
{
hostName = hostString;
port = 80;
return;
}
string[] hostParts = hostString.Split(':');
if (hostParts.Length != 2)
{
hostName = string.Empty;
port = 0;
return;
}
hostName = hostParts[0];
int.TryParse(hostParts[1], out port);
}
public static void UpsertAppSettings(string key, string value)
{
try
{
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var settings = configFile.AppSettings.Settings;
if (settings[key] == null)
{
settings.Add(key, value);
}
else
{
settings[key].Value = value;
}
configFile.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}
catch (ConfigurationErrorsException ex)
{
Console.WriteLine($"{DateTime.Now.GetTimeFormatted()}\tAddOrUpdateAppSettings\t{ex.Message}");
}
}
public static Rect ConvertRectangleToRect(Rectangle pictureBoxRoi, PictureBox pictureBoxPlateVideo)
{
Rect temp = new Rect
{
X = pictureBoxRoi.X * 1280 / pictureBoxPlateVideo.Width,
Y = pictureBoxRoi.Y * 720 / pictureBoxPlateVideo.Height,
Width = pictureBoxRoi.Width * 1280 / pictureBoxPlateVideo.Width,
Height = pictureBoxRoi.Height * 720 / pictureBoxPlateVideo.Height
};
return temp;
}
public static Rectangle ConvertStringToRectangle(string input)
{
var roi = JsonConvert.DeserializeObject<RoiConfig>(input);
return new Rectangle
{
X = roi.X,
Y = roi.Y,
Height = roi.Height,
Width = roi.Width
};
}
public static void AddApplicationToStartup()
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.SetValue("AIParkingApplication", "\"" + Application.ExecutablePath + "\"");
}
}
public static void RemoveApplicationFromStartup()
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true))
{
key.DeleteValue("AIParkingApplication", false);
}
}
}
@@ -180,4 +208,22 @@ namespace AIParkingApplication
public const string HTTP_POST_METHOD = "POST";
public const string HTTP_POST_CONTENTTYPE = "application/json";
}
public class RoiConfig
{
[JsonProperty("x")]
public int X { get; set; }
[JsonProperty("y")]
public int Y { get; set; }
[JsonProperty("width")]
public int Width { get; set; }
[JsonProperty("height")]
public int Height { get; set; }
[JsonProperty("camera_id")]
public string CameraID { get; set; }
}
}

View File

@@ -2,8 +2,12 @@
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
<package id="NLog" version="4.7.2" targetFramework="net461" />
<package id="NLog.Config" version="4.7.2" targetFramework="net461" />
<package id="NLog.Schema" version="4.7.2" targetFramework="net461" />
<package id="OpenCvSharp4" version="4.3.0.20200524" targetFramework="net461" />
<package id="OpenCvSharp4.runtime.win" version="4.3.0.20200524" targetFramework="net461" />
<package id="OpenCvSharp4.Windows" version="4.3.0.20200524" targetFramework="net461" />
<package id="System.Net.Http" version="4.3.4" targetFramework="net461" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.7.1" targetFramework="net461" />
</packages>

BIN
packages/NLog.4.7.2/.signature.p7s vendored Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
packages/NLog.4.7.2/lib/net35/NLog.dll vendored Normal file

Binary file not shown.

29160
packages/NLog.4.7.2/lib/net35/NLog.xml vendored Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
packages/NLog.4.7.2/lib/net45/NLog.dll vendored Normal file

Binary file not shown.

29589
packages/NLog.4.7.2/lib/net45/NLog.xml vendored Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
packages/NLog.4.7.2/lib/sl4/NLog.dll vendored Normal file

Binary file not shown.

21873
packages/NLog.4.7.2/lib/sl4/NLog.xml vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
packages/NLog.4.7.2/lib/sl5/NLog.dll vendored Normal file

Binary file not shown.

22039
packages/NLog.4.7.2/lib/sl5/NLog.xml vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
packages/NLog.4.7.2/lib/wp8/NLog.dll vendored Normal file

Binary file not shown.

21215
packages/NLog.4.7.2/lib/wp8/NLog.xml vendored Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<variable name="myvar" value="myvalue"/>
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets>
<!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
-->
<!--
Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
</targets>
<rules>
<!-- add your logging rules here -->
<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>
</nlog>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<variable name="myvar" value="myvalue"/>
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets>
<!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
-->
<!--
Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
</targets>
<rules>
<!-- add your logging rules here -->
<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>
</nlog>

View File

@@ -0,0 +1,12 @@
param($installPath, $toolsPath, $package, $project)
$configItem = $project.ProjectItems.Item("NLog.config")
# set 'Copy To Output Directory' to 'Copy if newer'
$copyToOutput = $configItem.Properties.Item("CopyToOutputDirectory")
$copyToOutput.Value = 2
# set 'Build Action' to 'Content'
$buildAction = $configItem.Properties.Item("BuildAction")
$buildAction.Value = 2

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff