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
|
{
|
|
/// <summary>
|
/// PLC连接集合
|
/// </summary>
|
public static List<PLCClient> Clients;
|
|
/// <summary>
|
/// 调度中心
|
/// </summary>
|
public static ISchedulerCenterServer scheduler;
|
|
/// <summary>
|
/// Job集合
|
/// </summary>
|
static List<JobOptions> jobs = new List<JobOptions>();
|
static List<HCJCenterEqDB> centerEqDBList;
|
#region 开启服务
|
/// <summary>
|
/// 开启服务
|
/// </summary>
|
/// <returns></returns>
|
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 关闭服务
|
/// <summary>
|
/// 关闭服务(调度及PLC连接)
|
/// </summary>
|
/// <returns></returns>
|
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 检查服务状态
|
/// <summary>
|
/// 检查服务状态
|
/// </summary>
|
/// <returns></returns>
|
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 暂停或恢复指定的计划任务
|
/// <summary>
|
/// 暂停或恢复指定的计划任务
|
/// </summary>
|
/// <param name="job"></param>
|
/// <returns></returns>
|
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 开启调度
|
/// <summary>
|
/// 开启调度
|
/// </summary>
|
/// <returns></returns>
|
public static WebResponseContent StartSchedule()
|
{
|
WebResponseContent responseContent = new WebResponseContent();
|
try
|
{
|
StdSchedulerFactory factory = new StdSchedulerFactory();
|
scheduler = new SchedulerCenterServer(factory);
|
List<JobOptions> 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 停止调度
|
/// <summary>
|
/// 停止调度
|
/// </summary>
|
/// <returns></returns>
|
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
|
/// <summary>
|
/// 连接PLC
|
/// </summary>
|
/// <returns></returns>
|
public static WebResponseContent ConnectServer()
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
if (Clients != null)
|
{
|
DisconnectServer();
|
}
|
//jobs = new List<JobOptions>();
|
//jobs = VV_DispatchRepository.Instance.FindJobOptions(x => true);
|
List<string> 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<PLCClient>();
|
//根据设备的禁用启用,判断plc是否需要链接
|
List<dt_plcinfohead> plcinfoheads = dt_plcinfoheadRepository.Instance.Find(x => plcNames.Contains(x.plcinfo_name));
|
//plc协议
|
List<dt_plcinfodetail> plcinfodetails = dt_plcinfodetailRepository.Instance.Find(x => true);
|
|
//链接消息
|
string connMs = string.Empty;
|
//防止重复链接
|
List<string> coonIpList = new List<string>();
|
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的连接
|
/// <summary>
|
/// 断开与PLC的连接
|
/// </summary>
|
/// <returns></returns>
|
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 获取任务触发器状态
|
/// <summary>
|
/// 获取任务触发器状态
|
/// </summary>
|
/// <returns></returns>
|
public static WebResponseContent GetTaskStaus()
|
{
|
WebResponseContent responseContent = new WebResponseContent();
|
List<TaskInfoDto> taskInfoDtos = new List<TaskInfoDto>();
|
if (jobs.FirstOrDefault() == null)
|
jobs = VV_DispatchRepository.Instance.FindJobOptions(x => true);
|
|
for (int i = 0; i < jobs.Count; i++)
|
{
|
List<TaskInfoDto> temp = new List<TaskInfoDto>();
|
if (scheduler == null)
|
{
|
temp = new List<TaskInfoDto>
|
{
|
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 立即执行 一个任务
|
/// <summary>
|
/// 立即执行 一个任务
|
/// </summary>
|
/// <param name="jobName"></param>
|
/// <returns></returns>
|
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 获取任务触发器状态
|
/// <summary>
|
/// 获取任务触发器状态
|
/// </summary>
|
/// <returns></returns>
|
public static PageGridData<TaskInfoDto> GetPageData()
|
{
|
try
|
{
|
List<TaskInfoDto> taskInfoDtos = new List<TaskInfoDto>();
|
if (jobs.FirstOrDefault() == null)
|
jobs = VV_DispatchRepository.Instance.FindJobOptions(x => true);
|
|
for (int i = 0; i < jobs.Count; i++)
|
{
|
List<TaskInfoDto> temp = new List<TaskInfoDto>();
|
if (scheduler == null)
|
{
|
|
temp = new List<TaskInfoDto>
|
{
|
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<TaskInfoDto> { rows = taskInfoDtos, total = taskInfoDtos?.Count ?? 0 };
|
}
|
catch (Exception ex)
|
{
|
return new PageGridData<TaskInfoDto> { 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<ResultLocationState> GetLocationState(string Devid)
|
{
|
List<ResultLocationState> result = new List<ResultLocationState>();
|
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;
|
}
|
}
|
}
|