|
|
using Masuit.Tools;
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
using Microsoft.Extensions.Hosting;
|
|
|
using Newtonsoft.Json;
|
|
|
using SlnMesnac.Config;
|
|
|
using SlnMesnac.Extensions;
|
|
|
using SlnMesnac.Model.domain;
|
|
|
using SlnMesnac.Model.dto.taskType;
|
|
|
using SlnMesnac.Model.dto.webapi;
|
|
|
using SlnMesnac.Plc;
|
|
|
using SlnMesnac.Rfid;
|
|
|
using SlnMesnac.Serilog;
|
|
|
using SlnMesnac.WCS.Global;
|
|
|
using SlnMesnac.WCS.Library;
|
|
|
using SlnMesnac.WCS.WCS;
|
|
|
using SqlSugar;
|
|
|
using System.Timers;
|
|
|
|
|
|
namespace SlnMesnac.WCS
|
|
|
{
|
|
|
public class MainCentralControl
|
|
|
{
|
|
|
private IHost host;
|
|
|
|
|
|
//删除日志定时器
|
|
|
private System.Timers.Timer deleteLogTimer;
|
|
|
|
|
|
//plc心跳交互定时器
|
|
|
private System.Timers.Timer plcHeartTimer;
|
|
|
|
|
|
// 新增一个标志位,用于表示方法是否正在执行
|
|
|
private bool isExecuting = false;
|
|
|
|
|
|
private readonly SerilogHelper _logger;
|
|
|
private IServiceProvider serviceProvider;
|
|
|
private ISqlSugarClient SqlSugarClient;
|
|
|
|
|
|
private BearAgv bearAgv;
|
|
|
#region 变量定义
|
|
|
public List<PlcAbsractFactory> plcList;
|
|
|
|
|
|
//容器里面的读写器集合
|
|
|
public List<RfidAbsractFactory> rfidList;
|
|
|
|
|
|
#endregion 变量定义
|
|
|
|
|
|
/// <summary>
|
|
|
/// 构造函数
|
|
|
/// </summary>
|
|
|
/// <param name="host"></param>
|
|
|
public MainCentralControl(IHost _host)
|
|
|
{
|
|
|
host = _host;
|
|
|
SqlSugarClient = host.Services.GetRequiredService<ISqlSugarClient>();
|
|
|
_logger = host.Services.GetRequiredService<SerilogHelper>();
|
|
|
plcList = host.Services.GetRequiredService<List<PlcAbsractFactory>>();
|
|
|
rfidList = host.Services.GetRequiredService<List<RfidAbsractFactory>>();
|
|
|
InitCacheData();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 加载缓存数据
|
|
|
/// </summary>
|
|
|
private void InitCacheData()
|
|
|
{
|
|
|
//加载plc地址信息
|
|
|
StaticData.BaseConfigList = SqlSugarClient.Queryable<BaseConfigInfo>().ToList();
|
|
|
StaticData.WmsMachineInfos = SqlSugarClient.Queryable<WmsMachineInfo>().ToList();
|
|
|
StaticData.WcsAgvCodeMaps = SqlSugarClient.Queryable<WcsAgvCodeMap>().ToList();
|
|
|
#region 定时删除日志
|
|
|
//DeleteLogsLogic();
|
|
|
//deleteLogTimer = new System.Timers.Timer(24 * 60 * 60 * 1000);
|
|
|
//deleteLogTimer.Elapsed += OnTimedEvent;
|
|
|
//deleteLogTimer.AutoReset = true;
|
|
|
//deleteLogTimer.Enabled = true;
|
|
|
#endregion 定时删除日志
|
|
|
#region 定时写入心跳
|
|
|
plcHeartTimer = new System.Timers.Timer(1000);
|
|
|
plcHeartTimer.Elapsed += OnTimedPlcHeartEvent;
|
|
|
plcHeartTimer.AutoReset = true;
|
|
|
plcHeartTimer.Enabled = true;
|
|
|
#endregion 定时写入心跳
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 启动程序
|
|
|
/// </summary>
|
|
|
public void Start()
|
|
|
{
|
|
|
StartCheckStatus();
|
|
|
GetAgvStatus();
|
|
|
DeleteTaskLogic();
|
|
|
|
|
|
//根据条件创建任务
|
|
|
CreateTaskByRecord createTaskByRecord = new CreateTaskByRecord(host.Services);
|
|
|
createTaskByRecord.StartPoint();
|
|
|
|
|
|
_logger.Agv("WCS调度程序启动成功!");
|
|
|
|
|
|
//背负式agv执行任务
|
|
|
bearAgv = new BearAgv(host.Services);
|
|
|
bearAgv.StartPoint();
|
|
|
}
|
|
|
|
|
|
#region
|
|
|
|
|
|
/// <summary>
|
|
|
/// 检查设备状态自动重连
|
|
|
/// </summary>
|
|
|
private void StartCheckStatus()
|
|
|
{
|
|
|
//数据库里面的读写器集合,仅用来更新状态
|
|
|
List<BaseRfidInfo> rfidDbList = SqlSugarClient.Ado.Context.CopyNew().Queryable<BaseRfidInfo>().ToList();
|
|
|
List<WcsBaseEquip> agvEquipList = SqlSugarClient.Ado.Context.CopyNew().Queryable<WcsBaseEquip>().Where(it => it.EquipType == 1).ToList();
|
|
|
Task.Run(async () =>
|
|
|
{
|
|
|
while (true)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
#region PLC状态
|
|
|
foreach (var plc in plcList)
|
|
|
{
|
|
|
PlcConfig? plcConfig = host.Services.GetService<AppConfig>().plcConfig.FirstOrDefault(x => x.plcKey == plc.ConfigKey);
|
|
|
if (plc != null && plc.IsConnected)
|
|
|
{
|
|
|
plc.IsConnected = plc.readHeartByAddress("M100"); //DB100.DBX0.0
|
|
|
if (!plc.IsConnected)
|
|
|
{
|
|
|
plc.IsConnected = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (plcConfig != null)
|
|
|
{
|
|
|
bool result = await plc.ConnectAsync(plcConfig.plcIp, plcConfig.plcPort);
|
|
|
plc.IsConnected = result;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion PLC状态
|
|
|
|
|
|
#region RFID状态
|
|
|
foreach (var rfid in rfidList)
|
|
|
{
|
|
|
if (rfid.ConfigKey == "2#Transplant")
|
|
|
{
|
|
|
}
|
|
|
bool status = rfid.GetOnlineStatus();
|
|
|
if (!status)
|
|
|
{
|
|
|
status = await rfid.ConnectAsync(rfid.ip, rfid.port);
|
|
|
}
|
|
|
//状态同步数据库
|
|
|
BaseRfidInfo? rfidDb = rfidDbList.FirstOrDefault(x => x.EquipIp == rfid.ip);
|
|
|
if (rfidDb != null)
|
|
|
{
|
|
|
rfidDb.IsOnline = status ? 1 : 0;
|
|
|
}
|
|
|
}
|
|
|
lock (string.Empty)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Updateable(rfidDbList).UpdateColumns(it => new { it.IsOnline }).ExecuteCommand();
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Error($"更新RFID状态异常:{ex.Message}",ex);
|
|
|
}
|
|
|
}
|
|
|
#endregion RFID状态
|
|
|
|
|
|
//色粉库位有未取走色粉声光报警
|
|
|
ListeningTonerLocation();
|
|
|
|
|
|
//大托盘库位有未取走色粉声光报警
|
|
|
ListeningBigPlateLocation();
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Error($"监听设备状态异常:{ex.Message}");
|
|
|
}
|
|
|
await Task.Delay(1000 * 10);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取agv状态
|
|
|
/// </summary>
|
|
|
private void GetAgvStatus()
|
|
|
{
|
|
|
List<WcsBaseEquip> agvEquipList = SqlSugarClient.Queryable<WcsBaseEquip>().Where(it => it.EquipType == 1).ToList();
|
|
|
Task.Run(async () =>
|
|
|
{
|
|
|
while (true)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
//实时获取agv状态
|
|
|
MessageSynchronousLogic(agvEquipList);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Error($"获取agv状态异常:{ex.Message}");
|
|
|
}
|
|
|
await Task.Delay(1000 * 30);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 监听色粉库位是否色粉未从料想取出,有的话通知plc声光报警
|
|
|
/// </summary>
|
|
|
private void ListeningTonerLocation()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
PlcAbsractFactory? workShop3Plc = plcList.FirstOrDefault(x => x.ConfigKey == "workShop3Plc");
|
|
|
// 构建查询并执行 Any 方法
|
|
|
bool hasRecords = SqlSugarClient.Ado.Context.CopyNew().Queryable<WcsBaseEquip>()
|
|
|
.InnerJoin<WmsPalletInfo>((wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode
|
|
|
&& !string.IsNullOrEmpty(wbe.ContainerCode)
|
|
|
&& wpi.TonerFlag == 1 && wbe.EquipType == 7).Any();
|
|
|
if (workShop3Plc != null && workShop3Plc.IsConnected)
|
|
|
{
|
|
|
if (hasRecords)
|
|
|
{
|
|
|
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#异常色粉未处理提示"), true);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#异常色粉未处理提示"), false);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Error($"监听色粉库位异常:{ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void ListeningBigPlateLocation()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
PlcAbsractFactory? workShop3Plc = plcList.FirstOrDefault(x => x.ConfigKey == "workShop3Plc");
|
|
|
bool hasRecords = SqlSugarClient.Ado.Context.CopyNew().Queryable<WmsBaseLocation>()
|
|
|
.InnerJoin<WmsPalletInfo>((wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode
|
|
|
&& !string.IsNullOrEmpty(wbe.ContainerCode)
|
|
|
&& wpi.Amount > 0 && wbe.MachineId > 0 && wbe.MachineId < 12).Any();
|
|
|
bool hasRecords12 = SqlSugarClient.Ado.Context.CopyNew().Queryable<WmsBaseLocation>()
|
|
|
.InnerJoin<WmsPalletInfo>((wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode
|
|
|
&& !string.IsNullOrEmpty(wbe.ContainerCode)
|
|
|
&& wpi.Amount > 0 && wbe.MachineId == 12).Any();
|
|
|
if (workShop3Plc != null && workShop3Plc.IsConnected)
|
|
|
{
|
|
|
if (hasRecords)
|
|
|
{
|
|
|
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), true);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#机台校验失败提示"), false);
|
|
|
}
|
|
|
|
|
|
if (hasRecords12)
|
|
|
{
|
|
|
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#12号机台未校验提示"), true);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#12号机台未校验提示"), false);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch(Exception ex)
|
|
|
{
|
|
|
_logger.Error($"监听大托盘库位异常:{ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// agv状态实时刷新
|
|
|
/// </summary>
|
|
|
private void MessageSynchronousLogic(List<WcsBaseEquip> agvEquipList)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
|
|
|
//List<WcsAgvStatus> agvList = SqlSugarClient.Queryable<WcsAgvStatus>().ToList();
|
|
|
List<WcsAgvStatus> agvList = SqlSugarClient.Ado.Context.CopyNew().Queryable<WcsAgvStatus>().ToList();
|
|
|
var data = new
|
|
|
{
|
|
|
reqCode = StaticData.SnowId.NextId(),
|
|
|
mapCode = "AA",
|
|
|
};
|
|
|
string result = HttpHelper.SendPostMessage(agvEquipList.First().ServerIp, agvEquipList.First().ServerPort, "rcms-dps/rest/queryAgvStatus", data.ToJsonString());
|
|
|
var reponse = JsonConvert.DeserializeObject<AgvStatusDto>(result);
|
|
|
if (reponse != null && reponse.code == "0")
|
|
|
{
|
|
|
foreach (var agv in agvList)
|
|
|
{
|
|
|
CardStatus? agvCard = reponse.data.FirstOrDefault(x => x.robotCode == agv.RobotCode);
|
|
|
if (agvCard != null)
|
|
|
{
|
|
|
agv.Battery = agvCard.battery;
|
|
|
agv.ExclType = agvCard.exclType;
|
|
|
agv.Online = agvCard.online;
|
|
|
agv.PosX = agvCard.posX;
|
|
|
agv.PosY = agvCard.posY;
|
|
|
agv.RobotDir = agvCard.robotDir;
|
|
|
agv.Speed = agvCard.speed;
|
|
|
agv.Status = agvCard.status;
|
|
|
WcsAgvCodeMap? wcsAgvCodeMap = StaticData.WcsAgvCodeMaps.FirstOrDefault(x => x.AgvCode == long.Parse(agv.Status));
|
|
|
if (wcsAgvCodeMap != null)
|
|
|
{
|
|
|
agv.StatusDetail = wcsAgvCodeMap.agv_display_content;
|
|
|
}
|
|
|
agv.Stop = agvCard.stop;
|
|
|
agv.Timestamp = DateTime.Now;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//TaskHandleByAgv(agvList);
|
|
|
//SqlSugarClient.Updateable(agvList).ExecuteCommand();
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Updateable(agvList).ExecuteCommand();
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Info($"同步agv状态信息异常:{ex.Message},{ex.StackTrace.ToJsonString()}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void TaskHandleByAgv(List<WcsAgvStatus> agvInfos)
|
|
|
{
|
|
|
if (agvInfos == null || agvInfos.Count == 0)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var targetPoint = new { X = 142430, Y = 108540 };
|
|
|
|
|
|
var agvInfo = agvInfos.OrderBy(agv => CalculateDistance(double.Parse(agv.PosX), double.Parse(agv.PosY), targetPoint.X, targetPoint.Y)).First();
|
|
|
|
|
|
_logger.Agv($"=====>>>>离接驳位最近的设备为:{agvInfo.RobotCode}");
|
|
|
|
|
|
//判断当前小车有没有送空箱任务,下发PLC触发取料信号
|
|
|
if (agvInfo.StatusDetail.Contains("待机模式") || agvInfo.StatusDetail.Contains("空闲"))
|
|
|
{
|
|
|
_logger.Agv($"当前空闲车辆{agvInfo.RobotCode};离取料点最近,优先进行取料,锁定线体,下发PLC触发取料信号");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
_logger.Agv($"当前没有空闲小车离取料点最近,等线体空闲后进行取料");
|
|
|
bearAgv.workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存请求"),true);
|
|
|
bool flag = bearAgv.workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#空箱进缓存允许"));
|
|
|
if (flag == true)
|
|
|
{
|
|
|
//线体空闲了,可以锁定进行取料
|
|
|
_logger.Agv($"线体空闲了,可以锁定使用远处小车进行取料");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static double CalculateDistance(double x1, double y1, double x2, double y2)
|
|
|
{
|
|
|
return Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
|
|
|
}
|
|
|
|
|
|
#region 删除任务 -- 已经下发的任务,需要通知agv取消
|
|
|
|
|
|
/// <summary>
|
|
|
/// 定时监测是否有待删除任务,完成删除
|
|
|
/// </summary>
|
|
|
private void DeleteTaskLogic()
|
|
|
{
|
|
|
Task.Run(() =>
|
|
|
{
|
|
|
var sqlClient = SqlSugarClient.Ado.Context.CopyNew();
|
|
|
List<WcsBaseEquip> agvEquipList = SqlSugarClient.Ado.Context.CopyNew().Queryable<WcsBaseEquip>().Where(it => it.EquipType == 1).ToList();
|
|
|
while (true)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
List<WcsTask> wcsTasks = SqlSugarClient.Ado.Context.CopyNew().Queryable<WcsTask>().Where(t => t.IsDelete == 1 || t.IsDelete == 2).ToList();
|
|
|
foreach (var item in wcsTasks)
|
|
|
{
|
|
|
WcsBaseEquip agvEquip = agvEquipList.First();
|
|
|
if (!string.IsNullOrEmpty(item.TaskCode))
|
|
|
{
|
|
|
var cancelTask = new
|
|
|
{
|
|
|
reqCode = StaticData.SnowId.NextId().ToString(),
|
|
|
taskCode = item.TaskCode
|
|
|
};
|
|
|
|
|
|
string reponse = HttpHelper.SendPostMessage(agvEquip.ServerIp, agvEquip.ServerPort, "rcms/services/rest/hikRpcService/cancelTask", cancelTask.ToJsonString());
|
|
|
var result = JsonConvert.DeserializeObject<ReponseMessage>(reponse);
|
|
|
if (result != null && result.code == "0")
|
|
|
{
|
|
|
#region 解锁起点库位与终点库位
|
|
|
//根据任务类型,如果是大料箱,解锁wmsbaseLocation
|
|
|
List<int> bigType = new List<int>() { 1, 3, 8, 10 };
|
|
|
if (bigType.Contains(item.TaskType))
|
|
|
{
|
|
|
List<WmsBaseLocation>? wmsBaseLocations = SqlSugarClient.Ado.Context.CopyNew().Queryable<WmsBaseLocation>().Where(x => x.LocationCode == item.CurrPointNo || x.LocationCode == item.EndPointNo).ToList();
|
|
|
if (wmsBaseLocations != null && wmsBaseLocations.Count > 0)
|
|
|
{
|
|
|
wmsBaseLocations.ForEach(x => x.LocationStatus = 0);
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Updateable(wmsBaseLocations).ExecuteCommand();
|
|
|
}
|
|
|
}
|
|
|
else //如果是小料箱,解锁wcsbaseEquip
|
|
|
{
|
|
|
List<WcsBaseEquip> equips = SqlSugarClient.Ado.Context.CopyNew().Queryable<WcsBaseEquip>().Where(x => x.AgvPositionCode == item.CurrPointNo || x.AgvPositionCode == item.EndPointNo).ToList();
|
|
|
if (equips != null && equips.Count > 0)
|
|
|
{
|
|
|
equips.ForEach(x => x.EquipStatus = 0);
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Updateable(equips).ExecuteCommand();
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Deleteable<WcsTask>(item).ExecuteCommand();
|
|
|
_logger.Agv($"任务id:{item.Id},任务名:{item.TaskName}已删除");
|
|
|
|
|
|
//
|
|
|
if (!string.IsNullOrEmpty(item.NextPointNo) && item.TaskStatus >= 2 && item.IsDelete == 2) //有执行任务的agv编号,并且需要去异常库位
|
|
|
{
|
|
|
WmsBaseLocation? endLocation = SqlSugarClient.Ado.Context.CopyNew().Queryable<WmsBaseLocation>().First(x => x.LocationCode == "3066" && x.LocationStatus == 0 && string.IsNullOrEmpty(x.ContainerCode));
|
|
|
if (endLocation != null)
|
|
|
{
|
|
|
WcsTask task = new WcsTask();
|
|
|
task.TaskType = StaticTaskType.ExceptionTask;
|
|
|
task.CurrPointNo = "ExceptionStart";
|
|
|
task.NextPointNo = item.NextPointNo; //指定agv
|
|
|
task.EndPointNo = endLocation.AgvPositionCode;
|
|
|
task.TaskStatus = 0;
|
|
|
task.CreatedTime = DateTime.Now;
|
|
|
task.CreatedBy = "wcs";
|
|
|
task.TaskName = "前往异常库位移库任务";
|
|
|
task.PalletInfoCode = item.PalletInfoCode;
|
|
|
sqlClient.AsTenant().BeginTran();
|
|
|
try
|
|
|
{
|
|
|
int id = SqlSugarClient.Ado.Context.CopyNew().Insertable(task).ExecuteReturnIdentity();
|
|
|
WcsTaskLog wcsTaskLog = CoreMapper.Map<WcsTaskLog>(task);
|
|
|
wcsTaskLog.Id = id;
|
|
|
//锁定库位
|
|
|
endLocation.LocationStatus = 1;
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Updateable(endLocation).ExecuteCommand();
|
|
|
SqlSugarClient.Ado.Context.CopyNew().Insertable(wcsTaskLog).ExecuteCommand();
|
|
|
sqlClient.AsTenant().CommitTran();
|
|
|
_logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}");
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Error($"生成移库任务提交事务异常:{ex.Message}");
|
|
|
sqlClient.AsTenant().RollbackTran();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
_logger.Error("想要创建异常库位任务,但是异常库位不可用或已经有托盘");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
_logger.Error($"任务id:{item.Id},任务名:{item.TaskName}删除失败,agv接口回复:{result.message}");
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
sqlClient.Deleteable<WcsTask>(item).ExecuteCommand();
|
|
|
_logger.Agv($"任务id:{item.Id},任务名:{item.TaskName}已删除");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
_logger.Error($"任务删除异常:{ex.Message}");
|
|
|
}
|
|
|
Thread.Sleep(2000);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
#endregion 删除任务 -- 已经下发的任务,需要通知agv
|
|
|
|
|
|
#region 定时删除日志处理
|
|
|
|
|
|
/// <summary>
|
|
|
/// 定时器触发的事件处理方法
|
|
|
/// </summary>
|
|
|
/// <param name="source"></param>
|
|
|
/// <param name="e"></param>
|
|
|
private void OnTimedEvent(Object source, ElapsedEventArgs e)
|
|
|
{
|
|
|
DeleteLogsLogic();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 清除日志文件
|
|
|
/// </summary>
|
|
|
private void DeleteLogsLogic()
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
// 获取当前程序运行目录下的 Log 文件夹
|
|
|
string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
|
|
|
|
|
// 检查 Log 文件夹是否存在
|
|
|
if (!Directory.Exists(logPath))
|
|
|
{
|
|
|
// 如果 Log 文件夹不存在,可以选择记录日志或者直接返回
|
|
|
Console.WriteLine($"Log 文件夹 {logPath} 不存在。");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 获取 Log 文件夹下的所有子文件夹
|
|
|
string[] logDirectories = Directory.GetDirectories(logPath);
|
|
|
|
|
|
foreach (string directoryPath in logDirectories)
|
|
|
{
|
|
|
string directoryName = Path.GetFileName(directoryPath);
|
|
|
if (!string.IsNullOrEmpty(directoryName) && DateTime.TryParse(directoryName, out DateTime directoryDate))
|
|
|
{
|
|
|
// 检查文件夹日期是否早于当前日期三天之前
|
|
|
if (directoryDate < DateTime.Now.AddDays(-3))
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
// 删除符合条件的文件夹
|
|
|
Directory.Delete(directoryPath, true);
|
|
|
Console.WriteLine($"已删除文件夹: {directoryPath}");
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
// 记录删除文件夹时的异常信息
|
|
|
Console.WriteLine($"删除文件夹 {directoryPath} 时出错: {ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
// 记录整体操作的异常信息
|
|
|
Console.WriteLine($"执行删除日志逻辑时出错: {ex.Message}");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 定时plc发送心跳脉冲
|
|
|
private bool heartFlag = true;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 定时器触发的事件处理方法
|
|
|
/// </summary>
|
|
|
/// <param name="source"></param>
|
|
|
/// <param name="e"></param>
|
|
|
private void OnTimedPlcHeartEvent(Object source, ElapsedEventArgs e)
|
|
|
{
|
|
|
// 检查方法是否正在执行
|
|
|
if (isExecuting)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try
|
|
|
{
|
|
|
// 设置标志位为 true,表示方法正在执行
|
|
|
isExecuting = true;
|
|
|
|
|
|
PlcAbsractFactory? plc3 = plcList.FirstOrDefault(x => x.ConfigKey == "workShop3Plc");
|
|
|
PlcAbsractFactory? plc2 = plcList.FirstOrDefault(x => x.ConfigKey == "workShop2Plc");
|
|
|
if (plc3 != null && plc3.IsConnected)
|
|
|
{
|
|
|
plc3.writeBoolByAddress("DB100.DBX84.0", heartFlag);
|
|
|
heartFlag = !heartFlag;
|
|
|
}
|
|
|
if (plc2 != null && plc2.IsConnected)
|
|
|
{
|
|
|
plc2.writeBoolByAddress("DB100.DBX24.0", heartFlag);
|
|
|
heartFlag = !heartFlag;
|
|
|
}
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
isExecuting = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
} |