using AutoMapper; using HslCommunication; using Newtonsoft.Json; using Quartz; using SqlSugar; using System.Reflection; using WIDESEAWCS_BasicInfoRepository; using WIDESEAWCS_BasicInfoService; using WIDESEAWCS_Common; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_Core.HttpContextUser; using WIDESEAWCS_DTO.MOM; using WIDESEAWCS_DTO.TaskInfo; using WIDESEAWCS_IProcessRepository; using WIDESEAWCS_ISystemServices; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.DeviceBase; using WIDESEAWCS_QuartzJob.DTO; using WIDESEAWCS_QuartzJob.Service; using WIDESEAWCS_SignalR; using WIDESEAWCS_Tasks.ConveyorLineJob; using ICacheService = WIDESEAWCS_Core.Caches.ICacheService; namespace WIDESEAWCS_Tasks { [DisallowConcurrentExecution] public partial class CommonConveyorLineJob : JobBase, IJob { public readonly ITaskService _taskService; private readonly ITaskRepository _taskRepository; private readonly ITaskExecuteDetailService _taskExecuteDetailService; private readonly IRouterService _routerService; private readonly IPlatFormRepository _platFormRepository; private readonly ISys_ConfigService _sys_ConfigService; private readonly IMapper _mapper; private readonly IDt_StationManagerService _stationManagerService; private readonly IDt_StationManagerRepository _stationManagerRepository; private readonly ICacheService _cacheService; private readonly INoticeService _noticeService; public CommonConveyorLineJob(ITaskService taskService, ITaskExecuteDetailService taskExecuteDetailService, IRouterService routerService, IMapper mapper, ITaskRepository taskRepository, IPlatFormRepository platFormRepository, ISys_ConfigService sys_ConfigService, IDt_StationManagerService stationManagerService, IDt_StationManagerRepository stationManagerRepository, ICacheService cacheService, INoticeService noticeService) { _taskService = taskService; _taskExecuteDetailService = taskExecuteDetailService; _routerService = routerService; _mapper = mapper; _taskRepository = taskRepository; _platFormRepository = platFormRepository; _sys_ConfigService = sys_ConfigService; _stationManagerService = stationManagerService; _stationManagerRepository = stationManagerRepository; _cacheService = cacheService; _noticeService = noticeService; } public Task Execute(IJobExecutionContext context) { try { CommonConveyorLine conveyorLine = (CommonConveyorLine)context.JobDetail.JobDataMap.Get("JobParams"); if (conveyorLine != null) { List childDeviceCodes = _routerService.QueryAllPositions(conveyorLine.DeviceCode); foreach (string childDeviceCode in childDeviceCodes) { ProcessDeviceAsync(conveyorLine, childDeviceCode); } List stationManagers = _stationManagerService.GetAllStationByDeviceCode(conveyorLine.DeviceCode); foreach (var station in stationManagers) { if (station.stationType == 11) { ConveyorLineTaskCommand command = conveyorLine.ReadCustomer(station.stationChildCode); ConveyorLineTaskCommandWrite commandWrite = conveyorLine.ReadCustomer(station.stationChildCode, "DeviceCommand"); if (command != null && commandWrite != null) { var structs = BitConverter.GetBytes(commandWrite.WriteInteractiveSignal).Reverse().ToArray().ToBoolArray(); if (structs[0] == true) { ConsoleHelper.WriteWarningLine($"【{conveyorLine.DeviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{station.stationChildCode}】空托盘请求扫码入库"); NGRequestTaskInbound(conveyorLine, command, station.stationChildCode, 0, station.stationLocation); } else { ConveyorLineSendFinish(conveyorLine, station.stationChildCode, 0, false); } } } } } } catch (Exception ex) { Console.Out.WriteLine(nameof(CommonConveyorLineJob) + ":" + ex.ToString()); } return Task.CompletedTask; } private void ProcessDeviceAsync(CommonConveyorLine conveyorLine, string childDeviceCode) { ConveyorLineTaskCommand command = conveyorLine.ReadCustomer(childDeviceCode); ConveyorLineTaskCommandWrite commandWrite = conveyorLine.ReadCustomer(childDeviceCode, "DeviceCommand"); if (command != null && commandWrite != null) { var structs = BitConverter.GetBytes(commandWrite.WriteInteractiveSignal).Reverse().ToArray().ToBoolArray(); List? deviceProtocolDetails = conveyorLine.DeviceProtocolDetailDTOs.Where(x => x.DeviceProParamName == nameof(ConveyorLineTaskCommand.InteractiveSignal)).ToList(); if (deviceProtocolDetails != null) { foreach (var item in deviceProtocolDetails) { var outDeviceCodes = _routerService.QueryOutDeviceCodes(conveyorLine.DeviceCode); if (structs[item.ProtocalDetailValue.ObjToInt()] == true) { MethodInfo? method = GetType().GetMethod(item.ProtocolDetailType); if (method != null) { var numRead = item.ProtocalDetailValue.ObjToInt(); var numWrite = item.ProtocalDetailValue.ObjToInt() + 1; ConsoleHelper.WriteWarningLine($"【{conveyorLine.DeviceName}】【{childDeviceCode}】【{numRead.ToString()}】位输送线读取信号:【{structs[item.ProtocalDetailValue.ObjToInt()]}】 【{numWrite}】位WCS写入信号:【{structs[item.ProtocalDetailValue.ObjToInt() + 1]}】"); if (structs[item.ProtocalDetailValue.ObjToInt() + 1] != structs[item.ProtocalDetailValue.ObjToInt()]) { command.InteractiveSignal = commandWrite.WriteInteractiveSignal; method.Invoke(this, new object[] { conveyorLine, command, childDeviceCode, item.ProtocalDetailValue.ObjToInt() }); } } } else { ConveyorLineSendFinish(conveyorLine, childDeviceCode, item.ProtocalDetailValue.ObjToInt(), false); //DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand) && x.DeviceChildCode == childDeviceCode).OrderBy(x => x.DeviceProOffset).FirstOrDefault(); //string[] x = devicePro.DeviceProAddress.Split('.'); //x[x.Length - 1] = (item.ProtocalDetailValue.ObjToInt() + 1).ToString(); //string DeviceProAddress = string.Join(".", x); //var writeRead = conveyorLine.Communicator.Read(DeviceProAddress); //if (writeRead) //{ // conveyorLine.Communicator.Write(DeviceProAddress, false); // //ConveyorLineSendFinish(conveyorLine, childDeviceCode, item.ProtocalDetailValue.ObjToInt(), false); //} } } } Platform platform = _platFormRepository.QueryFirst(x => x.PLCCode == conveyorLine.DeviceCode && x.PlatCode == childDeviceCode && x.Status == "Active"); if (platform != null) { if (command.InteractiveSignal != 2) { MethodInfo? method = GetType().GetMethod(platform.ExecutionMethod); if (method != null) { command.InteractiveSignal = commandWrite.WriteInteractiveSignal; int count = string.IsNullOrEmpty(platform.Location) ? 0 + 1 : platform.Location.Split(',').Count() + 1; method.Invoke(this, new object[] { conveyorLine, command, childDeviceCode, count, platform }); } } else { if (platform.Location != null && platform.Location != "") { var strings = platform.Location.Split(',').ToList(); foreach (var ite in strings) { //int index = strings.FindIndex(p => p == ite); ConveyorLineTaskCommand command1 = conveyorLine.ReadCustomer(ite); if (command1.InteractiveSignal != 2) { MethodInfo? method = GetType().GetMethod(platform.ExecutionMethod); if (method != null) { command.InteractiveSignal = commandWrite.WriteInteractiveSignal; //int count = strings.Count - index; int count = strings.Count; method.Invoke(this, new object[] { conveyorLine, command, childDeviceCode, count, platform }); } } } } } } #region 调用事件总线通知前端 var tokenInfos = _cacheService.Get>("Cache_UserToken"); if (tokenInfos == null || !tokenInfos.Any()) { //throw new Exception(conveyorLine.DeviceName + "缓存中未找到Token缓存"); return; } var userTokenIds = tokenInfos?.Select(x => x.Token_ID).ToList(); var userIds = tokenInfos?.Select(x => x.UserId).ToList(); object obj = new { command, commandWrite }; _noticeService.LineData(userIds?.FirstOrDefault(), userTokenIds, new { conveyorLine.DeviceName, childDeviceCode, data = obj }); #endregion 调用事件总线通知前端 } } #region 入库 /// /// 输送线请求入库 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 /// 线体当前bool读取偏移地址 public void RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue) { try { ConsoleHelper.WriteWarningLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】请求扫码入库"); var task = _taskService.QueryBarCodeConveyorLineTask(command.Barcode, childDeviceCode); if (task != null) { if (task.TaskType == (int)TaskOutboundTypeEnum.OutTray || task.TaskType == (int)TaskOutboundTypeEnum.Outbound) { HandleTaskOut(conveyorLine, command, childDeviceCode, ProtocalDetailValue, task); } } else { if (task == null && command.Barcode != "NoRead" && command.Barcode.IsNotEmptyOrNull()) { task = _taskService.QueryBarcodeTask(command.Barcode, childDeviceCode); if (task == null) HandleNewTask(conveyorLine, command, childDeviceCode, ProtocalDetailValue); } } } catch (Exception ex) { Console.Out.WriteLine(ex.ToString()); } } #region 输送线请求入库下一地址 /// /// 输送线请求入库下一地址 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 public void RequestInNextAddress(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode) { Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode); if (task != null) { if (command.Barcode == task.PalletCode) { Dt_Task? newTask = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress); if (newTask != null) { //ConveyorLineTaskCommand taskCommand = _mapper.Map(newTask); //taskCommand.InteractiveSignal = command.InteractiveSignal; var next = newTask.NextAddress; var taskCommand = MapTaskCommand(newTask, command); newTask.NextAddress = next; ConsoleHelper.WriteWarningLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】请求入库下一地址,下一目标地址【{taskCommand.TargetAddress}】"); conveyorLine.SendCommand(taskCommand, childDeviceCode); } } } } #endregion 输送线请求入库下一地址 /// /// 输送线入库完成 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 /// 线体当前bool读取偏移地址 public void ConveyorLineInFinish(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue) { ConsoleHelper.WriteWarningLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线入库完成"); var task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode); if (task != null && task.TaskState != (int)TaskInStatusEnum.Line_InFinish) { if (command.Barcode == task.PalletCode) { ConsoleHelper.WriteWarningLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线入库完成,下一目标地址【等待分配货位】"); ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true); if (task.TaskType == (int)TaskInboundTypeEnum.InNG) { int nextStatus = task.TaskState.GetNextNotCompletedStatus(); 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); } else { WebResponseContent content = _taskService.UpdateTaskStatusToNext(task); Console.Out.WriteLine(content.ToJsonString()); } } } } #endregion 入库 #region 出库 /// /// 输送线请求出信息 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 /// 线体当前bool读取偏移地址 public void RequestOutbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue) { var task = _taskService.QueryConveyorLineTask(conveyorLine.DeviceCode, childDeviceCode); ConsoleHelper.WriteSuccessLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库,task{task.ToJsonString()}"); if (task != null) { //if (command.Barcode == task.PalletCode) { //task.NextAddress = task.NextAddress.Replace("-1", ""); //ConveyorLineTaskCommand taskCommand = _mapper.Map(task); //taskCommand.InteractiveSignal = command.InteractiveSignal; //ConveyorLineTaskCommand taskCommand = MapTaskCommand(task, command); var next = task.NextAddress; var taskCommand = MapTaskCommand(task, command); task.NextAddress = next; ConsoleHelper.WriteSuccessLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库,下一目标地址【{taskCommand.TargetAddress}】"); conveyorLine.SendCommand(taskCommand, childDeviceCode); ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true); _taskService.UpdateTaskStatusToNext(task); if (task.TargetAddress == "1020-1") { _taskService.UpdateTaskStatusToNext(task); } } } } /// /// 输送线请求出库下一地址 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 public void RequestOutNextAddress(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue) { Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode); if (task != null) { if (command.Barcode == task.PalletCode) { Dt_Task? newTask = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress); if (newTask != null) { //ConveyorLineTaskCommand taskCommand = _mapper.Map(newTask); //taskCommand.InteractiveSignal = command.InteractiveSignal; //ConveyorLineTaskCommand taskCommand = MapTaskCommand(newTask, command); var next = newTask.NextAddress; var taskCommand = MapTaskCommand(newTask, command); newTask.NextAddress = next; ConsoleHelper.WriteSuccessLine($"【{conveyorLine._deviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线请求出库下一地址,下一目标地址【{taskCommand.TargetAddress}】"); conveyorLine.SendCommand(taskCommand, childDeviceCode); ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true); } } } } /// /// 输送线出库完成 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 public void ConveyorLineOutFinish(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue) { var task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode); if (task != null) { if (command.Barcode == task.PalletCode) { WebResponseContent content = new WebResponseContent(); //ConveyorLineTaskCommand taskCommand = _mapper.Map(task); //taskCommand.InteractiveSignal = command.InteractiveSignal; //ConveyorLineTaskCommand taskCommand = MapTaskCommand(task, command); var next = task.NextAddress; var taskCommand = MapTaskCommand(task, command); task.NextAddress = next; if (task.PalletCode != command.Barcode || task.Remark == "NG") { var NGAddress = _platFormRepository.QueryFirst(x => x.PlatCode == task.TargetAddress).Capacity; taskCommand.TargetAddress = NGAddress; } else { taskCommand.TargetAddress = 1000; } ConsoleHelper.WriteSuccessLine($"【{conveyorLine.DeviceName}】任务号:【{command.TaskNum}】,托盘条码:【{command.Barcode}】已到达【{childDeviceCode}】输送线出库完成,下一目标地址【{taskCommand.TargetAddress}】"); conveyorLine.SendCommand(taskCommand, childDeviceCode); ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true); content = _taskService.UpdateTaskStatusToNext(task); } } } #endregion 出库 /// /// 输送线交互完成 /// /// 输送线实例对象 /// 子设备编号 /// 线体当前bool读取偏移地址 /// 值 public void ConveyorLineSendFinish(CommonConveyorLine conveyorLine, string childDeviceCode, int ProtocalDetailValue, bool value) { DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.Where(x => x.DeviceProParamType == nameof(DeviceCommand) && x.DeviceChildCode == childDeviceCode).OrderBy(x => x.DeviceProOffset).FirstOrDefault(); string[] x = devicePro.DeviceProAddress.Split('.'); x[x.Length - 1] = (ProtocalDetailValue + 1).ToString(); string DeviceProAddress = string.Join(".", x); conveyorLine.Communicator.Write(DeviceProAddress, value); } #region 检测空盘实盘任务 /// /// 监测空托盘实盘出库 /// /// 输送线实例对象 /// 读取的请求信息 /// 子设备编号 /// 线体当前bool读取偏移地址 public async void EmptyTrayReturn(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int index, Platform platform) { try { TaskOutboundTypeEnum taskOutboundTypeEnum; if (platform.PlatformType.Contains("OutTray")) taskOutboundTypeEnum = TaskOutboundTypeEnum.OutTray; else taskOutboundTypeEnum = TaskOutboundTypeEnum.Outbound; await CheckAndCreateTask(taskOutboundTypeEnum, childDeviceCode, index, platform.Stacker, platform); } catch (Exception) { } } /// /// 检查任务并创建新任务 /// private async Task CheckAndCreateTask(TaskOutboundTypeEnum taskType, string childDeviceCode, int index, string roadWay, Platform platform) { var tasks = _taskRepository.QueryData(x => x.TaskType == (int)taskType && x.TargetAddress == childDeviceCode); if (tasks.Count < index) { //ConsoleHelper.WriteErrorLine($"【{childDeviceCode}】请求【{taskType.ToString()}】任务,已有【{taskType.ToString()}】任务【{tasks.Count}】,最多拥有【{index - 1}】"); #region 调用WMS获取出库任务 WMSTaskDTO taskDTO = new WMSTaskDTO(); // 获取WMSip地址 var config = _sys_ConfigService.GetConfigsByCategory(CateGoryConst.CONFIG_SYS_IPAddress); var wmsBase = config.FirstOrDefault(x => x.ConfigKey == SysConfigKeyConst.WMSIP_BASE)?.ConfigValue; var requestTrayOutTask = config.FirstOrDefault(x => x.ConfigKey == SysConfigKeyConst.RequestTrayOutTask)?.ConfigValue; if (wmsBase == null || requestTrayOutTask == null) { throw new InvalidOperationException("WMS IP 未配置"); } var wmsIpAddress = wmsBase + requestTrayOutTask; var result = await HttpHelper.PostAsync(wmsIpAddress, new { position = childDeviceCode, tag = (int)taskType, areaCdoe = roadWay, platform.ProductionLine }.ToJsonString()); //var result = await HttpHelper.PostAsync("http://localhost:5000/api/Task/RequestTrayOutTaskAsync", dynamic.ToJsonString()); WebResponseContent content = JsonConvert.DeserializeObject(result); // 检查状态并返回 if (!content.Status) return; taskDTO = JsonConvert.DeserializeObject(content.Data.ToString()); #endregion 调用WMS获取出库任务 CreateAndSendTask(taskDTO); } } /// /// 创建任务 /// public WebResponseContent CreateAndSendTask(WMSTaskDTO taskDTO) { var content = _taskService.ReceiveWMSTask(new List { taskDTO }); if (content.Status) { Console.WriteLine($"{taskDTO.TaskType}呼叫成功"); } return content; } #endregion 检测空盘实盘任务 #region 化成NG口入库 public void NGRequestTaskInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommand command, string childDeviceCode, int ProtocalDetailValue, string TargetAddress) { var config = _sys_ConfigService.GetConfigsByCategory(CateGoryConst.CONFIG_SYS_IPAddress); var wmsBase = config.FirstOrDefault(x => x.ConfigKey == SysConfigKeyConst.MOMIP_BASE)?.ConfigValue; var ipAddress = config.FirstOrDefault(x => x.ConfigKey == SysConfigKeyConst.TrayCellsStatus)?.ConfigValue; if (wmsBase == null || ipAddress == null) { throw new InvalidOperationException("MOM IP 未配置"); } Dt_StationManager stationManager = _stationManagerRepository.QueryFirst(x => x.stationPLC == conveyorLine.DeviceCode && x.stationChildCode == childDeviceCode); TrayCellsStatusDto trayCells = new TrayCellsStatusDto() { Software = "WMS", TrayBarcode = command.Barcode, EquipmentCode = stationManager.stationEquipMOM, SessionId = Guid.NewGuid().ToString(), EmployeeNo = "MITest", SceneType = "1", RequestTime = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now).ToString("yyyy-MM-ddTHH:mm:ss.fffZ") }; var MOMIpAddress = wmsBase + ipAddress; var result = HttpHelper.PostAsync(MOMIpAddress, trayCells.ToJsonString()).Result; WriteInfo("入站校验", $"【{childDeviceCode}】入站校验请求参数【{trayCells.ToJsonString()}】"); WriteInfo("入站校验", ""); WriteInfo("入站校验", $"【{childDeviceCode}】入站校验返回参数【{result}】"); ResultTrayCellsStatus result1 = JsonConvert.DeserializeObject(result); var serialNosError = result1.SerialNos.Where(x => x.SerialNoStatus != 1).ToList(); if (serialNosError.Count > 0) { return; } if (result1.SerialNos.Count <= 0) { // 空托盘入库逻辑 Dt_Task dt_Task = new Dt_Task() { TargetAddress = TargetAddress, PalletCode = command.Barcode, NextAddress = TargetAddress, TaskNum = 0 }; //ConveyorLineTaskCommand taskCommand = _mapper.Map(dt_Task); //taskCommand.InteractiveSignal = command.InteractiveSignal; //ConveyorLineTaskCommand taskCommand = MapTaskCommand(dt_Task, command); var next = dt_Task.NextAddress; var taskCommand = MapTaskCommand(dt_Task, command); dt_Task.NextAddress = next; conveyorLine.SendCommand(taskCommand, childDeviceCode); ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true); } else { // 空托盘入库逻辑 Dt_Task dt_Task = new Dt_Task() { TargetAddress = TargetAddress, PalletCode = command.Barcode, NextAddress = "1000", TaskNum = 0 }; ConveyorLineTaskCommand taskCommand = _mapper.Map(dt_Task); taskCommand.InteractiveSignal = command.InteractiveSignal; conveyorLine.SendCommand(taskCommand, childDeviceCode); ConveyorLineSendFinish(conveyorLine, childDeviceCode, ProtocalDetailValue, true); } } #endregion 化成NG口入库 } }