/// <summary> /// 处理队列 /// </summary> private void dealTelegramQueue() { while (isStart) { try { int nActionFlag = 0; CRequestAction requestAction = new CRequestAction(); requestAction.structTelegram = m_struTelegram; requestAction.PLCServer = m_commModule; requestAction.DicSound = m_dicSound; m_taskTrigger.DealTeleQueueInfo(ref nActionFlag, ref requestAction, m_nPLCID); requestAction.RequestAction(nActionFlag, m_sendTelegramAction, m_modifyDBAction, m_soundAction); Thread.Sleep(1000); } catch (Exception ex) { CWException.WriteError("WorkFlowLib.dealTelegramQueue 异常 " + ex.ToString()); Thread.Sleep(5000); } } }
/// <summary> /// 报文下发 /// </summary> /// <param name="objRequestParam"></param> public void TelegramSender(object objRequestParam) { try { CRequestAction RequestParam = (CRequestAction)objRequestParam; m_PLCServer = RequestParam.PLCServer; // 发送报文 foreach (struTelegram struSendTelegram in RequestParam.lstTelegram) { CWException.WriteLog(string.Format("Telegram ({0},{1}) will send ,devicecode:{2},iccode:{3}", struSendTelegram.nTelegramType, struSendTelegram.nSubTypeEMS, struSendTelegram.nEquipID, struSendTelegram.strICCardID), 4); Int16[] objTelegram; m_telegramParser.PackTelegram(out objTelegram, struSendTelegram); int warehouse = struSendTelegram.nEMSSendFlag; int equipID = struSendTelegram.nEquipID; //存在该位(nDeviceByteBit),表示在下发时要判断设备是否允许下发报文否,如果不存在该位,则可以直接下发当前报文 if (0 != struSendTelegram.nDeviceByteBit) { #region CDeviceStatusDto smg = CCommonMethods.myMethods.GetDeviceStatus(warehouse, equipID); #region if (smg == null) { //如果不存在设备号,则表示异常,先加入队列 CWException.WriteLog(string.Format("报文({0},{1})没有设备号,其卡号:{2}", struSendTelegram.nTelegramType, struSendTelegram.nSubTypeEMS, struSendTelegram.strICCardID), 4); //加入队列 InsertWorkQueue(objTelegram, struSendTelegram); continue; } #endregion if (smg.devicetype == (int)EnmSMGType.Hall) { #region 允许下发或加入队列 if (smg.devicemode == (int)EnmModel.Automatic && smg.isable == 1 && smg.isavailable == 1 && smg.tasktype == (int)EnmTaskType.Init) { smg.tasktype = struSendTelegram.nMasterType; smg.iccode = struSendTelegram.strICCardID; smg.prevnode = null; smg.currentnode = null; smg.scrloc = struSendTelegram.strSrcLocAddr; smg.desccloc = struSendTelegram.strDestLocAddr; new CDBEditor().updateTableDto(smg); //下发报文 DealSendTelegram(objTelegram, warehouse); } else { //加入队列 InsertWorkQueue(objTelegram, struSendTelegram); } #endregion } else if (smg.devicetype == (int)EnmSMGType.ETV) { #region 将(14,1)加入队列 if (struSendTelegram.nTelegramType == 14 && struSendTelegram.nSubTypeEMS == 1) { CWException.WriteLog(string.Format("warehouse:{0}, devicecode:{1} has telegram (14,1) add workqueue! ", smg.warehouse, smg.devicecode), 4); InsertWorkQueue(objTelegram, struSendTelegram); continue; } #endregion #region 判断避让, 执行(13,1)(11,1) if (smg.devicemode == (int)EnmModel.Automatic && smg.isable == 1 && smg.isavailable == 1 && smg.tasktype == (int)EnmTaskType.Init) { string toAddrss = ""; if (struSendTelegram.nTelegramType == 11 && struSendTelegram.nSubTypeEMS == 1) { toAddrss = struSendTelegram.strDestLocAddr; } else { toAddrss = struSendTelegram.strSrcLocAddr; } if (this.DealAvoid(smg, toAddrss, struSendTelegram.strICCardID)) { //允许下发,绑定设备,下发报文 smg.tasktype = struSendTelegram.nMasterType; smg.iccode = struSendTelegram.strICCardID; smg.prevnode = null; smg.currentnode = null; if (struSendTelegram.nMasterType != (int)EnmTaskType.MoveEquipTask) { smg.currentnode = (int)EnmFlowNodeDescp.Load; } smg.scrloc = struSendTelegram.strSrcLocAddr; smg.desccloc = struSendTelegram.strDestLocAddr; new CDBEditor().updateTableDto(smg); //下发报文 DealSendTelegram(objTelegram, warehouse); continue; } } //加入队列 InsertWorkQueue(objTelegram, struSendTelegram); #endregion } continue; #endregion } // 发送报文 DealSendTelegram(objTelegram, warehouse); } } catch (Exception ex) { CLOGException.Trace("AbstractActionLib.CTelegramSender.TelegramSender 异常", CBaseMethods.MyBase.GetExceptionInfo(ex)); } }
/// <summary> /// 装载、卸载、移动下发时,避让处理 /// </summary> /// <param name="smg"></param> /// <param name="toAddrs"></param> /// <returns></returns> public bool DealAvoid(CDeviceStatusDto smg, string toAddrs, string iccode) { List <CDeviceStatusDto> Etvs = CCommonMethods.myMethods.GetEtvsByLayer((int)smg.warehouse, (int)smg.devicelayer); int nWarehouse = smg.warehouse; int curEtvCol = CBaseMethods.MyBase.GetColumnByAddrs(smg.deviceaddr); int curToCol = CBaseMethods.MyBase.GetColumnByAddrs(toAddrs); //终点列 int curMax; int curMin; #region if (curEtvCol > curToCol) { curMax = curEtvCol; curMin = curToCol - 3; if (curMin < 1) { curMin = 1; } } else { curMax = curToCol + 3; if (curMax > 40) { curMax = 40; } curMin = curEtvCol; } #endregion //对面ETV CDeviceStatusDto otherEtv = null; #region foreach (CDeviceStatusDto et in Etvs) { if (et.devicecode != smg.devicecode) { otherEtv = et; break; } } #endregion if (otherEtv == null) { return(false); } int otherCol = CBaseMethods.MyBase.GetColumnByAddrs(otherEtv.deviceaddr); #region 列数与实际不合的,先不让其去执行 bool isTrue = true; if (smg.devicecode < otherEtv.devicecode) { if (curEtvCol < otherCol) { isTrue = false; } } else { if (curEtvCol > otherCol) { isTrue = false; } } if (!isTrue) { string msg = String.Format("异常: ETV{0} 当前列{1},ETV{2} 当前列{3}", smg.devicecode, curEtvCol, otherEtv.devicecode, otherCol); CWException.WriteLog(msg, 4); return(false); } #endregion if (otherEtv.tasktype == (int)EnmTaskType.Init) { #region if (curMin < otherCol && otherCol < curMax) { if (otherEtv.isable == 0) { return(false); } #region 生成移动并下发 string oLayer = Convert.ToString(otherEtv.devicelayer).PadLeft(2, '0'); string oList = ""; if (curEtvCol > curToCol) //需向左避让 { oList = curMin.ToString().PadLeft(2, '0'); } else { oList = curMax.ToString().PadLeft(2, '0'); } string toAddress = string.Concat("1", oList, oLayer); //建立移动作业 struTelegram moveTask = new struTelegram(); moveTask.nEMSSendFlag = nWarehouse; moveTask.nPLCSendFlag = 0; moveTask.nTelegramType = 11; moveTask.nSubTypeEMS = 1; moveTask.nSubTypePLC = 0; moveTask.nEquipID = otherEtv.devicecode; if (!CBaseMethods.MyBase.IsEmpty(iccode)) { moveTask.strICCardID = iccode; } moveTask.strSrcLocAddr = otherEtv.deviceaddr; moveTask.strDestLocAddr = toAddress; moveTask.nTelegramID = new CRequestAction().MessageID; moveTask.nEndFlag = 9999; moveTask.nMasterType = (int)EnmTaskType.AvoidMove; //打包并发送报文 Int16[] movTelegram; m_telegramParser.PackTelegram(out movTelegram, moveTask); if (otherEtv.isavailable == 1) { otherEtv.tasktype = (int)EnmTaskType.AvoidMove; otherEtv.iccode = iccode; otherEtv.prevnode = null; otherEtv.currentnode = null; otherEtv.scrloc = otherEtv.deviceaddr; otherEtv.desccloc = toAddress; //更新数据 new CDBEditor().updateTableDto(otherEtv); DealSendTelegram(movTelegram, nWarehouse); } else { //加入队列 InsertWorkQueue(movTelegram, moveTask); } #endregion } return(true); #endregion } else //对面的TV在作业, { #region 对面的TV有作业,则如果有交叉的,当前先不下发,让其先执行完其作业 string oToAddrs = ""; #region if (otherEtv.currentnode == (int)EnmFlowNodeDescp.Load) { oToAddrs = otherEtv.scrloc; } else { oToAddrs = otherEtv.desccloc; } if (CBaseMethods.MyBase.IsEmpty(oToAddrs)) { CWException.WriteLog(string.Format("另一TV{0},作业类型:{1},卡号:{2},判断避让时其源/目的地址为空", otherEtv.devicecode, otherEtv.tasktype, otherEtv.iccode == null ? "" : otherEtv.iccode), 4); return(true); } #endregion int toColumn = CBaseMethods.MyBase.GetColumnByAddrs(oToAddrs); #region 处于等待卸载时,如果路径出现冲突,也可进行避让作业 if (smg.tasktype != (int)EnmTaskType.Init) //要下发(14,1)时处理 { if (smg.currentnode == (int)EnmFlowNodeDescp.WillUnLoad && otherEtv.currentnode == (int)EnmFlowNodeDescp.WillUnLoad) { //优先1#下发 if (smg.region == 2) { return(false); } } if (otherEtv.currentnode == (int)EnmFlowNodeDescp.WillUnLoad) { if (curMin < otherCol && otherCol < curMax) { if (otherEtv.isavailable == 0) { return(false); } #region 生成移动并下发,直接下发 string oLayer = Convert.ToString(otherEtv.devicelayer).PadLeft(2, '0'); string oList = ""; if (curEtvCol > curToCol) //需向左避让 { oList = curMin.ToString().PadLeft(2, '0'); } else { oList = curMax.ToString().PadLeft(2, '0'); } string toAddress = string.Concat("1", oList, oLayer); //建立移动作业 struTelegram moveTask = new struTelegram(); moveTask.nEMSSendFlag = nWarehouse; moveTask.nPLCSendFlag = 0; moveTask.nTelegramType = 11; moveTask.nSubTypeEMS = 1; moveTask.nSubTypePLC = 0; //给假值 moveTask.strCarSize = "123"; moveTask.nWheelbase = 2600; moveTask.overallLg = 4500; moveTask.overHang = 900; moveTask.nEquipID = otherEtv.devicecode; if (!CBaseMethods.MyBase.IsEmpty(iccode)) { moveTask.strICCardID = iccode; } moveTask.strSrcLocAddr = otherEtv.deviceaddr; moveTask.strDestLocAddr = toAddress; moveTask.nTelegramID = new CRequestAction().MessageID; moveTask.nEndFlag = 9999; moveTask.nMasterType = (int)EnmTaskType.ForceMove; //打包并发送报文 Int16[] movTelegram; m_telegramParser.PackTelegram(out movTelegram, moveTask); //下发移动避让作业 DealSendTelegram(movTelegram, nWarehouse); //更改其TV的可用性 otherEtv.isavailable = 0; new CDBEditor().updateTableDto(otherEtv); #endregion } return(true); } } #endregion #region 如果当前TV还没有进行动作,则这里就限制其下发 if (otherCol >= curMin && otherCol <= curMax) { return(false); } if (toColumn >= curMin && toColumn <= curMax) { return(false); } if (otherCol > curMax) { if (toColumn < curMax) { return(false); } } if (toColumn > curMax) { if (toColumn < curMax) { return(false); } } if (otherCol < curMin) { if (toColumn > curMin) { return(false); } } if (toColumn < curMin) { if (otherCol > curMin) { return(false); } } #endregion #endregion } return(true); }
/// <summary> /// 发送报文并判断是否重发,如果重发次数不超过m_retryCount /// </summary> /// <param name="data"></param> /// <param name="wareHouse"></param> private bool DealSendTelegram(object data, int wareHouse) { if (null == m_PLCServer) { CWException.WriteLog("报文发送时,m_PLCServer为空", 4); return(false); } if (data.GetType() == typeof(short[])) { short[] mydt = (short[])data; if (mydt[6] == 0 || mydt[2] == 0 || mydt[3] == 0) { CWException.WriteLog(data, 1); return(true); } } int count = m_retryCount;//重发次数 bool bSendResult = false; bool bACKResult = false; while (0 < count--) { bSendResult = SendData(data, wareHouse); if (bSendResult) { m_PLCServer.AckAllowClear = false; int nMillisecond = 0; while (nMillisecond < 3000) { short recvBuffer = 0; bool isOK = m_PLCServer.Read(ref recvBuffer, 1); if (isOK) { if (recvBuffer == 9999) { Int16[] ackTelegram = null; m_PLCServer.Read(ref ackTelegram, 0);// 读取PLC回应ACK报文 bACKResult = CBaseMethods.MyBase.IsPLCAck((Int16[])data, ackTelegram); if (bACKResult) { //更新PLC发送缓冲区标志位为0 if (!m_PLCServer.Write(0, 1)) { ThreadPool.QueueUserWorkItem(new WaitCallback(ReWritePLCFlag)); } //接收报文ack成功 CCommonMethods.myMethods.InsertTelegramLog(ackTelegram, 0); break; } } } Thread.Sleep(50);//4000 nMillisecond += 50; } if (bACKResult) { break; } //重发时更改MessageID if (data.GetType() == typeof(short[])) { short[] mydt = (short[])data; mydt[48] = (short)new CRequestAction().MessageID; } } } m_PLCServer.AckAllowClear = true; if (!bSendResult) { CWException.WriteLog("以下报文发送不成功,SendResult:" + bSendResult.ToString() + " bAckResult:" + bACKResult.ToString(), 4); CWException.WriteLog(data, 1); short[] msg = (short[])data; string strWaitTelegram = m_telegramParser.Int16sToString(msg, 0, msg.Length - 1, 4); //加入队列,将其作业类型改为RetrySend CWorkQueueDto workQueueDto = new CWorkQueueDto { devicecode = msg[6], warehouse = wareHouse, iccode = msg[11].ToString().PadLeft(4, '0'), waitsendtelegram = strWaitTelegram, tasktype = (int)EnmTaskType.RetrySend }; CWorkQueueDto exitQueue = CCommonMethods.myMethods.GetSendTelegramInfo(wareHouse, (int)workQueueDto.devicecode, strWaitTelegram); if (exitQueue == null) { new CDBEditor().insertTableDto(workQueueDto); } } return(bSendResult); }