using HH.WCS.JingyuNongfu.core; using HH.WCS.JingyuNongfu.device; using HH.WCS.JingyuNongfu.dispatch; using HH.WCS.JingyuNongfu.util; using HH.WCS.JingyuNongfu.wms; using Newtonsoft.Json; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security.Cryptography; using static HH.WCS.JingyuNongfu.api.ApiModel; namespace HH.WCS.JingyuNongfu.process { internal class TaskProcess { private static HttpHelper httpHelper = new HttpHelper(); #region 任务相关 //--------------------------------------------------任务相关-------------------------------------------------- private static object locLocker = new object(); /// /// 申请出入库任务 /// /// /// /// /// /// /// /// /// internal static bool ApplyWMSTask(Location ls, ref List cntrs, string area, string itemCode, string itemBatch, string taskType, bool insStock = true) { var result = false; lock (locLocker) { try { if (insStock) { Console.WriteLine($"LocationHelperCreateTask: {area}-{itemCode}-{itemBatch}-{taskType}"); var endLocation = WMSHelper.IntensiveArea.GetLocation4In(area, itemCode, itemBatch, 3); if (endLocation != null) { var endLayer = endLocation.N_CURRENT_NUM == 0 ? 1 : 2; var taskNo = DateTime.Now.Ticks.ToString(); result = TaskProcess.CreateTransport(ls.S_LOC_CODE, endLocation.S_LOC_CODE, taskType, cntrs, 1, endLayer, 3, 70); } else { Console.WriteLine($"LocationHelperCreateTask: 未找到终点货位"); } } else { var startLocation = WMSHelper.IntensiveArea.GetLocation4Out(area, itemCode, itemBatch, 3); if (startLocation != null) { var startLayer = startLocation.N_CURRENT_NUM <= 3 ? 1 : 2; var taskNo = DateTime.Now.Ticks.ToString(); var carryCount = startLocation.N_CURRENT_NUM > 3 ? startLocation.N_CURRENT_NUM - 3 : startLocation.N_CURRENT_NUM; //出库要从起点获取托盘 var cntrList = LocationHelper.GetLocCntr(startLocation.S_LOC_CODE); if (cntrList.Count == startLocation.N_CURRENT_NUM) { cntrs = cntrList.OrderByDescending(a => a.T_CREATE).Take(carryCount).Select(a => a.S_CNTR_CODE.Trim()).ToList(); result = TaskProcess.CreateTransport(startLocation.S_LOC_CODE, ls.S_LOC_CODE, taskType, cntrs, startLayer, 1, carryCount, 65); } else { Console.WriteLine($"起点托盘数量和货位容器表不符合,请检查【货位表】和【货位容器表】"); } } } } catch (Exception ex) { Console.WriteLine("LocationHelperCreateTask:" + ex.Message); LogHelper.Error("LocationHelperCreateTask:" + ex.Message, ex); } } return result; } /// /// 取货卸货完成,缓存位状态更新 /// /// /// internal static void CacheBitUpdate(WMSTask mst, bool load) { var trayCarryCount = mst.N_CNTR_COUNT > 0 ? mst.N_CNTR_COUNT : 1; if (load) { Console.WriteLine($"任务{mst.S_TASK_NO} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTRS}"); LogHelper.Info($"任务{mst.S_TASK_NO} 货位{mst.S_START_LOC}取货完成,起点解绑容器{mst.S_CNTRS}"); LocationHelper.UnBindingLoc(mst.S_START_LOC, mst.S_CNTRS.Split(',').ToList()); } else { Console.WriteLine($"任务{mst.S_TASK_NO} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTRS}"); LogHelper.Info($"任务{mst.S_TASK_NO} 货位{mst.S_END_LOC}卸货完成,终点绑定容器{mst.S_CNTRS}"); LocationHelper.BindingLoc(mst.S_END_LOC, mst.S_CNTRS.Split(',').ToList()); } } /// /// 任务取消,缓存位状态更新 /// /// internal static void CacheBitCancelUpdate(WMSTask mst) { //任务取消,取货完成前的,起点的loadingCount和终点unLoadingCount都清除,取货完成的只处理终点 if (TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "4")) { //终点绑定 CacheBitUpdate(mst, false); //todo: 如果是电梯卸货任务电梯任务中间表状态,如 LocationHelper.UnLockLoc(mst.S_END_LOC); } else { //电梯卸货任务表直接删除 //起点终点解锁 LocationHelper.UnLockLoc(mst.S_START_LOC); LocationHelper.UnLockLoc(mst.S_END_LOC); //todo: 如果是电梯卸货任务取消删除,如果是电梯取货任务取消修改任务状态 } } /// /// 安全请求 /// /// /// /// /// internal static void OperateReq(string no, int state, string forkliftNo, string extData) { //1103呼叫空托 卸货 1104 呼叫空托 卸货完成 var mst = TaskHelper.GetTask(no); if (state == 1103 || state == 1104) { Console.WriteLine($"进入安全请求,state:{state}"); if (mst != null) { Console.WriteLine($"获取到任务,进行卸料"); DeviceProcess.Xieliao(mst, state == 1103); } else { Console.WriteLine($"没获取到任务,不进行卸料"); } } else if (state == 1101 || state == 1102) { Console.WriteLine($"进入安全请求,state:{state}"); if (mst != null) { Console.WriteLine($"获取到任务,进行取料"); DeviceProcess.QuLiao(mst, state == 1101); } else { Console.WriteLine($"获取到任务,不进行取料"); } } } /// /// 任务拦截 /// /// /// internal static bool Intercept(WMSTask mst) { var result = false; //翻斗机叠空框 //电梯任务不推送,单独处理 if (mst.S_TYPE.Contains("-电梯")) { result = true; } if (mst.S_TYPE.Trim() == "翻斗机叠空框" && mst.N_PRIORITY == 90) { //判断相同终点的叠托任务是否存在,是否取货完成 var list = TaskHelper.GetTaskByEnd(mst.S_END_LOC); var otherTask = list.Where(a => a.N_PRIORITY == 99).FirstOrDefault(); if (otherTask != null && !TaskHelper.CheckActionRecordExist(otherTask.S_TASK_NO, "4")) { TaskHelper.UpdateStatus(mst, "未执行"); result = true; } } return result; } /// /// 任务状态更新处理 /// /// /// internal static void OperateStatus(WMSTask mst, int state, string TaskNo) { LogHelper.Info("任务信息 Request:" + JsonConvert.SerializeObject(mst), "HosttoagvTask"); var db = new SqlHelper().GetInstance(); if (state == 4) { CacheBitUpdate(mst, true); } if (state == 6)//卸货完成 { CacheBitUpdate(mst, false); } if (state == 7 || state == -1) { //成品取消工单 删除托盘 if (mst.S_TYPE.Contains("栈板上线")) { //非成品取消工单,任务为取货完成直接失败 删除托盘 if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "4")) { //CacheBitCancelUpdate(mst); TaskHelper.UpdateStatus(TaskNo.Trim(), "失败"); //起点终点解绑 删除托盘表托盘 TaskProcess.CacheBitUpdate(mst, true); TaskProcess.CacheBitCancelUpdate(mst); var tpid = mst.S_CNTRS.Split(','); foreach (var item in tpid) { ContainerHelper.delCntrAndItem(item); } } else { //如果取货完成,开始卸货,卸货完成取消任务,则让任务直接强制完成 //CacheBitUpdate(mst, false); TaskHelper.UpdateStatus(TaskNo.Trim(), "强制完成"); TaskProcess.CacheBitUpdate(mst, false); if (mst.S_TYPE.Contains("成品下线")) { //var order = db.Queryable().Where(a => a.S_WorkNo == mst.S_SRC_NO).First(); // LogHelper.Info("成品工单信息" + JsonConvert.SerializeObject(order), "ThirdSystemLog"); if (mst.S_NOTE == "是" ) { LogHelper.Info($"有码模式进入任务完成状态回报,任务{mst.S_TASK_NO}", "ThirdSystemLog"); TaskProcess.ThirdReportStatus(mst); } } } } //成品取消工单 删除托盘 else if (mst.S_TYPE.Contains("成品下线")) { //非成品取消工单,任务为取货完成直接失败 删除托盘 if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "4")) { //CacheBitCancelUpdate(mst); TaskHelper.UpdateStatus(TaskNo.Trim(), "失败"); //起点终点解绑 删除托盘表托盘 TaskProcess.CacheBitUpdate(mst, true); TaskProcess.CacheBitCancelUpdate(mst); var tpid = mst.S_CNTRS.Split(','); foreach (var item in tpid) { ContainerHelper.delCntrAndItem(item); } } else { //如果取货完成,开始卸货,卸货完成取消任务,则让任务直接强制完成 //CacheBitUpdate(mst, false); TaskHelper.UpdateStatus(TaskNo.Trim(), "强制完成"); if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "5")) { TaskProcess.CacheBitUpdate(mst, false); } if (mst.S_TYPE.Contains("成品下线")) { // var order = db.Queryable().Where(a => a.S_WorkNo == mst.S_SRC_NO).First(); // LogHelper.Info("成品工单信息" + JsonConvert.SerializeObject(order), "ThirdSystemLog"); if (mst.S_NOTE == "是") { LogHelper.Info("有码模式进入任务完成状态回报", "ThirdSystemLog"); TaskProcess.ThirdReportStatus(mst); } } } } //移库取消 工单不删除托盘 else if (mst.S_TYPE.Contains("移库")) { //移库取货完成前取消任务,只解锁起点终点 if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "4")) { TaskHelper.UpdateStatus(TaskNo.Trim(), "失败"); //起点终点解绑 TaskProcess.CacheBitCancelUpdate(mst); } //如果取货完成,开始卸货,卸货完成取消任务,直接让货位放到终点 else { if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "6")) { TaskProcess.CacheBitUpdate(mst, false); } TaskHelper.UpdateStatus(TaskNo.Trim(), "强制完成"); if (mst.S_TYPE.Contains("移库") && !mst.S_CNTRS.Contains("TP")) { LogHelper.Info("有码模式进入任务完成状态回报", "ThirdSystemLog"); TaskProcess.ThirdReportStatus(mst); } } } //瓶坯 瓶盖流程取消订单,删除托盘 else { #region 复位信号 if (mst.S_TYPE.Contains("翻斗机") && !mst.S_TYPE.Contains("二期")) { if (mst.S_B_STATE == "开始取货") { LogHelper.Info($"任务取消,且翻斗机任务空取,不发送复位信号", "发送信号"); } else { var info = Settings.deviceInfos.Where(a => a.location.Contains(mst.S_END_LOC)).FirstOrDefault(); if (info == null) { info = Settings.deviceInfos.Where(a => a.location.Contains(mst.S_START_LOC)).FirstOrDefault(); } if (info != null) { LogHelper.Info($"任务取消,翻斗机发送复位信号", "发送信号"); PlcHelper.SendHex(info.address, "3F00100D0A"); } } } if (mst.S_TYPE.Contains("注塑")&&!mst.S_TYPE.Contains("二期")) { //注塑机下线判断 var start = Settings.deviceInfos.Where(a => a.location.Contains(mst.S_START_LOC)).FirstOrDefault(); if (start != null) { // var zuj = Settings.deviceInfos.Where(a => a.deviceName == start.deviceName).FirstOrDefault(); if (start.location[0] == mst.S_START_LOC) { LogHelper.Info($"任务取消,注塑机发送复位信号", "发送信号"); PlcHelper.SendHex(start.address, "3F00100D0A"); } else if (start.location[1] == mst.S_START_LOC) { LogHelper.Info($"任务取消,注塑机发送复位信号", "发送信号"); PlcHelper.SendHex(start.address, "3F00200D0A"); } } //注塑机上线发送复位信号,有3不发送复位信号 var end = Settings.deviceInfos.Where(a => a.location.Contains(mst.S_END_LOC)).FirstOrDefault(); if (end != null) { if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "3")) { if (end.location[0] == mst.S_END_LOC) { LogHelper.Info($"任务取消,注塑机发送复位信号", "发送信号"); PlcHelper.SendHex(end.address, "3F00100D0A"); } else if (end.location[1] == mst.S_END_LOC) { LogHelper.Info($"任务取消,注塑机发送复位信号", "发送信号"); PlcHelper.SendHex(end.address, "3F00200D0A"); } } } } #endregion //非成品取消工单,任务为取货完成直接失败 删除托盘 if (!TaskHelper.CheckActionRecordExist(mst.S_TASK_NO, "4")) { //CacheBitCancelUpdate(mst); TaskHelper.UpdateStatus(TaskNo.Trim(), "失败"); //起点终点解绑 删除托盘 TaskProcess.CacheBitUpdate(mst, true); TaskProcess.CacheBitCancelUpdate(mst); var tpid = mst.S_CNTRS.Split(','); foreach (var item in tpid) { ContainerHelper.delCntr(item); } } else { //CacheBitUpdate(mst, false); TaskHelper.UpdateStatus(TaskNo.Trim(), "强制完成"); TaskProcess.CacheBitUpdate(mst, false); } } if (state == -1) { TaskHelper.UpdateStatus(TaskNo.Trim(), "未收到车体反馈"); } } } /// /// 解锁锁定排上报 /// /// /// internal static void AreaRowLockState(string AreaRow, bool state = true) { string msg = ""; List areaList = new List(); var req = new SimpleResultJY(); List taskAreaList = new List(AreaRow.Split(',')); taskAreaList.ForEach(a => { if (!string.IsNullOrEmpty(a)) areaList.Add(a); }); string[] AreaInfo = areaList.ToArray(); var url = Settings.GetThirdPartyUrlList.Where(a => a.UrlNo == "2" && a.Enable == "1").FirstOrDefault(); var httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); if (httpVerify != null) { string sendMsg = JsonConvert.SerializeObject(new { areaNum = AreaInfo, repoNo = "JY02-2", areaLock = state ? "1" : "2" }); req = FuLeWebPost1(sendMsg, "areaRowLockState", url.Url + "/areaRowLockState");//YKRWSD AreaRowLockState } if (req != null && req.success) msg = $"YKRWSD:返回库位状态成功:{JsonConvert.SerializeObject(req)}!"; else msg = $"YKRWSD:返回库位状态失败:{JsonConvert.SerializeObject(req)}!"; LogHelper.Info(msg, "ThirdSystemLog"); } internal static int FindAgvSite(string loc, string type) { int agvsite; agvsite = LocationHelper.GetAgvSite1(loc, type); return agvsite; } /// /// 推送任务 /// /// internal static bool SendTask(WMSTask mst) { var result = false; var start = 0; var end = 0; var db = new SqlHelper().GetInstance(); if (mst.S_B_STATE == "未执行" || mst.S_B_STATE == "待推送") { var startLoc = LocationHelper.GetLocation(mst.S_START_LOC); var endLoc = LocationHelper.GetLocation(mst.S_END_LOC); //start = startLoc.N_AGV_CODE; //end = endLoc.N_AGV_CODE; //查询货位站点对照表 if (mst.N_START_LAYER > 1) { // var aaaa=db.Queryable().Where(a => a.S_LOC_CODE.Trim() == mst.S_START_LOC&&a.S_PICKUP_POINT== mst.N_START_LAYER.ToString()).First(); //查货位扩展表 LocationExt start = LocationHelper.GetAgvSite(mst.S_START_LOC, mst.N_START_LAYER.ToString()); } if (mst.N_END_LAYER > 1) { //查货位扩展表 LocationExt end = LocationHelper.GetAgvSite(mst.S_END_LOC, mst.N_END_LAYER.ToString()); } //瓶坯,瓶盖,转运上线下线流程需要找agv站点扩展表 if (mst.S_TYPE.Contains("注塑") || mst.S_TYPE.Contains("翻斗机") || mst.S_TYPE.Contains("转运")) { if (!mst.S_TYPE.Contains("二期")) { //上线下线转运任务先找agv站点扩展表 if (mst.S_TYPE.Contains("上线")) { start = FindAgvSite(mst.S_START_LOC, "1"); } else if (mst.S_TYPE.Contains("下线")) { end = FindAgvSite(mst.S_END_LOC, "2"); } else if (mst.S_TYPE.Contains("转运")) { end = FindAgvSite(mst.S_END_LOC, "2"); } } } //else if (mst.S_TYPE.Contains("顶升机")) //{ // if (mst.S_TYPE.Contains("留样品")) // { // start = FindAgvSite(mst.S_START_LOC, "11"); // } // else // { // start = FindAgvSite(mst.S_START_LOC, "10"); // } //} //找不到扩展表数据默认赋值货位表站点 if (start == 0) start = startLoc.N_AGV_CODE; if (end == 0) end = endLoc.N_AGV_CODE; //Console.WriteLine($"SendTask {mst.S_TASK_NO}"); //Console.WriteLine("start=" + start); //Console.WriteLine("end= " + end); LogHelper.Info($"任务信息:任务号:{mst.S_TASK_NO}起点:{start},终点:{end},类型:{mst.S_TYPE}", "任务"); try { bool res = false; /*任务参数0 IKEY 任务参数1 取货站点 任务参数2 卸货站点 任务参数3 FUNC 任务参数4 DATA 任务参数5 物料高度(品项) 任务参数6 托盘版型 任务参数7 起点列(注:第一列给0,以此类推) 任务参数8 终点列(注:第一列给0,以此类推) */ var dic = new Dictionary(); dic.Add("From", start.ToString()); dic.Add("To", end.ToString()); var ts = GetTS(mst); if (ts == 1) { dic.Add("FUNC", "0"); dic.Add("DATA", "0"); } else { string func = "0"; if (mst.S_TYPE.Contains("移库")) { func = "32"; } dic.Add("FUNC", func); /*状态值 说明 0x000F 卸货层数 取值:0-15 0x00F0 取货层数 取值:0-15 0x0F00 流程类型 取值:0-15 0xF000 托盘类型 取值:0-15 */ var tb = mst.S_CNTRS.Split(','); Container cntr = ContainerHelper.GetCntr(tb[0]); ; int size = 0; switch (cntr.S_TYPE) { case "集化板": size = 1; break; case "大板": size = 2; break; case "小板": size = 3; break; case "集化板前后超托": size = 4; break; case "大板前后超托": size = 5; break; case "小板前后超托": size = 6; break; case "集化板四面超托": size = 7; break; case "纸箱空托": size = 10; break; case "废料": size = 10; break; case "留样品": size = 11; break; } if (mst.S_TYPE.Contains("留样品下线")) { size = 1; } else if (mst.S_TYPE.Contains("纸箱下线")) { size = 10; } LogHelper.Info($"推送任务,任务号:{mst.S_TASK_NO},货位信息:" + JsonConvert.SerializeObject(endLoc), "任务"); //参数4 var data = (mst.N_END_LAYER) + (16 * mst.N_START_LAYER); dic.Add("DATA", data.ToString()); //参数5 //如果起点层或者终点层是3层,需要发对应三层TS高度 Console.WriteLine($"容器号:{mst.S_CNTRS}"); int height = 0; //是否查询富勒托盘,获取物料层高 var order = db.Queryable().Where(a => a.S_WorkNo == mst.S_SRC_NO && a.S_WorkState == "执行中").First(); if (order != null && order.withCode == "是") { height = ProcessHelperCP.GetTrayHeightByTrayFL(tb[0]); } else { //if (endLoc.N_LAYER == 3 || startLoc.N_LAYER == 3) //{ // var item = ContainerHelper.GetCntrItemRel(mst.S_CNTRS).First(); // var itemInfo = new SqlHelper().GetList(a => a.S_ITEM_CODE == item.S_ITEM_CODE)?.First(); // height = itemInfo.S_ITEM_LAYER1; // Console.WriteLine($"三层TS高度:{height}"); //} //else //{ if (mst.S_TYPE.Contains("留样品下线") || mst.S_TYPE.Contains("纸箱下线")) { height = 0; } else { height = ProcessHelperCP.GetTrayHeightByTray(tb[0]); Console.WriteLine($"二层TS高度:{height}"); } //} } if (height == 0) { if (mst.S_TYPE.Contains("成品")) { //找不到物料层高不推送任务 LogHelper.Info("根据物料信息找不到物料层高,物料信息有误,请检查", "任务"); return false; } } dic.Add("ItemHeight", height.ToString()); //参数6 dic.Add("TrayType", $"{size}"); dic.Add("ToCol", "0"); if (mst.S_TYPE.Contains("废料下线")) { dic.Add("FromCol", "0"); } else { dic["FromCol"] = startLoc.N_COL.ToString(); } //获取7和8 if (mst.S_TYPE.Contains("成品下线") || mst.S_TYPE == "成品移库" || mst.S_TYPE == "栈板上线") { Console.WriteLine("进入改终点"); Console.WriteLine($"终点库区编码:{endLoc.S_AREA_CODE},排号:{endLoc.N_ROW},列号:{endLoc.N_COL}"); //改终点 var flb = ProcessHelper.GetFreeLineBit(endLoc.S_AREA_CODE, endLoc.N_ROW, endLoc.N_COL); if (flb != null) { Console.WriteLine($"找到自由线段点位"); dic["ToCol"] = (endLoc.N_COL - flb.S_START_COL).ToString(); Console.WriteLine($"endLoc.N_COL:{endLoc.N_COL}"); Console.WriteLine($"flb.S_START_COL:{flb.S_START_COL}"); Console.WriteLine($"ToCol:{dic["ToCol"]}"); if (mst.N_END_LAYER == 1) { dic["To"] = flb.S_First_Bit.ToString(); } else if (mst.N_END_LAYER == 2) { dic["To"] = flb.S_Second_Bit.ToString(); } else { dic["To"] = flb.S_Three_Bit.ToString(); } } else { Console.WriteLine($"没找到自由线段点位"); } ////特殊移库没有用自由线段(均州) //var listAreas = new List { }; //if (mst.S_TYPE == "成品移库" && endLoc.S_AREA_CODE.StartsWith("III-HCZ02")) { // dic["To"] = end.ToString(); //} } if (mst.S_TYPE == "成品移库" || mst.S_TYPE == "栈板上线") { //改起点 var flb = ProcessHelper.GetFreeLineBit(startLoc.S_AREA_CODE, startLoc.N_ROW, startLoc.N_COL); if (flb != null) { dic["FromCol"] = (startLoc.N_COL - flb.S_START_COL).ToString(); Console.WriteLine($"startLoc.N_COL:{startLoc.N_COL}"); Console.WriteLine($"flb.S_START_COL:{flb.S_START_COL}"); Console.WriteLine($"FromCol:{dic["FromCol"]}"); if (mst.N_START_LAYER == 1) { dic["From"] = flb.S_First_Bit.ToString(); } else { dic["From"] = flb.S_Second_Bit.ToString(); } } else { Console.WriteLine($"没找到自由线段点位"); } } } res = NDCHelper.AddTaskNew(ts, mst.N_PRIORITY, mst.S_TASK_NO, dic); if (res) { TaskHelper.UpdateStatus(mst.S_TASK_NO, "已推送"); TaskHelper.AddActionRecord(mst.S_TASK_NO, 0, "", "AGV任务下达成功"); result = true; } else { TaskHelper.UpdateStatus(mst.S_TASK_NO, "未执行"); } } catch (Exception ex) { TaskHelper.UpdateStatus(mst.S_TASK_NO, "未执行"); } } return result; } private static int GetTS(WMSTask mst) { //根据任务类型判断成品(5)还是其它的(1) if (mst.S_TYPE.Contains("成品") || mst.S_TYPE.Contains("移库") || mst.S_TYPE.Contains("栈板上线") || mst.S_TYPE.Contains("留样品下线") || mst.S_TYPE.Contains("纸箱下线") || mst.S_TYPE.Contains("顶升机")|| mst.S_TYPE.Contains("废料下线")) { return 5; } return 1; } /// /// 创建搬运任务 /// /// /// /// /// /// /// /// /// /// public static bool CreateTransport(string start, string end, string taskType, List cntrs, int startLayer, int endLayer, int trayCarryCount = 1, int priority = 1, string srcno = "", string note = "否") { var result = false; //批次号存托盘号,1~3个托盘 var trayCodes = string.Join(",", cntrs); var taskNo = DateTime.Now.Ticks.ToString(); if (!string.IsNullOrEmpty(srcno)) { taskNo = srcno; } //配置文件如果配置优先级,用配置文件的优先级, //成品按设备区分优先级,先根据工单号找到成品工单,再根据产线号区分 if (taskType.Trim() == "成品下线") { WorkOrder1 workOrder1 = MESHelper.GetWorkByWorkno(srcno); if (workOrder1 != null) { var pri = Settings.taskTypePris.Where(a => a.name == workOrder1.S_PLineNo).FirstOrDefault(); if (pri != null) { priority = pri.pri; } } } else { var pri = Settings.taskTypePris.Where(a => a.name == taskType).FirstOrDefault(); if (pri != null) { priority = pri.pri; } } var res = TaskHelper.CreateTask(taskNo, start.Trim(), end.Trim(), taskType, priority, trayCodes, trayCarryCount, startLayer, endLayer, note); if (res) { result = true; //任务创建成功,起点货位出库锁定,终点货位入库锁定 LocationHelper.LockLoc(start, "出库锁"); LocationHelper.LockLoc(end, "入库锁"); //if (taskType.Contains("-电梯")) //{ // var elevatorTaskInfo = new ElevatorTaskInfo() // { // actionType = taskType == "满托-电梯" ? 1 : 2, // elevatorCacheBit = "", // start = start, // end = end, // sourceNo = taskNo, // count = trayCarryCount, // trayCode = trayCodes // }; //} } return result; } #endregion #region 回报接口 /// /// 第三方任务状态回报 /// /// /// internal static void ThirdReportStatus(WMSTask wmsTask = null) { TASK_STATUSFunc(wmsTask); } /// /// 接口状态回报处理 /// public class SimpleResultJY { public bool success { get; set; } public int errCode { get; set; } public string errMsg { get; set; } = ""; /// /// 响应数据 /// public Object data { get; set; } /// /// 响应编码 /// public string code { get; set; } /// /// 响应信息 /// public string message { get; set; } /// /// 响应信息类型 /// public string messageType { get; set; } /// /// 异常 /// public Exception exception { get; set; } } public class asnReferenceDModel { public string asnReferenceD { get; set; } } /// /// 任务信息接口--靖宇任务每个状态进行实时上传(包括任务创建时,上报 8) /// /// internal static void GeneralInterFaceFunc(WMSTask wmsTask, string taskStatus) { LogHelper.Info($"进入任务上报------", "ThirdSystemLog"); Console.WriteLine($"进入任务上报------"); string msg = ""; var req = new SimpleResultJY(); var db = new SqlHelper().GetInstance(); //取货完成取消任务上报2 if (TaskHelper.CheckActionRecordExist(wmsTask.S_TASK_NO, "4") && taskStatus == "7") taskStatus = "2"; try { //获取上报接口的URL var url = Settings.GetThirdPartyUrlList.Where(a => a.UrlNo == "4" && a.Enable == "1").FirstOrDefault(); LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_TASK_NO},任务状态:{taskStatus},获取URL:{url}", "ThirdSystemLog"); //任务类型数据处理 string taskType = ""; var taskTypeInfo = db.Queryable().Where(a => a.taskTypeName == wmsTask.S_TYPE.Trim()).First(); if (taskTypeInfo != null) { taskType = taskTypeInfo.taskType; LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_TASK_NO},任务状态:{taskStatus},任务类型数据处理:{taskType}", "ThirdSystemLog"); //托盘物料数据处理 List cntrList = new List(wmsTask.S_CNTRS.Split(','));//获取托盘数据 string itemCode = "";//物料编码 itemCode = GeneralInterFaceGetItemCodeFunc(wmsTask, db, cntrList, itemCode); if (itemCode == "") { itemCode = null; } LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_TASK_NO},任务状态:{taskStatus},物料编码:{itemCode}", "ThirdSystemLog"); List asnReferenceList = new List { };//托码数组 GeneralInterFaceGetTrayCodeFunc(wmsTask, db, out asnReferenceList, cntrList); LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_TASK_NO},任务状态:{taskStatus},获取托盘数据:{JsonConvert.SerializeObject(asnReferenceList)}", "ThirdSystemLog"); //AGV设备信息处理 string equipmentCode = ""; string orgCode = ""; string orgName = ""; string endTime = ""; string proxyInterfaceCode = "0050"; GeneralInterFaceGetAgvDeviceInfoFunc(wmsTask, db, ref equipmentCode, ref orgCode, ref orgName, ref proxyInterfaceCode); LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_TASK_NO},任务状态:{taskStatus},equipmentCode:{equipmentCode},orgCode:{orgCode},orgName:{orgName},proxyInterfaceCode:{proxyInterfaceCode}", "ThirdSystemLog"); DateTime dateTime = taskStatus == "1" ? Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8) : taskStatus == "2" || taskStatus == "7" ? Convert.ToDateTime(wmsTask.T_END_TIME).AddHours(-8) : taskStatus == "8" ? Convert.ToDateTime(wmsTask.T_CREATE).AddHours(-8) : DateTime.UtcNow; string createTime = GetTimeStamp(wmsTask.T_CREATE.AddHours(-8), 1, 2); string startTime = ""; //在C#中,使用DateTimeOffset.UtcNow.ToUnixTimeSeconds()方法获取Unix时间戳时,可能会多出一个毫秒。这是因为Unix时间戳是以秒为单位的,而DateTimeOffset.UtcNow返回的是UTC时间,其精度为100纳秒。 if (wmsTask.S_WORK_MODE != "agv" && !string.IsNullOrEmpty(wmsTask.S_WORK_MODE)) startTime = wmsTask.S_WORK_MODE; else { if (wmsTask.T_START_TIME == null || wmsTask.T_START_TIME.Value.Year == 1 || wmsTask.T_START_TIME.Value.Year == 1900) { startTime = null; } else { startTime = GetTimeStamp(Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8), 1, 2); } //startTime = wmsTask.T_START_TIME == null ? null : GetTimeStamp(Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8), 1, 2); if (startTime != null) { wmsTask.S_WORK_MODE = startTime; db.Updateable(wmsTask).UpdateColumns(a => new { a.S_WORK_MODE }).ExecuteCommand(); } } if (wmsTask.T_END_TIME == null || wmsTask.T_END_TIME.Value.Year == 1 || wmsTask.T_END_TIME.Value.Year == 1900) { endTime = null; } else { endTime = GetTimeStamp(Convert.ToDateTime(wmsTask.T_END_TIME).AddHours(-8), 1, 2); } //string endTime = wmsTask.T_END_TIME == null ? null : GetTimeStamp(Convert.ToDateTime(wmsTask.T_END_TIME).AddHours(-8), 1, 2); string businessTime = taskStatus == "1" ? startTime : taskStatus == "2" || taskStatus == "7" ? endTime : taskStatus == "8" ? createTime : GetTimeStamp(dateTime, 1, 2); //string dt = wmsTask.T_START_TIME == null ? null : Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8).ToString(); //string mill = wmsTask.T_START_TIME == null ? null : Convert.ToDateTime(wmsTask.T_START_TIME).AddHours(-8).Millisecond.ToString(); LogHelper.Info($"GeneralInterFaceFunc:任务号:{wmsTask.S_TASK_NO},任务状态:{taskStatus},任务开始时间:{wmsTask.T_START_TIME},转换后时间:{startTime}", "ThirdSystemLog"); string sendMsg = JsonConvert.SerializeObject(new { taskCode = wmsTask.S_TASK_NO,//任务编码 taskStatus = taskStatus,//任务状态-任务创建成功传输 8 taskType = taskType,//任务类型-需要根据 配置表数据进行转换,转换为MES的任务类型 createTime = createTime,//需转换为 时间戳 wmsTask.T_CREATE startTime = startTime,//需转换为 时间戳 wmsTask.T_START_TIME endTime = endTime,//需转换为 时间戳 wmsTask.T_END_TIME businessTime = businessTime,//当前任务时间-需转换为 时间戳 DateTime.Now startAddress = wmsTask.S_START_LOC,//起点 endAddress = wmsTask.S_END_LOC,//终点 equipmentNo = wmsTask.S_EQ_NO,//车辆编号 equipmentCode = equipmentCode,//车辆铭牌-需要根据 配置表数据,通过 车辆编号以及工厂编码 查询对应车辆铭牌 orgCode = Settings.FactoryCode,//工厂编码 orgName = Settings.FactoryName,//工厂名称 sku = itemCode,//物料编码 asnReferenceDList = asnReferenceList,//托码数组 此次叉车叉的托盘喷码, 一次叉辆车,有两个编码 产线下线且非无码模式时传输 appliactionId = "MOBOX" //proxyInterfaceCode = proxyInterfaceCode //接口唯一标识码 固定值:0050 }); //http://yst-open-zuul-qa.idc.yst.com.cn/proxy/v1/ req = FuLeWebPost(sendMsg, "generalInterface", url.Url, true);//YKRWSD AreaRowLockState if (req != null && req.success) msg = $"GeneralInterFaceFunc:返回任务状态成功:{JsonConvert.SerializeObject(req)}!"; else msg = $"GeneralInterFaceFunc:返回任务状态失败:{JsonConvert.SerializeObject(req)}!"; } } catch (Exception ex) { msg = $"GeneralInterFaceFunc Error:TaskInfo:{JsonConvert.SerializeObject(wmsTask)},TaskState:{taskStatus},ErrorMsg:{ex.Message}"; LogHelper.Info(msg, "ThirdSystemLog"); Console.WriteLine(msg); } LogHelper.Info(msg, "ThirdSystemLog"); } /// /// 任务完成状态回报--1.正常任务完成回报 2.移库任务完成回报 /// /// /// internal static void TASK_STATUSFunc(WMSTask wmsTask) { LogHelper.Info($"进入富勒上报------ ,任务{wmsTask.S_TASK_NO}", "ThirdSystemLog"); string msg = ""; List trayList = new List(); var req = new SimpleResultJY(); var StartInfo = new SqlHelper().GetInstance().Queryable().Where(a => a.S_LOC_CODE == wmsTask.S_START_LOC.Trim()).First(); var EndInfo = new SqlHelper().GetInstance().Queryable().Where(a => a.S_LOC_CODE == wmsTask.S_END_LOC.Trim()).First(); List taskTrayList = new List(wmsTask.S_CNTRS.Trim().Split(',')); taskTrayList.ForEach(a => { if (!string.IsNullOrEmpty(a)) trayList.Add(a.Replace(" ", "")); }); string[] trayInfo = trayList.ToArray(); var url = Settings.GetThirdPartyUrlList.Where(a => a.UrlNo == "2" && a.Enable == "1").FirstOrDefault(); if (wmsTask.S_TYPE.Contains("移库")) { //移库任务 完成回报 var httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); if (httpVerify != null) { string sendMsg = JsonConvert.SerializeObject(new { startAreaNo = StartInfo.S_LOC_CODE.Substring(0, 3).ToString() + "-" + StartInfo.N_ROW.ToString().Trim(), endAreaNo = EndInfo.S_LOC_CODE.Substring(0, 3).ToString() + "-" + EndInfo.N_ROW.ToString().Trim(), trayInfo = trayInfo, repoNo = "JY02-2" }); req = FuLeWebPost1(sendMsg, "yikuTaskStatus", url.Url + "/yikuTaskStatus");//YKRWSD AreaRowLockState } } else if (wmsTask.S_TYPE.Contains("下线")) { var db = new SqlHelper().GetInstance(); string SrcNo = wmsTask.S_SRC_NO?.Trim(); // var workInfo = db.Queryable().Where(a => a.S_WorkNo == SrcNo).First(); // if (workInfo != null) // { // if (workInfo.S_ORDER_TYPE.Trim() != "无码入库")// 生产下线 //{ //产线下线 完成回报 var httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); if (httpVerify != null) { string sendMsg = JsonConvert.SerializeObject(new { trayInfo = trayInfo, workNo = wmsTask.S_SRC_NO.Trim(), repoNo = "JY02-2", areaLoca = EndInfo.S_LOC_CODE.Substring(0, 3).ToString() + "-" + EndInfo.N_ROW.ToString().Trim() }); req = FuLeWebPost1(sendMsg, "proTaskStatus", url.Url + "/proTaskStatus");//YKRWSD AreaRowLockState } // } // } } if (req != null && req.success) msg = $"TASK_STATUS:返回任务状态成功:{JsonConvert.SerializeObject(req)}!"; else msg = $"TASK_STATUS:返回任务状态失败:{JsonConvert.SerializeObject(req)}!"; LogHelper.Info(msg, "ThirdSystemLog"); } /// /// 任务信息接口--获取物料编码 /// /// private static string GeneralInterFaceGetItemCodeFunc(WMSTask wmsTask, SqlSugarClient db, List cntrList, string itemCode) { if (cntrList.Count > 0) { string SrcNo = wmsTask.S_SRC_NO?.Trim(); if (!string.IsNullOrEmpty(SrcNo) && wmsTask.S_TYPE.Contains("下线")) { var workInfo = db.Queryable().Where(a => a.S_PLineNo == SrcNo).First(); if (workInfo != null) { var itemInfo = db.Queryable().Where(a => a.S_ITEM_NAME == workInfo.SQL_ItemName).First(); if (itemInfo != null) { itemCode = itemInfo.S_ITEM_CODE; } } } else { var cntrItemInfo = db.Queryable().Where(a => a.S_CNTR_CODE == cntrList[0]).First(); if (cntrItemInfo != null) { var itemInfo = db.Queryable().Where(a => a.S_ITEM_NAME == cntrItemInfo.S_ITEM_NAME).First(); if (itemInfo != null) { itemCode = itemInfo.S_ITEM_CODE; } } } } return itemCode; } /// /// 任务信息接口--获取托盘数据 /// /// private static void GeneralInterFaceGetTrayCodeFunc(WMSTask wmsTask, SqlSugarClient db, out List asnReferenceList, List cntrList) { string SrcNo = wmsTask.S_SRC_NO?.Trim(); asnReferenceList = new List(); //根据任务中存放的工单号,获取工单类型--因为淳安 满托下线任务包含 下线 值,因此多判断一步,减少工单表的查询 if (!string.IsNullOrEmpty(SrcNo) && wmsTask.S_TYPE.Contains("下线")) { var workInfo = db.Queryable().Where(a => a.S_PLineNo == SrcNo).First(); if (workInfo != null) { if (cntrList.Count > 0) { foreach (var item in cntrList) { if (!string.IsNullOrEmpty(item)) asnReferenceList.Add(new asnReferenceDModel { asnReferenceD = item }); } } } } } /// /// 任务信息接口--获取AGV设备信息数据 /// /// /// /// /// /// /// private static void GeneralInterFaceGetAgvDeviceInfoFunc(WMSTask wmsTask, SqlSugarClient db, ref string equipmentCode, ref string orgCode, ref string orgName, ref string proxyInterfaceCode) { if (!string.IsNullOrEmpty(wmsTask.S_EQ_NO)) { var agvDeviceInfo = db.Queryable().Where(a => a.equipmentNo == wmsTask.S_EQ_NO && a.orgCode == Settings.FactoryCode).First(); if (agvDeviceInfo != null) { equipmentCode = agvDeviceInfo.equipmentCode; orgCode = agvDeviceInfo.orgCode; orgName = agvDeviceInfo.orgName; proxyInterfaceCode = agvDeviceInfo.proxyInterfaceCode; } } } /// /// 任务信息接口--获取时间戳 /// /// 数据位数:值:32|64 含义:32位|64位 /// 获取时间类型:值:1|2 含义:1-秒级 2-毫秒级 /// 获取时间Utc类型:值:1|2 含义:1-本地时间 2-Utc时间 /// public static string GetTimeStamp(DateTime dateTime, int DataBitType, int TimeType) { string timeStamp = ""; //时间戳打印 TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0);//时间戳获取 double tsTime = TimeType == 1 ? ts.TotalSeconds : ts.TotalMilliseconds;//秒级|毫秒级时间获取 string TimeTypeInfo = TimeType == 1 ? "秒级" : "毫秒级"; timeStamp = DataBitType == 32 ? Convert.ToInt32(tsTime).ToString() : Convert.ToInt64(tsTime).ToString(); //double result = 0; //result = DataBitType == 32 ? Convert.ToInt32(tsTime) : Convert.ToInt64(tsTime); return timeStamp; } /// /// FuLeWebPost /// /// 发送内容 /// 接口名称 /// 扩展参数 /// public static SimpleResultJY FuLeWebPost(string param, string postName, string Par1 = "", bool extend = false) { string msg = ""; string feedback = ""; SimpleResultJY result = new SimpleResultJY(); try { string webAPIUrl = ""; var httpVerify = new Settings.HttpApiVerifyModel { }; if (extend) httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "5" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); else httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); if (httpVerify != null) { //采用接口加密方式进行传输 webAPIUrl = $"{Par1}"; string TokenMsg = ""; string timestamp = DateTime.Now.ToString("s").Replace("T", " "); TokenMsg = httpVerify.Extend[0] + "from" + httpVerify.Extend[1] + "timestamp" + timestamp; LogHelper.Info($"【NF Post {postName}】:加密前明文:{TokenMsg}", "ThirdSystemLog"); string TokenMsgEncrypt = CryptoDecryptHelper.GetMd5FromString(TokenMsg); LogHelper.Info($"【NF Post {postName}】:加密后密文:{TokenMsgEncrypt}", "ThirdSystemLog"); LogHelper.Info($"webAPIUrl:{webAPIUrl},Token:{TokenMsgEncrypt}", "ThirdSystemLog"); feedback = httpHelper.WebPost(webAPIUrl, param, "application/json", TokenMsgEncrypt, timestamp, extend); } else { //标准传输方式传输 webAPIUrl = $"{Par1}{postName}" + "&warehouseId=FLUXWMSDB"; feedback = httpHelper.WebPost(webAPIUrl, param); } if (!string.IsNullOrEmpty(feedback)) { msg = $"【NF Post {postName}】WebUrl={webAPIUrl};param={param} ;return={feedback}"; var req = JsonConvert.DeserializeObject(feedback); if (req.success) { result.success = true; msg = $"【NF Post {postName}】success!;WebUrl={webAPIUrl};param={param};return={feedback}"; } else { if (!string.IsNullOrEmpty(req.errMsg)) msg = $"【FuLe Post {postName}】fail!err={req.errMsg};WebUrl={webAPIUrl} ;param={param};return={feedback}"; else msg = $"【NF Post {postName}】fail!err={req.message};WebUrl={webAPIUrl} ;param={param};return={feedback}"; } } else { string errMsg = "can't find the address"; msg = $"【NF Post {postName}】fail!err={errMsg};WebUrl={webAPIUrl} ;param={param}"; } var db = new SqlHelper().GetInstance(); var RepeatUrl = db.Queryable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).First(); if (result.success) { if (RepeatUrl != null) db.Deleteable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).ExecuteCommand(); } else { if (RepeatUrl == null) { var RepeatInfo = new HttpRepeatSend() { SendMsg = param, UrlName = postName, Url = Par1, SendNum = 5 }; db.Insertable(RepeatInfo).ExecuteCommand(); } else { if (RepeatUrl.SendNum == 1) db.Deleteable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).ExecuteCommand(); else { RepeatUrl.SendNum = RepeatUrl.SendNum - 1; db.Updateable(RepeatUrl).UpdateColumns(a => new { a.SendNum }).ExecuteCommand(); } } } } catch (Exception ex) { msg = $"【NF Post {postName}】fail!err={ex.Message}"; } LogHelper.Info(msg, "ThirdSystemLog"); return result; } /// /// 富勒上报 /// /// /// /// /// /// public static SimpleResultJY FuLeWebPost1(string param, string postName, string Par1 = "", bool extend = false) { string msg = ""; string feedback = ""; SimpleResultJY result = new SimpleResultJY(); try { string webAPIUrl = ""; var httpVerify = new Settings.HttpApiVerifyModel { }; if (extend) httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "5" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); else httpVerify = Settings.GetHttpApiVerifyList.Where(a => a.VerifyNo == "1" && a.Project == Settings.ProjectName && a.Enable == "1").FirstOrDefault(); if (httpVerify != null) { //采用接口加密方式进行传输 webAPIUrl = $"{Par1}"; string TokenMsg = ""; string timestamp = DateTime.Now.ToString("s").Replace("T", " "); TokenMsg = httpVerify.Extend[0] + "from" + httpVerify.Extend[1] + "timestamp" + timestamp; LogHelper.Info($"【FuLe Post {postName}】:加密前明文:{TokenMsg}", "富勒上报"); string TokenMsgEncrypt = CryptoDecryptHelper.GetMd5FromString(TokenMsg); LogHelper.Info($"【FuLe Post {postName}】:加密后密文:{TokenMsgEncrypt}", "富勒上报"); LogHelper.Info($"webAPIUrl:{webAPIUrl},Token:{TokenMsgEncrypt}", "富勒上报"); feedback = httpHelper.WebPostFl(webAPIUrl, param, "application/json", TokenMsgEncrypt, timestamp); } else { //标准传输方式传输 webAPIUrl = $"{Par1}{postName}" + "&warehouseId=FLUXWMSDB"; feedback = httpHelper.WebPostFl(webAPIUrl, param); } if (!string.IsNullOrEmpty(feedback)) { msg = $"【FuLe Post {postName}】WebUrl={webAPIUrl};param={param} ;return={feedback}"; var req = JsonConvert.DeserializeObject(feedback); if (req.success) { result.success = true; msg = $"【FuLe Post {postName}】success!;WebUrl={webAPIUrl};param={param};return={feedback}"; } else { if (!string.IsNullOrEmpty(req.errMsg)) msg = $"【FuLe Post {postName}】fail!err={req.errMsg};WebUrl={webAPIUrl} ;param={param};return={feedback}"; else msg = $"【FuLe Post {postName}】fail!err={req.message};WebUrl={webAPIUrl} ;param={param};return={feedback}"; } } else { string errMsg = "can't find the address"; msg = $"【FuLe Post {postName}】fail!err={errMsg};WebUrl={webAPIUrl} ;param={param}"; } var db = new SqlHelper().GetInstance(); var RepeatUrl = db.Queryable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).First(); if (result.success) { if (RepeatUrl != null) db.Deleteable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).ExecuteCommand(); } else { if (RepeatUrl == null) { var RepeatInfo = new HttpRepeatSend() { SendMsg = param, UrlName = postName, Url = Par1, SendNum = 5 }; db.Insertable(RepeatInfo).ExecuteCommand(); } else { if (RepeatUrl.SendNum == 1) db.Deleteable().Where(a => a.SendMsg == param && a.UrlName == postName && a.Url == Par1).ExecuteCommand(); else { RepeatUrl.SendNum = RepeatUrl.SendNum - 1; db.Updateable(RepeatUrl).UpdateColumns(a => new { a.SendNum }).ExecuteCommand(); } } } } catch (Exception ex) { msg = $"【FuLe Post {postName}】fail!err={ex.Message}"; } LogHelper.Info(msg, "富勒上报"); return result; } #endregion } }