using System; using System.Collections.Generic; using System.Runtime.ConstrainedExecution; using System.Web.Http; using HH.WCS.Mobox3.DSZSH.core; using HH.WCS.Mobox3.DSZSH.device; using HH.WCS.Mobox3.DSZSH.models; using HH.WCS.Mobox3.DSZSH.util; using HH.WCS.Mobox3.DSZSH.wms; using Newtonsoft.Json; using static HH.WCS.Mobox3.DSZSH.api.ApiModel; using static HH.WCS.Mobox3.DSZSH.core.Monitor; namespace HH.WCS.Mobox3.DSZSH.api { /// /// 测试用:如果项目中要和设备对接,前期设备无法测试,用接口模拟 /// [RoutePrefix("api")] public class DebugController : ApiController { /// /// AGV状态一键回报134562 /// /// 容器号 /// [HttpPost] [Route("AGVSeriesReports")] public ReturnResults AGVSeriesReports(UpdateTaskState model) { //var db = new SqlHelper().GetInstance(); //var task = db.Queryable().Where(t => t.S_CODE == model.TaskID).First(); //if (task == null) return new ReturnResults(); //if (task.S_B_STATE == "完成" && task.N_B_STATE == 3 || task.S_B_STATE == "错误" && task.N_B_STATE == 4) { // return new ReturnResults(); //} var agvTaskState = new AgvTaskState() { task_no = model.TaskID, forklift_no = model.ForkliftNo, state = 1 }; ReturnResults returnResult = new ReturnResults(); returnResult.ResultList = new List(); var temp1 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp1); agvTaskState.state = 3; var temp3 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp3); agvTaskState.state = 4; var temp4 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp4); agvTaskState.state = 5; var temp5 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp5); agvTaskState.state = 6; var temp6 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp6); agvTaskState.state = 2; var temp2 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp2); return returnResult; } /// /// AGV状态一键回报134 /// /// 容器号 /// [HttpPost] [Route("AGVSeriesReports14")] public ReturnResults AGVSeriesReports14(UpdateTaskState model) { var agvTaskState = new AgvTaskState() { task_no = model.TaskID, forklift_no = model.ForkliftNo, state = 1 }; ReturnResults returnResult = new ReturnResults(); returnResult.ResultList = new List(); var temp1 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp1); agvTaskState.state = 3; var temp3 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp3); agvTaskState.state = 4; var temp4 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp4); return returnResult; } /// /// AGV状态一键回报562 /// /// 容器号 /// [HttpPost] [Route("AGVSeriesReports62")] public ReturnResults AGVSeriesReports62(UpdateTaskState model) { var agvTaskState = new AgvTaskState() { task_no = model.TaskID, forklift_no = model.ForkliftNo, state = 5 }; ReturnResults returnResult = new ReturnResults(); returnResult.ResultList = new List(); var temp5 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp5); agvTaskState.state = 6; var temp6 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp6); agvTaskState.state = 2; var temp2 = WCSCore.OperateAgvTaskStatus(agvTaskState); returnResult.ResultList.Add(temp2); return returnResult; } /// /// 初始化数据库 /// /// [HttpPost] [Route("CreateDatabase")] public string CreateDatabase(FalseOk model) { try { if (model.JumpOut) { return "跳出"; } var db = new SqlHelper().GetInstance(); var entityTypes = new Type[] { //typeof(TN_CAR_IN), //typeof(TN_CG_Detail), //typeof(TN_Container), //typeof(TN_Loc_Container), //typeof(TN_Location), //typeof(TN_Task), //typeof(TN_Task_Action), //typeof(SysHelper.OI_SYS_MAXID), //typeof(TN_Inbound_Order), //typeof(TN_Check_Detail), //typeof(TN_Check_Order), //typeof(TN_CNTR_ITEM), //typeof(TN_Outbound_Detail), //typeof(TN_Outbound_Order), //typeof(TN_Shift_Order), //typeof(TN_Shift_Detail) //typeof(TN_Container_Item), }; //var areaNameList = new List(); //foreach (var area in Settings.Areas) { // areaNameList.AddRange(area.Codes); //} //var locationList = new List(); //foreach (var area in areaNameList) { // int i = 0; // int j = 0; // int k = 0; // if (area == "KXHJQ" || area == "MTHJQ" || area == "MXHJQ") { // for (i = 1; i <= 4; i++) { // for (j = 1; j <= 5; j++) { // for (k = 1; k <= 3; k++) { // locationList.Add(new TN_Location() { // N_ROW = i, // N_COL = j, // N_LAYER = k, // S_AREA_CODE = area, // S_CODE = $"{area}-{i.ToString().PadLeft(2, '0')}-{j.ToString().PadLeft(2, '0')}" + // $"-{k.ToString().PadLeft(2, '0')}" // }); // } // } // } // continue; // } // if (area == "BZQ") { // for (i = 1; i <= 2; i++) { // for (j = 1; j <= 2; j++) { // locationList.Add(new TN_Location() { // N_ROW = i, // N_COL = j, // S_AREA_CODE = area, // S_CODE = $"{area}-{i.ToString().PadLeft(2, '0')}-{j.ToString().PadLeft(2, '0')}" // }); // } // } // continue; // } // i = 1; // for (j = 1; j <= 5; j++) { // locationList.Add(new TN_Location() { // N_ROW = i, // N_COL = j, // S_AREA_CODE = area, // S_CODE = $"{area}-{i.ToString().PadLeft(2, '0')}-{j.ToString().PadLeft(2, '0')}" // }); // } //} //using (var tran = db.Ado.UseTran()) { // //db.CodeFirst.InitTables(entityTypes); // if (db.Insertable(locationList).ExecuteCommand() <= 0) { // tran.RollbackTran(); // return "失败"; // } // tran.CommitTran(); //} } catch (Exception ex) { LogHelper.Info($"发生了异常"); return "初始化数据库错误" + ex.Message; } return "成功"; } /// /// DEBUG:插入货位、容器、货品信息 /// /// [HttpPost] [Route("InsertLocCntrCg")] public string InsertLocCntrCg(LocCntrCg locCntrCg) { var db = new SqlHelper().GetInstance(); try { using (var tran = db.UseTran()) { LogHelper.Info("LogCntrCg:" + JsonConvert.SerializeObject(locCntrCg)); if (string.IsNullOrEmpty(locCntrCg.LocCode)) return ""; var loc = db.Queryable().First(a => a.S_CODE == locCntrCg.LocCode); if (loc == null) { var newLoc = new TN_Location { S_CODE = locCntrCg.LocCode, S_AREA_CODE = locCntrCg.LocArea ?? "" }; if (db.Insertable(newLoc).ExecuteCommand() <= 0) { tran.RollbackTran(); LogHelper.Info($"插入位置{locCntrCg.LocCode}失败"); return "插入失败"; } loc = newLoc; } if (string.IsNullOrEmpty(locCntrCg.CntrCode)) { LogHelper.Info("容器号为空,不再读取后面的数据"); return ""; } var locCntrRel = db.Queryable().First(a => a.S_LOC_CODE == locCntrCg.LocCode && a.S_CNTR_CODE == locCntrCg.CntrCode); if (locCntrRel == null) { var newLocCntrRel = new TN_Loc_Container { S_LOC_CODE = locCntrCg.LocCode, S_CNTR_CODE = locCntrCg.CntrCode, S_CNTR_TYPE = locCntrCg.CntrType ?? "" }; loc.N_CURRENT_NUM = 1; if (db.Insertable(newLocCntrRel).ExecuteCommand() <= 0 && db.Updateable(loc).UpdateColumns(c => c.N_CURRENT_NUM).ExecuteCommand() <= 0) { tran.RollbackTran(); LogHelper.Info($"插入位置托盘关系{locCntrCg.LocCode}-{locCntrCg.CntrCode}失败"); return "插入失败"; } } if (string.IsNullOrEmpty(locCntrCg.ItemCode)) { LogHelper.Info("物料号为空,不再读取后面的数据"); return ""; } var cgDetail = db.Queryable().First(a => a.S_CNTR_CODE == locCntrCg.CntrCode && a.S_ITEM_CODE == locCntrCg.ItemCode); if (cgDetail == null) { var locList = new List(); locList.Add(new TN_CG_Detail { S_CNTR_CODE = locCntrCg.CntrCode, S_ITEM_CODE = locCntrCg.ItemCode, S_BATCH_NO = locCntrCg.BatchNo ?? "" }); if (db.Insertable(locList).ExecuteCommand() <= 0) { tran.RollbackTran(); LogHelper.Info($"插入托盘物料关系{locCntrCg.CntrCode}-{locCntrCg}失败"); return "插入失败"; } } tran.CommitTran(); } return "插入数据成功"; } catch (Exception ex) { return $"Error reading CSV file: {ex.Message}"; } } /// /// DEBUG:根据容器物料信息表,插入容器物料登记信息表 /// /// [HttpPost] [Route("InsertContainerItemByCgDetail")] public string InsertContainerItemByCgDetail(FalseOk _) { var db = new SqlHelper().GetInstance(); try { var cgDetailList = db.Queryable().ToList(); var cntrItemList = new List(); foreach (var cgDetail in cgDetailList) { if (db.Queryable().Where(i => i.S_CNTR_CODE == cgDetail.S_CNTR_CODE).Any()) { continue; } cntrItemList.Add(new TN_Container_ItemType { S_CNTR_CODE = cgDetail.S_CNTR_CODE, S_ITEM_CODE = cgDetail.S_ITEM_CODE, }); } if (db.Insertable(cntrItemList).ExecuteCommand() <= 0) { return "插入失败"; } return "插入成功"; } catch (Exception ex) { LogHelper.InfoEx(ex); return ex.Message; } } /// /// DEBUG:根据容器物料信息表,插入容器物料登记信息表 /// /// [HttpPost] [Route("InsertContainerItem")] public string InsertContainerItem(InsertCntrItemInfo cgDetail) { var db = new SqlHelper().GetInstance(); try { var cntrItem = new TN_Container_ItemType { S_CNTR_CODE = cgDetail.Cntr, S_ITEM_CODE = cgDetail.Item, }; if (db.Insertable(cntrItem).ExecuteCommand() <= 0) { return "插入失败"; } return "插入成功"; } catch (Exception ex) { LogHelper.InfoEx(ex); return ex.Message; } } /// /// DEBUG:模拟输送线产线满托盘下线流程 /// /// /// [HttpPost] [Route("AddInboundTask")] public string AddInboundTask(AddInboundTaskInfo model) { var db = new SqlHelper().GetInstance(); var info = ""; var taskName = TaskName.T托盘_满托下线入库; var startAreaName = AreaName.B包装区; try { var itemCode = model.ItemCode; var batchNo = model.BatchNo; var cntrCode = model.CntrCode; var startLocCode = model.StartLoc; var cgDetail = new TN_CG_Detail { S_ITEM_CODE = itemCode, S_BATCH_NO = batchNo, S_CNTR_CODE = cntrCode, }; // BEG 每次轮询都检查对应容器是否已登记,登记保持不变,未登记则插入 // TODO 可能会采用每次上线都更新的逻辑,后面再看 var cntrItemRel = db.Queryable() .Where(i => i.S_CNTR_CODE == cntrCode).First(); var insertTable = cntrItemRel == null; if (insertTable) { // 暂定在满托下线入库的时候,登记托盘容器-物料号关系(后面可能会改成系统维护) cntrItemRel = new TN_Container_ItemType { S_ITEM_CODE = itemCode, S_CNTR_CODE = cntrCode, S_CNTR_TYPE = "托盘", }; } // END var startLoc = db.Queryable() .Where(l => l.S_CODE == startLocCode) // 指定:起点货位号 .Where(l => l.N_LOCK_STATE == 0 && l.S_LOCK_STATE == "无" && l.C_ENABLE == "Y") // 筛选:未上锁 .Where(l => l.N_CURRENT_NUM == 0) .Where(l => Settings.AreaMap[startAreaName].Contains(l.S_AREA_CODE)) // 起点货区符合任务要求 .First(); if (startLoc == null) { info = $"起点位置 '{startLocCode}' 不存在或不具备取货要求"; LogHelper.Info(info); return info; } // 绑定货位和容器号 var locCntrRel = new TN_Loc_Container { S_LOC_CODE = startLocCode, S_CNTR_CODE = cgDetail.S_CNTR_CODE, S_CNTR_TYPE = "托盘", }; var endLoc = db.Queryable() .Where(a => Settings.AreaMap[AreaName.M满托货架区].Contains(a.S_AREA_CODE)) .Where(a => a.N_LOCK_STATE == 0 && a.S_LOCK_STATE == "无" && a.C_ENABLE == "Y") // 筛选:未上锁 .Where(a => a.N_CURRENT_NUM == 0) // 筛选:空货位 .OrderBy(l => l.N_LAYER) .First(); if (endLoc == null) { info = "空托入库暂时没有合适的货位可以入库"; LogHelper.Info(info); return info; } var cntId = locCntrRel.S_CNTR_CODE; var task = WCSHelper.BuildTask(startLoc, endLoc, cntId, taskName); LocationHelper.LockStartLoc(ref startLoc); // 起点出库锁 LocationHelper.LockEndLoc(ref endLoc); // 终点入库锁 using (var tran = db.Ado.UseTran()) { if (db.Insertable(cgDetail).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"插入容器货品信息表失败:物料编码{cgDetail.S_ITEM_CODE},容器编码{cgDetail.S_CNTR_CODE}"; LogHelper.Info(info); return info; } // BEG 插入或更新容器与物料类型的绑定表 if (insertTable) { if (db.Insertable(cntrItemRel).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"登记容器物料类型绑定表失败:物料编码{cntrItemRel.S_ITEM_CODE},容器编码{cntrItemRel.S_CNTR_CODE}"; LogHelper.Info(info); return info; } } //else { // if (db.Updateable(cntrItemRel).ExecuteCommand() <= 0) { // tran.RollbackTran(); // info = $"登记容器物料类型绑定表失败:物料编码{cntrItemRel.S_ITEM_CODE},容器编码{cntrItemRel.S_CNTR_CODE}"; // LogHelper.Info(info); // return info; // } //} // END if (db.Insertable(locCntrRel).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"插入货位容器关系表失败:货位编码{locCntrRel.S_LOC_CODE},容器编码{locCntrRel.S_CNTR_CODE}"; LogHelper.Info(info); return info; } if (db.Updateable(startLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"生成任务'{taskName}'失败:更新起点货位{startLoc.S_CODE}锁状态失败"; LogHelper.Info(info); return info; } if (db.Updateable(endLoc).UpdateColumns(it => new { it.N_LOCK_STATE, it.S_LOCK_STATE, it.S_LOCK_OP, it.T_MODIFY }).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"生成任务'{taskName}'失败:更新终点货位{endLoc.S_CODE}锁状态失败"; LogHelper.Info(info); return info; } if (db.Insertable(task).ExecuteCommand() <= 0) { tran.RollbackTran(); info = $"生成任务'{taskName}'失败,容器号{cntId},起点{startLoc.S_CODE},终点货架{endLoc.S_CODE}"; LogHelper.Info(info); return info; } tran.CommitTran(); info = $"生成任务'{taskName}'成功,容器号{cntId},起点{startLoc.S_CODE},终点货架{endLoc.S_CODE}"; LogHelper.Info(info); return info; } } catch (Exception ex) { LogHelper.InfoEx(ex); return ex.Message; } } } public class AddInboundTaskInfo { /// /// 物料编码 /// public string ItemCode { get; set; } /// /// 批次号 /// public string BatchNo { get; set; } /// /// 容器编码 /// public string CntrCode { get; set; } /// /// 起始货位 /// public string StartLoc { get; set; } } /// /// 模拟 AGV 传递信号,用于更改任务状态 /// public class UpdateTaskState { /// /// 任务ID /// public string TaskID { set; get; } /// /// AGV 小车号 /// public string ForkliftNo { set; get; } ///// ///// AGV 下一个状态 ///// //public int NextState { set; get; } } public class FalseOk { public bool JumpOut { set; get; } = true; } public class InsertCntrItemInfo { public string Cntr { set; get; } public string Item { set; get; } } /// /// /// public class ReturnResults { public List ResultList { set; get; } } public class LocCntrCg { public string Note { get; set; } // 仅用于备注 public string LocCode { get; set; } public string LocArea { get; set; } public string CntrCode { get; set; } public string CntrType { get; set; } public string ItemCode { get; set; } public string BatchNo { get; set; } } }