public void NotifyOpcJobFinished(string panelNo, string tolocation, string reallocation, bool panelfull)
        {
            try {
                var pState = panelfull ? PanelState.Full : PanelState.HalfFull;
                switch (pState)
                {
                case PanelState.HalfFull:
                    var lcode = FrmMain.taskQ.UFGetPanelLastRoll(tolocation, panelNo);
                    LableCode.UserSetPanelLastRoll(lcode);    //设置板最后一卷布。

                    log($"{reallocation} 半板信号发出,最后一卷布标签{lcode}。slot: {param.BAreaFloorFinish[reallocation]}", LogType.ROBOT_STACK);
                    client.TryWrite(param.BAreaFloorFinish[reallocation], true);
                    break;

                case PanelState.Full:
                    string msg;
                    ErpHelper.NotifyPanelEnd(erpapi, panelNo, reallocation, out msg);
                    log(msg, LogType.ROBOT_STACK);

                    LableCode.SetPanelFinished(panelNo);

                    // 满板时设置自由板位标志。
                    lock (TaskQueues.LOCK_LOCHELPER) {
                        TaskQueues.lochelper.OnFull(reallocation);
                    }

                    lock (client) {
                        PlcHelper.NotifyFullPanel(client, param, reallocation);
                    }

                    break;

                case PanelState.LessHalf:
                    break;

                default:
                    log($"!板状态不明,不发信号, {pState}", LogType.ROBOT_STACK);
                    break;
                }
            } catch (Exception ex) {
                log($"!来源: {nameof(NotifyOpcJobFinished)}, {ex}", LogType.ROBOT_STACK);
            }
        }
        public void NotifyOpcJobFinished(RollPosition roll)
        {
            try {
                switch (roll.PnlState)
                {
                case PanelState.HalfFull:
                    lock (client) {
                        client.TryWrite(param.BAreaFloorFinish[roll.RealLocation], true);
                    }
                    log($"{roll.RealLocation}: 半板信号发出。slot: {param.BAreaFloorFinish[roll.RealLocation]}", LogType.ROBOT_STACK);
                    break;

                case PanelState.Full:
                    string msg;
                    ErpHelper.NotifyPanelEnd(erpapi, roll.PanelNo, roll.RealLocation, out msg);
                    log(msg, LogType.ROBOT_STACK);

                    LableCode.SetPanelFinished(roll.PanelNo);

                    lock (TaskQueues.LOCK_LOCHELPER) {
                        TaskQueues.lochelper.OnFull(roll.RealLocation);
                    }

                    lock (client) {
                        PlcHelper.NotifyFullPanel(client, param, roll.RealLocation);
                    }

                    break;

                case PanelState.LessHalf:
                    break;

                default:
                    log($"!板状态不明,不发信号, {roll.PnlState}", LogType.ROBOT_STACK);
                    break;
                }

                if (roll.Status == (int)LableState.FloorLastRoll && roll.PnlState != PanelState.Full)
                {
                    BadShape(roll);
                }

                var panel = LableCode.GetPanel(roll.PanelNo);
                if (roll.Status == (int)LableState.FloorLastRoll && roll.PnlState != PanelState.Full && roll.Floor == panel.MaxFloor)
                {
                    log("!---异常板满状态处理---", LogType.ROBOT_STACK);
                    roll.PnlState = PanelState.Full;
                    string msg;
                    ErpHelper.NotifyPanelEnd(erpapi, roll.PanelNo, roll.RealLocation, out msg);
                    client.TryWrite(param.BAreaPanelFinish[roll.RealLocation], true);

                    log($"{roll.RealLocation}: 异常满板信号发出。slot: {param.BAreaPanelFinish[roll.RealLocation]}", LogType.ROBOT_STACK);
                    log(msg, LogType.ROBOT_STACK);

                    LableCode.SetPanelFinished(roll.PanelNo);

                    lock (TaskQueues.LOCK_LOCHELPER) {
                        TaskQueues.lochelper.OnFull(roll.RealLocation);
                    }

                    const int SIGNAL_3 = 3;
                    client.TryWrite(param.BAreaPanelState[roll.RealLocation], SIGNAL_3);
                    log($"{roll.RealLocation}: 异常板状态信号发出,状态值: {SIGNAL_3}。slot: {param.BAreaPanelState[roll.RealLocation]}", LogType.ROBOT_STACK);
                }
            } catch (Exception ex) {
                log($"!来源: {nameof(NotifyOpcJobFinished)}, {ex}", LogType.ROBOT_STACK);
            }
        }