diff --git a/CPF_Cef/Common/ChunkedUpload.cs b/CPF_Cef/Common/ChunkedUpload.cs index 20d6330..d3cbd2b 100644 --- a/CPF_Cef/Common/ChunkedUpload.cs +++ b/CPF_Cef/Common/ChunkedUpload.cs @@ -547,7 +547,7 @@ namespace AksWebBrowser.Common string parameters = jo3["parameters"].ToString(); JObject jo4 = (JObject)JsonConvert.DeserializeObject(parameters); string base64 = jo4["face_data"].ToString(); - if (Parame.isTMZ) + if (Parame.isSM) { var faceA = Utils.Base64ByImages(base64); //开启人脸比对 diff --git a/CPF_Cef/Common/TcpClients.cs b/CPF_Cef/Common/TcpClients.cs index 51856fa..fe75b3f 100644 --- a/CPF_Cef/Common/TcpClients.cs +++ b/CPF_Cef/Common/TcpClients.cs @@ -95,31 +95,6 @@ namespace AksWebBrowser.Common //Console.WriteLine("接收到服务端口返回数据:{0}", message); jsonstr = message; } - else if (message.Contains("@")) - { - string[] str = message.Split('@'); - string data = MainModel.Base64str2(str[1]); - if (data == "400" || data.Contains("fali")) - { - //读取签字版主动回复数据 - string result = "{\"message\":\"fail\",\"code\":\"400\",\"status\":false,\"suffix\":\"png\",\"data\":\"" + "签字失败" + "\"}"; - string _parm = "callback('" + result + "')"; - Task.Run(async () => - { - await Parame.webBrowser.ExecuteJavaScript(_parm); - }); - } - else - { - //读取签字版主动回复数据 - string result = "{\"message\":\"success\",\"code\":\"200\",\"status\":true,\"suffix\":\"png\",\"data\":\"" + str[1] + "\"}"; - string _parm = "callback('" + result + "')"; - Task.Run(async () => - { - await Parame.webBrowser.ExecuteJavaScript(_parm); - }); - } - } else { //收到服务器心跳反馈 diff --git a/CPF_Cef/Common/WebSocketClientWithHeartbeat.cs b/CPF_Cef/Common/WebSocketClientWithHeartbeat.cs new file mode 100644 index 0000000..e2b1f59 --- /dev/null +++ b/CPF_Cef/Common/WebSocketClientWithHeartbeat.cs @@ -0,0 +1,177 @@ +using AKSWebBrowser.Commen; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AksWebBrowser.Common +{ + public class WebSocketClientWithHeartbeat + { + private readonly string _serverUri; + private readonly ClientWebSocket _webSocket = new ClientWebSocket(); + public string funName = string.Empty; + public WebSocketClientWithHeartbeat() + { + try + { + _serverUri = Parame.smWebsocket; + _webSocket.ConnectAsync(new Uri(_serverUri), CancellationToken.None); + Task.WhenAll(ReceiveMessages(), SendHeartbeats()); + } + catch (Exception ex) + { + Log.Error("连接双目webSocket" + ex.Message); + } + } + + /// + /// 接收消息 + /// + /// + private async Task ReceiveMessages() + { + while (_webSocket.State == WebSocketState.Open) + { + try + { + var buffer = new byte[1024 * 1024 * 5]; + var result = await _webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + if (result.MessageType == WebSocketMessageType.Close) + { + // 关闭处理逻辑 + await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); + } + else + { + // 处理接收到的消息逻辑 + string body = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count); + if (!string.IsNullOrEmpty(body)) + { + if (funName == "CF_StartLiveDetect") + { + JObject jo = (JObject)JsonConvert.DeserializeObject(body); + string status = string.Empty; + if (body.Contains("success")) + { + status = jo["success"].ToString(); + } + if (string.IsNullOrEmpty(status)) + { + string functionName = jo["functionName"].ToString(); + string nEventId = jo["nEventId"].ToString(); + if (functionName == "LiveDetectResult" && nEventId == "100") + { + Parame.messageData = body; + } + } + else + { + if (status != "0") + { + Parame.messageData = body; + } + } + } + else + { + Parame.messageData = body; + } + } + } + } + catch (Exception ex) + { + Log.Error("接收消息双目websockt" + ex.Message); + Parame.messageData = "400"; + } + } + } + + /// + /// 发送心跳 + /// + /// + private async Task SendHeartbeats() + { + while (_webSocket.State == WebSocketState.Open) + { + try + { + // 心跳消息逻辑 + var heartbeat = "{\"function\":\"Heartbeat\"}"; + var sendBuffer = System.Text.Encoding.UTF8.GetBytes(heartbeat); + await _webSocket.SendAsync(new ArraySegment(sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None); + await Task.Delay(TimeSpan.FromSeconds(6), CancellationToken.None); //根据需要设置心跳间隔 + } + catch (Exception ex) + { + Log.Error("心跳消息逻辑双目websockt" + ex.Message); + } + } + } + + /// + /// 推送消息到双目websockt + /// + /// + /// + public async Task Send(string message, string _funName) + { + try + { + funName = _funName; + Parame.messageData = string.Empty; + if (_webSocket.State == WebSocketState.Open) + { + // 发送消息到服务器 + var buffer = System.Text.Encoding.UTF8.GetBytes(message); + await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + int timeout = 0; + while (string.IsNullOrEmpty(Parame.messageData) && timeout < 30000) + { + timeout = timeout + 10; + Task.Delay(10).Wait(); + } + if (timeout >= 30000) + { + Parame.messageData = "500"; + } + } + else + { + Parame.messageData = "700"; + } + } + catch (Exception ex) + { + Log.Error("推送消息到双目websockt" + ex.Message); + } + return Parame.messageData; + } + + /// + /// 关闭双目websockt + /// + /// + public async Task Close() + { + try + { + if (_webSocket.State == WebSocketState.Open) + { + await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); + } + } + catch (Exception ex) + { + Log.Error("关闭双目websockt" + ex.Message); + } + } + } +} diff --git a/CPF_Cef/FrmMain.cs b/CPF_Cef/FrmMain.cs index e7ac4a1..c1250c4 100644 --- a/CPF_Cef/FrmMain.cs +++ b/CPF_Cef/FrmMain.cs @@ -18,8 +18,8 @@ namespace AKS.EnterpriseLibrary.WebBrowser { public class FrmMain : Window { - public int w = 1080; - public int h = 1920; + public int h= 1080; + public int w = 1920; protected override void InitializeComponent() { diff --git a/CPF_Cef/MainModel.cs b/CPF_Cef/MainModel.cs index f8b63b1..0353c0b 100644 --- a/CPF_Cef/MainModel.cs +++ b/CPF_Cef/MainModel.cs @@ -2,6 +2,9 @@ using AksWebBrowser.Common; using AksWebBrowser.Devices; using AKSWebBrowser.Commen; +using CPF; +using CPF.Linux; +using CPF.Windows; using Fleck; using LibVLCSharp.Shared; using Newtonsoft.Json; @@ -22,6 +25,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Web; +using static System.Net.Mime.MediaTypeNames; namespace AKS.EnterpriseLibrary.WebBrowser { @@ -57,7 +61,7 @@ namespace AKS.EnterpriseLibrary.WebBrowser if (content != "ping" && !string.IsNullOrEmpty(content)) { //检测服务是否启动 - StartShll(); + //StartShll(); //返回内容 string result = string.Empty; content = Base64str2(content); @@ -154,6 +158,10 @@ namespace AKS.EnterpriseLibrary.WebBrowser case "aks100115": result = playVideo(content); break; + //刻录文件:{ "code":"aks100116","name":"测试文件","obj":"http://127.0.0.1/test.doc","ext":"doc"}, obj:可以是url地址或者base64 + case "aks100116": + result = BurnFile(content); + break; default: result = "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"keycode\":\"" + "" + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"无效指令\"}"; break; @@ -240,6 +248,16 @@ namespace AKS.EnterpriseLibrary.WebBrowser try { + + + Task.Run(async () => + { + StartFace(IdcardStr); + }); + @event9.WaitOne(); + + + var param = content.ConvertToAnonymousType(new { code = default(string), @@ -265,7 +283,17 @@ namespace AKS.EnterpriseLibrary.WebBrowser else { result = "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"keycode\":\"" + param.code + "\",\"message\":\"seccse\",\"code\":\"200\",\"status\":true,\"data\":" + IdcardStr + "}"; + if (Parame.isSM) + { + Task.Run(async () => + { + StartFace(IdcardStr); + }); + @event9.WaitOne(); + } + return result; } + } SubmitLogs(result, "IDCardRead"); return result; @@ -640,47 +668,6 @@ namespace AKS.EnterpriseLibrary.WebBrowser } } - - /// - /// 播放视频 (已国产化) - /// - /// - /// - private static string playVideo(string content) - { - try - { - var param = content.ConvertToAnonymousType(new - { - code = default(string), - title = default(string), - url = default(string) - }); - if (!isFuncisFuncObject("playVideo")) - { - - return "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + "视频播放设备未授权使用" + "\"}"; - } - else - { - Parame.frm.Invoke(() => - { - new AksVideoPlayer(Parame.frm, param.title, param.url); - }); - string result = "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"message\":\"success\",\"code\":\"200\",\"status\":true,\"suffix\":\"jpg\",\"data\":\"" + "播放成功" + "\"}"; - SubmitLogs(result, "playVideo"); - return result; - } - } - catch (Exception ex) - { - //Log.Error("关闭签字版异常: " + ex.Message + ""); - string result = "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + ex.Message + "\"}"; - SubmitLogs(result, "playVideo"); - return result; - } - } - /// /// aks100106指纹 (已国产化,未完成测试) /// @@ -1099,6 +1086,124 @@ namespace AKS.EnterpriseLibrary.WebBrowser } } + /// + /// aks100115 播放视频 (已国产化) + /// + /// + /// + private static string playVideo(string content) + { + try + { + var param = content.ConvertToAnonymousType(new + { + code = default(string), + title = default(string), + url = default(string) + }); + if (!isFuncisFuncObject("playVideo")) + { + + return "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + "视频播放设备未授权使用" + "\"}"; + } + else + { + Parame.frm.Invoke(() => + { + new AksVideoPlayer(Parame.frm, param.title, param.url); + }); + string result = "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"message\":\"success\",\"code\":\"200\",\"status\":true,\"suffix\":\"jpg\",\"data\":\"" + "播放成功" + "\"}"; + SubmitLogs(result, "playVideo"); + return result; + } + } + catch (Exception ex) + { + //Log.Error("关闭签字版异常: " + ex.Message + ""); + string result = "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + ex.Message + "\"}"; + SubmitLogs(result, "playVideo"); + return result; + } + } + + /// + /// aks100116 刻录文件 (已国产化) + /// + /// + /// + public static string BurnFile(string content) + { + try + { + var param = content.ConvertToAnonymousType(new + { + code = default(string), + name = default(string), + obj = default(string), + ext = default(string) + }); + if (param == null) + { + return "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"keycode\":\"" + "" + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + "参数解析错误" + "\"}"; + } + if (!isFuncisFuncObject("PrintBase64")) + { + return "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"keycode\":\"" + param.code + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + "刻录机设备未授权使用" + "\"}"; + } + else + { + DateTime dateTime = DateTime.Now; + string time = DateTime.Now.ToString( + "yyyyMMddHHmmss", DateTimeFormatInfo.InvariantInfo); + string dirpath = Utils.getSystemPaht() + @"/wwwroot/tmpFile"; + if (!Directory.Exists(dirpath)) + { + Directory.CreateDirectory(dirpath); + } + var filepath = System.IO.Path.Combine(dirpath, time); + string path = dirpath + @"/" + time + "." + param.ext; + if (param.obj.Contains("http:")) + { + //url地址 + WebRequest request = WebRequest.Create(param.obj); + WebResponse response = request.GetResponse(); + using (Stream stream = response.GetResponseStream()) + { + using (FileStream fileStream = new FileStream(path, FileMode.Create)) + { + stream.CopyTo(fileStream); + } + } + response.Close(); + } + else + { + //base64文件 + byte[] bytes = Convert.FromBase64String(param.obj); + System.IO.FileStream stream = new System.IO.FileStream(path, System.IO.FileMode.CreateNew); + System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream); + writer.Write(bytes, 0, bytes.Length); + writer.Close(); + } + + //// Log.Info("根据文件base64打印: " + path + ""); + string command = $"lp -d {PrinterName} {path}"; + ShllCommad(command); + + //弹出光驱 eject /dev/cdrom + //刻录文件 wodim -v dev=/dev/cdrom blank=fast -data file1.txt file2.txt + //growisofs -Z /dev/cdrom -R -V "label" -iso-level 2 /path/to/files + //growisofs -Z /dev/cdrom -R -V "VOLUME_LABEL" -iso-level 2 /path/to/files + } + return "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"keycode\":\"" + param.code + "\",\"message\":\"seccse\",\"code\":\"200\",\"status\":true,\"data\":\"" + "刻录成功" + "\"}"; + } + catch (Exception ex) + { + //Log.Error("唤醒键盘异常: " + ex.Message + ""); + return "{\"timestamp\":\"" + Utils.GetTimestamp() + "\",\"keycode\":\"" + "" + "\",\"message\":\"Falied\",\"code\":\"400\",\"status\":false,\"data\":\"" + ex.Message + "\"}"; + } + } + /// /// 执行文件 /// @@ -1515,6 +1620,73 @@ namespace AKS.EnterpriseLibrary.WebBrowser } } + /// + /// 人证合一 + /// + private static string smresults = string.Empty; + private static AutoResetEvent @event9 = new AutoResetEvent(false); + private static async void StartFace(string IdcardStr) + { + try + { + WebSocketClientWithHeartbeat webSocket = new WebSocketClientWithHeartbeat(); + var mode = new + { + function = "CF_OpenCamera", + show = 1, + fx = 200, + fy = 450, + fw = 640, + fh = 480 + }; + //打开摄像头 + webSocket.Send(JsonConvert.SerializeObject(mode), "CF_OpenCamera"); + //开始活检 + smresults = await webSocket.Send("{\"function\":\"CF_StartLiveDetect\"}", "CF_StartLiveDetect"); + if (smresults == "500" || smresults == "400")//500:超时,400:接收数据错误 + { + //关闭摄像头 + webSocket.Send("{\"function\":\"CF_CloseCamera\"}", "CF_CloseCamera"); + //关闭连接 + webSocket.Close(); + } + else if (smresults == "700")//服务端未启动 + { + //关闭连接 + webSocket.Close(); + } + else + { + + JObject jo = (JObject)JsonConvert.DeserializeObject(smresults); + string nEventId = jo["nEventId"].ToString(); + if (nEventId == "100") + { + string faceA = Utils.Base64ByImages(IdcardStr); + string faceB = Utils.Base64ByImages(jo["ImgBase64"].ToString()); + //开始人脸比对 + + } + else + { + //活体检测失败 + smresults = "600"; + } + //停止活检 + webSocket.Send("{\"function\":\"CF_StopLiveDetect\"}", "CF_StopLiveDetect"); + //关闭摄像头 + webSocket.Send("{\"function\":\"CF_CloseCamera\"}", "CF_CloseCamera"); + //关闭连接 + webSocket.Close(); + } + @event9.Set(); + } + catch (Exception ex) + { + Log.Error("人证合一异常:" + ex.Message); + } + } + /// /// 初始文件上传 /// diff --git a/CPF_Cef/Parame.cs b/CPF_Cef/Parame.cs index ef37542..e9c4cc9 100644 --- a/CPF_Cef/Parame.cs +++ b/CPF_Cef/Parame.cs @@ -31,6 +31,7 @@ namespace AksWebBrowser public static string gpydevIndex = "0"; //签字版、指纹、身份证 public static string signUrl = "http://127.0.0.1:9399/device"; + //请求超时 public static int timeout = 3000; //票据打印机 public static string pritPj = "/dev/ttyS7"; @@ -39,9 +40,13 @@ namespace AksWebBrowser //打印名字 public static string PrinterName = "Lexmark-MS430-Series"; //是否启用双目 - public static bool isTMZ = false; + public static bool isSM = true; //是否开启高拍仪 public static bool isGPY = false; + //双目摄像头 + public static string smWebsocket = "ws://192.168.0.234:22226"; + //消息推送 + public static string messageData { get; set; } } public struct Func { diff --git a/CPF_Cef/Ramark.txt b/CPF_Cef/Ramark.txt index 89b1d7f..0f375fa 100644 --- a/CPF_Cef/Ramark.txt +++ b/CPF_Cef/Ramark.txt @@ -16,6 +16,8 @@ sudo apt-get install imagemagick sudo apt-get install libvlc-dev sudo apt-get install vlc +sudo apt-get install growisofs +sudo apt-get install wodim git clone https://github.com/caixxiong/espeak-data/ cd espeak-data/