using Aucma.Scada.Model.domain; using HighWayIot.Config; using HighWayIot.Log4net; using HighWayIot.Plc; using HighWayIot.Repository.service; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace Aucma.Scada.Business { /// /// 入库任务处理 /// internal sealed class InStoreTaskHandle { #region 单例实现 private static readonly Lazy lazy = new Lazy(() => new InStoreTaskHandle()); public static InStoreTaskHandle Instance { get { return lazy.Value; } } #endregion #region 对象引用 private LogHelper logHelper = LogHelper.Instance; private AppConfig appConfig = AppConfig.Instance; private PlcConfig plcConfig = PlcConfig.Instance; private PlcPool _pool = PlcPool.Instance; private PlcSpaceConfig spaceConfig = PlcSpaceConfig.Instance; private RegisterServices registerServices = RegisterServices.Instance; /// /// 实时任务 /// private IRealTaskInfoService _taskInfoService; #endregion #region 私有变量 private Dictionary _plcDictionary = new Dictionary(); /// /// 泡后任务编号,PLC反馈后进行赋值 /// private string foamTaskCode = string.Empty; #endregion #region 委托事件 /// /// 入库应答,PLC收到下发的入库任务后进行应答 /// /// /// public delegate void InStoreAnswer(string storeCode, string taskCode); public event InStoreAnswer InStoreAnswerEvent; /// /// 入库完成 /// /// public delegate void InStoreFinsih(string taskCode); public event InStoreFinsih InStoreFinsihEvent; #endregion private InStoreTaskHandle() { _taskInfoService = registerServices.GetService(); _plcDictionary = _pool.GetAll(); List taskList = _taskInfoService.GetTaskInfosForInstore(appConfig.foamStoreCode, appConfig.instoreTaskType, 2); RealReadFinish(); } #region 判断入库是否完成 /// /// 实时读取入库完成信号 /// private void RealReadFinish() { Task.Run(() => { Thread.Sleep(2000); while (true) { if (_plcDictionary.Count > 0) { IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; if (_plc != null && _plc.IsConnected) { List taskList = _taskInfoService.GetTaskInfosForInstore(appConfig.foamStoreCode, appConfig.instoreTaskType, 2); if (taskList != null && taskList.Count > 0) { foreach (RealTaskInfo taskInfo in taskList) { SpaceAddress spaceAddress = spaceConfig.GetSpaceAddress(appConfig.foamStoreCode, taskInfo.spaceCode); JudgeIsFinish(taskInfo, _plc, spaceAddress); } } } else { logHelper.Info($"PLC信息为空或连接失败,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息"); } } Thread.Sleep(1000); }; }); } /// /// 判断该任务对应的货道是否有完成信号 /// /// /// public void JudgeIsFinish(RealTaskInfo taskInfo,IPlc _plc,SpaceAddress spaceAddress) { //读取入库完成反馈信号 if (_plc.readInt32ByAddress(spaceAddress.inStoreFinish) == 1) { _plc.writeInt32ByAddress(spaceAddress.inStoreFinish, 0); InStoreFinsihEvent(taskInfo.taskCode); } } #endregion #region 泡后入库任务下发处理 public int SendFoamTask_InStore(RealTaskInfo taskInfo) { int result = 0; try { IPlc _plc = _plcDictionary[taskInfo.storeCode]; if (_plc != null) { if (_plc.IsConnected) { if (_plc.readInt32ByAddress(plcConfig.in_foam_answer) == 1) { logHelper.Info("泡后入库应答字为1,货道号:" + plcConfig.in_foam_spaceCode + ";写" + short.Parse(taskInfo.spaceCode.Substring(5, 1))); //写入货道号 _plc.writeInt32ByAddress(plcConfig.in_foam_spaceCode, short.Parse(taskInfo.spaceCode.Substring(5, 1))); //写入应答字 // _plc.writeInt32ByAddress(plcConfig.in_foam_answer, 1); //写入任务号 // _plc.writeStringByAddress(plcConfig.in_foam_task, taskInfo.taskCode); //写入完成后读取应答字进行复位 ReadAnswer_InStore(taskInfo); result = 1; } else { result = 2; logHelper.Info("应答字为2,下发新任务plc未就绪"); } } else { logHelper.Info($"仓库{taskInfo.storeCode};PLC未连接"); } } else { logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息"); } } catch (Exception ex) { logHelper.Error("泡后入库任务下发异常", ex); } return result; } /// /// 读取泡后入库应答 /// private void ReadAnswer_InStore(RealTaskInfo taskInfo) { lock (string.Empty) { bool isFlag = true; IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; try { Task.Run(() => { if (_plc != null) { if (_plc.IsConnected) { do { //读取PLC应答字为2时,上位机清空写入的入库内容 if (_plc.readInt32ByAddress(plcConfig.in_foam_answer) == 2) { logHelper.PlcLog("入库应答字为2,货道号:" + plcConfig.in_foam_spaceCode + ";复位写0"); //写入货道号 _plc.writeInt32ByAddress(plcConfig.in_foam_spaceCode, 0); //写入应答字 // _plc.writeInt32ByAddress(plcConfig.in_foam_answer, 0); isFlag = false; InStoreAnswerEvent?.Invoke(appConfig.foamStoreCode, taskInfo.taskCode); } Thread.Sleep(500); } while (isFlag); } else { logHelper.Info($"仓库{appConfig.foamStoreCode};PLC未连接"); } } else { logHelper.Info($"PLC信息为空,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息"); } }); } catch (Exception ex) { logHelper.Error("读取泡后入库应答字异常", ex); } } } #endregion /// /// 通过PLC获取货道信息 /// /// /// public BaseSpaceInfo ReadSpaceInfoByPlc(BaseSpaceInfo spaceInfo) { var spaceAddress = spaceConfig.GetSpaceAddress(spaceInfo.storeCode, spaceInfo.spaceCode); IPlc _plc = _plcDictionary[spaceInfo.storeCode]; if (_plc != null) { if (_plc.IsConnected) { spaceInfo.spaceStock = _plc.readInt32ByAddress(spaceAddress.onStore); spaceInfo.onRouteAmount = _plc.readInt32ByAddress(spaceAddress.onRoute); // spaceInfo.spaceStatus = _plc.readInt32ByAddress(spaceAddress.spaceStatus); } } return spaceInfo; } #region 2023-01-04delete 入库逻辑修改,删除引用方法 /// /// 读取泡后入库完成 /// //private void ReadShellFinish_InStore(string taskCode) //{ // lock (string.Empty) // { // bool isFlag = true; // IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; // foamTaskCode = taskCode; // try // { // Task.Run(() => // { // if (_plc != null) // { // if (_plc.IsConnected) // { // do // { // //读取PLC入库任务完成 // if (_plc.readInt32ByAddress(plcConfig.in_foam_finish) == 1) // { // _plc.writeInt32ByAddress(plcConfig.in_foam_finish, 0); // //string taskCode = _plc.readStringByAddress(plcConfig.out_foam_task, 10); // InStoreFinsihEvent?.Invoke(taskCode); // isFlag = false; // } // Thread.Sleep(1000); // } while (isFlag); // } // else // { // logHelper.Info($"仓库{appConfig.foamStoreCode};PLC未连接"); // } // } // else // { // logHelper.Info($"PLC信息为空,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息"); // } // }); // } // catch (Exception ex) // { // logHelper.Error("读取泡后入库完成异常", ex); // } // } //} #endregion } }