using Hanhe.iWCS.Common; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Hanhe.iWCS.TaizhouGEMTwoProtocol { public class OITcpHelper { private static string url = Settings.OITcpSeverUrl; private static string token = ""; private static WebApiHelper apiHelper = new WebApiHelper(); public static string readip = ""; public static string writeip = ""; public static string writeAllIP = ""; #region 1. 中转请求操作 /// /// 1.1. 请求 json内容 /// public static void JsonTransit() { var req = JsonConvert.SerializeObject(new JsonTransitData()); var feedback = apiHelper.WebPost($"{url}/api/transit/json?access_token={token}", req); if (feedback != "") { var result = JsonConvert.DeserializeObject(feedback); } } /// /// 1.2. 请求 ascii内容 /// public static StrTransitResult AsciiTransit(StrTransitData model) { StrTransitResult result = null; var req = JsonConvert.SerializeObject(model); var feedback = apiHelper.WebPost($"{url}/api/transit/ascii?access_token={token}", req); if (feedback != "") { result = JsonConvert.DeserializeObject(feedback); } return result; } /// /// 1.3. 请求 hex内容 /// public static void HexTransit() { var req = JsonConvert.SerializeObject(new StrTransitData()); var feedback = apiHelper.WebPost($"{url}/api/transit/hex?access_token={token}", req); if (feedback != "") { var result = JsonConvert.DeserializeObject(feedback); } } public class BaseTransitData { public string host { get; set; } public int port { get; set; } public int timeout { get; set; } } public class JsonTransitData : BaseTransitData { public object data { get; set; } } public class JsonTransitResult : BaseResponseModel { public object result { get; set; } } public class StrTransitData : BaseTransitData { public string data { get; set; } } public class StrTransitResult : BaseResponseModel { public string result { get; set; } } #endregion #region 2. Modbus处理操作 #region 2.1. 读取输出线圈状态 01 功能 /// /// 2.1. 读取输出线圈状态 01 功能 /// public static RelayReadOutResult RelayReadOutPut(RelayReadOutPutModel model) { RelayReadOutResult result = null; var req = JsonConvert.SerializeObject(model); var feedback = apiHelper.WebPost($"{url}/api/modbus/relay/readoutput?access_token={token}", req); Console.WriteLine($"读取输出线圈状态 modbus/relay/readoutput req={req} res={feedback}"); CMMLog.Info($"读取输出线圈状态 modbus/relay/readoutput req={req} res={feedback}"); if (feedback != "") { result = JsonConvert.DeserializeObject(feedback); } return result; } public class RelayReadOutPutModel : BaseRequestModel { public int bitNum { get; set; } //public object tcpModel { get; set; } //public int msgNo { get; set; } } public class RelayReadOutResult : BaseResponseModel { public int[] result { get; set; } } #endregion #region 2.2. 读取输入离散量 02 功能 /// /// 2.2. 读取输入离散量 02 功能 /// public static void RelayReadInPut(BaseRequestModel model) { var req = JsonConvert.SerializeObject(model); var feedback = apiHelper.WebPost($"{url}/api/modbus/relay/readinput?access_token={token}", req); if (feedback != "") { var result = JsonConvert.DeserializeObject(feedback); } } public class RelayReadInPutResult : BaseRequestModel { public int result { get; set; } } #endregion #region 2.3. 读取输出寄存器数据 03 功能 /// /// 2.3. 读取输出寄存器数据 03 功能 /// public static RegisterReadOutPutResult RegisterReadOutPut(RegisterReadOutPutModel model) { RegisterReadOutPutResult result = null; //Settings.PlcInfo pmInfo = Settings.GetPlcInfo().Where(a => a.ip == model.host).FirstOrDefault(); //model.port = pmInfo.port; var req = JsonConvert.SerializeObject(model); #region 拦截相同IP延迟一秒发送 if (model.host == readip) { DateTime dateTime = DateTime.Now; int z = 1; while (z == 1) { if (DateTime.Now.Subtract(dateTime).TotalSeconds > 1) { z = 2; readip = model.host; } } } else { readip = model.host; } #endregion CMMLog.Debug($"读取输出寄存器数据03功能:IP:{readip},URL:{url}/api/modbus/register/readoutput?access_token={token},写入数据:{req}"); var feedback = apiHelper.WebPost($"{url}/api/modbus/register/readoutput?access_token={token}", req); if (feedback != "") { result = JsonConvert.DeserializeObject(feedback); } else { CMMLog.Error($"读取输出寄存器数据03功能:IP:{readip},返回值feedback为空!返回值:{feedback}"); } try { if (result != null) { if (result.errCode == 0) { var packNo = Settings.GetPlcInfo().Where(a => a.ip == model.host && a.deviceType == "1").FirstOrDefault(); if (packNo != null) { CMMLog.Debug($"读取输出寄存器数据 03 功能MODBUS参数:IP:{readip},包装机号:{packNo.location},通道地址为{model.addr},端口为{model.port},返回值{result.result[0]}"); //Console.WriteLine($"读取输出寄存器数据 03 功能MODBUS参数:IP:{readip},包装机号:{packNo.location},通道地址为{model.addr},端口为{model.port},返回值{result.result[0]}"); } } else if (result.errCode == 1025) { var packNo = Settings.GetPlcInfo().Where(a => a.ip == model.host && a.deviceType == "1").FirstOrDefault(); if (packNo != null) { CMMLog.Debug($"【1025异常】读取输出寄存器数据 03 功能MODBUS参数:IP:{readip},包装机号:{packNo.location},通道地址为{model.addr},端口为{model.port},发送值{req}"); //Console.WriteLine($"【1025异常】读取输出寄存器数据 03 功能MODBUS参数:通道地址为{model.addr},端口为{model.port},发送值{req}"); } } } else Console.WriteLine($"读取输出寄存器数据 03 功能MODBUS参数为空:IP:{readip},通道地址为{model.addr},端口为{model.port},发送值{req}"); #region 重发机制 //else if(result.errCode == 1125) //{ // int err = 0; // while (err == 0) // { // var req1 = JsonConvert.SerializeObject(model); // DateTime dateTime1 = DateTime.Now; // if (DateTime.Now.Subtract(dateTime1).TotalSeconds > 1) // { // var feedbackReset = apiHelper.WebPost($"{url}/api/modbus/register/readoutput?access_token={token}", req1); // CMMLog.Debug($"重新读取输出寄存器03功能输入数据:req:{req1},ip:{readip}"); // CMMLog.Debug($"重新读取输出寄存器数据03功能请求URL:readUrl:{url}/api/modbus/register/readoutput?access_token={token}"); // if (feedbackReset != "") // { // result = JsonConvert.DeserializeObject(feedbackReset); // if(result.errCode == 0) // { // err = 1; // CMMLog.Debug($"读取输出寄存器数据 03 功能MODBUS参数:通道地址为{model.addr},端口为{model.port},发送值{req},返回值{result.result[0]}"); // Console.WriteLine($"读取输出寄存器数据 03 功能MODBUS参数:通道地址为{model.addr},端口为{model.port},发送值{req},返回值{result.result[0]}"); // readip = model.host; // } // } // } // } //} #endregion } catch (Exception ex) { CMMLog.Error($"读取输出寄存器数据03功能抛出异常,IP:{readip},通道为:{model.addr},读取数量为:{model.dataNum},异常信息:{ex.Message}"); } //CMMLog.Debug($"读取输出寄存器数据03功能返回结果:{feedback}"); //Console.WriteLine($"读取输出寄存器数据03功能返回结果:{feedback}"); return result; } public class RegisterReadOutPutModel : BaseRequestModel { public int dataNum { get; set; } //public int msgNo { get; set; } } public class RegisterReadOutPutResult : BaseResponseModel { public int[] result { get; set; } } #endregion #region 2.4. 读取输入寄存器数据 04 功能 /// /// 2.4. 读取输入寄存器数据 04 功能 /// public static RegisterReadOutPutResult RegisterReadInPut(RegisterReadOutPutModel model) { RegisterReadOutPutResult result = null; var req = JsonConvert.SerializeObject(model); var feedback = apiHelper.WebPost($"{url}/api/modbus/register/readinput?access_token={token}", req); if (feedback != "") { result = JsonConvert.DeserializeObject(feedback); } //CMMLog.Debug($"读取输入寄存器数据 04 功能MODBUS参数返回值为:{result},发送值{req}"); //Console.WriteLine($"读取输入寄存器数据 04 功能MODBUS参数返回值为:{result},发送值{req}"); return result; } #endregion #region 2.5. 写单个输出线圈 05 功能 /// /// 2.5. 写单个输出线圈 05 功能 /// public static BaseResponseModel RelayWriteOutPut(RelayWriteOutPutModel model) { BaseResponseModel result = null; var req = JsonConvert.SerializeObject(model); var feedback = apiHelper.WebPost($"{url}/api/modbus/relay/writeoutput?access_token={token}", req); Console.WriteLine($"写单个输出线圈 modbus/relay/writeoutput req={req} res={feedback}"); CMMLog.Info($"写单个输出线圈 modbus/relay/writeoutput req={req} res={feedback}"); if (feedback != "") { result = JsonConvert.DeserializeObject(feedback); } return result; } public class RelayWriteOutPutModel : BaseRequestModel { public bool status { get; set; } } #endregion #region 2.6. 写单个输出寄存器 06 功能 public static BaseResponseModel RegisterWriteOutPut(RegisterWriteOutPutModel model) { BaseResponseModel result = null; //Settings.PlcInfo pmInfo = Settings.GetPlcInfo().Where(a => a.ip == model.host).FirstOrDefault(); //model.port = pmInfo.port; var req = JsonConvert.SerializeObject(model); #region 拦截相同IP延迟一秒发送 if (model.host == readip) { DateTime dateTime = DateTime.Now; int z = 1; while (z == 1) { if (DateTime.Now.Subtract(dateTime).TotalSeconds > 1) { z = 2; readip = model.host; } } } else { readip = model.host; } #endregion CMMLog.Debug($"写单个输出寄存器06功能写入值:IP:{readip},URL:{url}/api/modbus/register/writeoutput?access_token={token},写入数据:{req}"); var feedback = apiHelper.WebPost($"{url}/api/modbus/register/writeoutput?access_token={token}", req); if (feedback != "") result = JsonConvert.DeserializeObject(feedback); else CMMLog.Error($"写单个输出寄存器06功能写入值:异常:IP:{readip},返回值feedback为空!返回值:{feedback}"); try { if (result != null && result.errCode == 0) { CMMLog.Debug($"写单个输出寄存器 06 功能MODBUS参数:IP:{readip},通道地址为{model.addr},端口为:{model.port},错误码:{result.errCode},返回信息:{result.errMsg}"); //Console.WriteLine($"写单个输出寄存器 06 功能MODBUS参数:通道地址为{model.addr},端口为:{model.port},错误码:{result.errCode},返回信息:{result.errMsg}"); } else if (result.errCode == 1025) { var packNo = Settings.GetPlcInfo().Where(a => a.ip == model.host && a.deviceType == "1").FirstOrDefault(); if (packNo != null) { CMMLog.Error($"【1025异常】读取输出寄存器数据 03 功能MODBUS参数:IP:{readip},当前包装机号:{packNo.location},通道地址为{model.addr},端口为{model.port},发送值{req}"); //Console.WriteLine($"【1025异常】读取输出寄存器数据 03 功能MODBUS参数:当前包装机号:{packNo.location}通道地址为{model.addr},端口为{model.port},发送值{req}"); } } else if (result.errCode == 1125 || result.errCode != 0) { DateTime dateTime = DateTime.Now; int err = 3; int num = 0; while (err > 0) { if(DateTime.Now.Subtract(dateTime).TotalMilliseconds >= 300) { var feedbackReset = apiHelper.WebPost($"{url}/api/modbus/register/writeoutput?access_token={token}", req); CMMLog.Debug($"【1125异常】重新读取写入寄存器数据06-第{num + 1}次:IP:{readip},写入数据:{req},Url:{url}/api/modbus/register/readoutput?access_token={token}"); if (feedbackReset != "") { result = JsonConvert.DeserializeObject(feedbackReset); if (result.errCode == 0) { err = err - 1; num = num + 1; CMMLog.Debug($"【1125异常】写单个输出寄存器 06 功能MODBUS参数-第{num + 1}次:IP:{readip},通道地址为{model.addr},端口为{model.port},发送值{req},错误码:{result.errCode},返回信息:{result.errMsg}"); readip = model.host; } } } } } } catch (Exception ex) { CMMLog.Error($"写单个输出寄存器06功能功能抛出异常:IP:{readip},通道为:{model.addr},写入值为:{model.data},异常信息:{ex.Message}"); } return result; } public class RegisterWriteOutPutModel : BaseRequestModel { public int data { get; set; } } #endregion #region 2.7. 写多个输出线圈 15 功能 public static void RelayWriteOutPutMulti() { var req = JsonConvert.SerializeObject(new RelayWriteOutPutModelMulti()); var feedback = apiHelper.WebPost($"{url}/api/modbus/relay/writeoutputmulti?access_token={token}", req); if (feedback != "") { var result = JsonConvert.DeserializeObject(feedback); } } public class RelayWriteOutPutModelMulti : BaseRequestModel { public int bitNum { get; set; } public int[] data { get; set; } } #endregion #region 2.8. 写多个输出寄存器 16 功能 public static void RegisterWriteOutPutMulti() { var req = JsonConvert.SerializeObject(new RegisterWriteOutPutModelMulti()); var feedback = apiHelper.WebPost($"{url}/api/modbus/register/writeoutputmulti?access_token={token}", req); if (feedback != "") { var result = JsonConvert.DeserializeObject(feedback); } } public static BaseResponseModel RegisterWriteOutPutMulti(RegisterWriteOutPutModelMulti model) { BaseResponseModel result = null; //Settings.PlcInfo pmInfo = Settings.GetPlcInfo().Where(a => a.ip == model.host).FirstOrDefault(); //model.port = pmInfo.port; var req = JsonConvert.SerializeObject(model); #region 拦截相同IP延迟一秒发送 if (model.host == readip) { DateTime dateTime = DateTime.Now; int z = 1; while (z == 1) { if (DateTime.Now.Subtract(dateTime).TotalSeconds > 1) { z = 2; readip = model.host; } } readip = model.host; } else { readip = model.host; } #endregion CMMLog.Debug($"写多个输出寄存器16功能:IP:{readip},URL:{url}/api/modbus/register/writeoutputmulti?access_token={token},写入数据:{req}"); var feedback = apiHelper.WebPost($"{url}/api/modbus/register/writeoutputmulti?access_token={token}", req); if (feedback != "") { result = JsonConvert.DeserializeObject(feedback); } else CMMLog.Error($"写多个输出寄存器16功能:异常:IP:{readip},返回值feedback为空!"); try { if (result != null && result.errCode == 0) { CMMLog.Debug($"写多个输出寄存器16功能:IP:{readip},通道地址为{model.addr},端口为{model.port},发送值{req},错误码:{result.errCode},错误信息:{result.errMsg}"); //Console.WriteLine($"写多个输出寄存器 16 功能MODBUS参数,通道地址为{model.addr},端口为{model.port},发送值{req},返回值{result.errCode},{result.errMsg}"); } else if (result.errCode == 1025) { var packNo = Settings.GetPlcInfo().Where(a => a.ip == model.host && a.deviceType == "1").FirstOrDefault(); if (packNo != null) { CMMLog.Error($"【1025异常】写多个输出寄存器16功能:IP:{readip},包装机号:{packNo.location},通道地址为{model.addr},端口为{model.port},发送值{req}"); //Console.WriteLine($"【1025异常】读取输出寄存器数据 03 功能MODBUS参数:通道地址为{model.addr},端口为{model.port},发送值{req}"); } } #region 重发机制 else if (result.errCode == 1125 || result.errCode != 0) { int err = 3; int num = 0; while (err > 0) { var req1 = JsonConvert.SerializeObject(model); var feedbackReset = apiHelper.WebPost($"{url}/api/modbus/register/writeoutputmulti?access_token={token}", req); CMMLog.Debug($"重新读取写入多个寄存器16功能输入数据-第{num + 1}次:req:{req1},ip:{readip}"); CMMLog.Debug($"重新读取写入多个寄存器数据16功能请求URL-第{num + 1}次:readUrl:{url}/api/modbus/register/readoutput?access_token={token}"); if (feedbackReset != "") { result = JsonConvert.DeserializeObject(feedbackReset); if (result.errCode == 0) { err = err - 1; num = num + 1; CMMLog.Debug($"写多个输出寄存器 16 功能MODBUS参数-第{num + 1}次,通道地址为{model.addr},端口为{model.port},发送值{req},返回值{result.errCode},{result.errMsg}"); Console.WriteLine($"写多个输出寄存器 16 功能MODBUS参数-第{num + 1}次,通道地址为{model.addr},端口为{model.port},发送值{req},返回值{result.errCode},{result.errMsg}"); readip = model.host; } } } } #endregion } catch (Exception ex) { CMMLog.Error($"写多个输出寄存器16功能:异常:IP:{readip},通道为:{model.addr},写入值为:{model.data},异常信息:{ex.Message}"); } //CMMLog.Debug($"写多个输出寄存器16功能:{feedback}"); //Console.WriteLine($"写多个输出寄存器16功能:{feedback}"); return result; } public class RegisterWriteOutPutModelMulti : BaseRequestModel { public int[] data { get; set; } } #endregion #endregion public class ReadInPutResult : BaseResponseModel { public int result { get; set; } } public class BaseResponseModel { public int errCode { get; set; } public string errMsg { get; set; } } public class BaseRequestModel { public string host { get; set; } public int port { get; set; } = 502; public int timeout { get; set; } = 1000; public int deviceNo { get; set; } = 1; public int addr { get; set; } public object tcpModel { get; set; } = new { msgNo = 1 }; } } }