wxw
2025-04-27 33572be8da5fd6534b56e1e22d70e8cf56f5fe41
开发料桶转运功能
3个文件已修改
2个文件已添加
721 ■■■■ 已修改文件
Wms/Model/InterFaceModel/AgvModel.cs 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/Utility/Tools/RcsHelper.cs 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/Utility/Utility.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/WMS.BLL/BllTransServer/HopperTransportServer.cs 454 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/WMS.IBLL/IBllTransServer/IHopperTransportServer.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/Model/InterFaceModel/AgvModel.cs
New file
@@ -0,0 +1,192 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Security.Policy;
using System.Text;
using System.Threading.Channels;
using System.Threading;
using System.Text.RegularExpressions;
namespace Model.InterFaceModel
{
    public class AgvCreateTaskModel
    {
        /// <summary>
        /// 任务类型
        /// </summary>
        public string taskType { get; set; } = "PF-LMR-COMMON";
        /// <summary>
        /// 执行步骤集合。本次任务机器人需要执行的关键路径,如货架起点 A 至出库工作台 B
        /// </summary>
        public List<targetRoute> targetRoute { get; set; }
        /// <summary>
        /// 任务执行的初始优先顺序,数值越大,优先级越高。但机器人调度系统会根据任务繁忙程度,机器人的工作状态,以及其他优先级修正条件,进行综合判定后,实时动态调整任务实际的优先级数值。范围:1~120
        /// </summary>
        public int initPriority { get; set; }
        /// <summary>
        /// 任务截止时间,任务优先级修正条件之一。截止时间之前需要任务执行完成, 超过时间后,系统会将任务单做出超时提示。格式:秒精度。
        /// </summary>
        public string deadline { get; set; }
        /// <summary>
        /// 要求调度系统仅在当前指定的范围内选择机器人执行该任务。可能出现任务与机器人类型不匹配的异常,需要业务系统确保任务与机器人类型的匹配。如果不指定,则调度系统会在所有可用机器人的范围内寻找最优方案。
        /// 固定枚举值:
        /// GROUPS机器人资源组编号
        /// ROBOTS机器人编号
        /// </summary>
        public string robotType { get; set; }
        /// <summary>
        /// 与 robotType 匹配的资源类型唯一标识。支持单个和多个编号。若写入多个编号时,之间用逗号隔开。
        /// </summary>
        public string robotCode { get; set; }
        /// <summary>
        /// 能否打断,
        /// 1:可打断
        /// 该货架中途有其他任务时,打断当前任务。
        /// 0:不可打断
        /// 该货架中途有其他任务时,不能打断当前任务。默认不可打断。
        /// </summary>
        public int interrupt { get; set; }
        /// <summary>
        /// 外部任务唯一编号,如果为空,系统生成任务号并返回。
        /// </summary>
        public string robotTaskCode { get; set; }
        /// <summary>
        /// 任务组编号,全局唯一
        /// </summary>
        public string groupCode { get; set; }
        /// <summary>
        /// 自定义扩展字段,可随业务的差异而传入不同的扩展内容,在业务流程的执行中使用
        /// </summary>
        public extra extra { get; set; }
    }
    /// <summary>
    /// 执行步骤集合。本次任务机器人需要执行的关键路径,如货架起点 A 至出库工作台 B
    /// </summary>
    public class targetRoute
    {
        /// <summary>
        /// 目标路径序列。从 0 开始。
        /// </summary>
        public int seq { get; set; }
        /// <summary>
        /// 目标类型。可扩展枚举值。
        /// 预制枚举值:
        /// ZONE目标所处区域编号
        /// SITE站点别名
        /// STORAGE仓位别名
        /// MAT_LABEL物料标签
        /// CARRIER载具编号
        /// STACK巷道编号
        /// STACK_LABEL巷道特征值
        /// CHANNEL通道编号
        /// EQPT 外部设备
        /// PTL_WALL
        /// CTU 缓存架
        /// CARRIER_TYPE载具类型
        /// BIN_TYPE仓位类型
        /// AREA_STATION区域工作台
        /// PILE_COUNT一次搬几个
        /// MIX_CONDITION条件组合
        /// DEGREE 热度
        /// MULTI_BIN_GROUP多深位组号
        /// </summary>
        public string type { get; set; }
        /// <summary>
        /// 机器人到达目标位置后的操作。国标要求,
        /// 非必要。对 AMR 动作无影响。可扩展的枚举值。
        /// 预制枚举值:
        /// COLLECT取货
        /// DELIVERY送货
        /// ROTATE旋转
        /// </summary>
        public string code { get; set; }
        /// <summary>
        /// 要求调度系统仅在当前指定的范围内选择机器人执行该步骤。可能出现任务步骤与机器人类型不匹配的异常,需要业务系统确保任务与机器人类型的匹配。如果指定当前步骤的机器人选择范围,则调度系统无视任务中设定的机器人选择范围;如果任务中也没有指定机器人选择范围,则调度系统会在所有可用机器人的范围内寻找最优方案。
        /// 固定枚举值:
        /// GROUPS机器人资源组编号
        /// ROBOTS机器人编号
        /// </summary>
        public string robotType { get; set; }
        /// <summary>
        /// 与 robotType 匹配的资源类型唯一标识。
        /// </summary>
        public string robotCode { get; set; }
        /// <summary>
        /// 自定义扩展字段,可随业务的差异而传入不同的扩展内容,在业务流程的执行中使用
        /// </summary>
        public extra extra { get; set; }
    }
    public class extra
    {
        /// <summary>
        /// 角度信息,包含角度类型与角度值。
        /// </summary>
        public angleInfo angleInfo { get; set; }
        /// <summary>
        /// 载具的信息,包含载具编号、层号。
        /// 使用场景:
        /// 1.装卸机或输送线专用
        /// 2.载具与站点没有绑定,但需要传入载具的场景。
        /// </summary>
        public List<carrierInfo> carrierInfo { get; set; }
    }
    public class angleInfo
    {
        /// <summary>
        /// 角度类型。可扩展枚举值。
        /// 预制枚举值:
        ///绝对角度(与工作站的方向有关)ABSOLUTE
        /// </summary>
        public string type { get; set; }
        /// <summary>
        /// 与 type 对应的值
        /// 角度值[0, 90, 180, -90, 360]
        /// </summary>
        public string code { get; set; }
    }
    public class carrierInfo
    {
        /// <summary>
        /// 载具类型
        /// </summary>
        public string carrierType { get; set; }
        /// <summary>
        /// 载具编号
        /// </summary>
        public string carrierCode { get; set; }
        /// <summary>
        /// 层号: 从 0 开始、从下往上编号
        /// </summary>
        public int layer { get; set; }
    }
    /// <summary>
    /// 返回实体
    /// </summary>
    public class ResponseAgvDto
    {
        /// <summary>
        /// 返回码
        /// SUCCESS:成功
        /// FAIL:失败
        /// 是否必填:是
        /// </summary>
        public string code { get; set; }
        /// <summary>
        /// 返回消息
        /// 是否必填:是
        /// </summary>
        public string message { get; set; }
        /// <summary>
        /// 返回的数据结构
        /// 是否必填:否
        /// </summary>
        public data data { get; set; }
    }
    public class data
    {
        public string robotTaskCode { get; set; }
    }
}
Wms/Utility/Tools/RcsHelper.cs
New file
@@ -0,0 +1,69 @@
using Model.InterFaceModel;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using ZXing;
using static Model.InterFaceModel.RCSModel;
namespace Utility.Tools
{
    public static class RcsHelper
    {
        public static bool CreateTaskForAgv(TaskDetial taskDetial, string url, out string agvMsg, string priority = null)
        {
            bool result = false;
            List<targetRoute> pahtList = new List<targetRoute>();
            //起始位置
            targetRoute royte1 = new targetRoute();
            royte1.seq = 0;
            royte1.type = "ZONE";
            royte1.code = taskDetial.Startport;
            pahtList.Add(royte1);
            //目标位置
            targetRoute royte2 = new targetRoute();
            royte2.seq = 0;
            royte2.type = "ZONE";
            royte2.code = taskDetial.Endport;
            pahtList.Add(royte2);
            AgvCreateTaskModel taskModel = new AgvCreateTaskModel();
            taskModel.taskType = "PF-LMR-COMMON";
            taskModel.targetRoute = pahtList;
            // 正式运行程序放开
            var jsonData = JsonConvert.SerializeObject(taskModel);
            string response = HttpHelper.DoPost(url, jsonData, "下发给AGV转运命令", "AGV");
            //解析返回数据
            var agvModel = JsonConvert.DeserializeObject<OutCommanAgvDto>(response);
            if (agvModel.Code == "0")
            {
                result = true;//给下车下发任务成功
                agvMsg = "";
            }
            else
            {
                string logMsg = "";
                if (taskDetial.Crtype == "1")//叫桶(桶出库)
                {
                    logMsg = "申请叫桶";
                }
                else if (taskDetial.Crtype == "0")//申请储位(桶入库)
                {
                    logMsg = "申请储位";
                }
                var logStr = $@".\log\AGV\AGV{logMsg}" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
                LogFile.SaveLogToFile($"AGV{logMsg}异常:( {agvModel.Message} ),", logStr);
                agvMsg = agvModel.Message;
            }
            return result;
        }
    }
}
Wms/Utility/Utility.csproj
@@ -18,4 +18,8 @@
    <PackageReference Include="ZXing.Net" Version="0.16.7" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Model\Model.csproj" />
  </ItemGroup>
</Project>
Wms/WMS.BLL/BllTransServer/HopperTransportServer.cs
@@ -6,10 +6,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using Utility.Tools;
using WMS.BLL.LogServer;
using WMS.DAL;
using WMS.Entity.BllAsnEntity;
using WMS.Entity.BllSoEntity;
using WMS.Entity.Context;
using WMS.Entity.DataEntity;
using WMS.Entity.LogEntity;
@@ -354,7 +358,7 @@
                    string agvMsg = string.Empty;
                    //给下车下发任务
                    logTaskEntry.SendDate = DateTime.Now;//发送时间
                    var agvResult = CreateTaskForAgv(task, url, out agvMsg);
                    var agvResult = RcsHelper.CreateTaskForAgv(task, url, out agvMsg);
                    if (agvResult)//成功
                    {
                        //请求成功修改任务表相应字段状态
@@ -401,7 +405,7 @@
        /// <param name="lotNo">批次</param>
        /// <param name="userId">操作人</param>
        /// <exception cref="Exception"></exception>
        public void jiaoCheHopper(string areaNo, string StartLocate, string plnNo, string plnStatus, decimal weight,  string skuNo, string lotNo, int userId)
        public void jiaoCheHopper(string areaNo, string StartLocate, string plnNo, string plnStatus, decimal weight,  string skuNo, string lotNo, string url,int userId)
        {
            try
            {
@@ -409,7 +413,7 @@
                if (string.IsNullOrWhiteSpace(areaNo) || string.IsNullOrWhiteSpace(StartLocate) || string.IsNullOrWhiteSpace(plnStatus))
                {
                    throw new Exception("区域/目标位/桶类型不能为空");
                    throw new Exception("区域/起始位/桶类型不能为空");
                }
                //if (plnStatus == "0" && string.IsNullOrWhiteSpace(standard))
@@ -421,29 +425,24 @@
                {
                    throw new Exception("满桶请选择物料与批次");
                }
                //判断目标叫料储位状态
                var endLocateInfo = Db.Queryable<SysStorageLocat>().First(m => m.IsDel == "0" && m.LocatNo == StartLocate && m.AreaNo == areaNo);
                if (endLocateInfo == null)
                {
                    throw new Exception("没有查询到目标储位信息");
                }
                if (endLocateInfo.Flag != "0")
                {
                    throw new Exception("目标储位标识不是正常可用的");
                }
                if (endLocateInfo.Status != "0")
                {
                    throw new Exception("目标储位状态不是空储位");
                }
                #endregion
                //开启事务
                Db.BeginTran();
                var pln = Db.Queryable<SysPallets>().First(m => m.IsDel == "0" && m.PalletNo == plnNo);
                var locate = Db.Queryable<SysStorageLocat>().First(m => m.IsDel == "0" && m.AreaNo == areaNo && m.LocatNo == StartLocate);
                var skuName = "";
                var packagNo = "";
                if (plnStatus == "2")
                //桶信息
                var pln = Db.Queryable<SysPallets>().First(w => w.IsDel == "0" && w.PalletNo == plnNo);
                if (pln == null)
                {
                    throw new Exception("未查询到桶信息");
                }
                //起始储位信息
                var startLoction = Db.Queryable<SysStorageLocat>().First(m => m.IsDel == "0" && m.AreaNo == areaNo && m.LocatNo == StartLocate);
                var skuName = "";//物料名称
                var packagNo = "";
                if (plnStatus == "2")//满桶
                {
                    //物料信息
                    var sku = Db.Queryable<SysMaterials>().First(m => m.IsDel == "0" && m.SkuNo == skuNo);
                    if (sku == null)
                    {
@@ -455,7 +454,17 @@
                {
                }
                //目标楼层
                var layer = startLoction.Layer;
                var houseStr = layer == 3 ? "3楼中间站" : layer == 4 ? "4楼中间站" : "";
                //通过仓库名称查询仓库信息
                var house = Db.Queryable<SysWareHouse>().First(m => m.IsDel == "0" && m.WareHouseName == houseStr);
                if (house == null)
                {
                    throw new Exception("没有查询到仓库信息");
                }
                //桶库存明细
                var stockDetail = Db.Queryable<DataStockDetail>().First(m => m.PalletNo == plnNo);
                if (stockDetail == null)
                {
@@ -471,7 +480,7 @@
                        FrozenQty = 0,
                        InspectQty = 0,
                        WareHouseNo = locate.WareHouseNo,
                        WareHouseNo = startLoction.WareHouseNo,
                        AreaNo = areaNo,
                        LocatNo = StartLocate,
                        PalletNo = plnNo,
@@ -497,20 +506,26 @@
                    Db.Updateable(stockDetail).ExecuteCommand();
                }
                //获取储位地址
                //分配储位
                var endLocatInfo = GetLocatModel(house.WareHouseNo, plnStatus, skuNo, pln.Standard);//目标储位
                //没有可用空储位
                if (endLocatInfo == null)
                {
                    throw new Exception("没有找到合适的目标储位");
                }
                var taskNo = new Common().GetMaxNo("TK");
                //添加任务
                var task = new LogTask
                var logTaskEntry = new LogTask
                {
                    TaskNo = taskNo,
                    Sender = "WMS",
                    Receiver = "WCS",
                    IsSuccess = 0, //是否下发成功 0失败 1成功
                    StartLocat = "",//起始位置
                    EndLocat = StartLocate,//目标位置
                    PalletNo = "",//托盘码
                    StartLocat = StartLocate,//起始位置
                    EndLocat = endLocatInfo.LocatNo,//目标位置
                    PalletNo = plnNo,//托盘码
                    IsSend = 1,//是否可再次下发
                    IsCancel = 1,//是否可取消
                    IsFinish = 1,//是否可完成
@@ -520,17 +535,187 @@
                    CreateTime = DateTime.Now
                };
                Db.Insertable(task).ExecuteCommand();
                Db.Insertable(logTaskEntry).ExecuteCommand();
                //组织下发小车任务信息
                var task = new TaskDetial
                {
                    Taskno = taskNo,//任务号
                    Startport = StartLocate,//起始位置
                    Endport = endLocatInfo.LocatNo,//目标位置
                    Pallno = plnNo,//桶号
                    Crtype = "1",//叫桶
                };
                //调用AGV接口下发任务
                string agvMsg = string.Empty;
                //给下车下发任务
                logTaskEntry.SendDate = DateTime.Now;//发送时间
                var agvResult = RcsHelper.CreateTaskForAgv(task, url, out agvMsg);
                if (agvResult)//成功
                {
                    //请求成功修改任务表相应字段状态
                    logTaskEntry.IsSuccess = 1;
                    logTaskEntry.IsSend = 0;
                    //logTaskEntry.IsCancel = 0;
                    logTaskEntry.BackDate = DateTime.Now;
                    logTaskEntry.Status = "1";//正在执行
                    Db.Insertable(logTaskEntry).ExecuteCommand();
                    startLoction.Status = "3";//出库中
                    Db.Updateable(startLoction).ExecuteCommand();
                    endLocatInfo.Status = "2";//入库中
                    Db.Updateable(endLocatInfo).ExecuteCommand();
                }
                else//失败
                {
                    logTaskEntry.IsSuccess = 0;
                    logTaskEntry.Information = agvMsg;
                    Db.Insertable(logTaskEntry).ExecuteCommand();
                }
                //提交事务
                Db.CommitTran();
            }
            catch (Exception e)
            {
                //回滚事务
                Db.RollbackTran();
                throw new Exception(e.Message);
            }
        }
        /// <summary>
        /// 小车反馈任务完成
        /// </summary>
        /// <param name="taskNo"></param>
        /// <param name="status"></param>
        /// <param name="comeFrom"></param>
        /// <param name="userId"></param>
        /// <exception cref="Exception"></exception>
        public void RCSFinishTask(string taskNo, string status, string comeFrom, int userId = 0)
        {
            try
            {
                #region 条件判断
                var resultModel = new ErpModel() { Success = -1, Message = "" };
                if (string.IsNullOrEmpty(taskNo))
                {
                    throw new Exception("任务号不可为空");
                }
                //任务信息
                var taskInfo = Db.Queryable<LogTask>().First(w => w.TaskNo == taskNo);
                if (taskInfo == null)
                {
                    throw new Exception($"任务号为:{taskNo}的任务不存在!");
                }
                if (taskInfo.Status != "1" && comeFrom != "WMS")
                {
                    throw new Exception($"任务号为:{taskNo}的任务状态异常");
                }
                #endregion
                //开启事务
                Db.BeginTran();
                var comTime = DateTime.Now;
                if (status == "0")
                {
                    taskInfo.Status = "3";//异常结束
                    //修改任务状态
                    Db.Updateable(taskInfo).ExecuteCommand();
                    resultModel.Success = 0;
                    resultModel.Message = "成功";
                    //提交事务
                    Db.CommitTran();
                    return;
                }
                //库存明细
                var stockDetail = Db.Queryable<DataStockDetail>().First(w => w.PalletNo == taskInfo.PalletNo);
                if (stockDetail == null)
                {
                    throw new Exception($"桶库存信息不存在");
                }
                //起始储位信息
                var startLocatInfo = Db.Queryable<SysStorageLocat>().First(w => w.LocatNo == taskInfo.StartLocat && w.IsDel == "0");
                if (startLocatInfo == null)
                {
                    throw new Exception($"起始储位信息不存在");
                }
                startLocatInfo.Status = "0";//空储位
                //修改起始储位状态
                Db.Updateable(startLocatInfo).ExecuteCommand();
                //目标储位信息
                var endLocatInfo = Db.Queryable<SysStorageLocat>().First(w => w.LocatNo == taskInfo.EndLocat && w.IsDel == "0");
                if (endLocatInfo == null)
                {
                    throw new Exception($"目标储位信息不存在");
                }
                endLocatInfo.Status = "1";//有物品
                //修改目标储位状态
                Db.Updateable(endLocatInfo).ExecuteCommand();
                //目标储位所属区域
                var endAreaInfo = Db.Queryable<SysStorageArea>().First(w => w.IsDel == "0" && w.WareHouseNo == endLocatInfo.WareHouseNo && w.AreaNo == endLocatInfo.AreaNo);
                if (endAreaInfo == null)
                {
                    throw new Exception($"目标储位所属区域信息不存在");
                }
                stockDetail.WareHouseNo = endLocatInfo.WareHouseNo;//所属仓库
                stockDetail.RoadwayNo = endLocatInfo.RoadwayNo;//所属巷道
                stockDetail.AreaNo = endLocatInfo.AreaNo;//所属区域
                stockDetail.LocatNo = endLocatInfo.LocatNo;//储位地址
                stockDetail.UpdateTime = DateTime.Now;//更新时间
                if (endAreaInfo.Type == "0")//净桶区
                {
                    stockDetail.PalletStatus = "0";
                    stockDetail.Status = "0";//待分配
                }
                else if (endAreaInfo.Type == "1")//满桶区
                {
                    stockDetail.PalletStatus = "1";
                    stockDetail.Status = "0";//待分配
                }
                else if (endAreaInfo.Type == "2")//脏桶区
                {
                    stockDetail.PalletStatus = "3";
                    stockDetail.LotNo = "";//批次
                    stockDetail.SkuNo = "";
                    stockDetail.SkuName = "";
                    stockDetail.Status = "0";//待分配
                    stockDetail.InspectStatus = "0";//待检验
                }
                //修改库存明细
                Db.Updateable(stockDetail).ExecuteCommand();
                taskInfo.Status = "2";//执行完成
                taskInfo.IsSend = 0;
                taskInfo.IsCancel = 0;
                taskInfo.IsFinish = 0;
                taskInfo.FinishDate = DateTime.Now;//完成时间
                //修改任务状态
                Db.Updateable(taskInfo).ExecuteCommand();
                if (comeFrom == "WMS")
                {
                    //添加操作日志记录
                    var k = new OperationCrServer().AddLogOperationCr("库内作业", "库内日志", taskInfo.TaskNo, "完成", $"点击完成按钮、任务号为:{taskInfo.TaskNo}的任务", userId);
                }
                //提交事务
                Db.CommitTran();
            }
            catch (Exception ex)
            {
                //回滚事务
                Db.RollbackTran();
                throw new Exception(ex.Message);
            }
        }
        private bool YikuTask(string palletNo, string taskNo, string url)
        {
@@ -624,7 +809,7 @@
                        string agvMsg = string.Empty;
                        //给下车下发任务
                        logTaskEntry.SendDate = DateTime.Now;//发送时间
                        var agvResult = CreateTaskForAgv(task, url, out agvMsg, "70");
                        var agvResult = RcsHelper.CreateTaskForAgv(task, url, out agvMsg, "70");
                        if (agvResult)//成功
                        {
                            //请求成功修改任务表相应字段状态
@@ -719,7 +904,7 @@
                    string agvMsg = string.Empty;
                    //给下车下发任务
                    logTaskInfoZ.SendDate = DateTime.Now;//发送时间
                    var agvResult = CreateTaskForAgv(task, url, out agvMsg, "70");
                    var agvResult = RcsHelper.CreateTaskForAgv(task, url, out agvMsg, "70");
                    if (agvResult)//成功
                    {
                        //请求成功修改任务表相应字段状态
@@ -794,59 +979,7 @@
                            continue;
                        }
                        //分配储位
                        var endLocatInfo = new SysStorageLocat();//目标储位
                        string areaNo = string.Empty;
                        switch (detailInfo.PalletStatus)
                        {
                            case "0"://净桶
                                //查到到净桶区域编号
                                areaNo = Db.Queryable<SysStorageArea>().Where(w => w.IsDel == "0" && w.WareHouseNo == itemHouseNo && w.Type == "0").Select(s => s.AreaNo).First();
                                //分配储位
                                endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                                    && w.WareHouseNo == detailInfo.WareHouseNo && w.AreaNo == areaNo)
                                                    .OrderBy(o => o.Row).OrderByDescending(o => o.Column).First();
                                break;
                            case "2"://满桶
                                //查到到满桶区域编号
                                areaNo = Db.Queryable<SysStorageArea>().Where(w => w.IsDel == "0" && w.WareHouseNo == itemHouseNo && w.Type == "1").Select(s => s.AreaNo).First();
                                //分配储位
                                //先查到同物料的组
                                string sql = $@"select Row from SysStorageLocat where WareHouseNo='{itemHouseNo}' and AreaNo='{areaNo}' and LocatNo in(
                                                select LocatNo from DataStockDetail where SkuNo='{detailInfo.SkuNo}' and SkuName='{detailInfo.SkuName}' and Standard='{detailInfo.Standard}' and WareHouseNo='{itemHouseNo}' and AreaNo='{areaNo}'
                                            ) group by Row";
                                List<int> RowList = Db.Ado.SqlQuery<int>(sql).ToList();
                                foreach (var rowItem in RowList)
                                {
                                    endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                                   && w.WareHouseNo == detailInfo.WareHouseNo && w.AreaNo == areaNo && w.Row == rowItem)
                                                   .OrderByDescending(o => o.Column).First();
                                    if (endLocatInfo != null)
                                    {
                                        break;
                                    }
                                }
                                //没有找到相同物料同组的空储位
                                if (endLocatInfo == null)
                                {
                                    endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                                   && w.WareHouseNo == detailInfo.WareHouseNo && w.AreaNo == areaNo)
                                                   .OrderBy(o => o.Row).OrderByDescending(o => o.Column).First();
                                }
                                break;
                            case "3"://脏桶
                               //查到到脏桶区域编号
                                areaNo = Db.Queryable<SysStorageArea>().Where(w => w.IsDel == "0" && w.WareHouseNo == itemHouseNo && w.Type == "2").Select(s => s.AreaNo).First();
                                //分配储位
                                endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                                    && w.WareHouseNo == detailInfo.WareHouseNo && w.AreaNo == areaNo)
                                                    .OrderBy(o => o.Row).OrderByDescending(o => o.Column).First();
                                break;
                        }
                        var endLocatInfo = GetLocatModel(itemHouseNo,detailInfo.PalletStatus,detailInfo.SkuNo,detailInfo.Standard);//目标储位
                        //没有可用空储位
                        if (endLocatInfo == null)
                        {
@@ -888,7 +1021,7 @@
                        string agvMsg = string.Empty;
                        //给下车下发任务
                        logTaskEntry.SendDate = DateTime.Now;//发送时间
                        var agvResult = CreateTaskForAgv(task, url, out agvMsg);
                        var agvResult = RcsHelper.CreateTaskForAgv(task, url, out agvMsg);
                        if (agvResult)//成功
                        {
                            //请求成功修改任务表相应字段状态
@@ -928,110 +1061,79 @@
                throw new Exception(e.Message);
            }
        }
        /// <summary>
        /// 给小车下发任务
        /// 分配储位
        /// </summary>
        /// <param name="req"></param>
        /// <param name="houseNo">仓库编号</param>
        /// <param name="palletStatus">桶状态</param>
        /// <param name="skuNo">物料编码</param>
        /// <param name="standard">桶规格</param>
        /// <returns></returns>
        public bool CreateTaskForAgv(TaskDetial taskDetial, string url, out string agvMsg, string priority = null)
        /// <exception cref="Exception"></exception>
        private SysStorageLocat GetLocatModel(string houseNo, string palletStatus,string skuNo="",string standard="")
        {
            bool result = false;
            try
            {
                var endLocatInfo = new SysStorageLocat();//目标储位
                string areaNo = string.Empty;
                switch (palletStatus)
                {
                    case "0"://净桶
                             //查到到净桶区域编号
                        areaNo = Db.Queryable<SysStorageArea>().Where(w => w.IsDel == "0" && w.WareHouseNo == houseNo && w.Type == "0").Select(s => s.AreaNo).First();
                        //分配储位
                        endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                            && w.WareHouseNo == houseNo && w.AreaNo == areaNo)
                                            .OrderBy(o => o.Row).OrderByDescending(o => o.Column).First();
                        break;
                    case "2"://满桶
                             //查到到满桶区域编号
                        areaNo = Db.Queryable<SysStorageArea>().Where(w => w.IsDel == "0" && w.WareHouseNo == houseNo && w.Type == "1").Select(s => s.AreaNo).First();
                        //分配储位
                        //先查到同物料的组
                        string sql = $@"select Row from SysStorageLocat where WareHouseNo='{houseNo}' and AreaNo='{areaNo}' and LocatNo in(
                                                select LocatNo from DataStockDetail where SkuNo='{skuNo}' and Standard='{standard}' and WareHouseNo='{houseNo}' and AreaNo='{areaNo}'
                                            ) group by Row";
            #region 呼叫小车代码
            List<PositionCodePath> pahtList = new List<PositionCodePath>();
            //起始位置
            PositionCodePath path1 = new PositionCodePath();
            path1.positionCode = taskDetial.Startport;
            if (taskDetial.Crtype == "1")//叫桶(桶出库)
                        List<int> RowList = Db.Ado.SqlQuery<int>(sql).ToList();
                        foreach (var rowItem in RowList)
            {
                path1.type = "05";
            }
            else if (taskDetial.Crtype == "0")//申请储位(桶入库)
            {
                path1.type = "00";
            }
            else//同车间平层搬运
            {
                path1.type = "05";
            }
            pahtList.Add(path1);
                            endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                           && w.WareHouseNo == houseNo && w.AreaNo == areaNo && w.Row == rowItem)
                                           .OrderByDescending(o => o.Column).First();
            //目标位置
            PositionCodePath path2 = new PositionCodePath();
            path2.positionCode = taskDetial.Endport;
            if (taskDetial.Crtype == "1")//叫桶(桶出库)
                            if (endLocatInfo != null)
            {
                path2.type = "00";
                                break;
            }
            else if (taskDetial.Crtype == "1")//申请储位(桶入库)
            {
                path2.type = "05";
            }
            else //同车间平层搬运
                        //没有找到相同物料同组的空储位
                        if (endLocatInfo == null)
            {
                path2.type = "05";
            }
            pahtList.Add(path2);
            //下车任务单
            AgvSchedulingTask agvTask = new AgvSchedulingTask();
            agvTask.reqCode = taskDetial.Taskno;//请求编号
            agvTask.taskCode = taskDetial.Taskno;//任务号
            agvTask.ctnrCode = taskDetial.Pallno;//桶号
            agvTask.reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");//请求时间
            agvTask.wbCode = "";
            agvTask.positionCodePath = pahtList;//小车路径
            agvTask.podCode = "";
            agvTask.userCallCode = "";//taskDetial.Endport;//目标位置
            agvTask.priority = priority;//优先级
            //判断容器类型
            agvTask.ctnrTyp = "1";// 1:桶 2:桶(小) 3:托盘
            //判断任务类型
            if (taskDetial.Crtype == "1")//叫桶(桶出库)
            {
                agvTask.taskTyp = "Z3";//任务类型 线边到托盘收集器 Z1, 托盘垛申请入库 Z2
            }
            else if (taskDetial.Crtype == "0")//申请储位(桶入库)
            {
                agvTask.taskTyp = "Z4";//任务类型 线边到托盘收集器 Z1, 托盘垛申请入库 Z2
            }
            else//同车间平层搬运
            {
                agvTask.taskTyp = "Z5";
                            endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                           && w.WareHouseNo == houseNo && w.AreaNo == areaNo)
                                           .OrderBy(o => o.Row).OrderByDescending(o => o.Column).First();
            }
            // 正式运行程序放开
            var jsonData = JsonConvert.SerializeObject(agvTask);
            string response = HttpHelper.DoPost(url, jsonData, "下发给AGV转运命令", "AGV");
            //解析返回数据
            var agvModel = JsonConvert.DeserializeObject<OutCommanAgvDto>(response);
            if (agvModel.Code == "0")
            {
                result = true;//给下车下发任务成功
                agvMsg = "";
            }
            else
            {
                string logMsg = "";
                if (taskDetial.Crtype == "1")//叫桶(桶出库)
                {
                    logMsg = "申请叫桶";
                }
                else if (taskDetial.Crtype == "0")//申请储位(桶入库)
                {
                    logMsg = "申请储位";
                }
                var logStr = $@".\log\AGV\AGV{logMsg}" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
                LogFile.SaveLogToFile($"AGV{logMsg}异常:( {agvModel.Message} ),", logStr);
                agvMsg = agvModel.Message;
            }
            return result;
            #endregion
        }
                        break;
                    case "3"://脏桶
                             //查到到脏桶区域编号
                        areaNo = Db.Queryable<SysStorageArea>().Where(w => w.IsDel == "0" && w.WareHouseNo == houseNo && w.Type == "2").Select(s => s.AreaNo).First();
                        //分配储位
                        endLocatInfo = Db.Queryable<SysStorageLocat>().Where(w => w.IsDel == "0" && w.Status == "0" && w.Flag == "0"
                                            && w.WareHouseNo == houseNo && w.AreaNo == areaNo)
                                            .OrderBy(o => o.Row).OrderByDescending(o => o.Column).First();
                        break;
                }
                return endLocatInfo;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}
Wms/WMS.IBLL/IBllTransServer/IHopperTransportServer.cs
@@ -17,7 +17,7 @@
        List<string> GetSku();
        void jiaoLiaoHopper(string areaNo, string endLocate, string plnStatus, string standard, string skuNo, string lotNo, string url, int userId);
        void jiaoCheHopper(string areaNo, string StartLocate, string plnNo, string plnStatus, decimal weight, string skuNo, string lotNo, int userId);
        void jiaoCheHopper(string areaNo, string StartLocate, string plnNo, string plnStatus, decimal weight, string skuNo, string lotNo, string url, int userId);
    }