using System;
|
using System.Collections.Generic;
|
using System.Text;
|
using WIDESEA_WCS.WCSClient;
|
using WIDESEA_Entity.DomainModels;
|
using WIDESEA_Services.Repositories;
|
using System.Linq;
|
using System.Threading;
|
using WIDESEA_Core.Utilities;
|
using System.Diagnostics;
|
using Quartz.Impl;
|
using WIDESEA_Common.CutomerModel;
|
using WIDESEA_Common;
|
using WIDESEA_Services.IRepositories;
|
using WIDESEA_WCS.EquipBaseInfo;
|
using WIDESEA_Core;
|
using MySqlX.XDevAPI.Common;
|
using Quartz;
|
using static Quartz.Logging.OperationName;
|
using Microsoft.Extensions.Options;
|
using Google.Protobuf.WellKnownTypes;
|
using WIDESEA_Core.EFDbContext;
|
using StackExchange.Profiling.Internal;
|
|
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>();
|
|
#region 开启服务
|
/// <summary>
|
/// 开启服务
|
/// </summary>
|
/// <returns></returns>
|
public static WebResponseContent StartService()
|
{
|
WebResponseContent responseContent = new WebResponseContent();
|
try
|
{
|
if (!CheckServerState().Status)//开启服务之前检查调度是否已开启及PLC是否已连接
|
{
|
WebResponseContent content = ConnectServer();
|
if (content.Status)
|
{
|
responseContent = StartSchedule();
|
if (!responseContent.Status)
|
{
|
DisconnectServer();
|
}
|
foreach (var item in Clients)
|
{
|
item.Thread.Start();
|
}
|
}
|
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 (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(() =>
|
{
|
Idt_equipmentinfoRepository repository = new dt_equipmentinfoRepository(new WIDESEA_Core.EFDbContext.VOLContext());
|
dt_equipmentinfo equipmentinfo = repository.FindFirst(x => x.equipment_name == saveModel.MainData["equipNum"].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["equipStatus"].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
|
{
|
VOLContext context = new VOLContext();
|
IVV_DispatchRepository repository = new VV_DispatchRepository(context);
|
StdSchedulerFactory factory = new StdSchedulerFactory();
|
scheduler = new SchedulerCenterServer(factory);
|
List<JobOptions> jobOptions = repository.FindToJobOptions(x => x.Enable == EquipmentState.Enable.ToString());
|
jobOptions.ForEach(x => { x.JobParams = Clients.Where(y => y.PLCName == x.JobName).FirstOrDefault(); });
|
if (!jobOptions.Any())
|
{
|
responseContent = WebResponseContent.Instance.Error("当前未配置调度");
|
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();
|
VOLContext volContext = new VOLContext();
|
//IVV_DispatchRepository dispatchRepository = new VV_DispatchRepository(volContext);
|
Idt_plcinfoheadRepository plcinfoheadRepository = new dt_plcinfoheadRepository(volContext);
|
Idt_plcinfodetailRepository plcinfodetailRepository = new dt_plcinfodetailRepository(volContext);
|
Idt_equipmentinfoRepository equipmentinfoRepository = new dt_equipmentinfoRepository(volContext);
|
try
|
{
|
if (Clients != null)
|
{
|
DisconnectServer();
|
}
|
//jobs = new List<JobOptions>();
|
//jobs = dispatchRepository.FindJobOptions(x => x.Enable == EquipmentState.Enable.ToString());
|
//List<string> plcNames = dispatchRepository.FindToJobOptions(x => x.Enable == EquipmentState.Enable.ToString()).Select(x => x.JobName).ToList();
|
//if (plcNames.Count == 0)
|
// return content.Error("当前无PLC连接配置或设备被禁用");
|
Clients = new List<PLCClient>();
|
List<string> strings = equipmentinfoRepository.Find(x => x.equipment_state == EquipmentState.Enable.ToString()).Select(x=>x.equipment_name).ToList();
|
List<dt_plcinfohead> plcinfoheads = plcinfoheadRepository.Find(x => strings.Contains(x.plcinfo_name));
|
|
foreach (dt_plcinfohead item in plcinfoheads)
|
{
|
PLCClient client = new PLCClient
|
{
|
PLCIPAddress = item.plcinfo_ip,
|
PLCName = item.plcinfo_name,
|
PLCDescroption = item.plcinfo_remark,
|
ConnectionMessage = item.plcinfo_name.Contains("C") ? "拆包间" : "投料间",
|
PLCDBItems = plcinfodetailRepository.Find(x => x.plcdetail_headid == item.plcinfo_id).Select(x => new DBItemGroup { ItemAddress = x.plcdetail_db.Trim() + "." + x.plcdetail_value.Trim(), ItemDataType = x.plcdetail_valtype.Trim(), ItemName = x.plcdetail_name.Trim(), ItemOperatorType = x.plcdetail_opratortype?.Trim(), EquipNum = x.plcdetail_number.Trim(), Remark = x.plcdetail_remark.Trim() }).ToList()
|
};
|
string msg = client.Connect();
|
if (msg.Contains("连接失败"))
|
{
|
Console.WriteLine($"{client.PLCDescroption + msg}");
|
return content.Error(msg);
|
}
|
//client.Start(() => { Read(client); });
|
//jobs.Where(x => x.JobName == item.plcinfo_name).FirstOrDefault().PLCConnectState = msg;
|
Clients.Add(client);
|
Console.WriteLine($"{client.PLCDescroption + msg}");
|
}
|
content.OK("PLC连接成功!");
|
}
|
catch (Exception ex)
|
{
|
content.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.Any() && Clients != null)
|
{
|
for (int i = 0; i < Clients.Count; i++)
|
{
|
Clients[i]?.Disconnect();
|
}
|
//ConveyorLineInfo.PLCClient?.SiemensS7NetClient?.ConnectClose();
|
content = WebResponseContent.Instance.OK(message: "已断开与PLC的连接!");
|
}
|
else
|
{
|
content = WebResponseContent.Instance.Error("当前与PLC无连接!");
|
}
|
Clients = null;
|
}
|
catch (Exception ex)
|
{
|
content = WebResponseContent.Instance.Error(ex.Message);
|
}
|
return content;
|
}
|
#endregion
|
|
#region ThreadMethod PLC连接内置线程 方法
|
static void Read(PLCClient client)
|
{
|
//Console.Out.WriteLine(client.Read("DB3.0", "INT"));
|
#region 调度是否存在
|
if (jobs != null)
|
{
|
JobOptions jobOptions = jobs.Where(x => x.JobName == client.PLCName).FirstOrDefault();
|
JobOptions options = new JobOptions { JobName = jobOptions.JobName, JobGroup = jobOptions.JobGroup };
|
bool isexist = scheduler.IsExistScheduleJobAsync(jobOptions).Result;
|
if (isexist)
|
{
|
List<TaskInfoDto> dtos = scheduler.GetTaskStaus(options).Result;
|
foreach (TaskInfoDto taskInfoDto in dtos)
|
{
|
if (taskInfoDto.TriggerStatus != "暂停")
|
{
|
//dt_equipmentinfo equipmentinfo = SqlSugarHelper.WCSDB.Queryable<dt_equipmentinfo>().First(x => x.equipment_name == client.PLCName);
|
dt_equipmentinfo equipmentinfo = JobWorker.equipmentinfos.Where(x => x.equipment_name == client.PLCName).FirstOrDefault();
|
if (equipmentinfo != null)
|
{
|
if (equipmentinfo.equipment_state == EquipmentState.Disenable.ToString())
|
{
|
WebResponseContent content = scheduler.PauseJob(options).Result;
|
}
|
}
|
}
|
|
}
|
|
}
|
}
|
#endregion
|
|
}
|
#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();
|
}
|
}
|
}
|