Commit 2b28637c authored by 姜春辉's avatar 姜春辉

完成验证流程(缺少服务对接)

parent 44266b66
......@@ -115,6 +115,22 @@
<Link>Addons\GS.Terminal.DeviceManager\Device\GS.Terminal.DeviceManager.DeviceLocker.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Logic\GS.Terminal.VisitorSelfService.Logic\bin\Debug\GS.Terminal.Common.dll">
<Link>Addons\GS.Terminal.VisitorSelfService.Logic\GS.Terminal.Common.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Logic\GS.Terminal.VisitorSelfService.Logic\bin\Debug\SafeObjectPool.dll">
<Link>Addons\GS.Terminal.VisitorSelfService.Logic\SafeObjectPool.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Logic\GS.Terminal.VisitorSelfService.Logic\bin\Debug\SuperSocket.ClientEngine.dll">
<Link>Addons\GS.Terminal.VisitorSelfService.Logic\SuperSocket.ClientEngine.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\Logic\GS.Terminal.VisitorSelfService.Logic\bin\Debug\WebSocket4Net.dll">
<Link>Addons\GS.Terminal.VisitorSelfService.Logic\WebSocket4Net.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Addons\GS.Terminal.MainShell\Images\logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
......
......@@ -14,21 +14,7 @@
<Property Caption="服务地址" Name="ServiceUri"/>
</Declare>
<Datas>
<Data Description="下载门禁人员信息" Key="IncreasePersonFaceByTerminal" ServiceUri="/Services/PersonFace/IncreasePersonFaceByTerminal/json" />
<Data Description="确认人员信息合并完成" Key="PersonInfoMerged" ServiceUri="/Services/PersonFace/MergeData/json" />
<Data Description="获取门锁设备列表" Key="GetAccesscontrolList" ServiceUri="/Services/PersonFace/GetAccesscontrolList/json"/>
<Data Description="获取基建信息" Key="GetBuildingRoom" ServiceUri="/Services/PersonFace/GetBuildingRoom/json"/>
<Data Description="获取设备分组信息列表" Key="GetGroupInfo" ServiceUri="/Services/PersonFace/GetGroupInfo/json"/>
<Data Description="更新设备信息(状态)" Key="RefreshDevices" ServiceUri="/Services/PersonFace/RefreshDevices/json"/>
<Data Description="远程开门" Key="RemoteOpenDoor" ServiceUri="/Services/PersonFace/OpenDoor/json"/>
<Data Description="获取门锁设备列表(基本信息)" Key="GetAccesscontrolListBasicInfo" ServiceUri="/Services/PersonFace/GetAccesscontrolList/json"/>
<Data Description="获取开门记录" Key="GetOpenRecord" ServiceUri="/Services/PersonFace/GetOpenDoorRecord/json"/>
<Data Description="获取本地基本信息" Key="GetAccessControlInfo" ServiceUri="/Services/PersonFace/GetAccessControlInfo/json"/>
<Data Description="获取未授权设备列表" Key="GetNoPowerAccessControlList" ServiceUri="/Services/PersonFace/GetNoPowerAccessControlList/json"/>
<Data Description="申请权限" Key="AuthorityApplication" ServiceUri="/Services/PersonFace/AuthorityApplication/json"/>
<Data Description="我的开门记录" Key="GetAuthorityApplicationList" ServiceUri="/Services/PersonFace/GetAuthorityApplicationList/json"/>
<Data Description="获取人员特征值" Key="GetUserFaceFeature" ServiceUri="/Services/PersonFace/GetUserFaceFeature"/>
<Data Description="保存人员特征值" Key="UploadFaceFeature" ServiceUri="/Services/PersonFace/UploadFaceFeature"/>
<Data Description="获取人员有效预约单" Key="IncreasePersonFaceByTerminal" ServiceUri="/Services/PersonFace/IncreasePersonFaceByTerminal/json" />
</Datas>
</Structure>
</Structures>
......
using GalaSoft.MvvmLight.Threading;
using GS.Terminal.LogicShell.Interface;
using Newtonsoft.Json;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocket4Net;
namespace GS.Terminal.VisitorSelfService.Logic.Core
{
public class AuthenticationPageHandler : Corebase<ViewModels.Pages.AuthenticationPage.ViewModel>
/// <summary>
/// 身份认证成功后
/// </summary>
/// <param name="authenticationMode">认证方式</param>
/// <param name="data">认证成功后的数据.face: 访客证件号(string); qrcode: 二维码内容(string); idcard: 身份证信息dynamic对象.</param>
/// <returns></returns>
public delegate Task<bool> AuthenticationSuccessDelegate(ViewModels.Pages.AuthenticationPage.AuthenticationMode authenticationMode, object data);
public partial class AuthenticationPageHandler : Corebase<ViewModels.Pages.AuthenticationPage.ViewModel>
{
private string _FaceEngineId = string.Empty;
private Action<string> _AuthSuccessCallback;
private AuthenticationSuccessDelegate _AuthSuccessCallback;
private IViewModel _ExitView;
/*读取二代证任务*/
private Task _secondCardReader;
private CancellationTokenSource _CTS;
private EventWaitHandle _waiter;
/*读取二代证任务*/
private WebSocket _faceWebSocket;
private bool _faceValidating = false;
public override void Init()
{
VM.OnExitClick += VM_OnExitClick;
......@@ -24,12 +42,63 @@ namespace GS.Terminal.VisitorSelfService.Logic.Core
_FaceEngineId = ThirdAddon.FastRecognization.CreateFastFaceRecognized(null, null, null, 0.85f);
ThirdAddon.FastRecognization.Pause(_FaceEngineId);
ThirdAddon.FastRecognization.RegistFeatureExtracted(_FaceEngineId, FaceFeatureExtracted);
_secondCardReader = Task.Factory.StartNew(_SecondCardRead);
_CTS = new CancellationTokenSource();
_waiter = new EventWaitHandle(false, EventResetMode.ManualReset);
_faceWebSocket = new WebSocket("ws://192.168.1.68:5432/face/sdk2");
_faceWebSocket.Opened += _faceWebSocket_Opened;
_faceWebSocket.Closed += _faceWebSocket_Closed;
_faceWebSocket.Error += _faceWebSocket_Error;
_faceWebSocket.MessageReceived += _faceWebSocket_MessageReceived;
}
private void _faceWebSocket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
Debug.WriteLine($"{e.Message}");
if (!_faceValidating)
try
{
var result = JsonConvert.DeserializeObject<FaceValidateResult>(e.Message);
if (result?.result != null)
{
_faceValidating = true;
if (_AuthSuccessCallback != null)
{
bool execResult = _AuthSuccessCallback.Invoke(VM.AuthMode, result.result.Key).Result;
if (!execResult)
{
_faceValidating = false;
}
}
}
}
catch (Exception)
{
throw;
}
}
private void _faceWebSocket_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
}
private void _faceWebSocket_Closed(object sender, EventArgs e)
{
}
private void _faceWebSocket_Opened(object sender, EventArgs e)
{
}
private void VM_OnAuthModeChanged(ViewModels.Pages.AuthenticationPage.AuthenticationMode nowMode)
{
if (nowMode == ViewModels.Pages.AuthenticationPage.AuthenticationMode.Face)
{
_faceWebSocket.Open();
ThirdAddon.FaceRecognization.RegistOutPutMatEvent(VideoOut);
ThirdAddon.FastRecognization.Restart(_FaceEngineId);
}
......@@ -37,12 +106,23 @@ namespace GS.Terminal.VisitorSelfService.Logic.Core
{
ThirdAddon.FastRecognization.Pause(_FaceEngineId);
ThirdAddon.FaceRecognization.UnRegistOutPutMatEvent(VideoOut);
_faceWebSocket.Close();
}
if (nowMode == ViewModels.Pages.AuthenticationPage.AuthenticationMode.IdCard)
{
_waiter.Set();
}
else
{
_waiter.Reset();
}
}
private void FaceFeatureExtracted(byte[] feature, string fid)
{
if (!_faceValidating)
_faceWebSocket.Send(feature, 0, feature.Length);
}
/// <summary>
......@@ -52,7 +132,7 @@ namespace GS.Terminal.VisitorSelfService.Logic.Core
/// <param name="useFace">是否启用人脸认证</param>
/// <param name="useIdCard">是否启用二代证认证</param>
/// <param name="useQRCode">其否启用二维码认证</param>
public void BeginAuth(Action<string> successAction, IViewModel exitView = null, bool useFace = true, bool useIdCard = true, bool useQRCode = true)
public void BeginAuth(AuthenticationSuccessDelegate successAction, IViewModel exitView = null, bool useFace = true, bool useIdCard = true, bool useQRCode = true)
{
_ExitView = exitView;
VM.EnableFace = useFace;
......@@ -65,15 +145,14 @@ namespace GS.Terminal.VisitorSelfService.Logic.Core
private void VM_OnNavigateOut()
{
_AuthSuccessCallback = null;
_faceWebSocket.Close();
ThirdAddon.FastRecognization.Pause(_FaceEngineId);
ThirdAddon.FaceRecognization.UnRegistOutPutMatEvent(VideoOut);
}
private void VM_OnNavigateInto()
{
//启动摄像头
ThirdAddon.FaceRecognization.RegistOutPutMatEvent(VideoOut);
ThirdAddon.FastRecognization.Restart(_FaceEngineId);
VM.AuthMode = ViewModels.Pages.AuthenticationPage.AuthenticationMode.Face;
}
private void VideoOut(Mat mat)
......@@ -91,5 +170,50 @@ namespace GS.Terminal.VisitorSelfService.Logic.Core
else
ThirdAddon.LogicShell.ShowView(_ExitView);
}
private async void _SecondCardRead()
{
while (!_CTS.IsCancellationRequested)
{
_waiter.WaitOne();
var readResult =
ThirdAddon.DeviceManager.CallDeviceByTypeWithDynamic("Second", "true");
if (readResult != null)
{
//读二代证大概有600到700毫秒的延迟,所以回调前再次验证一下验证方式是否变更
if (VM.AuthMode == ViewModels.Pages.AuthenticationPage.AuthenticationMode.IdCard)
{
if (_AuthSuccessCallback != null)
{
bool execResult = await _AuthSuccessCallback.Invoke(VM.AuthMode, readResult);
if (execResult)
{
_waiter.Reset();
}
}
}
}
else
{
await Task.Delay(200);
}
}
Program._Context.Logger.Error("二代证读取线程退出.", null);
}
}
public class FaceValidateResult
{
public FacePersonInfo result { get; set; }
public float score { get; set; }
}
public class FacePersonInfo
{
public string Key { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Target { get; set; }
}
}
......@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ViewModels.Pages.AuthenticationPage;
namespace GS.Terminal.VisitorSelfService.Logic.Core
{
......@@ -18,16 +19,38 @@ namespace GS.Terminal.VisitorSelfService.Logic.Core
{
if (menuItem == ViewModels.Pages.MenuPage.MenuItemType.HasAppointment)
{
Handlers.GetHandler<AuthenticationPageHandler>()?.BeginAuth(v =>
{
}, useQRCode: false,
exitView: vmLocator.AppointmentDetailPage);
Handlers.GetHandler<AuthenticationPageHandler>()?.BeginAuth(AuthSuccess,
exitView: vmLocator.MenuPage);
}
else if (menuItem == ViewModels.Pages.MenuPage.MenuItemType.NoAppointment)
{
}
else
{
var result = DeviceManager.CallDeviceByTypeWithDynamic("Second");
Handlers.GetHandler<AuthenticationPageHandler>()?.BeginAuth(HistoryAuthSuccess, useQRCode: false,
exitView: vmLocator.MenuPage);
}
}
private async Task<bool> AuthSuccess(AuthenticationMode mode, object data)
{
MainShell.ShowLoading("正在查找");
await Task.Delay(2000);
MainShell.ShowPrompt($"查找完成");
MainShell.HideLoading();
//ThirdAddon.LogicShell.ShowView(vmLocator.AppointmentDetailPage);
return false;
}
private async Task<bool> HistoryAuthSuccess(AuthenticationMode mode, object data)
{
MainShell.ShowLoading("正在查找");
await Task.Delay(2000);
MainShell.ShowPrompt($"查找完成");
MainShell.HideLoading();
//ThirdAddon.LogicShell.ShowView(vmLocator.AppointmentDetailPage);
return false;
}
}
}
......@@ -46,6 +46,9 @@
<Reference Include="GalaSoft.MvvmLight.Platform, Version=5.4.1.0, Culture=neutral, PublicKeyToken=5f873c45e98af8a1, processorArchitecture=MSIL">
<HintPath>..\..\packages\MvvmLightLibs.5.4.1.1\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath>
</Reference>
<Reference Include="GS.Terminal.Common">
<HintPath>..\..\..\..\Tools\GS.Terminal.Common.dll</HintPath>
</Reference>
<Reference Include="GS.Terminal.LogicShell.Interface">
<HintPath>..\..\..\..\Addons\GS.Terminal.LogicShell\GS.Terminal.LogicShell.Interface.dll</HintPath>
</Reference>
......@@ -79,6 +82,12 @@
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="SafeObjectPool, Version=2.3.1.0, Culture=neutral, PublicKeyToken=2979badd66b9f481, processorArchitecture=MSIL">
<HintPath>..\..\packages\SafeObjectPool.2.3.1\lib\net45\SafeObjectPool.dll</HintPath>
</Reference>
<Reference Include="SuperSocket.ClientEngine, Version=0.10.0.0, Culture=neutral, PublicKeyToken=ee9af13f57f00acc, processorArchitecture=MSIL">
<HintPath>..\..\packages\SuperSocket.ClientEngine.Core.0.10.0\lib\net45\SuperSocket.ClientEngine.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
......@@ -91,14 +100,19 @@
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WebSocket4Net, Version=0.15.2.11, Culture=neutral, PublicKeyToken=eb4e154b696bf72a, processorArchitecture=MSIL">
<HintPath>..\..\packages\WebSocket4Net.0.15.2\lib\net45\WebSocket4Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Core\AuthenticationPageHandler.cs" />
<Compile Include="Core\Corebase.cs" />
<Compile Include="Core\MenuPageHandler.cs" />
<Compile Include="Handlers.cs" />
<Compile Include="LocalSetting.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Remote\WebApi.cs" />
<Compile Include="ThirdAddon\DeviceManager.cs" />
<Compile Include="ThirdAddon\FaceRecognization.cs" />
<Compile Include="ThirdAddon\FastRecognization.cs" />
......
using GS.Terminal.Common.LocalSetting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GS.Terminal.VisitorSelfService.Logic
{
public static class LocalSetting
{
static LocalSetting()
{
AppConfig = LocalSettingLoader.Load<AppConfig>(Program._Context);
ServiceList = LocalSettingLoader.Load<ServiceList>(Program._Context);
AddonDefaultConfig = LocalSettingLoader.Load<AddonDefaultConfig>(Program._Context);
}
public static AddonDefaultConfig AddonDefaultConfig { get; }
public static AppConfig AppConfig { get; }
public static ServiceList ServiceList { get; }
}
public class AddonDefaultConfig : IDictSetting
{
public float FaceMinValue { get; set; }
public int HeartPort { get; set; }
public string DictName => "defaultconfig";
}
public class AppConfig : IGlobalSetting
{
public string WebPath { get; set; }
public string ServerIP { get; set; }
public string dCode { get; set; }
}
public class ServiceList : IStructureSetting<ServiceListItem>
{
public List<ServiceListItem> Datas { get; set; } = new List<ServiceListItem>();
public string StructureName => "ServiceList";
public string GetSerivceUri(string key)
{
var find = Datas.FirstOrDefault(ss => ss.Key == key);
if (find != null)
return find.ServiceUri;
return "";
}
}
public class ServiceListItem : IStructureSettingItem
{
public string Description { get; set; }
public string Key { get; set; }
public string ServiceUri { get; set; }
}
}
......@@ -13,6 +13,7 @@ namespace GS.Terminal.VisitorSelfService.Logic
{
internal static IAddonContext _Context;
internal static Locator vmLocator;
internal static string _logicVersion = "0730";
public void Start(IAddonContext Context)
{
......
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace GS.Terminal.VisitorSelfService.Logic.Remote
{
public static class WebApi
{
private static SafeObjectPool.ObjectPool<HttpClient> _httpclientPool = null;
static WebApi()
{
_httpclientPool = new SafeObjectPool.ObjectPool<HttpClient>(10, () =>
{
var _client = new HttpClient();
_client.BaseAddress = new Uri(LocalSetting.AppConfig.WebPath);
_client.Timeout = TimeSpan.FromSeconds(30);
_client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("GS.Terminal.VisitorSelfService", Program._logicVersion));
return _client;
});
}
public static async Task<T> GetTAsync<T>(string service)
{
var _clientPoolObject = await _httpclientPool.GetAsync();
var _client = _clientPoolObject.Value;
try
{
var result = await _client.GetAsync(service);
if (result.IsSuccessStatusCode)
{
var responseBody = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseBody);
}
else
{
Program._Context.Logger.Error($"请求服务[{service}]异常,StatusCode:{result.StatusCode}", null);
}
return default(T);
}
finally
{
_httpclientPool.Return(_clientPoolObject);
}
}
public static async Task<T> PostAsync<T>(string service, object requestBody)
{
var bodyString = JsonConvert.SerializeObject(requestBody);
var content = new StringContent(bodyString);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
var _clientPoolObject = await _httpclientPool.GetAsync();
var _client = _clientPoolObject.Value;
try
{
var result = await _client.PostAsync(service, content);
if (result.IsSuccessStatusCode)
{
var responseBody = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseBody);
}
else
{
Program._Context.Logger.Error($"请求服务[{service}]异常,StatusCode:{result.StatusCode}", null);
}
return default(T);
}
finally
{
_httpclientPool.Return(_clientPoolObject);
}
}
public static T Post<T>(string service, object requestBody)
{
var bodyString = JsonConvert.SerializeObject(requestBody);
var content = new StringContent(bodyString);
var _clientPoolObject = _httpclientPool.Get();
var _client = _clientPoolObject.Value;
try
{
var result = _client.PostAsync(service, content).Result;
if (result.IsSuccessStatusCode)
{
var responseBody = result.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<T>(responseBody);
}
return default(T);
}
finally
{
_httpclientPool.Return(_clientPoolObject);
}
}
}
}
......@@ -37,6 +37,16 @@ namespace GS.Terminal.VisitorSelfService.Logic.ThirdAddon
_UIService?.ShowPrompt(msg);
}
public static void ShowLoading(string title = "请稍后...")
{
_UIService?.ShowLoading(title);
}
public static void HideLoading()
{
_UIService?.HideLoading();
}
public static string AddGarnitureControl(UserControl uc, double top, double left)
{
return _UIService.AddGarnitureControl(uc, top, left);
......
......@@ -7,4 +7,7 @@
<package id="MvvmLightLibs" version="5.4.1.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
<package id="OpenCvSharp3-AnyCPU" version="4.0.0.20181129" targetFramework="net452" />
<package id="SafeObjectPool" version="2.3.1" targetFramework="net452" />
<package id="SuperSocket.ClientEngine.Core" version="0.10.0" targetFramework="net452" />
<package id="WebSocket4Net" version="0.15.2" targetFramework="net452" />
</packages>
\ No newline at end of file
......@@ -13,7 +13,8 @@ namespace ViewModels.Pages.MenuPage
public enum MenuItemType
{
HasAppointment,
NoAppointment
NoAppointment,
History
}
public partial class ViewModel : ViewModelBase, IViewModel
{
......@@ -39,6 +40,11 @@ namespace ViewModels.Pages.MenuPage
OnMenuItemClick?.Invoke(MenuItemType.NoAppointment);
});
public RelayCommand HistoryCommand => new RelayCommand(() =>
{
OnMenuItemClick?.Invoke(MenuItemType.History);
});
public void Reset()
{
......
......@@ -34,7 +34,7 @@
<gs:ImageButtonFix Command="{Binding HasAppointmentCommand}" Width="500" Height="500" Grid.Row="1" Image="/Views;component/Resources/menu_btn_has.png"/>
<Image Grid.Row="2" Source="/Views;component/Resources/menu_or.png" Stretch="None" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<gs:ImageButtonFix Command="{Binding NoAppointmentCommand}" Width="500" Height="500" Grid.Row="3" Image="/Views;component/Resources/menu_btn_no.png"/>
<Button Style="{StaticResource MenuPage_HistoryButton}"/>
<Button Command="{Binding HistoryCommand}" Style="{StaticResource MenuPage_HistoryButton}"/>
</Grid>
</Grid>
</Page>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment