Files
16-Xikai-MesProjectNew/Interface_WebAPI/SlMesDbIterface/WebAPI/AGV/TCSAGV_BusinessLogic.cs

837 lines
37 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Http;
using MesServerWork;
using MisDataSaveDate.Helper;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static MisDataSaveDate.Helper.ApiLogHelper;
namespace MisDataSaveDate
{
/// <summary>
/// TCS插拔任务业务处理。PLC自动任务与Web人工任务共用此入口。
/// </summary>
public class TCSAGV_BusinessLogic
{
private const string TaskTypeCombined = "nav_action_program";
private const string TaskTypeProgram = "program";
public static TCSAGV_CallResult DispatchStationTask(string stationCode, string actionType,
string portCombination, string source, string operatorCode, string parentExternalCode, bool notifyPlc)
{
TCSAGV_Config config = ReadConfig(true);
TCSAGV_PointConfig point = ReadPointConfig(stationCode);
string normalizedAction = NormalizeAction(actionType);
string productModel = "";
string combination;
if (string.IsNullOrWhiteSpace(portCombination))
{
productModel = ReadCurrentProductModel(point.StationCode);
combination = ReadModelActionCombination(point.LineCode, productModel, normalizedAction);
}
else
{
combination = NormalizePortCombination(portCombination);
}
JArray parameters = new JArray
{
new JObject { { "workStation", point.WorkStation } }
};
if (combination.Contains("XSD"))
{
parameters.Add(new JObject
{
{ "programName", normalizedAction == "插" ? point.InsertXsdProgram : point.PullXsdProgram }
});
}
if (combination.Contains("XSE"))
{
parameters.Add(new JObject
{
{ "programName", normalizedAction == "插" ? point.InsertXseProgram : point.PullXseProgram }
});
}
string externalCode = CreateExternalCode(normalizedAction == "插" ? "PLUG" : "PULL");
return CreateAndSendTask(config, point, externalCode, parentExternalCode, normalizedAction, "",
productModel, combination, TaskTypeCombined, parameters.ToString(Formatting.None), source,
operatorCode, notifyPlc);
}
public static TCSAGV_CallResult DispatchSingleStep(string stationCode, string programName,
string operatorCode, string parentExternalCode)
{
TCSAGV_Config config = ReadConfig(true);
TCSAGV_PointConfig point = ReadPointConfig(stationCode);
EnsureRobotAtPoint(config, point);
string normalizedProgram = (programName ?? "").Trim();
if (!IsConfiguredProgram(point, normalizedProgram))
{
throw new Exception("所选programName不属于该工位配置");
}
string action = normalizedProgram.Contains("拔") ? "拔-单步" : "插-单步";
JArray parameters = new JArray
{
new JObject { { "programName", normalizedProgram } }
};
return CreateAndSendTask(config, point, CreateExternalCode("STEP"), parentExternalCode,
action, normalizedProgram, "", normalizedProgram.Contains("XSD") ? "XSD" : "XSE",
TaskTypeProgram, parameters.ToString(Formatting.None),
"MANUAL", operatorCode, false);
}
public static TCSAGV_CallResult RetryTask(string externalCode, string operatorCode)
{
DataRow original = ReadTask(externalCode);
if (!IsFailureStatus(ToInt(original["任务状态"], -1)))
{
throw new Exception("仅任务错误状态允许整单重发");
}
if (ToBool(original["处理状态"]))
{
throw new Exception("失败任务已处理,不能再次重发");
}
if (!ToBool(original["已复位"]))
{
throw new Exception("请先复位移动机器人再重发任务");
}
TCSAGV_Config config = ReadConfig(true);
TCSAGV_PointConfig point = ReadPointConfig(Convert.ToString(original["MES工位号"]));
string action = Convert.ToString(original["任务动作"]);
string programName = Convert.ToString(original["ProgramName"]);
string productModel = Convert.ToString(original["产品型号"]);
string combination = Convert.ToString(original["动作组合"]);
string taskType = Convert.ToString(original["任务类型"]);
string param = Convert.ToString(original["参数"]);
return CreateAndSendTask(config, point, CreateExternalCode("RETRY"), externalCode,
action, programName, productModel, combination, taskType, param, "RETRY", operatorCode, false);
}
public static TCSAGV_CallResult CancelTask(string externalCode, string operatorCode)
{
if (string.IsNullOrWhiteSpace(externalCode))
{
throw new Exception("外部任务编号不能为空");
}
TCSAGV_Config config = ReadConfig(true);
TCSAGV_CallResult result = GetFromTcs(config, "cancelExternalBusinessTask",
"/api/cancelExternalBusinessTask", new Dictionary<string, string> { { "externalCode", externalCode } });
if (result.Success)
{
SetLocalTaskStatus(externalCode, 3, "已取消", "");
}
SaveOperation(externalCode, "", "取消任务", operatorCode, result.RequestText,
result.ResponseText, result.Success, result.Message);
return result;
}
public static TCSAGV_CallResult StopPendingTasks(string externalCode, string operatorCode)
{
TCSAGV_Config config = ReadConfig(true);
TCSAGV_CallResult result = GetFromTcs(config, "stopExternalBusinessTask",
"/api/stopExternalBusinessTask", null);
if (result.Success && !string.IsNullOrWhiteSpace(externalCode))
{
DataRow task = ReadTask(externalCode);
if (ToInt(task["任务状态"], -1) == 0)
{
SetLocalTaskStatus(externalCode, 3, "已停止", "停止全部未开始任务");
}
}
SaveOperation(externalCode, "", "停止未开始任务", operatorCode, result.RequestText,
result.ResponseText, result.Success, result.Message);
return result;
}
public static TCSAGV_CallResult ResetRobot(string externalCode, string ip, string operatorCode)
{
TCSAGV_Config config = ReadConfig(true);
string robotIp = string.IsNullOrWhiteSpace(ip) ? config.McrIp : ip.Trim();
if (string.IsNullOrWhiteSpace(robotIp))
{
throw new Exception("未配置AGV IP");
}
TCSAGV_CallResult result = GetFromTcs(config, "reset", "/api/reset",
new Dictionary<string, string> { { "ip", robotIp } });
if (result.Success && !string.IsNullOrWhiteSpace(externalCode))
{
try
{
SqlParameter[] parameters =
{
new SqlParameter("@外部任务编号", externalCode.Trim())
};
EnsureBusinessSuccess(ExecuteProcedure("XD_TCS_AGV_任务_复位标记", parameters));
}
catch (Exception ex)
{
SaveOperation(externalCode, "", "移动机器人复位", operatorCode, result.RequestText,
result.ResponseText, false, "TCS复位成功但MES复位标记失败" + ex.Message);
throw;
}
}
SaveOperation(externalCode, "", "移动机器人复位", operatorCode, result.RequestText,
result.ResponseText, result.Success, result.Message);
return result;
}
public static TCSAGV_CallResult StopNow(string externalCode, string ip, string operatorCode)
{
TCSAGV_Config config = ReadConfig(true);
string robotIp = string.IsNullOrWhiteSpace(ip) ? config.McrIp : ip.Trim();
if (string.IsNullOrWhiteSpace(robotIp))
{
throw new Exception("未配置AGV IP");
}
TCSAGV_CallResult result = GetFromTcs(config, "stopNow", "/api/stopNow",
new Dictionary<string, string> { { "ip", robotIp } });
if (result.Success && !string.IsNullOrWhiteSpace(externalCode))
{
SetLocalTaskStatus(externalCode, 4, "任务错误", "人工紧急停止");
}
SaveOperation(externalCode, "", "紧急停止", operatorCode, result.RequestText,
result.ResponseText, result.Success, result.Message);
return result;
}
public static TCSAGV_CallResult SyncTaskStatus(string externalCode, string operatorCode)
{
TCSAGV_Config config = ReadConfig(true);
TCSAGV_CallResult result = GetFromTcs(config, "getExternalBusinessTaskStatus",
"/api/getExternalBusinessTaskStatus", new Dictionary<string, string> { { "externalCode", externalCode } });
if (result.Success)
{
JObject task = FirstResultObject(result.Response);
if (task != null && task["status"] != null)
{
int status = ToInt(task["status"], -1);
if (status >= 0 && status <= 5)
{
UpdateTaskStatus(externalCode, status,
Convert.ToString(task["ip"] ?? ""), Convert.ToString(task["type"] ?? ""),
Convert.ToString(task["beginTime"] ?? ""), Convert.ToString(task["endTime"] ?? ""),
Convert.ToString(task["remark"] ?? ""));
}
}
}
SaveOperation(externalCode, "", "同步任务状态", operatorCode, result.RequestText,
result.ResponseText, result.Success, result.Message);
return result;
}
public static TCSAGV_CallResult QueryRobotInfo()
{
TCSAGV_Config config = ReadConfig(true);
return QueryRobotInfo(config);
}
private static TCSAGV_CallResult QueryRobotInfo(TCSAGV_Config config)
{
Dictionary<string, string> query = new Dictionary<string, string>
{
{ "mcrGroup", config.McrGroup }
};
if (!string.IsNullOrWhiteSpace(config.McrIp))
{
query.Add("mcrIp", config.McrIp);
}
return GetFromTcs(config, "getMcrInfo", "/api/getMcrInfo", query);
}
public static void HandleFailure(string externalCode, string operatorCode, string remark, bool notifyPlc)
{
DataRow task = ReadTask(externalCode);
if (!IsFailureStatus(ToInt(task["任务状态"], -1)))
{
throw new Exception("仅任务错误状态允许人工处理");
}
if (!ToBool(task["已复位"]))
{
throw new Exception("请先复位移动机器人再完成人工处理");
}
if (string.IsNullOrWhiteSpace(remark))
{
throw new Exception("处理说明不能为空");
}
if (notifyPlc)
{
WritePlcCompletion(task);
}
SqlParameter[] parameters =
{
new SqlParameter("@外部任务编号", externalCode ?? ""),
new SqlParameter("@处理人", operatorCode ?? ""),
new SqlParameter("@处理说明", remark ?? "")
};
EnsureBusinessSuccess(ExecuteProcedure("XD_TCS_AGV_任务_人工处理", parameters));
SaveOperation(externalCode, Convert.ToString(task["MES工位号"]), "失败任务人工处理",
operatorCode, "", "", true, remark);
}
public static string ProcessTaskStatus(string url, [FromBody] JObject jobj)
{
string requestText = jobj == null ? "" : jobj.ToString(Formatting.None);
SaveLog_Interface_Request(url, 2, requestText, out int aid);
TCSAGV_ApiResponse response;
try
{
if (jobj == null)
{
throw new Exception("请求参数不能为空");
}
TCSAGV_TaskStatusPushRequest request = jobj.ToObject<TCSAGV_TaskStatusPushRequest>();
if (request == null || string.IsNullOrWhiteSpace(request.externalCode))
{
throw new Exception("外部任务编号不能为空");
}
int status = ToInt(request.status, -1);
if (status < 0 || status > 5)
{
throw new Exception("任务状态必须为0至5");
}
UpdateTaskStatus(request.externalCode, status, request.ip, request.type,
request.beginTime, request.endTime, request.remark);
response = TCSAGV_ApiResponse.Ok("接收成功", "接收成功");
}
catch (Exception ex)
{
response = TCSAGV_ApiResponse.Fail(ex.Message);
SaveMesLog("TCS任务状态推送", ex.Message, MesLogType.ERROR);
}
string responseText = JsonConvert.SerializeObject(response);
SaveLog_Interface_Response(responseText, aid);
return responseText;
}
public static string ProcessPositionPush(string url, [FromBody] JObject jobj)
{
string requestText = jobj == null ? "" : jobj.ToString(Formatting.None);
SaveLog_Interface_Request(url, 2, requestText, out int aid);
TCSAGV_ApiResponse response;
try
{
if (jobj == null)
{
throw new Exception("请求参数不能为空");
}
TCSAGV_PositionPushRequest request = jobj.ToObject<TCSAGV_PositionPushRequest>();
if (request == null || string.IsNullOrWhiteSpace(request.ip))
{
throw new Exception("机器人IP不能为空");
}
SqlParameter[] parameters =
{
new SqlParameter("@机器人IP", request.ip ?? ""),
new SqlParameter("@当前站点", request.currentPos ?? ""),
new SqlParameter("@目标站点", request.objectivePos ?? ""),
new SqlParameter("@原始报文", requestText)
};
ExecuteProcedure("XD_TCS_AGV_位置_更新", parameters);
response = TCSAGV_ApiResponse.Ok("接收成功", "接收成功");
}
catch (Exception ex)
{
response = TCSAGV_ApiResponse.Fail(ex.Message);
SaveMesLog("TCS位置推送", ex.Message, MesLogType.ERROR);
}
string responseText = JsonConvert.SerializeObject(response);
SaveLog_Interface_Response(responseText, aid);
return responseText;
}
private static TCSAGV_CallResult CreateAndSendTask(TCSAGV_Config config, TCSAGV_PointConfig point,
string externalCode, string parentExternalCode, string action, string programName,
string productModel, string combination, string taskType, string param, string source,
string operatorCode, bool notifyPlc)
{
TCSAGV_TaskRequest request = new TCSAGV_TaskRequest
{
externalCode = externalCode,
type = taskType,
priority = config.DefaultPriority,
param = param,
mcrgroup = config.McrGroup,
mcrip = config.McrIp,
operatoruserid = config.OperatorUserId
};
SqlParameter[] createParameters =
{
new SqlParameter("@外部任务编号", externalCode),
new SqlParameter("@原任务编号", parentExternalCode ?? ""),
new SqlParameter("@MES工位号", point.StationCode),
new SqlParameter("@任务动作", action),
new SqlParameter("@产品型号", productModel ?? ""),
new SqlParameter("@动作组合", combination ?? ""),
new SqlParameter("@ProgramName", programName ?? ""),
new SqlParameter("@任务类型", taskType),
new SqlParameter("@参数", param),
new SqlParameter("@优先级", config.DefaultPriority),
new SqlParameter("@机器人组", config.McrGroup ?? ""),
new SqlParameter("@机器人IP", config.McrIp ?? ""),
new SqlParameter("@来源", source ?? ""),
new SqlParameter("@操作人", operatorCode ?? ""),
new SqlParameter("@是否通知PLC", notifyPlc)
};
EnsureBusinessSuccess(ExecuteProcedure("XD_TCS_AGV_任务_创建", createParameters));
TCSAGV_CallResult result;
try
{
result = PostToTcs(config, "createExternalBusinessTask", "/api/createExternalBusinessTask", request);
}
catch (Exception ex)
{
UpdateDispatchResult(externalCode, JsonConvert.SerializeObject(request), "", false, ex.Message);
SaveOperation(externalCode, point.StationCode, "下发" + action + "任务", operatorCode,
JsonConvert.SerializeObject(request), "", false, ex.Message);
throw;
}
UpdateDispatchResult(externalCode, result.RequestText, result.ResponseText, result.Success,
result.Success ? "" : result.Message);
SaveOperation(externalCode, point.StationCode, "下发" + action + "任务", operatorCode,
result.RequestText, result.ResponseText, result.Success, result.Message);
result.ExternalCode = externalCode;
return result;
}
private static void UpdateTaskStatus(string externalCode, int status, string ip, string type,
string beginTime, string endTime, string remark)
{
SqlParameter[] parameters =
{
new SqlParameter("@外部任务编号", externalCode ?? ""),
new SqlParameter("@任务状态", status),
new SqlParameter("@机器人IP", ip ?? ""),
new SqlParameter("@任务类型", type ?? ""),
new SqlParameter("@开始时间", beginTime ?? ""),
new SqlParameter("@结束时间", endTime ?? ""),
new SqlParameter("@备注", remark ?? "")
};
DataTable result = ExecuteProcedure("XD_TCS_AGV_任务_状态更新", parameters);
EnsureBusinessSuccess(result);
if (status == 2 && result.Rows.Count > 0 && ToBool(result.Rows[0]["是否通知PLC"])
&& !ToBool(result.Rows[0]["PLC已通知"]))
{
DataRow task = ReadTask(externalCode);
WritePlcCompletion(task);
SqlParameter[] notified = { new SqlParameter("@外部任务编号", externalCode) };
ExecuteProcedure("XD_TCS_AGV_任务_PLC通知完成", notified);
}
}
private static bool IsFailureStatus(int status)
{
return status == 4 || status == 5;
}
private static void WritePlcCompletion(DataRow task)
{
string stationCode = Convert.ToString(task["MES工位号"]);
string action = Convert.ToString(task["任务动作"]);
int tagCode = action.StartsWith("插", StringComparison.Ordinal) ? 400
: action.StartsWith("拔", StringComparison.Ordinal) ? 401 : 0;
if (tagCode == 0)
{
throw new Exception("任务动作无法确定PLC完成码");
}
if (!MIS_BASE.WritePLC(tagCode, stationCode, true))
{
throw new Exception("任务完成但PLC完成信号写入失败");
}
SaveMesLog(stationCode, "TCS任务完成已写入PLC功能码" + tagCode, MesLogType.INFO);
}
private static TCSAGV_Config ReadConfig(bool requireEnabled)
{
DataTable table = ExecuteProcedure("XD_TCS_AGV_配置_获取", new SqlParameter[0]);
if (table.Rows.Count == 0)
{
throw new Exception("未配置TCS参数");
}
DataRow row = table.Rows[0];
TCSAGV_Config config = new TCSAGV_Config
{
BaseUrl = Convert.ToString(row["TCS_BaseUrl"]),
Enabled = Convert.ToString(row["TCS_Enabled"]) == "1",
McrGroup = Convert.ToString(row["McrGroup"]),
McrIp = Convert.ToString(row["McrIp"]),
OperatorUserId = Convert.ToString(row["TCS_OperatorUserId"]),
DefaultPriority = ToInt(row["DefaultPriority"], 1),
HttpTimeoutSeconds = ToInt(row["HttpTimeoutSeconds"], 15)
};
if (string.IsNullOrWhiteSpace(config.BaseUrl))
{
throw new Exception("未配置TCS服务地址");
}
if (string.IsNullOrWhiteSpace(config.OperatorUserId))
{
throw new Exception("未配置TCS任务状态推送标识");
}
if (requireEnabled && !config.Enabled)
{
throw new Exception("TCS真实下发开关未启用请先确认现场地址和AGV IP");
}
return config;
}
private static TCSAGV_PointConfig ReadPointConfig(string stationCode)
{
if (string.IsNullOrWhiteSpace(stationCode))
{
throw new Exception("MES工位号不能为空");
}
SqlParameter[] parameters = { new SqlParameter("@MES工位号", stationCode.Trim()) };
DataTable table = ExecuteProcedure("XD_TCS_AGV_点位配置_查询", parameters);
if (table.Rows.Count == 0)
{
throw new Exception("MES工位未配置TCS站点和programName");
}
DataRow row = table.Rows[0];
return new TCSAGV_PointConfig
{
LineCode = Convert.ToString(row["产线代码"]),
StationCode = Convert.ToString(row["MES工位号"]),
PositionName = Convert.ToString(row["现场位置"]),
WorkStation = Convert.ToString(row["WorkStation"]),
InsertXsdProgram = Convert.ToString(row["插XSDProgramName"]),
InsertXseProgram = Convert.ToString(row["插XSEProgramName"]),
PullXsdProgram = Convert.ToString(row["拔XSDProgramName"]),
PullXseProgram = Convert.ToString(row["拔XSEProgramName"])
};
}
private static string ReadCurrentProductModel(string stationCode)
{
SqlParameter[] parameters = { new SqlParameter("@MES工位号", stationCode) };
DataTable table = ExecuteProcedure("XD_TCS_AGV_库位产品_查询", parameters);
string productModel = table.Rows.Count == 0 ? "" : Convert.ToString(table.Rows[0]["产品型号"]);
if (string.IsNullOrWhiteSpace(productModel))
{
throw new Exception("工位" + stationCode + "未获取到当前产品型号");
}
return productModel.Trim();
}
private static string ReadModelActionCombination(string lineCode, string productModel, string action)
{
SqlParameter[] parameters =
{
new SqlParameter("@产线代码", lineCode),
new SqlParameter("@产品型号", productModel),
new SqlParameter("@任务动作", action)
};
DataTable table = ExecuteProcedure("XD_TCS_AGV_型号动作映射_查询", parameters);
if (table.Rows.Count == 0)
{
throw new Exception("产品型号" + productModel + "未配置" + action + "动作组合");
}
return Convert.ToString(table.Rows[0]["动作组合"]);
}
private static DataRow ReadTask(string externalCode)
{
if (string.IsNullOrWhiteSpace(externalCode))
{
throw new Exception("外部任务编号不能为空");
}
SqlParameter[] parameters = { new SqlParameter("@外部任务编号", externalCode.Trim()) };
DataTable table = ExecuteProcedure("XD_TCS_AGV_任务_获取", parameters);
if (table.Rows.Count == 0)
{
throw new Exception("外部任务不存在");
}
return table.Rows[0];
}
private static void EnsureRobotAtPoint(TCSAGV_Config config, TCSAGV_PointConfig point)
{
TCSAGV_CallResult result = QueryRobotInfo(config);
if (!result.Success)
{
throw new Exception("查询AGV实时位置失败" + result.Message);
}
JObject robot = FirstResultObject(result.Response);
if (robot == null)
{
throw new Exception("未查询到AGV状态不能执行单步任务");
}
if (ToInt(robot["status"], -1) == 4)
{
throw new Exception("AGV当前未连接不能执行单步任务");
}
string currentPosition = Convert.ToString(robot["currentPos"]);
if (string.IsNullOrWhiteSpace(currentPosition))
{
throw new Exception("未获取到AGV当前位置不能执行单步任务");
}
if (!string.Equals(currentPosition, point.WorkStation, StringComparison.OrdinalIgnoreCase))
{
throw new Exception("AGV当前位置" + currentPosition + "与所选站点" + point.WorkStation + "不一致");
}
}
private static void UpdateDispatchResult(string externalCode, string requestText, string responseText,
bool success, string errorMessage)
{
SqlParameter[] parameters =
{
new SqlParameter("@外部任务编号", externalCode ?? ""),
new SqlParameter("@请求报文", requestText ?? ""),
new SqlParameter("@响应报文", responseText ?? ""),
new SqlParameter("@是否成功", success),
new SqlParameter("@错误信息", errorMessage ?? "")
};
ExecuteProcedure("XD_TCS_AGV_任务_下发结果更新", parameters);
}
private static void SetLocalTaskStatus(string externalCode, int status, string statusText, string errorMessage)
{
SqlParameter[] parameters =
{
new SqlParameter("@外部任务编号", externalCode ?? ""),
new SqlParameter("@任务状态", status),
new SqlParameter("@状态说明", statusText ?? ""),
new SqlParameter("@错误信息", errorMessage ?? "")
};
ExecuteProcedure("XD_TCS_AGV_任务_本地状态设置", parameters);
}
private static void SaveOperation(string externalCode, string stationCode, string operationType,
string operatorCode, string requestText, string responseText, bool success, string message)
{
try
{
SqlParameter[] parameters =
{
new SqlParameter("@外部任务编号", externalCode ?? ""),
new SqlParameter("@MES工位号", stationCode ?? ""),
new SqlParameter("@操作类型", operationType ?? ""),
new SqlParameter("@操作人", operatorCode ?? ""),
new SqlParameter("@请求报文", requestText ?? ""),
new SqlParameter("@响应报文", responseText ?? ""),
new SqlParameter("@是否成功", success),
new SqlParameter("@操作结果", message ?? "")
};
ExecuteProcedure("XD_TCS_AGV_操作记录_增加", parameters);
}
catch (Exception ex)
{
SaveMesLog("TCS操作记录", ex.Message, MesLogType.ERROR);
}
}
private static TCSAGV_CallResult PostToTcs(TCSAGV_Config config, string interfaceName,
string path, object request)
{
string url = config.BaseUrl.TrimEnd('/') + path;
string requestText = JsonConvert.SerializeObject(request);
SaveLog_Interface_Request("TCS_" + interfaceName, 1, requestText, out int aid);
string responseText;
using (HttpClient client = CreateHttpClient(config))
using (StringContent content = new StringContent(requestText, Encoding.UTF8, "application/json"))
{
HttpResponseMessage response = client.PostAsync(url, content).GetAwaiter().GetResult();
responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (string.IsNullOrWhiteSpace(responseText) && !response.IsSuccessStatusCode)
{
responseText = "HTTP " + (int)response.StatusCode;
}
}
SaveLog_Interface_Response(responseText, aid);
return ParseCallResult(requestText, responseText);
}
private static TCSAGV_CallResult GetFromTcs(TCSAGV_Config config, string interfaceName,
string path, IDictionary<string, string> query)
{
StringBuilder url = new StringBuilder(config.BaseUrl.TrimEnd('/') + path);
JObject request = new JObject();
if (query != null && query.Count > 0)
{
url.Append('?');
bool first = true;
foreach (KeyValuePair<string, string> item in query)
{
if (!first) url.Append('&');
first = false;
url.Append(HttpUtility.UrlEncode(item.Key));
url.Append('=');
url.Append(HttpUtility.UrlEncode(item.Value ?? ""));
request[item.Key] = item.Value ?? "";
}
}
string requestText = request.ToString(Formatting.None);
bool skipInterfaceLog = string.Equals(interfaceName, "getMcrInfo",
StringComparison.OrdinalIgnoreCase);
int aid = 0;
if (!skipInterfaceLog)
{
SaveLog_Interface_Request("TCS_" + interfaceName, 1, requestText, out aid);
}
string responseText;
using (HttpClient client = CreateHttpClient(config))
{
HttpResponseMessage response = client.GetAsync(url.ToString()).GetAwaiter().GetResult();
responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (string.IsNullOrWhiteSpace(responseText) && !response.IsSuccessStatusCode)
{
responseText = "HTTP " + (int)response.StatusCode;
}
}
if (!skipInterfaceLog)
{
SaveLog_Interface_Response(responseText, aid);
}
return ParseCallResult(requestText, responseText);
}
private static HttpClient CreateHttpClient(TCSAGV_Config config)
{
return new HttpClient
{
Timeout = TimeSpan.FromSeconds(config.HttpTimeoutSeconds > 0 ? config.HttpTimeoutSeconds : 15)
};
}
private static TCSAGV_CallResult ParseCallResult(string requestText, string responseText)
{
JObject response;
try
{
response = JObject.Parse(responseText ?? "");
}
catch (Exception ex)
{
return new TCSAGV_CallResult
{
Success = false,
Code = 500,
Message = "TCS返回非JSON响应" + ex.Message,
RequestText = requestText,
ResponseText = responseText,
Response = null
};
}
bool successFlag = false;
bool hasSuccessFlag = response["success"] != null;
if (hasSuccessFlag)
{
bool.TryParse(Convert.ToString(response["success"]), out successFlag);
}
int code = ToInt(response["code"], successFlag ? 200 : 500);
bool success = hasSuccessFlag ? successFlag && code == 200 : code == 200;
string message = Convert.ToString(response["message"] ?? response["msg"] ?? response["result"] ?? "");
return new TCSAGV_CallResult
{
Success = success,
Code = code,
Message = message,
RequestText = requestText,
ResponseText = responseText,
Response = response
};
}
private static JObject FirstResultObject(JObject response)
{
if (response == null || response["result"] == null) return null;
JToken result = response["result"];
if (result.Type == JTokenType.Array)
{
JArray array = (JArray)result;
return array.Count > 0 ? array[0] as JObject : null;
}
return result as JObject;
}
private static DataTable ExecuteProcedure(string procedureName, SqlParameter[] parameters)
{
SqlParameter[] procedureParameters = parameters ?? new SqlParameter[0];
DataLinkMesWork2.DataAccess2.ExecuteStoredProcedure(procedureName, ref procedureParameters,
out DataTable table, out string errorMessage);
if (!string.IsNullOrWhiteSpace(errorMessage))
{
throw new Exception(errorMessage);
}
return table ?? new DataTable();
}
private static void EnsureBusinessSuccess(DataTable table)
{
if (table == null || table.Rows.Count == 0)
{
throw new Exception("数据库未返回业务结果");
}
if (ToInt(table.Rows[0]["result"], 0) != 1)
{
string message = table.Columns.Contains("msg") ? Convert.ToString(table.Rows[0]["msg"]) : "业务操作失败";
throw new Exception(message);
}
}
private static string NormalizeAction(string actionType)
{
string value = (actionType ?? "").Trim();
if (value == "插" || value.Equals("plug", StringComparison.OrdinalIgnoreCase)) return "插";
if (value == "拔" || value.Equals("pull", StringComparison.OrdinalIgnoreCase)) return "拔";
throw new Exception("任务动作只支持插或拔");
}
private static string NormalizePortCombination(string portCombination)
{
string value = (portCombination ?? "").Trim().ToUpperInvariant();
if (value == "XSD" || value == "XSE" || value == "XSD+XSE") return value;
throw new Exception("动作组合只支持XSD、XSE或XSD+XSE");
}
private static bool IsConfiguredProgram(TCSAGV_PointConfig point, string programName)
{
return programName == point.InsertXsdProgram || programName == point.InsertXseProgram
|| programName == point.PullXsdProgram || programName == point.PullXseProgram;
}
private static string CreateExternalCode(string prefix)
{
return "XD_" + prefix + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + "_"
+ Guid.NewGuid().ToString("N").Substring(0, 6).ToUpperInvariant();
}
private static int ToInt(object value, int defaultValue)
{
int result;
return int.TryParse(Convert.ToString(value), out result) ? result : defaultValue;
}
private static bool ToBool(object value)
{
string text = Convert.ToString(value);
return text == "1" || text.Equals("true", StringComparison.OrdinalIgnoreCase);
}
}
}