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
{
///
/// TCS插拔任务业务处理。PLC自动任务与Web人工任务共用此入口。
///
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 { { "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 { { "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 { { "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 { { "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 query = new Dictionary
{
{ "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();
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();
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 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 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);
}
}
}