using Fleck; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using WebSocketToolsConsole; using System.Runtime.Serialization; //using static System.Net.Mime.MediaTypeNames; using static WebSocketToolsConsole.Entity; using System.Drawing.Imaging; using System.Drawing; using Face.Web.Areas.App.Models; using System.Linq; using Newtonsoft.Json.Linq; using System.Threading.Tasks; using System.Text.RegularExpressions; using System.Buffers.Text; using Org.BouncyCastle.Bcpg; using System.Data.Entity.Core.Metadata.Edm; using System.Collections.Concurrent; using Org.BouncyCastle.Asn1.Tsp; using System.Runtime.CompilerServices; using System.Messaging; using System.Web.UI.WebControls.WebParts; using System.Net.Http; namespace TestWebSocket { public class SocketCount { public string path { get; set; } public int count { get; set; } } public partial class Program { //有几台设备连接,出错,再连接,再出错。会影响控制台逻辑处理, //经过日志分析后,确认这样的设备不再处理,放到这个表里面。 //在处理到这样的设备时,一律不做处理。 private static List NoProcessSN; //链路表和链路表表级别锁。 //表级别锁,用在两处: //1. 收到新建链路请求,将新建链路保存到链路表的时候。 //2. 收到关闭链路请求,将已建链路,不存在链路清空,可能会影响链路表。 private static Object dicSocksLock = new Object(); private static Dictionary _dicSockets; private static string SerialNo2 = ""; //每个表初始化清理的时候用表级别锁 //每个链路的ping计数时使用行锁pingCount[currentLinkKey] private static int pingLinkNum = 0; private static SocketCount[] pingCount = new SocketCount[4096]; //所有链路ping计数表。预留4096个位置,我们现在大概有690个设备。 private static Dictionary reverseDic = new Dictionary();//所有链路ping计数表的反向映射,以便快速找到对象。 private static Dictionary _dicSocketsPingLastStat; //所有链路历史状态表,用来做比较反转。 private static int pingCountLowValue = 3; //活的门槛值,30秒一次ping,两分钟内应该收到4到5次,大于等于3次就认为活。 public static System.Threading.Timer gDeviceCheckPingTimer = null; public class FactoryAndSn { public string factory; public string sn; } static void Main(string[] args) { //每次重启把所有状态设置成不在线。 //稍后的服务器会和每个活动的设备通信,获得正确的状态。 //永远不活动的不会被设置状态,就是保持不在线状态 //本地测试时需要注释这个方法 SetAllStatusToInactive(); //Thread 1 Read Command from MessageQueue which is original from web server interface. //read, sleep 1 second, then again Thread revT = new Thread(ReceiveCmdLoop); revT.Start(); //Timmer on thread pool for Web Socket server logging //Delay 5 minuutes to give enough time for the connection established and finished the 1st ping count time period. gDeviceCheckPingTimer = new System.Threading.Timer(WritePingStatusToDB, null, 5 * 60 * 1000, 4 * 30 * 1000); //Thread2 as Web Socket server Index(); //Main thread block at keyboard input while (true) { var set = Console.ReadLine(); if (set == "1") { GetUIwordSand(); Console.WriteLine("到此"); } if (set == "2") { GetUiImgdSand(); Console.WriteLine("2到此"); } } ; } public static string queueName = @".\private$\facesvrcmd"; public static MessageQueue mq = null; public static string queueName2 = @".\private$\faceServerToWeb"; public static MessageQueue mq2 = null; /// /// 从消息队列中读取命令,并执行 /// public static void ReceiveCmdLoop() { while (true) { try { //判断队列是否存在 if (MessageQueue.Exists(queueName)) { mq = new MessageQueue(queueName); } else { //创建队列 mq = MessageQueue.Create(queueName); } //给管理员队列权力 mq.SetPermissions("Administrator", MessageQueueAccessRights.FullControl); //匿名登录 mq.SetPermissions("ANONYMOUS LOGON", MessageQueueAccessRights.FullControl); mq.SetPermissions("Everyone", MessageQueueAccessRights.FullControl); while (true) { Message msgRx = mq.Receive(); msgRx.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); string strRx = msgRx.Body.ToString(); LogHelper.WriteLine("mq.Receive = " + strRx); processWebCmdOneThreadByMSMQ(strRx); Thread.Sleep(1300); //阻塞当前线程1秒,让其他线程运行 } } catch (Exception ex) { LogHelper.WriteLine("控制台程序从Web程序通过消息队列读取命令线程异常,被重新启动。异常:" + ex.Message); Thread.Sleep(5000); //阻塞当前线程5秒,再重新启动 continue; } } } /// /// 向消息队列中发送消息 /// /// 消息 /// public static string QueueSend(string sendMsg) { try { if (mq2 == null) { if (MessageQueue.Exists(queueName2)) { mq2 = new MessageQueue(queueName2); } else { mq2 = MessageQueue.Create(queueName2); } mq2.SetPermissions("Administrator", MessageQueueAccessRights.FullControl); mq2.SetPermissions("ANONYMOUS LOGON", MessageQueueAccessRights.FullControl); mq2.SetPermissions("Everyone", MessageQueueAccessRights.FullControl); } Message msgTx = new Message { Body = sendMsg, Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }) }; mq2.Send(msgTx); return "Succeed push msg to MQ !"; } catch (Exception ex) { mq2 = null; LogHelper.WriteLine("控制台程序给Web程序通过消息队列发送信息线程报错。异常:" + ex.Message); return ex.ToString(); } } /// ///接收和处理wed端发送数据的方法 /// /// wed端发送的参数字符串 public static void processWebCmdOneThreadByMSMQ(string receiveString) { string id = ""; Entity.Rootinfo Elist = JsonConvert.DeserializeObject(receiveString);//josn转换实体类 Entity.Rootinfo NoPhotoElist = JsonConvert.DeserializeObject(receiveString); //msginfo info = JsonConvert.DeserializeObject(NoPhotoElist.msgx.msg); string[] arr = NoPhotoElist.msgx.msg.Split('&'); if (arr[0] == "key=abcdef") { id = Elist.msgx.msgid; string serializerinfo = "";//对象转换josn string serializerIgnorImageForLoginfo = ""; if (Elist.msgx.cmd == "GetModelInfo") { Sendmessageinfo deviceinfo = new Sendmessageinfo(); deviceinfo.SN = Elist.msgx.sn; deviceinfo.CMD = "GetModelInfo"; deviceinfo.MsgID = Guid.NewGuid().ToString(); deviceinfo.Para.Key = "abc"; deviceinfo.Token = "Boonlive JSON command system"; deviceinfo.ProtocolVersion = "2.1"; deviceinfo.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); deviceinfo.Brand = "yh"; serializerinfo = JsonConvert.SerializeObject(deviceinfo);//对象转换josn serializerIgnorImageForLoginfo = JsonConvert.SerializeObject(deviceinfo); } else if (Elist.msgx.cmd == "SetUI") { string[] strarr = arr[1].Split('='); datainfo infos = JsonConvert.DeserializeObject(strarr[1]); var imageBj = ""; var imagelogo = ""; string str1 = ""; string str2 = ""; string str3 = ""; string str4 = ""; if (!string.IsNullOrEmpty(infos.imageBj)) { str1 = infos.imageBj.Substring(infos.imageBj.IndexOf("<"), infos.imageBj.IndexOf(">") - infos.imageBj.IndexOf("<") + 1); str3 = infos.imageBj.Substring(infos.imageBj.IndexOf("<") + 1, infos.imageBj.IndexOf(">") - 1); imageBj = Program.YHFileImage(str3); } if (!string.IsNullOrEmpty(infos.imagelogo)) { str2 = infos.imagelogo.Substring(infos.imagelogo.IndexOf("<"), infos.imagelogo.IndexOf(">") - infos.imagelogo.IndexOf("<") + 1); str4 = infos.imagelogo.Substring(infos.imagelogo.IndexOf("<") + 1, infos.imagelogo.IndexOf(">") - 1); //var imageBj = Program.YHFileImage(str3); imagelogo = Program.YHFileImage(str4); } SenbJandrnameandlogo sabaral = new SenbJandrnameandlogo(); sabaral.SN = Elist.msgx.sn; sabaral.CMD = "SetUI"; sabaral.MsgID = Guid.NewGuid().ToString(); sabaral.Token = "Boonlive JSON command system"; sabaral.ProtocolVersion = "2.1"; sabaral.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); sabaral.Brand = "yh"; sabaral.Para.Key = "abc"; sabaral.Para.Logo = imagelogo; sabaral.Para.BkgImg = imageBj; sabaral.Para.RoomNo = infos.Roomname; //下发内容 serializerinfo = JsonConvert.SerializeObject(sabaral);//对象转换josn //日志内容 serializerIgnorImageForLoginfo = JsonConvert.SerializeObject(sabaral); if (imagelogo.Length != 0) { serializerIgnorImageForLoginfo = serializerIgnorImageForLoginfo.Replace(imagelogo, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + imagelogo.Length); } if (imageBj.Length != 0) { serializerIgnorImageForLoginfo = serializerIgnorImageForLoginfo.Replace(imageBj, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + imageBj.Length); } } else if (Elist.msgx.cmd == "RestoreFactorySetting") { Sendmessageinfo deviceinfo = new Sendmessageinfo(); deviceinfo.SN = Elist.msgx.sn; deviceinfo.CMD = "RestoreFactorySetting"; deviceinfo.MsgID = Guid.NewGuid().ToString(); deviceinfo.Para.Key = "abc"; deviceinfo.Token = "Boonlive JSON command system"; deviceinfo.ProtocolVersion = "2.1"; deviceinfo.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); deviceinfo.Brand = "yh"; serializerinfo = JsonConvert.SerializeObject(deviceinfo);//对象转换josn serializerIgnorImageForLoginfo = JsonConvert.SerializeObject(deviceinfo); } else if (Elist.msgx.cmd == "UploadLogData") { SendUpData send = new SendUpData(); send.SN = Elist.msgx.sn; send.CMD = "UploadLogData"; send.MsgID = Guid.NewGuid().ToString(); send.Token = "Boonlive JSON command system"; send.ProtocolVersion = "2.1"; send.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); send.Brand = "yh"; send.Para.Key = "abc"; string[] strarr1 = arr[1].Split('='); send.Para.Host = strarr1[1]; string[] strarr2 = arr[3].Split('='); send.Para.Port = strarr2[1]; string[] strarr3 = arr[2].Split('='); send.Para.UserName = strarr3[1]; string[] strarr4 = arr[4].Split('='); send.Para.PW = strarr4[1] + "&" + arr[5]; string[] strarr5 = arr[6].Split('='); send.Para.Folder = strarr5[1]; serializerinfo = JsonConvert.SerializeObject(send);//对象转换josn serializerIgnorImageForLoginfo = JsonConvert.SerializeObject(send); } else if (Elist.msgx.cmd == "updateAPK2") { SendUpDataAPK send = new SendUpDataAPK(); send.SN = Elist.msgx.sn; send.CMD = "updateAPK2"; send.MsgID = Guid.NewGuid().ToString(); send.Token = "Boonlive JSON command system"; send.ProtocolVersion = "2.1"; send.DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); send.Brand = "yh"; send.Para.Key = "abc"; string[] strarr1 = arr[2].Split('='); send.Para.Host = strarr1[1]; string[] strarr2 = arr[4].Split('='); send.Para.Port = strarr2[1]; string[] strarr3 = arr[3].Split('='); send.Para.UserName = strarr3[1]; string[] strarr4 = arr[5].Split('='); send.Para.PW = strarr4[1] + "&" + arr[6]; ; string[] strarr5 = arr[1].Split('='); send.Para.File = strarr5[1]; serializerinfo = JsonConvert.SerializeObject(send);//对象转换josn serializerIgnorImageForLoginfo = JsonConvert.SerializeObject(send); } pmsProcess pmsinfo = new pmsProcess() { messageid = id, issuestate = 0, receive = 1, Issueface = 0, cmdType = Elist.msgx.cmd }; //BLL.pmsmemory(pms); //发送确认 //LogHelper.WriteLine("到 4"); SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, cmd = "0", msg = "已收到..." }); SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, cmd = "1", msg = "正处理..." }); //LogHelper.WriteLine("到 5"); //if (Elist.pmsid != -1) //{ // pmsLog log1 = new pmsLog() // { // app = 2, // Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), // Data = serializerIgnorImageForLoginfo, // step = 4, // message = "控制台已发送数据给人脸机," + "SN:" + Elist.msgx.sn + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), // pmsid = Elist.pmsid // }; // BLL.addPmsLog(log1); //} //LogHelper.WriteLine("到 6"); var oks = false; for (int i = 0; i < 6; i++) { //LogHelper.WriteLine("到 7发送设备前, 第" + i + "次"); var s = SendMsgToDevice(Elist.msgx.sn, serializerinfo, serializerIgnorImageForLoginfo).Result; //LogHelper.WriteLine("到 7发送设备后, 第" + i + "次"); if (s) //第1次或者第n次发送设备成功, 则break { facedevicerxtxinfo logdeviceitem = new facedevicerxtxinfo() { pmsid = Elist.pmsid, sn = Elist.msgx.sn, msgid = Elist.msgx.msgid, cmd = Elist.msgx.cmd, data = serializerIgnorImageForLoginfo, datatime = DateTime.Now, direction = "Tx", trresult = 1, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem).ExecuteCommand(); //LogHelper.WriteLine("到 8 发送设备成功后, 第" + i + "次"); SendWebDatabase(new Entity.msgx() { msgid = Elist.msgx.msgid, msg = "已成功...", cmd = "3" }); //LogHelper.WriteLine("到 9发送设备成功后, 第" + i + "次"); if (Elist.msgx.cmd == "removePerson") { BLL.getmessage(Elist.pmsid); } if (Elist.pmsid == -1)//Log information send down to device only for test { pmsLog logprevtest = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = serializerIgnorImageForLoginfo, step = 501, message = Elist.msgx.sn + "|控制台已成功发送数据到设备" + "SN:" + Elist.msgx.sn, pmsid = 0 }; BLL.addPmsLog(logprevtest); } //LogHelper.WriteLine("到 10 发送设备成功后, 第" + i + "次"); oks = true; break; } else //第1次或者第n次发送设备失败 { facedevicerxtxinfo logdeviceitem1 = new facedevicerxtxinfo { pmsid = Elist.pmsid, sn = Elist.msgx.sn, msgid = Elist.msgx.msgid, cmd = Elist.msgx.cmd, data = serializerIgnorImageForLoginfo, datatime = DateTime.Now, direction = "Tx", trresult = 0, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem1).ExecuteCommand(); //LogHelper.WriteLine("到 11 发送设备失败后, 第" + i + "次"); Elist.msgx.msg = $"SN:{Elist.msgx.sn}重发{i}次失败~"; if (Elist.pmsid != -1) { pmsLog log3 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), step = 502, message = "SN:" + Elist.msgx.sn + "重发人脸机次数" + i, pmsid = Elist.pmsid }; BLL.addPmsLog(log3); } //LogHelper.WriteLine("到 12 发送设备失败后, 第" + i + "次"); } //10s后重发 Task.Delay(10000).Wait(); } if (!oks)//发完60次依然失败 { SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, msg = "失败," + "SN:" + Elist.msgx.sn + "重发达到最大", cmd = "2" }); faceerrormsg fmsg = new faceerrormsg(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == Elist.msgx.sn); if (devinfo != null) { if (devinfo.Factory == "移海") { fmsg.brandinfo = "yh"; //fmsg.errorcode = ms.status; //fmsg.errormsg = ms.msg; fmsg.creationtime = DateTime.Now; fmsg.sn = Elist.msgx.sn; fmsg.step = 504; fmsg.pmsid = IsLikeGuidByArr(Elist.msgx.msgid) ? -1 : int.Parse(Elist.msgx.msgid); fmsg.remary = "已经超过了重发次数"; fmsg.APKVersion = devinfo.APKVersion; fmsg.hotelid = devinfo.HotelCode; fmsg.Roomid = devinfo.RoomId.ToString(); fmsg.cmd = Elist.msgx.cmd; int d = SqlSugarBase.FaceDb.Insertable(fmsg).ExecuteCommand(); } } //LogHelper.WriteLine("到 13 发送设备60次失败后"); //if (Elist.pmsid != -1) //{ // pmsLog log4 = new pmsLog() // { // app = 2, // Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), // //step = 6, // step = 7, // message = "pms数据发送人脸机失败" + "SN:" + Elist.msgx.sn + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), // pmsid = Elist.pmsid // }; // BLL.addPmsLog(log4); //} //LogHelper.WriteLine("到 14 发送设备60次失败后"); }//end of if (!ok)//发完60次依然失败 } else { if (arr.Length == 12) { string roomid = arr[10].Split('=')[1].ToString(); string isgqu = arr[11].Split('=')[1].ToString(); //Console.WriteLine(roomid); //Console.WriteLine(isgqu); #region 数据处理 if (Elist.pmsid != -1) { pmsLog log = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = receiveString, step = 505, message = "控制台已接收到数据," + "SN:" + Elist.msgx.sn + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), pmsid = Elist.pmsid }; BLL.addPmsLog(log); } //LogHelper.WriteLine("到 2"); //client.Close();//关闭连接 //判定是接口上来的数据还是Web端 if (Elist.msgx.cmd == "setPerson") { string str4 = ""; string str2 = Elist.msgx.msg.Substring(Elist.msgx.msg.IndexOf("<"), Elist.msgx.msg.IndexOf(">") - Elist.msgx.msg.IndexOf("<") + 1); int datatype = 2; //old device always use base64 of image. int pos = -1; string str3 = ""; pos = Elist.msgx.msg.IndexOf("&datatype="); if (pos >= 0) { datatype = int.Parse(Elist.msgx.msg.Substring(pos + 10, 1)); } if (datatype == 0)//dataype == 0; use base64 of 特征值 of image. { str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); str4 = ImageToBase64(str3); } else if (datatype == 1)//datatype==1, use ftp url path { str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); str4 = str3; } else //datatype == 2 ; old device or use base64 of image. { str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); str4 = ImageToBase64(str3); } Elist.msgx.msg = Elist.msgx.msg.Replace(str2, str4); NoPhotoElist.msgx.msg = NoPhotoElist.msgx.msg.Replace(str2, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + str4.Length); } else if (Elist.msgx.cmd == "setPerson)") { string truncate = Elist.msgx.cmd.Substring(Elist.msgx.cmd.IndexOf(")")); Elist.msgx.cmd = Elist.msgx.cmd.Replace(truncate, ""); string str2 = Elist.msgx.msg.Substring(Elist.msgx.msg.IndexOf("<"), Elist.msgx.msg.IndexOf(">") - Elist.msgx.msg.IndexOf("<") + 1); string str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); string str4 = getFileBase64(str3); Elist.msgx.msg = Elist.msgx.msg.Replace(str2, str4); NoPhotoElist.msgx.msg = NoPhotoElist.msgx.msg.Replace(str2, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + str4.Length); } else if (Elist.msgx.cmd == "updateMainPageBG" || Elist.msgx.cmd == "updateLogoRoomNo") { string str2 = Elist.msgx.msg.Substring(Elist.msgx.msg.IndexOf("<"), Elist.msgx.msg.IndexOf(">") - Elist.msgx.msg.IndexOf("<") + 1); string str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); var set = Program.YHFileImage(str3); //LogHelper.WriteLine("base64为:" + set); Elist.msgx.msg = Elist.msgx.msg.Replace(str2, set); NoPhotoElist.msgx.msg = NoPhotoElist.msgx.msg.Replace(str2, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + set.Length); } //LogHelper.WriteLine("到 3"); id = Elist.msgx.msgid; string serializerinfo = JsonConvert.SerializeObject(Elist.msgx);//对象转换josn string serializerIgnorImageForLoginfo = JsonConvert.SerializeObject(NoPhotoElist.msgx); pmsProcess pmsinfo = new pmsProcess() { messageid = id, issuestate = 0, receive = 1, Issueface = 0, cmdType = Elist.msgx.cmd }; //BLL.pmsmemory(pms); //发送确认 //LogHelper.WriteLine("到 4"); SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, cmd = "0", msg = "已收到..." }); SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, cmd = "1", msg = "正处理..." }); //LogHelper.WriteLine("到 5"); if (Elist.pmsid != -1) { pmsLog log1 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = serializerIgnorImageForLoginfo, step = 506, message = "控制台已发送数据给人脸机," + "SN:" + Elist.msgx.sn + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), pmsid = Elist.pmsid }; BLL.addPmsLog(log1); } //LogHelper.WriteLine("到 6"); var oks = false; for (int i = 0; i < 6; i++) { //LogHelper.WriteLine("到 7发送设备前, 第" + i + "次"); var s = SendMsgToDevice(Elist.msgx.sn, serializerinfo, serializerIgnorImageForLoginfo).Result; //LogHelper.WriteLine("到 7发送设备后, 第" + i + "次"); if (s) //第1次或者第n次发送设备成功, 则break { facedevicerxtxinfo logdeviceitem = new facedevicerxtxinfo() { pmsid = Elist.pmsid, sn = Elist.msgx.sn, msgid = Elist.msgx.msgid, cmd = Elist.msgx.cmd, data = serializerIgnorImageForLoginfo, datatime = DateTime.Now, direction = "Tx", trresult = 1, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem).ExecuteCommand(); //LogHelper.WriteLine("到 8 发送设备成功后, 第" + i + "次"); SendWebDatabase(new Entity.msgx() { msgid = Elist.msgx.msgid, msg = "已成功...", cmd = "3" }); //LogHelper.WriteLine("到 9发送设备成功后, 第" + i + "次"); if (Elist.msgx.cmd == "removePerson") { BLL.getmessage(Elist.pmsid); } if (Elist.pmsid == -1)//Log information send down to device only for test { pmsLog logprevtest = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = serializerIgnorImageForLoginfo, step = 501, message = Elist.msgx.sn + "|控制台已成功发送数据到设备" + "SN:" + Elist.msgx.sn + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), pmsid = 0 }; BLL.addPmsLog(logprevtest); } //LogHelper.WriteLine("到 10 发送设备成功后, 第" + i + "次"); oks = true; break; } else //第1次或者第n次发送设备失败 { facedevicerxtxinfo logdeviceitem1 = new facedevicerxtxinfo { pmsid = Elist.pmsid, sn = Elist.msgx.sn, msgid = Elist.msgx.msgid, cmd = Elist.msgx.cmd, data = serializerIgnorImageForLoginfo, datatime = DateTime.Now, direction = "Tx", trresult = 0, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem1).ExecuteCommand(); //LogHelper.WriteLine("到 11 发送设备失败后, 第" + i + "次"); Elist.msgx.msg = $"SN:{Elist.msgx.sn}重发{i}次失败~"; if (Elist.pmsid != -1) { pmsLog log3 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), step = 508, message = "SN:" + Elist.msgx.sn + "重发人脸机次数" + i + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), pmsid = Elist.pmsid }; BLL.addPmsLog(log3); } //LogHelper.WriteLine("到 12 发送设备失败后, 第" + i + "次"); } //2024-5-8修改成10s重发一次 //10s后重发 Task.Delay(10000).Wait(); } if (!oks)//发完60次依然失败 { SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, msg = "失败," + "SN:" + Elist.msgx.sn + "重发达到最大" + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), cmd = "2" }); //LogHelper.WriteLine("到 13 发送设备60次失败后"); if (Elist.pmsid != -1) { pmsLog log4 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), //step = 6, step = 509, message = "pms数据发送人脸机失败" + "SN:" + Elist.msgx.sn + ",房间号:" + roomid + ",是否公区:" + (int.Parse(isgqu) == 1 ? "是" : "否"), pmsid = Elist.pmsid }; BLL.addPmsLog(log4); } faceerrormsg fmsg = new faceerrormsg(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == Elist.msgx.sn); if (devinfo != null) { if (devinfo.Factory == "移海") { fmsg.brandinfo = "yh"; //fmsg.errorcode = ms.status; //fmsg.errormsg = ms.msg; fmsg.creationtime = DateTime.Now; fmsg.sn = Elist.msgx.sn; fmsg.step = 504; fmsg.pmsid = IsLikeGuidByArr(Elist.msgx.msgid) ? -1 : int.Parse(Elist.msgx.msgid); fmsg.remary = "已经超过了重发次数"; fmsg.APKVersion = devinfo.APKVersion; fmsg.hotelid = devinfo.HotelCode; fmsg.Roomid = devinfo.RoomId.ToString(); fmsg.cmd = Elist.msgx.cmd; int d = SqlSugarBase.FaceDb.Insertable(fmsg).ExecuteCommand(); } } //LogHelper.WriteLine("到 14 发送设备60次失败后"); }//end of if (!ok)//发完60次依然失败 #endregion } else { //LogHelper.WriteLine("到 1"); #region 数据处理 if (Elist.pmsid != -1) { pmsLog log = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = receiveString, step = 520, message = "控制台已接收到数据," + "SN:" + Elist.msgx.sn, pmsid = Elist.pmsid }; BLL.addPmsLog(log); } //LogHelper.WriteLine("到 2"); //client.Close();//关闭连接 //判定是接口上来的数据还是Web端 if (Elist.msgx.cmd == "setPerson") { string str4 = ""; string str2 = Elist.msgx.msg.Substring(Elist.msgx.msg.IndexOf("<"), Elist.msgx.msg.IndexOf(">") - Elist.msgx.msg.IndexOf("<") + 1); int datatype = 2; //old device always use base64 of image. int pos = -1; string str3 = ""; pos = Elist.msgx.msg.IndexOf("&datatype="); if (pos >= 0) { datatype = int.Parse(Elist.msgx.msg.Substring(pos + 10, 1)); } if (datatype == 0)//dataype == 0; use base64 of 特征值 of image. { str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); str4 = ImageToBase64(str3); } else if (datatype == 1)//datatype==1, use ftp url path { str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); str4 = str3; } else //datatype == 2 ; old device or use base64 of image. { str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); str4 = ImageToBase64(str3); } Elist.msgx.msg = Elist.msgx.msg.Replace(str2, str4); NoPhotoElist.msgx.msg = NoPhotoElist.msgx.msg.Replace(str2, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + str4.Length); } else if (Elist.msgx.cmd == "setPerson)") { string truncate = Elist.msgx.cmd.Substring(Elist.msgx.cmd.IndexOf(")")); Elist.msgx.cmd = Elist.msgx.cmd.Replace(truncate, ""); string str2 = Elist.msgx.msg.Substring(Elist.msgx.msg.IndexOf("<"), Elist.msgx.msg.IndexOf(">") - Elist.msgx.msg.IndexOf("<") + 1); string str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); string str4 = getFileBase64(str3); Elist.msgx.msg = Elist.msgx.msg.Replace(str2, str4); NoPhotoElist.msgx.msg = NoPhotoElist.msgx.msg.Replace(str2, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + str4.Length); } else if (Elist.msgx.cmd == "updateMainPageBG" || Elist.msgx.cmd == "updateLogoRoomNo") { string str2 = Elist.msgx.msg.Substring(Elist.msgx.msg.IndexOf("<"), Elist.msgx.msg.IndexOf(">") - Elist.msgx.msg.IndexOf("<") + 1); string str3 = str2.Substring(str2.IndexOf("<") + 1, str2.IndexOf(">") - 1); //Console.WriteLine(str3); var set = Program.YHFileImage(str3); //LogHelper.WriteLine("base64为:" + set); //下发内容 Elist.msgx.msg = Elist.msgx.msg.Replace(str2, set); //日志内容 NoPhotoElist.msgx.msg = NoPhotoElist.msgx.msg.Replace(str2, "PHOTO_IMAGE_AT_HERE_WITH_LENGTH_" + set.Length); } //LogHelper.WriteLine("到 3"); id = Elist.msgx.msgid; string serializer = JsonConvert.SerializeObject(Elist.msgx);//对象转换josn string serializerIgnorImageForLog = JsonConvert.SerializeObject(NoPhotoElist.msgx); pmsProcess pms = new pmsProcess() { messageid = id, issuestate = 0, receive = 1, Issueface = 0, cmdType = Elist.msgx.cmd }; //BLL.pmsmemory(pms); //发送确认 //LogHelper.WriteLine("到 4"); SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, cmd = "0", msg = "已收到..." }); SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, cmd = "1", msg = "正处理..." }); //LogHelper.WriteLine("到 5"); if (Elist.pmsid != -1) { pmsLog log1 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = serializerIgnorImageForLog, step = 521, message = "控制台已发送数据给人脸机," + "SN:" + Elist.msgx.sn, pmsid = Elist.pmsid }; BLL.addPmsLog(log1); } //LogHelper.WriteLine("到 6"); var ok = false; for (int i = 0; i < 6; i++) { //LogHelper.WriteLine("到 7发送设备前, 第" + i + "次"); var s = SendMsgToDevice(Elist.msgx.sn, serializer, serializerIgnorImageForLog).Result; //LogHelper.WriteLine("到 7发送设备后, 第" + i + "次"); if (s) //第1次或者第n次发送设备成功, 则break { facedevicerxtxinfo logdeviceitem = new facedevicerxtxinfo() { pmsid = Elist.pmsid, sn = Elist.msgx.sn, msgid = Elist.msgx.msgid, cmd = Elist.msgx.cmd, data = serializerIgnorImageForLog, datatime = DateTime.Now, direction = "Tx", trresult = 1, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem).ExecuteCommand(); //LogHelper.WriteLine("到 8 发送设备成功后, 第" + i + "次"); SendWebDatabase(new Entity.msgx() { msgid = Elist.msgx.msgid, msg = "已成功...", cmd = "3" }); //LogHelper.WriteLine("到 9发送设备成功后, 第" + i + "次"); if (Elist.msgx.cmd == "removePerson") { BLL.getmessage(Elist.pmsid); } if (Elist.pmsid == -1)//Log information send down to device only for test { pmsLog logprevtest = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Data = serializerIgnorImageForLog, step = 501, message = Elist.msgx.sn + "|控制台已成功发送数据到设备" + "SN:" + Elist.msgx.sn, pmsid = 0 }; BLL.addPmsLog(logprevtest); } //LogHelper.WriteLine("到 10 发送设备成功后, 第" + i + "次"); ok = true; break; } else //第1次或者第n次发送设备失败 { facedevicerxtxinfo logdeviceitem1 = new facedevicerxtxinfo { pmsid = Elist.pmsid, sn = Elist.msgx.sn, msgid = Elist.msgx.msgid, cmd = Elist.msgx.cmd, data = serializerIgnorImageForLog, datatime = DateTime.Now, direction = "Tx", trresult = 0, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem1).ExecuteCommand(); //LogHelper.WriteLine("到 11 发送设备失败后, 第" + i + "次"); Elist.msgx.msg = $"SN:{Elist.msgx.sn}重发{i}次失败~"; if (Elist.pmsid != -1) { pmsLog log3 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), step = 502, message = "SN:" + Elist.msgx.sn + "重发人脸机次数" + i, pmsid = Elist.pmsid }; BLL.addPmsLog(log3); } //LogHelper.WriteLine("到 12 发送设备失败后, 第" + i + "次"); } //2024-5-8修改成10s重发一次 //10s后重发 Task.Delay(10000).Wait(); } if (!ok)//发完60次依然失败 { SendWebDatabase(new Entity.msgx { msgid = Elist.msgx.msgid, msg = "失败," + "SN:" + Elist.msgx.sn + "重发达到最大", cmd = "2" }); //LogHelper.WriteLine("到 13 发送设备60次失败后"); if (Elist.pmsid != -1) { pmsLog log4 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), //step = 6, step = 509, message = "pms数据发送人脸机失败" + "SN:" + Elist.msgx.sn, pmsid = Elist.pmsid }; BLL.addPmsLog(log4); } faceerrormsg fmsg = new faceerrormsg(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == Elist.msgx.sn); if (devinfo != null) { if (devinfo.Factory == "移海") { fmsg.brandinfo = "yh"; //fmsg.errorcode = ms.status; //fmsg.errormsg = ms.msg; fmsg.creationtime = DateTime.Now; fmsg.sn = Elist.msgx.sn; fmsg.step = 504; fmsg.pmsid = IsLikeGuidByArr(Elist.msgx.msgid) ? -1 : int.Parse(Elist.msgx.msgid); fmsg.remary = "已经超过了重发次数"; fmsg.APKVersion = devinfo.APKVersion; fmsg.hotelid = devinfo.HotelCode; fmsg.Roomid = devinfo.RoomId.ToString(); fmsg.cmd = Elist.msgx.cmd; int d = SqlSugarBase.FaceDb.Insertable(fmsg).ExecuteCommand(); } } //LogHelper.WriteLine("到 14 发送设备60次失败后"); }//end of if (!ok)//发完60次依然失败 #endregion //LogHelper.WriteLine("到 15 全部处理完毕"); } } //LogHelper.WriteLine(receiveString); } public static void SendWebDatabase(Entity.msgx Elist) { try { using (var dr = SqlSugarBase.FaceDbClient()) { transferFace sx = dr.Queryable().First(x => x.infoid == Elist.msgid); if (sx != null) sx.faultState = int.Parse(Elist.cmd); FaceIssue issue = dr.Queryable().First(x => x.messageid == Elist.msgid); if (issue != null && Elist.cmd == "2") { issue.issuestate = 2; var assed = dr.Queryable().First(x => x.SerialNo == sx.faceSN); SqlSugarBase.FaceDb.Updateable().SetColumns(it => it.maintainStatus == 1).Where(it => it.SerialNo == sx.faceSN).ExecuteCommand(); SqlSugarBase.FaceDb.Updateable().SetColumns(it => it.issuestate == 2).Where(x => x.messageid == Elist.msgid).ExecuteCommand(); } SqlSugarBase.FaceDb.Updateable().SetColumns(it => it.faultState == int.Parse(Elist.cmd)).Where(x => x.infoid == Elist.msgid).ExecuteCommand(); } } catch (Exception ex) { LogHelper.WriteLine("函数SendWebDatabase()访问transerface,faceissue,devicemanage异常: " + ex.ToString()); } } public static void SetAllStatusToInactive() { try { string sqlBackTable = "DROP TABLE IF EXISTS devicemanage_bak; "; sqlBackTable += "CREATE TABLE devicemanage_bak SELECT * FROM devicemanage; "; SqlSugarBase.FaceDb.Ado.ExecuteCommand(sqlBackTable); SqlSugarBase.FaceDb.Updateable().SetColumns(it => it.Status == false).Where(it => 1 == 1).ExecuteCommand(); } catch (Exception ex) { LogHelper.WriteLine("函数SetAllStatusToInactive()清除所有设备的初始状态异常: " + ex.ToString()); } } /// /// 统计ping周期写入数据库 /// /// public static void WritePingStatusToDB(object objTmp) { LogHelper.Write("事件:ping周期统计。链路个数:" + pingLinkNum + "。\r\n"); int i = 0; string strPathKey = ""; int strCntVal = -1; string strTestOut = ""; for (i = 0; i < pingLinkNum; i++) { lock (pingCount[i]) { SocketCount curItem = pingCount[i]; strPathKey = curItem.path; strCntVal = curItem.count; pingCount[i].count = 0; }// end of lock (pingCount[i]) //一定会有,这两个是同时初始化的。 //if(!_dicSocketsPingLastStat.ContainsKey(strPathKey)) //{ // continue; //} strTestOut = ""; if (strCntVal >= pingCountLowValue && !_dicSocketsPingLastStat[strPathKey]) //is still active { strTestOut += "处理第" + (i + 1) + "条链路:'" + strPathKey + "'。" + "收到Ping次数:" + strCntVal + "。"; strTestOut += "触发状态反转:从死到活。"; strTestOut += "\r\n"; FactoryAndSn fands = extractSN(strPathKey); //update to history log table, update to device table InsertHistoryLog(fands.sn, fands.factory, true, "Ping周期采样状态反转触发"); _dicSocketsPingLastStat[strPathKey] = true; UpdateDeviceLivingStatus(fands.sn, true); } else if (strCntVal < pingCountLowValue && _dicSocketsPingLastStat[strPathKey])//is low active, or maybe dead. { strTestOut += "处理第" + (i + 1) + "条链路:'" + strPathKey + "'。" + "收到Ping次数:" + strCntVal + "。"; strTestOut += "触发状态反转:从活到死。"; strTestOut += "\r\n"; FactoryAndSn fands1 = extractSN(strPathKey); //update to history log table, update to device table InsertHistoryLog(fands1.sn, fands1.factory, false, "Ping周期采样状态反转触发"); _dicSocketsPingLastStat[strPathKey] = false; UpdateDeviceLivingStatus(fands1.sn, false); } }// end of for(i = 0; i < pingLinkNum; i ++) if (!String.IsNullOrEmpty(strTestOut)) LogHelper.Write(strTestOut); } //public class // GET: Default /// /// Websocket服务 /// public static void Index() { int i = 0; NoProcessSN = new List(); //1分钟1次onerror NoProcessSN.Add("717582042B8F443A"); NoProcessSN.Add("11EA322437F396B4"); //NoProcessSN.Add("E8AB3597C832F79C"); //NoProcessSN.Add("52B2A330DAD13749"); FleckLog.Level = LogLevel.Debug; // var allSockets = new List(); var server = new WebSocketServer("ws://0.0.0.0:82"); server.RestartAfterListenError = true;//出错后进行重启 _dicSockets = new Dictionary(); _dicSocketsPingLastStat = new Dictionary(); LogHelper.Write("启动 web socket服务器之前,初始化字典对象 pingCount 为 4098 个类型为SocketCount的默认值对象。\r\n"); server.Start(socket => { //这个回调函数被执行前,已经收到了客户端的Accept返回的socket,并且解析了ws协议 //这个回调函数的参数socket 是一个 WebSocketConnection 类型的实例 //内部重要属性有: /* Socket 是一个SocketWrapper类型的实例,里面有一个链路socket, 所以可以认为这个实例是一个链路的socket * ConnectionInfo */ //这个回调函数被执行后,发送握手包到客户端。 //发送握手包的stream write end成功之后,调用onOpen回调 //没有串号的设备不符合协议,不做任何记录,不做任何处理。本地测试注释掉 if (String.IsNullOrWhiteSpace(extractSN(socket.ConnectionInfo.Path).sn)) { socket.OnOpen = () => { }; socket.OnPing = bytes => { }; socket.OnMessage = message => { }; socket.OnError = exception => { }; socket.OnClose = () => { }; return; } //指定黑名单的设备,不做任何记录,不做任何处理,不做任何响应。本地测试注释掉 if (NoProcessSN.Contains(extractSN(socket.ConnectionInfo.Path).sn)) { socket.OnOpen = () => { }; socket.OnPing = bytes => { }; socket.OnMessage = message => { }; socket.OnError = exception => { }; socket.OnClose = () => { }; return; } string serialNo = "", factory = "未知厂家", ip = ""; socket.OnOpen = () => { if (!socket.IsAvailable) { return; } ip = socket.ConnectionInfo.ClientIpAddress;//获取ip地址 FactoryAndSn facandsn = extractSN(socket.ConnectionInfo.Path); factory = facandsn.factory; serialNo = facandsn.sn; try { /* * 第一次 * 四个集合建立的时候要表级别锁,因为建立的时候会移动位置,多线程抢入可能使用错误位置。 * 链路字典 * ping统计数组 * ping工具数组的反向索引字典 * 最新链路状态字典 * * * 第 n 次 * 后续更新 * 链路字典任然需要表级别锁。 * ping相关的两个集合都不需要锁,但是难以分离逻辑。使用if(!xxx)逻辑快速跳过 */ int matchedPos = -1; bool firstCreateStat = false; lock (dicSocksLock) { //1. 链路字典。 字典增加item时,内部实现也是要更新插入位置,插入对象,多线程并行执行会导致位置放错 //这里简化,第一次,第n次都锁。 _dicSockets[serialNo] = socket; //2. ping统计信息 //ping统计信息数组,第一次建立时,处理位置信息和对象时不能多线程并行执行。 //ping统计信息数组的反向索引表,第一次建立时也不能多线程并行执行。 matchedPos = -1; if (reverseDic.Count > 0 && reverseDic.ContainsKey(socket.ConnectionInfo.Path)) { matchedPos = reverseDic[socket.ConnectionInfo.Path]; } if (matchedPos < 0)//第一次连接,建立所有链路的ping统计数组,不能多线程并行执行 { pingCount[pingLinkNum] = new SocketCount { path = socket.ConnectionInfo.Path, count = 0 }; reverseDic.Add(socket.ConnectionInfo.Path, pingLinkNum); pingLinkNum++; } //3. 最近状态字典。第一次建立所有链路的最近状态集合时,也不能多线程并行执行。 //第一次时加item,并设置为true; //第n次时由ping统计计数来更新 if (!_dicSocketsPingLastStat.ContainsKey(socket.ConnectionInfo.Path)) { firstCreateStat = true; _dicSocketsPingLastStat.Add(socket.ConnectionInfo.Path, true); } //Add 和 Update都设置为true _dicSocketsPingLastStat[socket.ConnectionInfo.Path] = true; } //简化逻辑,后续重新建立链路,不再影响ping统计计数。 //所有上线事件写上线日志记录,并区分第一次建立链路,还是后续重新建立链路。 InsertHistoryLog(serialNo, factory, true, (firstCreateStat ? "链路第一次OnOpen触发" : "链路重新OnOpen触发")); //BLL.SaveDevice(serialNo, factory, ip, location); //将人脸机数据添加到数据库 //if(firstCreateStat) //{ // string location = GetBaiduIp(ip); // InsertDeviceLivingStatus(serialNo, factory, ip, location, true);//将人脸机数据添加到数据库 //} //else //{ // UpdateDeviceLivingStatus(serialNo, true); //} InsertOrUpdateDeviceLivingStatus(serialNo, factory, ip, true); } catch (Exception ex) { LogHelper.WriteLine("控制台与人脸机设备" + ip + "建立连接后,创建内部数据字典,获取连接路径(人脸机串号),将串号加入数据库时出错。 " + ex.Message); } }; socket.OnPing = bytes => { //ping因为很频繁,不try,不记文本日志,不记数据库日志。 //回复pong格式包。不过历史原因,依然保留pong字符串。 string oldPongString = "pong"; socket.SendPong(Encoding.UTF8.GetBytes(oldPongString)); int matchedPos1 = -1; if (reverseDic.Count > 0 && reverseDic.ContainsKey(socket.ConnectionInfo.Path)) { matchedPos1 = reverseDic[socket.ConnectionInfo.Path]; } if (matchedPos1 >= 0) { lock (pingCount[matchedPos1]) { pingCount[matchedPos1].count++; } } }; socket.OnMessage = message =>//接收数据 { LogHelper.Write("xxxxx" + JsonConvert.SerializeObject(message)); try { //收到消息,则pingpong计数可以加1 int matchedPos2 = -1; if (reverseDic.Count > 0 && reverseDic.ContainsKey(socket.ConnectionInfo.Path)) { matchedPos2 = reverseDic[socket.ConnectionInfo.Path]; } if (matchedPos2 >= 0) { lock (pingCount[matchedPos2]) { (pingCount[matchedPos2].count)++; } } //两种格式,注意msg里面,一种是字符串,一种是对象 //{"msgid":"5a671c4b-bf1d-4cfd-ac0b-76ade09de40a","sn":"11E8C6B16D7A0DE2","cmd":"open","msg":"{\"status\":0,\"msg\":\"成功\"}"} //{"msgid":"197529","sn":"41437ccd65dadcc1","cmd":"","msg":{"status":0,"msg":"OK"}} //LogHelper.Write("设备上报消息:" + message); //LogHelper.Write("设备上报消息:" + message + "\r\n" + "事件:收到设备端Ping事件。链路:‘" + socket.ConnectionInfo.Path + "’。Ping统计信息:" + _dicSocketsPingCount[socket.ConnectionInfo.Path]); //socket.Send("pong"); ///string oldPongString = "pong"; //socket.SendPong(Encoding.UTF8.GetBytes(oldPongString)); i++; //Entity.msgxs Elist = JsonConvert.DeserializeObject(message);//josn转换实体类 //Entity.msgx Elist = JsonConvert.DeserializeObject(message);//josn转换实体类 Entity.msgx itmsg = new Entity.msgx(); string[] sepArr = { "\"msgid\":", "\"sn\":", "\"cmd\":", "\"msg\":{", "\"msg\":\"{" }; string[] msgItemArr = message.Split(sepArr, StringSplitOptions.RemoveEmptyEntries); itmsg.msgid = msgItemArr[1].Substring(1, msgItemArr[1].Length - 3); itmsg.sn = msgItemArr[2].Substring(1, msgItemArr[2].Length - 3); itmsg.cmd = msgItemArr[3].Substring(1, msgItemArr[3].Length - 3);//"open", // 20250508修改,添加json解析 XU ToWebFaceinfo faceinfo = JsonConvert.DeserializeObject(message); try { if (itmsg.cmd == "getDeviceInfo") { cmdinfo info = JsonConvert.DeserializeObject(message); List pmsinfosd = SqlSugarBase.FaceDb.Queryable().Where(it => it.faceSn == info.sn).ToList(); for (int x = 0; x < pmsinfosd.Count(); x++) { FaceIssue sd = new FaceIssue(); sd.id = pmsinfosd[x].id; if (factory == "移海") { sd.Factory = "yh"; } else if (factory == "实义德") { sd.Factory = "devs"; } else if (factory == "深圳嘉禾兴") { sd.Factory = "szjhx"; } else { sd.Factory = " "; } int d = SqlSugarBase.FaceDb.Updateable(sd).UpdateColumns(b => new { b.Factory }).Where(b => b.id == sd.id).ExecuteCommand(); //arr.Add(sd); } if (info.msg.data.APKVersion != null) { //List pmsinfo = SqlSugarBase.FaceDb.Queryable().Where(it => it.faceSn == info.msg.data.sn).ToList(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == info.msg.data.sn); devinfo.APKVersion = info.msg.data.APKVersion; int s = SqlSugarBase.FaceDb.Updateable(devinfo).Where(x => x.SerialNo == info.msg.data.sn).ExecuteCommand(); for (int x = 0; x < pmsinfosd.Count(); x++) { FaceIssue sd = new FaceIssue(); sd.id = pmsinfosd[x].id; sd.APKVersion = info.msg.data.APKVersion; int d = SqlSugarBase.FaceDb.Updateable(sd).UpdateColumns(b => new { b.APKVersion }).Where(b => b.id == sd.id).ExecuteCommand(); } } else { //List pmsinfo = SqlSugarBase.FaceDb.Queryable().Where(it => it.faceSn == info.sn).ToList(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == info.sn); devinfo.APKVersion = " "; int s = SqlSugarBase.FaceDb.Updateable(devinfo).Where(x => x.SerialNo == info.sn).ExecuteCommand(); for (int x = 0; x < pmsinfosd.Count(); x++) { FaceIssue sd = new FaceIssue(); sd.id = pmsinfosd[x].id; sd.APKVersion = " "; int d = SqlSugarBase.FaceDb.Updateable(sd).UpdateColumns(b => new { b.APKVersion }).Where(b => b.id == sd.id).ExecuteCommand(); } } } else if (itmsg.cmd == "GetModelInfo") { Facereturuhandlingmethod(message, itmsg.msgid); } else if (itmsg.cmd == "SetUI") { //Faceinfos fs = JsonConvert.DeserializeObject>(message); } else if (itmsg.cmd == "RestoreFactorySetting") { Facereturuhandlingmethod(message, itmsg.msgid); } else if (itmsg.cmd == "UpdateApk2") { Facereturuhandlingmethod(message, itmsg.msgid); } else if (itmsg.cmd == "UploadLogData") { Facereturuhandlingmethod(message, itmsg.msgid); } else if (faceinfo.cmd == "FaceRecognized") // 2025.5.8新增 { // LogHelper.Write("FaceRecognized" + JsonConvert.SerializeObject(faceinfo)); var rt = QueueSend(message); var assck = _dicSockets[faceinfo.sn]; devicemanage sinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == faceinfo.sn); using (var client = new HttpClient()) { var parameters = new FormUrlEncodedContent(new[] { new KeyValuePair("HotelId",faceinfo.msg.Para.HotelID), new KeyValuePair("RoomId", faceinfo.msg.Para.RoomID), }); var parameterstest = new FormUrlEncodedContent(new[] { new KeyValuePair("HotelId","841"), new KeyValuePair("RoomId","38555"), }); var response = client.PostAsync("https://www.boonlive-rcu.com/api/QueryFaceInfo", parameters).Result; var typeName = response.Content.ReadAsStringAsync().Result; FaceRoomType tnv = JsonConvert.DeserializeObject(typeName); if (tnv.RoomTypeName == "餐厅" || tnv.RoomTypeName == "中餐厅" || tnv.RoomTypeName == "西餐厅" || tnv.RoomTypeName == "早餐厅") { WebToSocketErrMsg asmsg = new WebToSocketErrMsg { Token = "Boonlive JSON command system", ProtocolVersion = "2.1", MsgID = itmsg.msgid, DateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), Brand = sinfo.Factory, SN = itmsg.sn, CMD = itmsg.cmd, }; if (rt == "Succeed push msg to MQ !") { asmsg.Para = new ParaClass { ErrCode = 0, ErrMsg = "OK" }; } else { asmsg.Para = new ParaClass { ErrCode = -1, ErrMsg = rt }; } assck.Send(JsonConvert.SerializeObject(asmsg)); } } } else { #region 一次性处理完移海的所有老命令 FaceReturuinfo finfo = JsonConvert.DeserializeObject(message); faceerrormsg fmsg = new faceerrormsg(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == finfo.sn); if (devinfo != null) { if (devinfo.Factory == "移海") { //magsinfo ms = JsonConvert.DeserializeObject(finfo.msg); var dg = JsonConvert.DeserializeObject(message); if (finfo.msg.status != 0) { fmsg.brandinfo = "yh"; fmsg.errorcode = finfo.msg.status; fmsg.errormsg = finfo.msg.msg; fmsg.creationtime = DateTime.Now; fmsg.sn = finfo.sn; fmsg.step = 514; fmsg.pmsid = IsLikeGuidByArr(itmsg.msgid) ? -1 : int.Parse(itmsg.msgid); fmsg.remary = "人脸机回复失败信息"; fmsg.APKVersion = devinfo.APKVersion; fmsg.hotelid = devinfo.HotelCode; fmsg.Roomid = devinfo.RoomId.ToString(); fmsg.cmd = itmsg.cmd; int d = SqlSugarBase.FaceDb.Insertable(fmsg).ExecuteCommand(); } } } #endregion } } catch (Exception e) { LogHelper.Write("控制台收到人脸机信息,处理命令时异常: " + e.Message + " 收到设备端上报的内容:" + message); //throw; } //To ourself log database. facedevicerxtxinfo logdeviceitem2 = new facedevicerxtxinfo { pmsid = IsLikeGuidByArr(itmsg.msgid) ? -1 : int.Parse(itmsg.msgid), //guid is from test, int id from pmsid, so maybe guid should not add pms log sn = itmsg.sn, msgid = itmsg.msgid, cmd = itmsg.cmd, data = message, datatime = DateTime.Now, direction = "Rx", trresult = 0, ipaddr = "", iplocation = "" }; SqlSugarBase.FaceDb.Insertable(logdeviceitem2).ExecuteCommand(); //"{\"status\":0,\"msg\":\"成功\"}"} //{\"status\":0,\"msg\":\"成功\"}} //{\"status\":0,\"msg\":\"成功\"}} //null} Entity.Msg twoFormatJson = new Entity.Msg(); twoFormatJson.status = 0; twoFormatJson.msg = ""; string strTmp = msgItemArr[4].Replace("\\\"", "\""); //去除多余的反斜杠 strTmp = strTmp.Replace("}\"}", "}}"); //去除后面多余的双引号,前面的已经在split里面去掉了。 strTmp = "{" + strTmp.Substring(0, strTmp.Length - 1); // 大括号配对。 //LogHelper.Write("控制台收到人脸机信息,4: " + strTmp); if (!strTmp.Contains("null")) //not msg:{null} { twoFormatJson = JsonConvert.DeserializeObject(strTmp);//josn转换实体类 } //LogHelper.Write("控制台收到人脸机信息,5 "); pmsLog log = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), step = 550, Data = message, message = IsLikeGuidByArr(itmsg.msgid) ? itmsg.sn + "|人脸机" + itmsg.sn + "已回复" : "人脸机" + itmsg.sn + "已回复", pmsid = IsLikeGuidByArr(itmsg.msgid) ? -1 : int.Parse(itmsg.msgid) //guid is from test, int id from pmsid, so maybe guid should not add pms log }; BLL.addPmsLog(log); if (twoFormatJson.status == 0) { pmsLog log2 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), step = 551, message = IsLikeGuidByArr(itmsg.msgid) ? itmsg.sn + "|人脸机" + itmsg.sn + "已处理成功" : "人脸机" + itmsg.sn + "已处理成功", pmsid = IsLikeGuidByArr(itmsg.msgid) ? -1 : int.Parse(itmsg.msgid) //guid is from test, int id from pmsid, so maybe guid should not add pms log }; BLL.addPmsLog(log2); } else { pmsLog log3 = new pmsLog() { app = 2, Creationtime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), step = 540, message = IsLikeGuidByArr(itmsg.msgid) ? itmsg.sn + "|人脸机" + itmsg.sn + "处理失败" : "人脸机" + itmsg.sn + "处理失败", pmsid = IsLikeGuidByArr(itmsg.msgid) ? -1 : int.Parse(itmsg.msgid) //guid is from test, int id from pmsid, so maybe guid should not add pms log }; BLL.addPmsLog(log3); } } catch (Exception e) { LogHelper.Write("控制台收到人脸机信息,处理时异常: " + e.Message + " 收到设备端上报的内容:" + message); } }; socket.OnError = exception => { string sktInfo = ""; sktInfo += "设备端IP地址:" + socket.ConnectionInfo.ClientIpAddress; sktInfo += " 设备端端口号:" + socket.ConnectionInfo.ClientPort; sktInfo += " 设备端请求路径:" + socket.ConnectionInfo.Path; sktInfo += " 设备端请求主机:" + socket.ConnectionInfo.Host; sktInfo += " 设备端请求来源:" + socket.ConnectionInfo.Origin; sktInfo += " 使用子协议: " + socket.ConnectionInfo.SubProtocol + " 协商子协议:" + socket.ConnectionInfo.NegotiatedSubProtocol; try { //链路错误,则pingpong计数清零 int matchedPos3 = -1; if (reverseDic.Count > 0 && reverseDic.ContainsKey(socket.ConnectionInfo.Path)) { matchedPos3 = reverseDic[socket.ConnectionInfo.Path]; } if (matchedPos3 >= 0) { lock (pingCount[matchedPos3]) { pingCount[matchedPos3].count = 0; if (_dicSocketsPingLastStat.ContainsKey(socket.ConnectionInfo.Path))//可能第一次来error事件,所以字典里面可能没有创建条目。 _dicSocketsPingLastStat[socket.ConnectionInfo.Path] = false; } } //链路错误事件要更新设备最后一次状态,要更新到历史记录表。 FactoryAndSn facandsnTmp2 = extractSN(socket.ConnectionInfo.Path); InsertHistoryLog(facandsnTmp2.sn, facandsnTmp2.factory, false, "链路OnError触发"); } catch (Exception ex) { LogHelper.WriteLine("时间:" + DateTime.Now + "内容:OnError处理时异常。 链路信息:" + sktInfo + "。 异常:" + ex.ToString()); } }; socket.OnClose = () => { try { //链路关闭,则pingpong计数清零 FactoryAndSn facandsnTmp3 = extractSN(socket.ConnectionInfo.Path); int matchedPos4 = -1; if (reverseDic.Count > 0 && reverseDic.ContainsKey(socket.ConnectionInfo.Path)) { matchedPos4 = reverseDic[socket.ConnectionInfo.Path]; } if (matchedPos4 >= 0) { lock (pingCount[matchedPos4]) { pingCount[matchedPos4].count = 0; } } lock (dicSocksLock)//close 和 open 抢dictionary { if (_dicSocketsPingLastStat.ContainsKey(socket.ConnectionInfo.Path))//可能第一次来close事件,所以字典里面可能没有创建条目。 _dicSocketsPingLastStat[socket.ConnectionInfo.Path] = false; //释放链路对象 if (_dicSockets.ContainsKey(facandsnTmp3.sn))//可能第一次来close事件,所以字典里面可能没有创建条目。 _dicSockets[facandsnTmp3.sn] = null;//要释放对象,要不然就进入了死循环?结束服务? } //链路关闭事件要更新设备最后一次状态,要更新到历史记录表。 InsertHistoryLog(facandsnTmp3.sn, facandsnTmp3.factory, false, "链路OnClose触发"); //链路关闭肯定是更新状态到掉线。 //UpdateDeviceLivingStatus(facandsnTmp3.sn, false); InsertOrUpdateDeviceLivingStatus(facandsnTmp3.sn, facandsnTmp3.factory, socket.ConnectionInfo.ClientIpAddress, false); } catch (Exception ex) { LogHelper.WriteLine("时间:" + DateTime.Now + "内容:OnClose处理时异常。 链路:" + socket.ConnectionInfo.Path + "。 异常:" + ex.ToString()); } }; }); } private static FactoryAndSn extractSN(string strPath) { FactoryAndSn retObj = new FactoryAndSn(); retObj.factory = "未知厂家"; retObj.sn = ""; if (String.IsNullOrWhiteSpace(strPath)) return retObj; if (strPath.Length < 12)//串号至少16位,出现过没有串号的情况 /devs/ return retObj; if (strPath.StartsWith("/devs/"))//深圳实义德注册:/devs/514F9589072575A4 { retObj.factory = "实义德"; retObj.sn = strPath.Substring(6); } else if (strPath.StartsWith("/szjhx/"))//深圳嘉禾兴注册:/szjhx/12位mac地址 { retObj.sn = strPath.Substring(6); } else if (strPath.StartsWith("/yh/")) { retObj.factory = "移海"; retObj.sn = strPath.Substring(4); } return retObj; } /// /// 插入历史状态数据库日志 /// /// /// /// /// private static void InsertHistoryLog(string strSN, string strFactory, bool beLive, string strReason = "") { try { devicestatushistory log = new devicestatushistory { SN = strSN, Factory = strFactory, Status = beLive ? 1 : 0, CreateTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), Reason = strReason }; SqlSugarBase.FaceDb.Insertable(log).ExecuteCommand(); /*if(strReason == "Ping周期采样状态反转触发") { List selDeviceList = SqlSugarBase.FaceDb.Queryable().Where(t => t.SerialNo == strSN).ToList(); if (selDeviceList.Count > 0) { SqlSugarBase.FaceDb.Tracking(selDeviceList[0]);//创建跟踪 selDeviceList[0].Status = beLive; SqlSugarBase.FaceDb.Updateable(selDeviceList[0]).ExecuteCommand(); } }*/ } catch (Exception ex) { LogHelper.WriteLine("时间:" + DateTime.Now + "内容:插入历史状态数据库异常。数据详情:SN:" + strSN + " Status:" + beLive + " Reason:" + strReason + " 异常:" + ex.ToString()); } } /// /// 更新设备在线状态 /// /// /// private static void UpdateDeviceLivingStatus(string strSN, bool beLive) { // 只有数据库有,才更新 List selDeviceList = SqlSugarBase.FaceDb.Queryable().Where(t => t.SerialNo == strSN).ToList(); if (selDeviceList.Count > 0) { SqlSugarBase.FaceDb.Tracking(selDeviceList[0]);//创建跟踪 selDeviceList[0].Status = beLive; SqlSugarBase.FaceDb.Updateable(selDeviceList[0]).ExecuteCommand(); } } /// /// 插入或更新设备在线状态 /// /// /// /// /// private static void InsertOrUpdateDeviceLivingStatus(string strSN, string strFactory, string strIp, bool beLive) { // 只有数据库没有,才添加。 List selDeviceList = SqlSugarBase.FaceDb.Queryable().Where(t => t.SerialNo == strSN).ToList(); if (selDeviceList.Count <= 0) { var tmpObj = new devicemanage { SerialNo = strSN, CreatedDate = DateTime.Now, Factory = strFactory, Status = beLive, bindingStatus = true, faceIp = strIp, faceAddress = GetBaiduIp(strIp), maintainStatus = 0 }; SqlSugarBase.FaceDb.Insertable(tmpObj).ExecuteCommand(); } else { SqlSugarBase.FaceDb.Tracking(selDeviceList[0]);//创建跟踪 selDeviceList[0].Status = beLive; selDeviceList[0].Factory = strFactory; //移海要换请求url,数据库这里要重新填厂商名字。 SqlSugarBase.FaceDb.Updateable(selDeviceList[0]).ExecuteCommand(); } } /// /// 发信息给人脸机 /// /// /// public static async Task SendMsgToDevice(string serialNo, string sendMsg, string shortSendMsgForLog) { try { LogHelper.WriteLine("人脸机SN:" + serialNo + ",信息内容:" + shortSendMsgForLog); if (_dicSockets.ContainsKey(serialNo) && _dicSockets[serialNo] != null) { await _dicSockets[serialNo].Send(sendMsg); return true; } else { LogHelper.WriteLine("人脸机SN:" + serialNo + ",没有设备链路可用。"); return false; } } catch (Exception ex) { LogHelper.WriteLine("控制台下发信息到人脸机异常:" + ex.Message); return false; } } /// /// 图片转换base64 /// /// /// public static string getFileBase64(string fileName) { byte[] arr = FileImage(fileName); var d = string.Format("data:image/{0};base64,{1}", "jpg", Convert.ToBase64String(arr)); string str = d.Substring(d.IndexOf(",") + 1); return str; } /// /// byte转换base64 /// /// /// public static string getbyteBase64(byte[] fileName) { byte[] arr = fileName; var d = string.Format("data:image/{0};base64,{1}", "png", Convert.ToBase64String(arr)); string str = d.Substring(d.IndexOf(",") + 1); return str; } /// /// 从ftp获取图片 /// /// 路径 /// public static byte[] FileImage(string url, string ftp = "") { //Logs.WriteLog("222获取图片开始"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")); if (ftp != "") { url = "ftp://auth.blv-oa.com:50/uts_Manager/oyl_FTP/Image/" + url; } else { url = "ftp://auth.blv-oa.com:50/uts_Manager/oyl_FTP/Image/" + url; } FtpWebRequest ftpWeb; try { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); try { ftpWeb = (FtpWebRequest)FtpWebRequest.Create(url);//创建ftp连接 ftpWeb.Credentials = new NetworkCredential("uts_manager", "uts_Inhaos@all");//账号,密码 ftpWeb.KeepAlive = false; ftpWeb.EnableSsl = false; ftpWeb.Method = WebRequestMethods.Ftp.DownloadFile; ftpWeb.UseBinary = true; ftpWeb.UsePassive = true; WebResponse ftpResponse = (FtpWebResponse)ftpWeb.GetResponse(); Stream ftpStream = ftpResponse.GetResponseStream();//获取图片流 MemoryStream outstream = new MemoryStream();//转成MS流 int bufferLen = 4096;//缓冲区 byte[] buffer = new byte[bufferLen]; int count = 0; while ((count = ftpStream.Read(buffer, 0, bufferLen)) > 0) { outstream.Write(buffer, 0, count); } var img = outstream.ToArray(); ftpResponse.Close(); ftpStream.Close(); outstream.Close(); return img; } catch (Exception e) { LogHelper.WriteLine(e.Message); return null; } } catch (Exception ex) { LogHelper.WriteLine(ex.Message); return null; } } /// /// 从YH获取文件 /// /// /// public static string YHFileImage(string url) { //Logs.WriteLog("222获取图片开始"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")); url = "ftp://auth.blv-oa.com:50/uts_Manager/oyl_FTP/YH/" + url; FtpWebRequest ftpWeb; try { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); try { ftpWeb = (FtpWebRequest)FtpWebRequest.Create(url);//创建ftp连接 ftpWeb.Credentials = new NetworkCredential("uts_manager", "uts_Inhaos@all");//账号,密码 ftpWeb.KeepAlive = false; ftpWeb.EnableSsl = false; ftpWeb.Method = WebRequestMethods.Ftp.DownloadFile; ftpWeb.UseBinary = true; ftpWeb.UsePassive = true; //AUTS.Services.Manager.Logs.WriteLog("获取图片数据开始" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")); WebResponse ftpResponse = (FtpWebResponse)ftpWeb.GetResponse(); //AUTS.Services.Manager.Logs.WriteLog("获取图片数据结束" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")); Stream ftpStream = ftpResponse.GetResponseStream();//获取图片流 MemoryStream outstream = new MemoryStream();//转成MS流 int bufferLen = 4096;//缓冲区 byte[] buffer = new byte[bufferLen]; int count = 0; while ((count = ftpStream.Read(buffer, 0, bufferLen)) > 0) { outstream.Write(buffer, 0, count); } //var img = outstream.ToArray(); //Logs.WriteLog(img.ToString()); var img = outstream.ToArray(); ftpResponse.Close(); ftpStream.Close(); outstream.Close(); return getbyteBase64(img); //return File(img, "image/jpeg"); //return new Task(() => outstream.ToArray()); } catch (Exception e) { return null; } } catch (Exception ex) { return null; } } /// /// 无证书Ftp操作 /// /// /// /// /// /// public static bool ValidateServerCertificate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } /// /// URL图片转换成图片格式 /// /// /// #region Image To base64 public static Image UrlToImage(string url) { WebClient mywebclient = new WebClient(); try { byte[] Bytes = mywebclient.DownloadData(url); using (MemoryStream ms = new MemoryStream(Bytes)) { Image outputImg = Image.FromStream(ms); return outputImg; } } catch (Exception ex) { LogHelper.WriteLine(ex.Message); //Console.WriteLine("地址有误"); throw; } } /// /// 读取图片文件 /// /// 图片文件路径 /// 图片文件 private Bitmap ReadImageFile(String path) { Bitmap bitmap = null; try { FileStream fileStream = File.OpenRead(path); Int32 filelength = 0; filelength = (int)fileStream.Length; Byte[] image = new Byte[filelength]; fileStream.Read(image, 0, filelength); System.Drawing.Image result = System.Drawing.Image.FromStream(fileStream); fileStream.Close(); bitmap = new Bitmap(result); } catch (Exception ex) { // 异常输出 LogHelper.WriteLine(ex.Message); } return bitmap; } /// /// Image 转成 base64 /// /// public static string ImageToBase64(Image img) { try { Bitmap bmp = new Bitmap(img); MemoryStream ms = new MemoryStream(); bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); //Console.WriteLine(ms.Length); byte[] arr = new byte[ms.Length]; ms.Position = 0; ms.Read(arr, 0, (int)ms.Length); ms.Close(); return Convert.ToBase64String(arr); } catch (Exception ex) { LogHelper.WriteLine(ex.Message); return null; } } public static string ImageToBase64(string url) { return ImageToBase64(UrlToImage(url)); } #endregion /// /// 处理人脸机返回信息错误 /// /// public static void Facereturuhandlingmethod(string info, string msgid) { try { Faceinfo finfo = JsonConvert.DeserializeObject(info); if (finfo != null) { faceerrormsg fmsg = new faceerrormsg(); devicemanage devinfo = SqlSugarBase.FaceDb.Queryable().First(it => it.SerialNo == finfo.sn); if (devinfo != null) { if (devinfo.Factory == "移海") { //magsinfo ms = JsonConvert.DeserializeObject(finfo.msg); if (finfo.msg.Para.ErrCode != 0) { fmsg.brandinfo = "yh"; fmsg.errorcode = finfo.msg.Para.ErrCode; fmsg.errormsg = finfo.msg.Para.ErrMsg; fmsg.creationtime = DateTime.Now; fmsg.sn = finfo.sn; fmsg.step = 514; fmsg.pmsid = IsLikeGuidByArr(msgid) ? -1 : int.Parse(msgid); fmsg.remary = "人脸机回复失败信息"; fmsg.APKVersion = devinfo.APKVersion; fmsg.hotelid = devinfo.HotelCode; fmsg.Roomid = devinfo.RoomId.ToString(); fmsg.cmd = finfo.cmd; int d = SqlSugarBase.FaceDb.Insertable(fmsg).ExecuteCommand(); } } } } } catch (Exception e) { LogHelper.Write("控制台收到人脸机信息,处理命令时异常: " + e.Message + " 收到设备端上报的内容:" + info); } } public static string GetBaiduIp(string ip) { string location = ""; try { string url = $"https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query={ip}&co=&resource_id=6006&oe=utf8"; WebClient client = new WebClient(); var buffer = client.DownloadData(url); string jsonText = Encoding.UTF8.GetString(buffer); JObject jo = JObject.Parse(jsonText); Root root = JsonConvert.DeserializeObject(jo.ToString()); foreach (var item in root.data) { location = item.location; } return location; } catch (Exception ex) { //Console.WriteLine(ex); return location; } } static bool IsLikeGuidByArr(string strSrc) { string testStr; testStr = strSrc.Trim(); if (String.IsNullOrEmpty(strSrc)) { return false; } for (int i = 0; i < testStr.Length; i++) { char a = testStr[i]; if (a == '-' || (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z')) { return true; } } return false; } } }