huangxiaoqiang
15 小时以前 eaa7c0d999c6dd7901bf4f0de79b861eae38e978
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob/CommonConveyorLineJob.cs
@@ -76,28 +76,7 @@
                CommonConveyorLine conveyorLine = (CommonConveyorLine)context.JobDetail.JobDataMap.Get("JobParams");
                if (conveyorLine != null)
                {
                    // æŸ¥è¯¢æ‰€æœ‰å­è®¾å¤‡çš„位置
                    List<string> childDeviceCodes = _routerService.QueryAllPositions(conveyorLine.DeviceCode);
                    // èŽ·å–æ‰€æœ‰ç«™ç‚¹ç®¡ç†å™¨
                    List<Dt_StationManager> stationManagers = _stationManagerService.GetAllStationByDeviceCode(conveyorLine.DeviceCode);
                    // å¹¶è¡Œå¤„理每个子设备
                    var tasks = childDeviceCodes.Select(childDeviceCode => ProcessDeviceAsync(conveyorLine, childDeviceCode)).ToList();
                    // å¹¶è¡Œå¤„理每个站点管理器
                    tasks = stationManagers.Select(station => Task.Run(async () =>
                    {
                        ConveyorLineTaskCommand command = ReadCommand(conveyorLine, station.stationChildCode);
                        if (command == null )
                        {
                            return;
                        }
                        IStationHandler handler = StationHandlerFactory.GetHandler(station.stationType, this);
                        await handler.HandleStationAsync(conveyorLine, station, command);
                    })).ToList();
                    await Task.WhenAll(tasks);
                }
            }
            catch (Exception ex)
@@ -106,507 +85,6 @@
                Console.Out.WriteLine(nameof(CommonConveyorLineJob) + ":" + ex.ToString());
            }
            return;
        }
        private Task ProcessDeviceAsync(CommonConveyorLine conveyorLine, string childDeviceCode)
        {
            try
            {
                // è¯»å–任务命令和设备命令
                ConveyorLineTaskCommand command = ReadCommand(conveyorLine, childDeviceCode);
                if (command != null)
                {
                    #region è°ƒç”¨äº‹ä»¶æ€»çº¿é€šçŸ¥å‰ç«¯
                    // èŽ·å–ç¼“å­˜ä¸­çš„ç”¨æˆ·ä¿¡æ¯
                    var tokenInfos = _cacheService.Get<List<UserInfo>>("Cache_UserToken");
                    if (tokenInfos != null && tokenInfos.Any())
                    {
                        userTokenIds = tokenInfos.Select(x => x.Token_ID).ToList();
                        userIds = tokenInfos.Select(x => x.UserId).ToList();
                        // æž„造通知数据
                        object obj = new
                        {
                            command
                        };
                        // å‘送通知
                        _noticeService.LineData(userIds.FirstOrDefault(), userTokenIds, new { conveyorLine.DeviceName, childDeviceCode, data = obj });
                    }
                    #endregion è°ƒç”¨äº‹ä»¶æ€»çº¿é€šçŸ¥å‰ç«¯
                    var structs = BitConverter.GetBytes(command.InteractiveSignal).Reverse().ToArray().ToBoolArray();
                    // èŽ·å–è®¾å¤‡åè®®è¯¦æƒ…
                    List<DeviceProtocolDetailDTO>? deviceProtocolDetails = conveyorLine.DeviceProtocolDetailDTOs.Where(x => x.DeviceProParamName == nameof(ConveyorLineTaskCommand.InteractiveSignal)).ToList();
                    if (deviceProtocolDetails != null)
                    {
                        foreach (var item in deviceProtocolDetails)
                        {
                            int itemValue = item.ProtocalDetailValue.ObjToInt();
                            if (structs[itemValue] == true)
                            {
                                // èŽ·å–å¤„ç†æ–¹æ³•
                                MethodInfo? method = GetType().GetMethod(item.ProtocolDetailType);
                                if (method != null)
                                {
                                    // è°ƒç”¨å¤„理方法
                                    method.Invoke(this, new object[] { conveyorLine, command, childDeviceCode, itemValue });
                                }
                            }
                        }
                    }
               }
            }
            catch (Exception ex)
            {
            }
            return Task.CompletedTask;
        }
        #region å…¥åº“
        /// <summary>
        /// è¾“送线请求入库
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="command">读取的请求信息</param>
        /// <param name="childDeviceCode">子设备编号</param>
        /// <param name="ProtocalDetailValue">线体当前bool读取偏移地址</param>
        public async Task RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue)
        {
            try
            {
                // è¾“出警告信息,表示任务已到达子设备并请求扫码入库
                var log = $"时间:【{DateTime.Now}】【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】请求扫码入库";
                ConsoleHelper.WriteWarningLine(log);
                // å‘送通知
                await _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" });
                WriteInfo(conveyorLine.DeviceName, log);
                // æŸ¥è¯¢æ¡ç å¯¹åº”的任务
                var task = _taskService.QueryBarCodeConveyorLineTask(command.Barcode.ToString(), childDeviceCode);
                if (task != null)
                {
                    // å¦‚果任务类型是出库或出托盘,则处理出库任务
                    if (task.TaskType == (int)TaskOutboundTypeEnum.OutTray || task.TaskType == (int)TaskOutboundTypeEnum.Outbound)
                    {
                        HandleTaskOut(conveyorLine, command, childDeviceCode, ProtocalDetailValue, task);
                    }
                    else
                    {
                        // èŽ·å–ä»»åŠ¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                        var next = task.NextAddress;
                        // å°†ä»»åŠ¡æ˜ å°„ä¸ºå‘½ä»¤
                        var taskCommand = MapTaskCommand(task, command);
                        // æ¢å¤ä»»åŠ¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                        task.NextAddress = next;
                        // å‘送命令到子设备
                        conveyorLine.SendCommand(taskCommand, childDeviceCode);
                        // è¾“出警告信息,表示任务已到达子设备并请求扫码入库,下一目标地址
                        var logs = $"时间:【{DateTime.Now}】【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】请求扫码入库,下一目标地址【{taskCommand.TargetAddress}】";
                        ConsoleHelper.WriteWarningLine(logs);
                        await _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                        WriteInfo(conveyorLine.DeviceName, logs);
                        // å‘送任务完成通知
                        ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                        // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸ºä¸‹ä¸€çŠ¶æ€
                        _taskService.UpdateTaskStatusToNext(task);
                    }
                }
                else
                {
                    // å¦‚果任务为空且条码不为"NoRead"且条码不为空,则处理新任务
                    if (task == null && command.Barcode.ToString() != "NoRead" && command.Barcode.IsNotEmptyOrNull())
                    {
                        // æŸ¥è¯¢æ¡ç å¯¹åº”的任务
                        task = _taskService.QueryBarcodeTask(command.Barcode.ToString(), childDeviceCode);
                        if (task == null)
                            // å¼‚步处理新任务
                            await HandleNewTaskAsync(conveyorLine, command, childDeviceCode, ProtocalDetailValue);
                    }
                }
            }
            catch (Exception ex)
            {
                // æ•获并输出异常信息
                Console.Out.WriteLine(ex.ToString());
            }
        }
        #region è¾“送线请求入库下一地址
        /// <summary>
        /// è¾“送线请求入库下一地址
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="command">读取的请求信息</param>
        /// <param name="childDeviceCode">子设备编号</param>
        public void RequestInNextAddress(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode)
        {
            var log = $"时间:【{DateTime.Now}】【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】请求入库下一地址";
            ConsoleHelper.WriteWarningLine(log);
            _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" });
            WriteInfo(conveyorLine.DeviceName, log);
            Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode, command.Barcode.ToString());
            if (task != null)
            {
                if (command.Barcode.ToString() == task.PalletCode)
                {
                    Dt_Task? newTask = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
                    if (newTask != null)
                    {
                        //ConveyorLineTaskCommand taskCommand = _mapper.Map<ConveyorLineTaskCommand>(newTask);
                        //taskCommand.InteractiveSignal = command.InteractiveSignal;
                        var next = newTask.NextAddress;
                        var taskCommand = MapTaskCommand(newTask, command);
                        newTask.NextAddress = next;
                        var logs = $"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】请求入库下一地址,下一目标地址【{taskCommand.TargetAddress}】";
                        ConsoleHelper.WriteWarningLine(logs);
                        _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                        WriteInfo(conveyorLine.DeviceName, logs);
                        conveyorLine.SendCommand(taskCommand, childDeviceCode);
                        _taskService.UpdateData(newTask);
                    }
                }
            }
        }
        #endregion è¾“送线请求入库下一地址
        /// <summary>
        /// è¾“送线入库完成
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="command">读取的请求信息</param>
        /// <param name="childDeviceCode">子设备编号</param>
        /// <param name="ProtocalDetailValue">线体当前bool读取偏移地址</param>
        public void ConveyorLineInFinish(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue)
        {
            try
            {
                var log = $"时间:【{DateTime.Now}】【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线入库完成";
                ConsoleHelper.WriteWarningLine(log);
                _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" });
                WriteInfo(conveyorLine.DeviceName, log);
                var task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode, command.Barcode.ToString());
                if (task != null && task.TaskState != (int)TaskInStatusEnum.Line_InFinish)
                {
                    if (command.Barcode.ToString() == task.PalletCode && childDeviceCode == task.NextAddress)
                    {
                        if (task.TaskType == (int)TaskInboundTypeEnum.InNG)
                        {
                            int nextStatus = task.TaskState.GetNextNotCompletedStatus<TaskInStatusEnum>();
                            var station = _stationManagerRepository.QueryFirst(x => x.stationChildCode == task.SourceAddress);
                            task.CurrentAddress = station.stationLocation;
                            task.NextAddress = station.stationNGLocation;
                            task.TargetAddress = task.NextAddress;
                            task.TaskState = nextStatus;
                            task.ModifyDate = DateTime.Now;
                            task.Modifier = "System";
                            _taskRepository.UpdateData(task);
                            conveyorLine.SetValue(ConveyorLineDBName.WriteConveyorLineTargetAddress, "1000", childDeviceCode);
                            var logs = $"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线入库完成,下一目标地址【等待分配货位,并写入1000】";
                            ConsoleHelper.WriteWarningLine(logs);
                            _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                            WriteInfo(conveyorLine.DeviceName, logs);
                            ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                        }
                        else
                        {
                            WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                            WriteInfo(conveyorLine.DeviceName, content.ToJsonString());
                            if (!content.Status)
                            {
                                ConsoleHelper.WriteWarningLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线入库完成,任务执行失败{JsonConvert.SerializeObject(content)}");
                                return;
                            }
                            conveyorLine.SetValue(ConveyorLineDBName.WriteConveyorLineTargetAddress, "1000", childDeviceCode);
                            var logs = $"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线入库完成,下一目标地址【等待分配货位,并写入1000】";
                            ConsoleHelper.WriteWarningLine(logs);
                            _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                            WriteInfo(conveyorLine.DeviceName, logs);
                            ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                            Console.Out.WriteLine(content.ToJsonString());
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
        #endregion å…¥åº“
        #region å‡ºåº“
        /// <summary>
        /// è¾“送线请求出信息
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="command">读取的请求信息</param>
        /// <param name="childDeviceCode">子设备编号</param>
        /// <param name="ProtocalDetailValue">线体当前bool读取偏移地址</param>
        public void RequestOutbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue)
        {
            try
            {
                // æŸ¥è¯¢è¾“送线任务,根据输送线设备和子设备代码获取任务信息
                var task = _taskService.QueryConveyorLineTask(conveyorLine.DeviceCode, childDeviceCode);
                // è¾“出成功信息,包括输送线名称、任务号、托盘条码和子设备代码,以及任务信息
                var logs = $"时间:【{DateTime.Now}】【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库,task{task.ToJsonString()}";
                ConsoleHelper.WriteSuccessLine(logs);
                _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                WriteInfo(conveyorLine.DeviceName, logs);
                // å¦‚果任务不为空,则执行以下操作
                if (task != null)
                {
                    // èŽ·å–ä»»åŠ¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                    var next = task.NextAddress;
                    // å°†ä»»åŠ¡å‘½ä»¤æ˜ å°„åˆ°å½“å‰ä»»åŠ¡
                    var taskCommand = MapTaskCommand(task, command);
                    // æ¢å¤ä»»åŠ¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                    task.NextAddress = next;
                    // è¾“出成功信息,包括输送线名称、任务号、托盘条码、子设备代码和下一目标地址
                    var log = $"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库,下一目标地址【{taskCommand.TargetAddress}】";
                    ConsoleHelper.WriteSuccessLine(log);
                    _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" });
                    WriteInfo(conveyorLine.DeviceName, log);
                    // å‘输送线发送命令
                    conveyorLine.SendCommand(taskCommand, childDeviceCode);
                    // å®Œæˆè¾“送线发送任务,并更新任务状态
                    ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                    // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€ä¸ªçŠ¶æ€
                    _taskService.UpdateTaskStatusToNext(task);
                    // å¦‚果任务的目标地址是"1020-1",则再次更新任务状态到下一个状态
                    if (task.TargetAddress == "1020-1"|| task.TargetAddress == "1049-8")
                    {
                        _taskService.UpdateTaskStatusToNext(task);
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
        /// <summary>
        /// è¾“送线请求出库下一地址
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="command">读取的请求信息</param>
        /// <param name="childDeviceCode">子设备编号</param>
        public void RequestOutNextAddress(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue)
        {
            // æ‰“印成功日志,显示当前设备名称、任务号、托盘条码以及请求出库下一地址的子设备代码
            var log = $"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库下一地址";
            ConsoleHelper.WriteSuccessLine(log);
            _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" });
            WriteInfo(conveyorLine.DeviceName, log);
            // æŸ¥è¯¢æ­£åœ¨æ‰§è¡Œçš„输送线任务,根据任务号和子设备代码获取任务信息
            Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode, command.Barcode.ToString());
            // å¦‚果任务存在
            if (task != null)
            {
                // æ£€æŸ¥ä»»åŠ¡ä¸­çš„æ‰˜ç›˜æ¡ç æ˜¯å¦ä¸Žå‘½ä»¤ä¸­çš„æ‰˜ç›˜æ¡ç ä¸€è‡´
                if (command.Barcode.ToString() == task.PalletCode)
                {
                    // æ›´æ–°ä»»åŠ¡çš„ä½ç½®ä¿¡æ¯ï¼Œå¹¶èŽ·å–æ›´æ–°åŽçš„ä»»åŠ¡å¯¹è±¡
                    Dt_Task? newTask = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
                    // å¦‚果更新后的任务对象不为空
                    if (newTask != null)
                    {
                        // èŽ·å–ä¸‹ä¸€ç›®æ ‡åœ°å€
                        var next = newTask.NextAddress;
                        // å°†æ–°ä»»åŠ¡å¯¹è±¡æ˜ å°„ä¸ºä»»åŠ¡å‘½ä»¤å¯¹è±¡
                        var taskCommand = MapTaskCommand(newTask, command);
                        // æ¢å¤æ–°ä»»åŠ¡å¯¹è±¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                        newTask.NextAddress = next;
                        // æ‰“印成功日志,显示当前设备名称、任务号、托盘条码、子设备代码以及下一目标地址
                        var logs = $"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库下一地址,下一目标地址【{taskCommand.TargetAddress}】";
                        ConsoleHelper.WriteSuccessLine(logs);
                        _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                        WriteInfo(conveyorLine.DeviceName, logs);
                        // å‘送任务命令到子设备
                        conveyorLine.SendCommand(taskCommand, childDeviceCode);
                        // æ ‡è®°è¾“送线发送任务完成
                        ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                        _taskService.UpdateData(newTask);
                    }
                }
            }
        }
        /// <summary>
        /// è¾“送线出库完成
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="command">读取的请求信息</param>
        /// <param name="childDeviceCode">子设备编号</param>
        public void ConveyorLineOutFinish(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue)
        {
            try
            {
                // æ‰“印成功信息,表示托盘已到达指定输送线并完成出库
                var logs = $"【{conveyorLine.DeviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线出库完成";
                ConsoleHelper.WriteSuccessLine(logs);
                _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = logs, time = DateTime.Now.ToString("G"), color = "red" });
                WriteInfo(conveyorLine.DeviceName, logs);
                // æŸ¥è¯¢æ­£åœ¨æ‰§è¡Œçš„输送线任务
                var task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode, command.Barcode.ToString());
                // å¦‚果任务存在
                if (task != null)
                {
                    // å¦‚果任务中的托盘条码与命令中的托盘条码一致
                    if (command.Barcode.ToString() == task.PalletCode)
                    {
                        // åˆ›å»ºä¸€ä¸ªç©ºçš„WebResponseContent对象
                        WebResponseContent content = new WebResponseContent();
                        // ä¿å­˜ä»»åŠ¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                        var next = task.NextAddress;
                        // å°†ä»»åŠ¡æ˜ å°„ä¸ºå‘½ä»¤
                        var taskCommand = MapTaskCommand(task, command);
                        // æ¢å¤ä»»åŠ¡çš„ä¸‹ä¸€ç›®æ ‡åœ°å€
                        task.NextAddress = next;
                        // å¦‚果任务的托盘条码与命令中的托盘条码不一致或者任务备注为"NG"
                        if (task.PalletCode != command.Barcode.ToString() || task.Remark == "NG")
                        {
                            // è®¾ç½®å‘½ä»¤çš„目标地址为NG地址
                            taskCommand.TargetAddress = 1;
                        }
                        else
                        {
                            // è®¾ç½®å‘½ä»¤çš„目标地址为1000
                            taskCommand.TargetAddress = 1000;
                        }
                        // æ‰“印成功信息,表示托盘已到达指定输送线并完成出库,下一目标地址已确定
                        var log = $"【{conveyorLine.DeviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线出库完成,下一目标地址【{taskCommand.TargetAddress}】";
                        ConsoleHelper.WriteSuccessLine(log);
                        _noticeService.Logs(userTokenIds, new { conveyorLine.DeviceName, log = log, time = DateTime.Now.ToString("G"), color = "red" });
                        WriteInfo(conveyorLine.DeviceName, log);
                        // å‘送命令到输送线
                        conveyorLine.SendCommand(taskCommand, childDeviceCode);
                        // å®Œæˆè¾“送线发送
                        ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                        // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€ä¸ªçŠ¶æ€
                        content = _taskService.UpdateTaskStatusToNext(task);
                    }
                    else
                    {
                        // å®Œæˆè¾“送线发送
                        ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true);
                        // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€ä¸ªçŠ¶æ€
                        _taskService.UpdateTaskStatusToNext(task);
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
        #endregion å‡ºåº“
        /// <summary>
        /// è¾“送线交互完成
        /// </summary>
        /// <param name="conveyorLine">输送线实例对象</param>
        /// <param name="childDeviceCode">子设备编号</param>
        /// <param name="ProtocalDetailValue">线体当前bool读取偏移地址</param>
        /// <param name="value">值</param>
        public void ConveyorLineSendFinish(CommonConveyorLine conveyorLine, string childDeviceCode, int ProtocalDetailValue, bool value)
        {
            // ä»ŽconveyorLine中的DeviceProDTOs列表中查找第一个符合条件的DeviceProDTO对象
            // æ¡ä»¶æ˜¯DeviceProParamType等于DeviceCommand,且DeviceChildCode等于childDeviceCode
            // æŸ¥æ‰¾ç»“果按DeviceProOffset升序排列
            DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand) && x.DeviceChildCode == childDeviceCode).OrderBy(x => x.DeviceProOffset).FirstOrDefault();
            // å°†devicePro的DeviceProAddress按'.'分割成字符串数组x
            string[] x = devicePro.DeviceProAddress.Split('.');
            // å°†æ•°ç»„x的最后一个元素替换为ProtocalDetailValue加1后的字符串形式
            x[x.Length - 1] = (ProtocalDetailValue + 1).ToString();
            // å°†ä¿®æ”¹åŽçš„æ•°ç»„x重新拼接成字符串,作为新的DeviceProAddress
            string DeviceProAddress = string.Join(".", x);
            var writeBool = conveyorLine.Communicator.Read<bool>(DeviceProAddress);
            if (writeBool != value)
            {
                // ä½¿ç”¨conveyorLine的Communicator对象的Write方法,将value写入新的DeviceProAddress地址
                conveyorLine.Communicator.Write(DeviceProAddress, value);
            }
        }
        public async Task LogAndWarn(string deviceName, string log, string color = "red")
        {
            ConsoleHelper.WriteWarningLine(log);
            await _noticeService.Logs(userTokenIds, new { deviceName, log = log, time = DateTime.Now.ToString("G"), color = color });
            WriteInfo(deviceName, log);
        }
        private ConveyorLineTaskCommand ReadCommand(CommonConveyorLine conveyorLine,string childDeviceCode)
        {
            ConveyorLineTaskCommand command = conveyorLine.ReadCustomer<ConveyorLineTaskCommand>(childDeviceCode);
            DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.Where(x => x.DeviceChildCode == childDeviceCode && x.DeviceProParamName == "ConveyorLineBarcode").FirstOrDefault();
            byte[] Barcode = conveyorLine.Communicator.Read(devicePro.DeviceProAddress, 10);
            command.Barcode = Encoding.ASCII.GetString(Barcode);
            return command;
        }
    }