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;
}
}
}