using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Quartz.Impl; using System; using System.Collections.Generic; using System.Configuration; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using WIDESEA_Common; using WIDESEA_Common.CutomerModel; using WIDESEA_Common.Tools; using WIDESEA_Core.Utilities; using WIDESEA_Entity.DomainModels; using WIDESEA_Entity.DomainModels.Equipment; using WIDESEA_Services.IRepositories; using WIDESEA_Services.Repositories; using WIDESEA_WCS.WCSClient; namespace WIDESEA_WCS { public class WCSService { /// /// PLC连接集合 /// public static List Clients; /// /// 调度中心 /// public static ISchedulerCenterServer scheduler; /// /// Job集合 /// static List jobs = new List(); static List centerEqDBList; #region 开启服务 /// /// 开启服务 /// /// public static WebResponseContent StartService() { var configTxt = File.ReadAllText(Directory.GetCurrentDirectory() + "/time_allocation.json"); var jsonObject = JObject.Parse(configTxt); jsonObject["MM"] = "456"; var convertString = Convert.ToString(jsonObject); File.WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "time_allocation.json"), convertString); //File.WriteAllText(Path.Combine(_basePath, _appsettingsProductionJson), convertString); WebResponseContent responseContent = new WebResponseContent(); try { if (!CheckServerState().Status)//开启服务之前检查调度是否已开启及PLC是否已连接 { WIDESEA.Helper.GetToken();//hsl授权 WebResponseContent content = ConnectServer(); if (content.Status) { responseContent = StartSchedule(); if (!responseContent.Status) { DisconnectServer(); } } else { DisconnectServer(); responseContent = content; } } else { responseContent = WebResponseContent.Instance.Error("服务已开启"); } } catch (Exception ex) { responseContent = responseContent.Error(ex.Message); } return responseContent; } #endregion #region 关闭服务 /// /// 关闭服务(调度及PLC连接) /// /// public static WebResponseContent CloseService() { WebResponseContent content = new WebResponseContent(); try { //if (!UserContext.Current.UserName.Contains("admin")) //{ // content.Message = "未授权操作!"; // content.Status = false; // return content; //} if (scheduler != null) { CloseSchedule(); DisconnectServer(); scheduler = null; content = content.OK(); } else { content = WebResponseContent.Instance.Error("任务调度已停止"); } } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } return content; } #endregion #region 检查服务状态 /// /// 检查服务状态 /// /// public static WebResponseContent CheckServerState() { WebResponseContent content = new WebResponseContent(); try { if (scheduler != null && Clients.Any()) { content = content.OK(message: ""); } else { CloseService(); content = content.Error(message: "服务已关闭"); } } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } return content; } #endregion #region 暂停或恢复指定的计划任务 /// /// 暂停或恢复指定的计划任务 /// /// /// public static WebResponseContent PauseOrResumeJob(SaveModel saveModel) { return dt_equipmentinfoRepository.Instance.DbContextBeginTransaction(() => { string equipment_name = saveModel.MainData["equipment_name"].ToString(); Idt_equipmentinfoRepository repository = new dt_equipmentinfoRepository(new WIDESEA_Core.EFDbContext.VOLContext()); dt_equipmentinfo equipmentinfo = repository.FindFirst(x => x.equipment_name == saveModel.MainData["equipment_name"].ToString()); if (equipmentinfo == null) return WebResponseContent.Instance.Error($"未找到该设备【{saveModel.MainData["equipNum"]}】"); if (equipmentinfo.equipment_state == EquipmentState.Enable.ToString()) equipmentinfo.equipment_state = EquipmentState.DisEnable.ToString(); else equipmentinfo.equipment_state = EquipmentState.Enable.ToString(); if (dt_equipmentinfoRepository.Instance.Update(equipmentinfo, true) <= 0) return WebResponseContent.Instance.Error("设备状态修改失败"); JobOptions options = new JobOptions { JobName = equipmentinfo.equipment_name, JobGroup = equipmentinfo.equipment_type }; if (scheduler == null) return WebResponseContent.Instance.OK("设备状态修改成功"); if (!scheduler.IsExistScheduleJobAsync(options).Result) { return WebResponseContent.Instance.OK("设备状态修改成功"); } if (saveModel.MainData["equipment_state"].ToString() == EquipmentState.Enable.ToString()) { return scheduler.PauseJob(options).Result; } else { return scheduler.ResumeJob(options).Result; } }); } #endregion #region 开启调度 /// /// 开启调度 /// /// public static WebResponseContent StartSchedule() { WebResponseContent responseContent = new WebResponseContent(); try { StdSchedulerFactory factory = new StdSchedulerFactory(); scheduler = new SchedulerCenterServer(factory); List jobOptions = VV_DispatchRepository.Instance.FindToJobOptions(x => true && x.Enable == EquipmentState.Enable.ToString()); jobOptions.ForEach(x => { x.JobParams = Clients.Where(y => y.PLCName == x.JobName).FirstOrDefault(); }); //未连接plc,默认不开启调度 //jobOptions = jobOptions.Where(t => t.JobParams != null).ToList(); if (!jobOptions.Any()) { responseContent = WebResponseContent.Instance.Error("当前未配置调度,或调度PLC连接失败"); return responseContent; } for (int i = 0; i < jobOptions.Count; i++) { WebResponseContent content = scheduler.AddScheduleJobAsync(jobOptions[i]).Result; if (!content.Status) { factory = null; scheduler = null; return content; } } responseContent = scheduler.StartScheduleAsync().Result; } catch (Exception ex) { responseContent = responseContent.Error(ex.Message); scheduler = null; } return responseContent; } #endregion #region 停止调度 /// /// 停止调度 /// /// public static WebResponseContent CloseSchedule() { WebResponseContent content = new WebResponseContent(); try { content = scheduler.StopScheduleAsync().Result; } catch (Exception ex) { content = content.Error(ex.Message); } return content; } #endregion #region 连接PLC /// /// 连接PLC /// /// public static WebResponseContent ConnectServer() { WebResponseContent content = new WebResponseContent(); try { if (Clients != null) { DisconnectServer(); } //jobs = new List(); //jobs = VV_DispatchRepository.Instance.FindJobOptions(x => true); List plcNames = dt_equipmentinfoRepository.Instance.Find(x => x.equipment_state == EquipmentState.Enable.ToString()).Select(t => t.equipment_name).ToList(); if (plcNames.Count == 0) return content = WebResponseContent.Instance.Error("当前无PLC连接配置或设备被禁用"); Clients = new List(); //根据设备的禁用启用,判断plc是否需要链接 List plcinfoheads = dt_plcinfoheadRepository.Instance.Find(x => plcNames.Contains(x.plcinfo_name)); //plc协议 List plcinfodetails = dt_plcinfodetailRepository.Instance.Find(x => true); //链接消息 string connMs = string.Empty; //防止重复链接 List coonIpList = new List(); foreach (dt_plcinfohead head in plcinfoheads) { try { PLCClient client = new PLCClient(head, plcinfodetails) { PLCName = head.plcinfo_name, PLCDescroption = head.plcinfo_remark, PLCDownLoc = head.plcinfo_down, EquipType = head.plcinfo_equiptype }; if (!coonIpList.Contains(head.plcinfo_ip) || true)//调试时用ture { coonIpList.Add(head.plcinfo_ip); client.Connect(); } //else //{ // switch (client.PLCType) // { // case "SiemensPLC": // client.SiemensPLCClient = Clients.FirstOrDefault(t => t.PLCName == haveCoonIpClient.plcinfo_name).SiemensPLCClient; // break; // case "MelsecPLC": // client.MelsecPLCClient = Clients.FirstOrDefault(t => t.PLCName == haveCoonIpClient.plcinfo_name).MelsecPLCClient; // break; // default: // break; // } //} Clients.Add(client); } catch (Exception ex) { connMs += $"{head.plcinfo_name},{ex.Message}\n"; } } WriteLog.GetLog().Write(connMs, "服务启动"); content = WebResponseContent.Instance.OK("PLC连接成功!"); } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); Clients = null; } return content; } #endregion #region 断开与PLC的连接 /// /// 断开与PLC的连接 /// /// public static WebResponseContent DisconnectServer() { WebResponseContent content = new WebResponseContent(); try { if (Clients != null && Clients.Any()) { for (int i = 0; i < Clients.Count; i++) { Clients[i]?.Disconnect(); } content = WebResponseContent.Instance.OK(message: "已断开与PLC的连接!"); } else { content = WebResponseContent.Instance.Error("当前与PLC无连接!"); } } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } finally { Clients = null; } return content; } #endregion #region ThreadMethod PLC连接内置线程 方法 static void Read(PLCClient client) { //Console.Out.WriteLine(client.Read("DB3.0", "INT")); } #endregion #region 获取任务触发器状态 /// /// 获取任务触发器状态 /// /// public static WebResponseContent GetTaskStaus() { WebResponseContent responseContent = new WebResponseContent(); List taskInfoDtos = new List(); if (jobs.FirstOrDefault() == null) jobs = VV_DispatchRepository.Instance.FindJobOptions(x => true); for (int i = 0; i < jobs.Count; i++) { List temp = new List(); if (scheduler == null) { temp = new List { new TaskInfoDto() { JobId = jobs[i].JobName.ObjToString(), JobGroup = jobs[i].JobGroup, TriggerId = "", TriggerGroup = "", TriggerStatus = "不存在", IsConnected = Clients.Where(x=>x.PLCName == jobs[i].JobName).FirstOrDefault()?.IsConnected??false } }; } else { temp = scheduler.GetTaskStaus(jobs[i]).Result; } taskInfoDtos.AddRange(temp); } return WebResponseContent.Instance.OK(data: taskInfoDtos); } #endregion #region 立即执行 一个任务 /// /// 立即执行 一个任务 /// /// /// public static WebResponseContent ExecuteJobAsync(string jobName) { WebResponseContent result = new WebResponseContent(); try { JobOptions job = jobs.Where(x => x.JobName == jobName).FirstOrDefault(); if (job == null) { result = WebResponseContent.Instance.Error($"立即执行计划任务失败:未找到该任务计划,任务计划:{jobName}"); } else { result = scheduler.ExecuteJobAsync(job).Result; } } catch (Exception ex) { result.Message = $"立即执行计划任务失败:【{ex.Message}】"; } return result; } #endregion #region 获取任务触发器状态 /// /// 获取任务触发器状态 /// /// public static PageGridData GetPageData() { try { List taskInfoDtos = new List(); if (jobs.FirstOrDefault() == null) jobs = VV_DispatchRepository.Instance.FindJobOptions(x => true); for (int i = 0; i < jobs.Count; i++) { List temp = new List(); if (scheduler == null) { temp = new List { new TaskInfoDto() { JobId = jobs[i].JobName.ObjToString(), JobGroup = jobs[i].JobGroup, TriggerId = "", TriggerGroup = "", TriggerStatus = "不存在", PLCConnetState = jobs[i].PLCConnectState, IsConnected = false } }; } else { temp = scheduler.GetTaskStaus(jobs[i]).Result; if (Clients != null) { for (int j = 0; j < temp.Count; j++) { temp[j].IsConnected = Clients.Where(x => x.PLCName == temp[j].JobId).FirstOrDefault()?.IsConnected ?? false; } } } taskInfoDtos.AddRange(temp); } return new PageGridData { rows = taskInfoDtos, total = taskInfoDtos?.Count ?? 0 }; } catch (Exception ex) { return new PageGridData { rows = null, total = 0, status = 404, msg = ex.Message }; } } #endregion public static JobOptions GetJobOptions(string jobName) { return jobs.Where(x => x.JobName == jobName).FirstOrDefault(); } public static ResultMaterstateUp Updatestockstate(MESupdateMaterStateRequest request) { ResultMaterstateUp result = new ResultMaterstateUp(); try { var stock = bill_group_stockRepository.Instance.FindFirst(v => v.BarCode == request.BarCode); if (stock == null) throw new Exception(string.Format("当前物料编号{0}未查询到库存", request.BarCode)); if (stock.location_id == null) throw new Exception(string.Format("当前物料{0}未绑定货位", request.BarCode)); var location = base_ware_locationRepository.Instance.FindFirst(v => v.id == stock.location_id); if (location.equipment_type == "TBHCJ") { stock.TB_Status = request.MaterialStatus; } else if (location.equipment_type == "GYHCJ") { stock.GY_Status = request.MaterialStatus; } else if (location.equipment_type == "QXHCJ") { stock.QX_Status = request.MaterialStatus; } else { stock.FQ_Status = request.MaterialStatus; } stock.MaterialStatus = request.MaterialStatus; stock.updated_time = DateTime.Now; bill_group_stockRepository.Instance.Update(stock, true); result.Code = 0; } catch (Exception ex) { result.Message = ex.Message; result.Code = 1; } return result; } public static List GetLocationState(string Devid) { List result = new List(); try { if (Devid == null) { var Id = base_ware_locationRepository.Instance.FindFirst(v => v.down_code == Devid || v.upper_code == Devid); var location = bill_group_stockRepository.Instance.FindFirst(v => v.location_id == Id.id); ResultLocationState content = new ResultLocationState(); content.BarCode = location.BarCode; content.MaterialStatus = location.MaterialStatus; content.MaterialType = location.MaterialType; content.Devid = Devid; result.Add(content); } else { var IdList = base_ware_locationRepository.Instance.Find(v => v.down_code == Devid || v.upper_code == Devid).ToList(); for (int i = 0; i < IdList.Count; i++) { ResultLocationState content = new ResultLocationState(); var locationList = bill_group_stockRepository.Instance.FindFirst(v => v.location_id == IdList[i].id); if (locationList != null) { content.BarCode = locationList.BarCode; content.MaterialStatus = locationList.MaterialStatus; content.MaterialType = locationList.MaterialType; content.Devid = Devid; } else { content.BarCode = ""; content.MaterialStatus = ""; content.MaterialType = ""; content.Devid = IdList[i].down_code;//暂时不知道给那个 } result.Add(content); } } // //result.Code = 0; } catch (Exception) { //result.Code = 1; } return result; } } }