using Infrastructure.Attribute; using Infrastructure.Model; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using SqlSugar.IOC; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using DOAN.Common; using DOAN.Model.Dto; using DOAN.Model.MES.andon; using DOAN.Service.MES.andon.IService; using DOAN.Model.MES.base_; using System.Net.Sockets; using MimeKit; using Infrastructure; using NPOI.HPSF; using DOAN.Common.SocketHelper; using NPOI.OpenXml4Net.OPC; using DOAN.ServiceCore.MyMatchPush; namespace DOAN.Service.MES.andon { [AppService(ServiceType = typeof(IAndonInteractionService), ServiceLifetime = LifeTime.Transient)] public class AndonInteractionService : BaseService, IAndonInteractionService { private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private OptionsSetting OptionsSetting; private readonly SocketGatewayServer _socketGateway; public AndonInteractionService(IOptions options, SocketGatewayServer socketGateway) { OptionsSetting = options.Value; _socketGateway=socketGateway; } /// /// 获取线 /// /// public string[] GetLine() { return Context.Queryable().Where(it => it.Status == 1).Select(it => it.Code).ToArray(); } /// /// 呼叫请求 /// /// /// private static int PackageSort=1; public int CallHandle(AndonFaultRecord record) { //发送报警信息 string message = $"产线:{record.LineCode},\n故障类型:{record.FaultDict},\n故障内容:{record.FaultContext},\n报警人:{record.AskPerson}"; //发送手表 Watchup.StartPush(message, _socketGateway); record.Id = SnowFlakeSingle.Instance.NextId().ToString(); record.StartTime = DateTime.Now; record.Status = 1; record.CreatedBy = "system"; record.CreatedTime = DateTime.Now; return Context.Insertable(record).ExecuteCommand(); // return 0; } public string CallHandleSCREEN(AndonFaultRecord record) { //发送报警信息 string message = $"产线:{record.LineCode},\n故障类型:{record.FaultDict},\n故障内容:{record.FaultContext},\n报警人:{record.AskPerson}"; //发送手表 Watchup.StartPush(message, _socketGateway); record.Id = SnowFlakeSingle.Instance.NextId().ToString(); record.StartTime = DateTime.Now; record.Status = 1; record.CreatedBy = "system"; record.CreatedTime = DateTime.Now; int result= Context.Insertable(record).ExecuteCommand(); if(result>0) { return record.Id; } return ""; } /// /// test手表 /// /// //public int TestWatch1() //{ // string serverIp = "192.168.1.22"; // int port = 4021; // try // { // // 1. 创建并连接 Socket // Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // socket.Connect(serverIp, port); // Console.WriteLine($"已连接到服务器 {serverIp}:{port}"); // // 2. 使用工具类发送字符串报文 // //分步构造 byte[],然后发送 // //包头 // byte[] packageHeader = { 0x5A }; // //包序号 // byte[] packsort = { 1 }; // // 地址 // byte[] IPaddress = { 0xff, 0xff, 0xff, 0xff }; // //命令码 // byte[] CommandCode = { 0xE0 }; // //数据长 // string message = "你好 hello 123"; // byte[] MessageData = Encoding.GetEncoding("GBK").GetBytes(message); // byte[] MessageLength = { (byte)MessageData.Length }; // // === 先拼接除 CRC 之外的所有部分 === // byte[] dataWithoutCRC = // packageHeader // .Concat(packsort) // .Concat(IPaddress) // .Concat(CommandCode) // .Concat(MessageLength) // .Concat(MessageData).ToArray(); // //CRC : 校验和,CRC 前面所有数据之和除 256 的余数 // byte[] CRC = { SocketSenderHelper.CalculateChecksum(dataWithoutCRC) }; // byte[] Body = dataWithoutCRC.Concat(CRC).ToArray(); // // SocketSenderHelper.SendBytesMessage(socket, Body); // Console.WriteLine($"已发送消息: {message}"); // // 3. 关闭连接 // socket.Shutdown(SocketShutdown.Both); // socket.Close(); // } // catch (Exception ex) // { // throw new CustomException($"发生错误: {ex.Message}"); // Console.WriteLine($"发生错误: {ex.Message}"); // } // return 0; //} public int TestWatch() { // 2. 使用工具类发送字符串报文 //分步构造 byte[],然后发送 //包头 byte[] packageHeader = { 0x5A }; //包序号 byte[] packsort = { 1 }; // 地址 byte[] IPaddress = { 0xff, 0xff, 0xff, 0xff }; //命令码 byte[] CommandCode = { 0xE0 }; //数据长 string message = "你好 hello 123"; byte[] MessageData = Encoding.GetEncoding("GBK").GetBytes(message); byte[] MessageLength = { (byte)MessageData.Length }; // === 先拼接除 CRC 之外的所有部分 === byte[] dataWithoutCRC = packageHeader .Concat(packsort) .Concat(IPaddress) .Concat(CommandCode) .Concat(MessageLength) .Concat(MessageData).ToArray(); //CRC : 校验和,CRC 前面所有数据之和除 256 的余数 byte[] CRC = { SocketSenderHelper.CalculateChecksum(dataWithoutCRC) }; byte[] Body = dataWithoutCRC.Concat(CRC).ToArray(); // 创建服务端,监听本机 8888 端口 var server = new SocketGatewayServer("192.168.1.11", 4021); server.Start(); // 启动接收线程(可选,如果你想接收网关发来的字节数据) server.StartReceiving(); Console.WriteLine("服务端已启动,等待网关(客户端)连接..."); // 模拟等待网关连接(你可以等几秒,或者根据实际情况判断) Console.WriteLine("等待网关连接中,5秒后尝试发送字节数据..."); global::System.Threading.Thread.Sleep(5000); // 构造一个字节数据报文,比如 0x01 0x02 0x03 ... //byte[] testData = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }; server.SendToGateway(Body); return 1; } public int SignIn(AndonFaultRecord record) { record.StartTime = Context.Queryable().Where(it => it.Id == record.Id).Select(it => it.StartTime).First(); record.EndTime = DateTime.Now; TimeSpan timeDifference = (record.EndTime ?? DateTime.MinValue) - (record.StartTime ?? DateTime.MinValue); record.Duration = Math.Round((decimal)timeDifference.TotalMinutes, 2); record.Status = 2; return Update(record, true); } /// /// 获取待响应的 记录 /// /// public List WaitingResponse() { return Context.Queryable().Where(it => it.Status == 1).ToList(); } private static List GetFaultDicts() { return DbScoped.SugarScope.CopyNew().Queryable().ToList(); } /// /// 监测超时发送邮件 /// /// public string[] MonitoringMails() { string[] result = null; // 获取异常字典 List andonFaults = GetFaultDicts(); // 获取超时记录 DateTime Overtime = DateTime.Now.AddHours(-1); // 获取没有被响应的故障 List AlarmRecord = Context.Queryable().Where(it => it.Status == 1).Where(it => it.StartTime <= Overtime).ToList(); if (AlarmRecord != null && AlarmRecord.Count > 0 && andonFaults.Count > 0) { result = new string[AlarmRecord.Count]; foreach (var alarm in AlarmRecord) { foreach (var fault in andonFaults) { if (alarm.FaultDict == fault.Name) { double overSpan = Math.Round((DateTime.Now - alarm.StartTime.Value).TotalHours, 2); SendEmailDto sendEmailVo = new SendEmailDto(); sendEmailVo.Subject = "上海干巷总装车间 Andon [报警升级]通知"; // 邮箱责任 sendEmailVo.ToUser = fault.Email ?? "qianhao.xu@doan-tech.com"; StringBuilder msg = new StringBuilder(); msg.Append($"Dear [{fault.Director}]经理:"); msg.Append("\n"); msg.Append("\n"); msg.Append($"[{alarm.LineCode}]产线发生[{alarm.FaultDict}]类型异常, [{alarm.AskPerson}]报警人 在{alarm.StartTime.Value.ToString("yyyy-MM-dd HH:mm:ss")}时间发起报警,已经超过{overSpan}小时未处理,请立刻到现场扫码签到并处理异常,报警内容如下:\n"); msg.Append("\n"); msg.Append($"{alarm.FaultContext ?? "[无报警内容]"}。"); msg.Append("\n"); msg.Append("\n"); msg.Append("\n"); msg.Append($"Andon系统将每10分钟发送一次邮件,直至[{alarm.FaultDict}]类型异常,被签到并处理!"); msg.Append("\n"); msg.Append("\n"); msg.Append("\n"); msg.Append("如果邮件中有任务不清楚的地方或者需要我们提供任何帮助,请联系苏州道安自动化有限公司IT部门,邮件地址为qianhao.xu@doan-tech.com\n"); msg.Append($"故障id {alarm.Id}"); sendEmailVo.Content = msg.ToString(); sendEmailVo.SendMe = true; sendEmailVo.AddTime = DateTime.Now; result[AlarmRecord.IndexOf(alarm)] = SendEmail(sendEmailVo); continue; } } } } return result; } /// /// 定时 触发手表推送任务 /// public void WatchPushAndon() { //获取没有被响应的故障 List AlarmRecord = Context.Queryable().Where(it => it.Status == 1).ToList(); //推送手表 StringBuilder stringBuilder = new StringBuilder(); foreach (var record in AlarmRecord) { stringBuilder.Append($"产线:{record.LineCode},故障类型:{record.FaultDict}\n"); } Watchup.StartPush(stringBuilder.ToString(), _socketGateway); } /// /// 发送邮件任务 /// /// /// private string SendEmail(SendEmailDto sendEmailVo) { if (sendEmailVo == null) { return "请求参数不完整"; } if (string.IsNullOrEmpty(OptionsSetting.MailOptions.FromEmail) || string.IsNullOrEmpty(OptionsSetting.MailOptions.Password)) { return "请配置邮箱信息"; } MailHelper mailHelper = new(); string[] toUsers = sendEmailVo.ToUser.Split(",", StringSplitOptions.RemoveEmptyEntries); if (sendEmailVo.SendMe) { toUsers.Append(mailHelper.FromEmail); } string result = mailHelper.SendMail(toUsers, sendEmailVo.Subject, sendEmailVo.Content, sendEmailVo.FileUrl, sendEmailVo.HtmlContent); logger.Info($"发送邮件{JsonConvert.SerializeObject(sendEmailVo)}, 结果{result}"); return result; } } }