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.Linq; using System.Threading; using System.Threading.Tasks; namespace Aucma.Scada.Business { /// /// 出库任务处理 /// internal sealed class OutStoreTaskHandle { #region 单例实现 private static readonly Lazy lazy = new Lazy(() => new OutStoreTaskHandle()); public static OutStoreTaskHandle Instance { get { return lazy.Value; } } #endregion #region 对象引用 /// /// PLC应答 /// /// /// public delegate void OutStoreAnswer(string storeCode, string taskCode); public event OutStoreAnswer OutStoreAnswerEvent; 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 私有变量 /// /// 字典存放PLC连接 /// private static Dictionary _plcDictionary = new Dictionary(); #endregion #region 委托事件 /// /// 出库完成 /// /// /// public delegate void OutStoreFinsih(string storeCode, string taskCode); public event OutStoreFinsih OutStoreFinsihEvent; #endregion private OutStoreTaskHandle() { _plcDictionary = _pool.GetAll(); _taskInfoService = registerServices.GetService(); // RealReadFinish(); } #region 出库完成 /// /// 实时读取出库完成信号 /// private void RealReadFinish() { Task.Run(() => { Thread.Sleep(2000); while (true) { RealTaskInfo task = GetTaskInfoByTaskStatus(appConfig.foamStoreCode).OrderBy(x => x.createTime).FirstOrDefault(); if (task != null) { _plcDictionary = _pool.GetAll(); if (_plcDictionary.Count > 0) { IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; if (_plc != null) { //出库完成 if (_plc.readInt32ByAddress(plcConfig.out_foam_finish) == 1) { _plc.writeInt32ByAddress(plcConfig.out_foam_finish, 0); OutStoreFinsihEvent?.Invoke(appConfig.foamStoreCode, task.taskCode); } } else { logHelper.Info($"PLC信息为空或连接失败,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息"); } } } Thread.Sleep(500); }; }); } /// /// 根据任务状态获取执行中的出库任务 /// /// /// private List GetTaskInfoByTaskStatus(string storeCode, int taskStatus = 2) { List result = null; try { result = _taskInfoService.GetTaskInfosByTaskStatus(new string[] { storeCode }, appConfig.outstoreTaskType, taskStatus); } catch (Exception ex) { logHelper.Error("根据任务状态获取执行中的任务异常", ex); } return result; } #endregion #region 泡后出库任务下发处理 /// /// 泡后出库任务下发 /// /// public int SendFoamTask_OutStore(RealTaskInfo taskInfo) { int result = 0; try { _plcDictionary = _pool.GetAll(); IPlc _plc = _plcDictionary[taskInfo.storeCode]; if (_plc != null) { if (_plc.readInt32ByAddress(plcConfig.out_foam_answer) == 1) { logHelper.Info("泡后出库应答字为1,货道号:" + plcConfig.out_foam_spaceCode + ";写" + short.Parse(taskInfo.spaceCode.Substring(5, 1))); //写入货道号 _plc.writeInt32ByAddress(plcConfig.out_foam_spaceCode, short.Parse(taskInfo.spaceCode.Substring(5, 1))); //写入出库数量 _plc.writeInt32ByAddress(plcConfig.out_foam_amount, taskInfo.planAmount); //写入完成后读取应答字进行复位 ReadAnswer_OutStore(taskInfo); result = 1; } else { result = 2; logHelper.Info("应答字为2,下发新任务plc未就绪"); } } else { logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息"); } } catch (Exception ex) { logHelper.Error("泡后出库任务下发异常", ex); } return result; } /// /// 读取泡后出库应答 /// private void ReadAnswer_OutStore(RealTaskInfo taskInfo) { lock (string.Empty) { bool isFlag = true; _plcDictionary = _pool.GetAll(); IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; try { Task.Run(() => { if (_plc != null) { do { //读取PLC应答字为2时,上位机清空写入的出库内容 if (_plc.readInt32ByAddress(plcConfig.out_foam_answer) == 2) { logHelper.Info("出库应答字写3,应答字为2,货道号:" + plcConfig.out_foam_spaceCode + ";复位写0"); //写入货道号 _plc.writeInt32ByAddress(plcConfig.out_foam_spaceCode, 0); //写入应答字3 _plc.writeInt32ByAddress(plcConfig.out_foam_answer, 3); //写入出库数量 _plc.writeInt32ByAddress(plcConfig.out_foam_amount, 0); isFlag = false; OutStoreAnswerEvent?.Invoke(appConfig.foamStoreCode, taskInfo.taskCode); } Thread.Sleep(500); } while (isFlag); } 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); _plcDictionary = _pool.GetAll(); IPlc _plc = _plcDictionary[spaceInfo.storeCode]; if (_plc != null) { spaceInfo.spaceStock = _plc.readInt32ByAddress(spaceAddress.onStore); spaceInfo.onRouteAmount = _plc.readInt32ByAddress(spaceAddress.onRoute); // spaceInfo.spaceStatus = _plc.readInt32ByAddress(spaceAddress.spaceStatus); } return spaceInfo; } ///// ///// 读取泡后出库完成 ///// //private void ReadFinish_OutStore(RealTaskInfo taskInfo) //{ // lock (string.Empty) // { // bool isFlag = true; // IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; // try // { // if (_plc != null) // { // // do // { // //读取PLC出库任务完成 // if (_plc.readInt32ByAddress(plcConfig.out_foam_finish) == 1) // { // _plc.writeInt32ByAddress(plcConfig.out_foam_finish, 0); // OutStoreFinsihEvent?.Invoke(appConfig.foamStoreCode, taskInfo.taskCode); // isFlag = false; // } // Thread.Sleep(1000); // } while (isFlag); // // } // else // { // logHelper.Info($"PLC信息为空,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息"); // } // } // catch (Exception ex) // { // logHelper.Error("读取箱壳出库出库完成异常", ex); // } // } //} } }