/// <summary> /// 转换托盘抵达分拣口报文-PDA。 /// </summary> /// <param name="xml">托盘抵达分拣口报文。</param> /// <param name="dbContext">数据库上下文。</param> /// <returns>成功解析的实体。</returns> public static AST_PalletArrived_PDA ConvertRequestPDA(string xml, GeelyPtlEntities dbContext) { XDocument xDocument = XDocument.Parse(xml); XElement serviceElement = xDocument.Descendants("Service").First(); XElement dataElement = serviceElement.Descendants("Data").First(); XElement requestElement = dataElement.Descendants("Request").First(); XElement arrivedElement = requestElement.Descendants("ASSEMBLE").First(); AST_PalletArrived_PDA astPalletArrived = new AST_PalletArrived_PDA(); astPalletArrived.ProjectCode = arrivedElement.Element("ProjectCode").Value; astPalletArrived.WbsId = arrivedElement.Element("PS_POSID").Value; astPalletArrived.ProjectStep = arrivedElement.Element("StageCode").Value; string batchCode = arrivedElement.Element("BatchCode").Value; if (!dbContext.AST_LesTask_PDAs.Any(lt => lt.BatchCode == batchCode)) { throw new InterfaceDataException("该批次的任务未下发:" + batchCode); } astPalletArrived.BatchCode = batchCode; string cfgChannelCode = arrivedElement.Element("ChannelCode").Value; CFG_Channel cfgChannel = dbContext.CFG_Channels .FirstOrDefault(c => c.Code == cfgChannelCode); if (cfgChannel == null) { throw new InterfaceDataException("无效的分拣巷道:" + cfgChannelCode); } astPalletArrived.CFG_ChannelId = cfgChannel.Id; string cfgPalletCode = arrivedElement.Element("PalletCode").Value; CFG_Pallet cfgPallet = dbContext.CFG_Pallets .FirstOrDefault(c => c.Code == cfgPalletCode); if (cfgPallet == null) { throw new InterfaceDataException("无效的托盘编码:" + cfgPalletCode); } cfgPallet.PalletType = arrivedElement.Element("PalletType").Value; astPalletArrived.CFG_PalletId = cfgPallet.Id; astPalletArrived.PickBillIds = arrivedElement.Element("PickBillIDs").Value; astPalletArrived.ArrivedTime = DateTime.Now; return(astPalletArrived); }
/// <summary> /// 转换 LES 原始任务报文。 /// </summary> /// <param name="xml">LES 原始任务报文。</param> /// <param name="dbContext">数据库上下文。</param> /// <returns>成功解析的实体。</returns> public static AST_LesTask ConvertRequest(string xml, GeelyPtlEntities dbContext) { XDocument xDocument = XDocument.Parse(xml); XElement serviceElement = xDocument.Descendants("Service").First(); XElement dataElement = serviceElement.Descendants("Data").First(); XElement requestElement = dataElement.Descendants("Request").First(); XElement taskElement = requestElement.Descendants("ASSEMBLE").First(); List <XElement> taskItemElements = requestElement.Descendants("ASSEMBLEITEM").ToList(); if (taskItemElements.Count == 0) { throw new InterfaceDataException("没有明细。"); } AST_LesTask astLesTask = new AST_LesTask(); string projectCode = taskElement.Element("ProjectCode").Value; string projectStep = taskElement.Element("StageCode").Value; string[] codes = projectCode.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); string[] steps = projectStep.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (codes.Length > 1 && codes[0] == codes[1]) { projectCode = codes[0]; } if (steps.Length > 1 && steps[0] == steps[1]) { projectStep = steps[0]; } astLesTask.ProjectCode = projectCode; astLesTask.WbsId = taskElement.Element("PS_POSID").Value; astLesTask.ProjectStep = projectStep; astLesTask.BillCode = taskElement.Element("PickNO").Value; astLesTask.BillDate = DateTime.Parse(taskElement.Element("Bill_Date").Value, CultureInfo.InvariantCulture); //工位随时会新增 string cfgWorkStationCode = taskElement.Element("STATIONCODE").Value; CFG_WorkStation cfgWorkStation = dbContext.CFG_WorkStations .FirstOrDefault(ws => ws.Code == cfgWorkStationCode); if (cfgWorkStation == null) { using (GeelyPtlEntities innerDbContext = new GeelyPtlEntities()) { cfgWorkStation = new CFG_WorkStation(); cfgWorkStation.Code = cfgWorkStationCode; cfgWorkStation.Name = cfgWorkStation.Code; innerDbContext.CFG_WorkStations.Add(cfgWorkStation); //每个工位有 8 个车位 for (int position = 1; position <= 8; position++) { CFG_WorkStationCurrentCart cfgWorkStationCurrentCart = new CFG_WorkStationCurrentCart(); cfgWorkStationCurrentCart.CFG_WorkStation = cfgWorkStation; cfgWorkStationCurrentCart.Position = position; innerDbContext.CFG_WorkStationCurrentCarts.Add(cfgWorkStationCurrentCart); } innerDbContext.SaveChanges(); } } astLesTask.CFG_WorkStationId = cfgWorkStation.Id; astLesTask.GzzList = taskElement.Element("GZZLIST").Value; astLesTask.BatchCode = taskElement.Element("BatchCode").Value; string cfgChannelCode = taskElement.Element("ChannelCode").Value; CFG_Channel cfgChannel = dbContext.CFG_Channels .FirstOrDefault(c => c.Code == cfgChannelCode); if (cfgChannel == null) { throw new InterfaceDataException("无效的分拣巷道:" + cfgChannelCode); } astLesTask.CFG_ChannelId = cfgChannel.Id; //托盘随时会增加 string cfgPalletCode = taskElement.Element("PalletCode").Value; CFG_Pallet cfgPallet = dbContext.CFG_Pallets .FirstOrDefault(p => p.Code == cfgPalletCode); if (cfgPallet == null) { using (GeelyPtlEntities innerDbContext = new GeelyPtlEntities()) { cfgPallet = new CFG_Pallet(); cfgPallet.Code = cfgPalletCode; cfgPallet.PalletType = "01"; innerDbContext.CFG_Pallets.Add(cfgPallet); innerDbContext.SaveChanges(); } } astLesTask.CFG_PalletId = cfgPallet.Id; astLesTask.BoxCode = taskElement.Element("BoxCode").Value; astLesTask.FromPalletPosition = int.Parse(taskElement.Element("FromPalletPosition").Value, CultureInfo.InvariantCulture); if (astLesTask.FromPalletPosition < 1 || astLesTask.FromPalletPosition > 10) { astLesTask.FromPalletPosition = 1; } astLesTask.RequestTime = DateTime.Now; foreach (XElement taskItemElement in taskItemElements) { AST_LesTaskItem astLesTaskItem = new AST_LesTaskItem(); astLesTaskItem.AST_LesTask = astLesTask; astLesTaskItem.BillDetailId = taskItemElement.Element("BillDtlID").Value; astLesTaskItem.MaterialCode = taskItemElement.Element("MaterialCode").Value; astLesTaskItem.MaterialName = taskItemElement.Element("MaterialName").Value; astLesTaskItem.MaterialBarcode = taskItemElement.Element("MaterialBarcode").Value; astLesTaskItem.ToPickQuantity = (int)decimal.Parse(taskItemElement.Element("NEED_PICK_NUM").Value, CultureInfo.InvariantCulture); astLesTaskItem.MaxQuantityInSingleCartPosition = (int)decimal.Parse(taskItemElement.Element("MaxQuantityInSingleCartPosition").Value, CultureInfo.InvariantCulture); if (astLesTaskItem.MaxQuantityInSingleCartPosition <= 0) { astLesTaskItem.MaxQuantityInSingleCartPosition = int.MaxValue; } astLesTaskItem.IsSpecial = taskItemElement.Element("IsSpecial").Value == "1"; astLesTaskItem.IsBig = taskItemElement.Element("STORETYPE").Value == "04"; astLesTask.AST_LesTaskItems.Add(astLesTaskItem); } return(astLesTask); }
/// <summary> /// 停靠小车到分拣口。 /// </summary> /// <param name="cfgChannelId">分拣口的主键。</param> /// <param name="position">车位。</param> /// <param name="cfgCartId">待停靠小车的主键。</param> /// <exception cref="System.ArgumentException">position 车位上的小车还未解除绑定。</exception> public void Dock(int cfgChannelId, int position, int cfgCartId) { using (GeelyPtlEntities dbContext = new GeelyPtlEntities()) { CFG_Channel cfgChannel = dbContext.CFG_Channels .First(c => c.Id == cfgChannelId); CFG_Cart cfgCart = dbContext.CFG_Carts .First(c => c.Id == cfgCartId); CFG_ChannelCurrentCart cfgChannelCurrentCart = dbContext.CFG_ChannelCurrentCarts .FirstOrDefault(ccc => ccc.CFG_ChannelId == cfgChannelId && ccc.Position == position); if (cfgCart.CartStatus != CartStatus.Free) { throw new ArgumentException("小车 " + cfgCart.Code + " 未释放:" + cfgCart.CartStatus + "。"); } if (!cfgCart.OnLine) { throw new ArgumentException("小车 " + cfgCart.Code + " 不在线。"); } foreach (CFG_CartPtlDevice cfgCartPtlDevice in cfgCart.CFG_CartPtlDevices) { if (!cfgCartPtlDevice.OnLine) { throw new ArgumentException("小车上的 " + cfgCartPtlDevice.DeviceAddress + " 号标签不在线。"); } } if (cfgChannelCurrentCart == null) { throw new ArgumentException("车位 " + position + " 不存在。", "position"); } if (cfgChannelCurrentCart.CFG_CartId != null && cfgChannelCurrentCart.CFG_CartId != cfgCartId) { throw new ArgumentException("车位 " + position + " 上的小车还未解除绑定。", "position"); } if (cfgChannelCurrentCart.CFG_CartId == null) { CFG_ChannelCurrentCart dockedCfgChannelCurrentCart = dbContext.CFG_ChannelCurrentCarts .FirstOrDefault(ccc => ccc.CFG_CartId == cfgCartId); if (dockedCfgChannelCurrentCart != null) { throw new ArgumentException("小车 " + dockedCfgChannelCurrentCart.CFG_Cart.Code + " 已停靠在 " + dockedCfgChannelCurrentCart.CFG_Channel.Name + " 车位 " + dockedCfgChannelCurrentCart.Position + "。", "cfgCartId"); } //停靠即开始播种 cfgCart.CartStatus = CartStatus.WaitingAssorting; cfgChannelCurrentCart.CFG_CartId = cfgCart.Id; cfgChannelCurrentCart.DockedTime = DateTime.Now; //清空小车上的物料 List <CFG_CartCurrentMaterial> cfgCartCurrentMaterials = cfgCart.CFG_CartCurrentMaterials .ToList(); foreach (CFG_CartCurrentMaterial cfgCartCurrentMaterial in cfgCartCurrentMaterials) { cfgCartCurrentMaterial.AST_CartTaskItemId = null; cfgCartCurrentMaterial.ProjectCode = null; cfgCartCurrentMaterial.WbsId = null; cfgCartCurrentMaterial.ProjectStep = null; cfgCartCurrentMaterial.CFG_WorkStationId = null; cfgCartCurrentMaterial.BatchCode = null; cfgCartCurrentMaterial.CFG_ChannelId = null; cfgCartCurrentMaterial.CFG_PalletId = null; cfgCartCurrentMaterial.BoxCode = null; cfgCartCurrentMaterial.FromPalletPosition = null; cfgCartCurrentMaterial.MaterialCode = null; cfgCartCurrentMaterial.MaterialName = null; cfgCartCurrentMaterial.MaterialBarcode = null; cfgCartCurrentMaterial.Quantity = null; cfgCartCurrentMaterial.AssortedTime = null; cfgCartCurrentMaterial.CFG_EmployeeId = null; if (cfgCartCurrentMaterial.Usability != CartPositionUsability.DisableByOffLineDevice) { cfgCartCurrentMaterial.Usability = CartPositionUsability.Enable; } } dbContext.SaveChanges(); //设备控制 CartPtl cartPtl = CartPtlHost.Instance.GetCartPtl(cfgCart.Id); Ptl900U ptl900UPublisher = cartPtl.GetPtl900UPublisher(); Display900UItem publisherDisplay900UItem = new Display900UItem(); publisherDisplay900UItem.Name = "停靠成功"; publisherDisplay900UItem.Description = cfgChannel.Name; publisherDisplay900UItem.Count = (ushort)position; publisherDisplay900UItem.Unit = "位"; ptl900UPublisher.Clear(true); ptl900UPublisher.Lock(); ptl900UPublisher.Display(publisherDisplay900UItem, LightColor.Off); Logger.Log(this.GetType().Name, DateTime.Now.ToString("HH:mm:ss") + "停靠 " + cfgCart.Name + " 到 " + cfgChannel.Name + " 车位 " + position + Environment.NewLine); } } }
/// <summary> /// 确保基础数据已经初始化。 /// </summary> public static void EnsureInitialized() { using (GeelyPtlEntities dbContext = new GeelyPtlEntities()) { if (!dbContext.CFG_Employees.Any()) { //操作员 CFG_Employee cfgEmployee = new CFG_Employee(); cfgEmployee.Code = "Administrator"; cfgEmployee.Name = "管理员"; cfgEmployee.LoginName = "admin"; cfgEmployee.Password = string.Empty; cfgEmployee.IsEnabled = true; dbContext.CFG_Employees.Add(cfgEmployee); //巷道 //转台上的标签,托盘有 5 个库位,但只在单侧使用 3 个标签 //7 个巷道共用 1 个 4 口 XGate,按现场走线,总线 1 对应 1、2 巷道,总线 2 对应 3 巷道,总线 3 对应 4、5 巷道,总线 4 对应 6、7 巷道 //标签地址分别为:1、2、3,4、5、6,51、52、53,101、102、103,104、105、106,151、152、153,154、155、156。 //托盘库位定义为:1、2 在远端需旋转,3、4、5 在近段 string channelXGateIP = "10.34.36.17"; Dictionary <int, byte[]> channelPtl900UAddressesByChannelNumber = new Dictionary <int, byte[]>(); channelPtl900UAddressesByChannelNumber.Add(1, new byte[] { 3, 1, 1, 2, 3 }); channelPtl900UAddressesByChannelNumber.Add(2, new byte[] { 6, 4, 4, 5, 6 }); channelPtl900UAddressesByChannelNumber.Add(3, new byte[] { 53, 51, 51, 52, 53 }); channelPtl900UAddressesByChannelNumber.Add(4, new byte[] { 103, 101, 101, 102, 103 }); channelPtl900UAddressesByChannelNumber.Add(5, new byte[] { 106, 104, 104, 105, 106 }); channelPtl900UAddressesByChannelNumber.Add(6, new byte[] { 153, 151, 151, 152, 153 }); channelPtl900UAddressesByChannelNumber.Add(7, new byte[] { 156, 154, 154, 155, 156 }); for (int channelNumber = 1; channelNumber <= channelPtl900UAddressesByChannelNumber.Count; channelNumber++) { CFG_Channel cfgChannel = new CFG_Channel(); cfgChannel.Code = string.Format(CultureInfo.InvariantCulture, "{0}", channelNumber); cfgChannel.Name = string.Format(CultureInfo.InvariantCulture, "巷道 {0}", channelNumber); dbContext.CFG_Channels.Add(cfgChannel); //转台上的标签 byte[] deviceAddresses = channelPtl900UAddressesByChannelNumber[channelNumber]; for (int position = 1; position <= 5; position++) { byte deviceAddress = deviceAddresses[position - 1]; byte busIndex = (byte)(deviceAddress / 50); CFG_ChannelPtlDevice cfgChannelPtlDevice = new CFG_ChannelPtlDevice(); cfgChannelPtlDevice.CFG_Channel = cfgChannel; cfgChannelPtlDevice.Position = position; cfgChannelPtlDevice.XGateIP = channelXGateIP; cfgChannelPtlDevice.RS485BusIndex = busIndex; cfgChannelPtlDevice.Ptl900UAddress = deviceAddress; dbContext.CFG_ChannelPtlDevices.Add(cfgChannelPtlDevice); } //巷道边的 4 个车位,多加两个备用车位 for (int position = 1; position <= 6; position++) { CFG_ChannelCurrentCart cfgChannelCurrentCart = new CFG_ChannelCurrentCart(); cfgChannelCurrentCart.CFG_Channel = cfgChannel; cfgChannelCurrentCart.Position = position; dbContext.CFG_ChannelCurrentCarts.Add(cfgChannelCurrentCart); } //巷道上的 1 个托盘 CFG_ChannelCurrentPallet cfgChannelCurrentPallet = new CFG_ChannelCurrentPallet(); cfgChannelCurrentPallet.CFG_Channel = cfgChannel; dbContext.CFG_ChannelCurrentPallets.Add(cfgChannelCurrentPallet); } //小车 for (int cartNumber = 1; cartNumber <= 100; cartNumber++) { CFG_Cart cfgCart = new CFG_Cart(); cfgCart.Code = string.Format(CultureInfo.InvariantCulture, "{0:000000}", 100000 + cartNumber); cfgCart.Name = string.Format(CultureInfo.InvariantCulture, "料车 {0}", cartNumber); cfgCart.Rfid1 = "AABBCCDDEEFF"; cfgCart.XGateIP = "192.168.0.10"; cfgCart.CartStatus = CartStatus.Free; dbContext.CFG_Carts.Add(cfgCart); //小车上的 8 个库位 for (int position = 1; position <= 8; position++) { CFG_CartCurrentMaterial cfgCartCurrentMaterial = new CFG_CartCurrentMaterial(); cfgCartCurrentMaterial.CFG_Cart = cfgCart; cfgCartCurrentMaterial.Position = position; cfgCartCurrentMaterial.Usability = CartPositionUsability.Enable; dbContext.CFG_CartCurrentMaterials.Add(cfgCartCurrentMaterial); } //小车上的 10 个标签 for (byte deviceAddress = 1; deviceAddress <= 10; deviceAddress++) { CFG_CartPtlDevice cfgCartPtlDevice = new CFG_CartPtlDevice(); cfgCartPtlDevice.CFG_Cart = cfgCart; cfgCartPtlDevice.DeviceAddress = deviceAddress; dbContext.CFG_CartPtlDevices.Add(cfgCartPtlDevice); } } //dbContext.SaveChanges(); } ////线边工位的8个车位 //List<CFG_WorkStation> cfgWorkStations = dbContext.CFG_WorkStations.ToList(); //foreach (CFG_WorkStation cfgWorkStation in cfgWorkStations) //{ // if (cfgWorkStation.CFG_WorkStationCurrentCarts != null && cfgWorkStation.CFG_WorkStationCurrentCarts.Count > 0) // { // continue; // } // for (int position = 1; position <= 8; position++) // { // CFG_WorkStationCurrentCart cfgWorkStationCurrentCart = new CFG_WorkStationCurrentCart(); // cfgWorkStationCurrentCart.CFG_WorkStation = cfgWorkStation; // cfgWorkStationCurrentCart.Position = position; // dbContext.CFG_WorkStationCurrentCarts.Add(cfgWorkStationCurrentCart); // } //} //AGV开关信息 if (!dbContext.DST_AgvSwitchs.Any()) { DST_AgvSwitch dstAgvSwitch = new DST_AgvSwitch(); dstAgvSwitch.isOpen = false; dstAgvSwitch.lastCloseTime = DateTime.Now; dbContext.DST_AgvSwitchs.Add(dstAgvSwitch); } dbContext.SaveChanges(); } }