Form_Home_SaveData.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Text;
  6. using NPOI.Util;
  7. using Newtonsoft.Json;
  8. using System.Threading.Tasks;
  9. using MainForm.ClassFile.XiaomiAPI;
  10. using MainForm.ClassFile.XiaomiAPI_MES;
  11. using static MainForm.ClassFile.XiaomiAPI.XiaomiMqttClient_Extend;
  12. using static MainForm.ClassFile.XiaomiAPI_MES.XiaomiMESHttp_StationInbound;
  13. using static MainForm.ClassFile.XiaomiAPI_MES.XiaomiMESHttp_StationOutbound;
  14. namespace MainForm
  15. {
  16. /// <summary>
  17. /// Form_Home类 - 保存数据
  18. /// 简单拆分Form_Home类
  19. /// </summary>
  20. public partial class Form_Home
  21. {
  22. #region 保存数据
  23. #region 进站数据
  24. /// <summary>
  25. /// 调用进站接口并保存进站数据
  26. /// </summary>
  27. /// <param name="stationNameStr">工站信息</param>
  28. /// <param name="workorder_code">工单号</param>
  29. /// <param name="mtltmrk">型号(物料号)</param>
  30. /// <param name="sn">产品SN</param>
  31. /// <param name="items">进站数据</param>
  32. /// <returns>1成功;5MES报警;6上位机报警</returns>
  33. public int SaveStationInData(string stationNameStr, string workorder_code, string mtltmrk, string sn, List<TestItem> items,out string msg)
  34. {
  35. int result = 0;
  36. msg = "";
  37. XmMES_StationInRequest_Body inRequest_Body = new XmMES_StationInRequest_Body();
  38. switch (stationNameStr)
  39. {
  40. case "[S1]Tray盘上料装备":
  41. inRequest_Body.machineId = GlobalContext.S1_MachineId; // 装备ID(可配置)
  42. inRequest_Body.stationId = GlobalContext.S1_StationId; // ⼯位ID(可配置)
  43. break;
  44. case "[S2]FCT":
  45. inRequest_Body.machineId = GlobalContext.S2_MachineId; // 装备ID(可配置)
  46. inRequest_Body.stationId = GlobalContext.S2_StationId; // ⼯位ID(可配置)
  47. break;
  48. case "[S3]值板机":
  49. inRequest_Body.machineId = GlobalContext.S3_MachineId; // 装备ID(可配置)
  50. inRequest_Body.stationId = GlobalContext.S3_StationId; // ⼯位ID(可配置)
  51. break;
  52. case "[S4_1]载具下线装备":
  53. inRequest_Body.machineId = GlobalContext.S4_MachineId; // 装备ID(可配置)
  54. inRequest_Body.stationId = GlobalContext.S4_StationId; // ⼯位ID(可配置)
  55. break;
  56. case "[S4_3]提升机1":
  57. //inRequest_Body.machineId = GlobalContext.S5_1_MachineId; // 装备ID(可配置)
  58. //inRequest_Body.stationId = GlobalContext.S5_1_StationId; // ⼯位ID(可配置)
  59. break;
  60. case "[S4_4]提升机2":
  61. //inRequest_Body.machineId = GlobalContext.S5_2_MachineId; // 装备ID(可配置)
  62. //inRequest_Body.stationId = GlobalContext.S5_2_StationId; // ⼯位ID(可配置)
  63. break;
  64. case "[S4_5]载具上线装备":
  65. inRequest_Body.machineId = GlobalContext.S6_MachineId; // 装备ID(可配置)
  66. inRequest_Body.stationId = GlobalContext.S6_StationId; // ⼯位ID(可配置)
  67. break;
  68. case "[S5]Tray盘下料装备":
  69. inRequest_Body.machineId = GlobalContext.S7_MachineId; // 装备ID(可配置)
  70. inRequest_Body.stationId = GlobalContext.S7_StationId; // ⼯位ID(可配置)
  71. break;
  72. default:
  73. break;
  74. }
  75. inRequest_Body.clientMac = GlobalContext.MacStr; // 客⼾端本机MAC地址,格式:XX-XX-XX-XX-XX-XX
  76. inRequest_Body.clientTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); // 客⼾端请求时间,格式yyyy-MM-dd HH:mm:ss.fff
  77. inRequest_Body.unitSn = sn; // 产品SN
  78. inRequest_Body.userId = GlobalContext.MESUserId; // 用户ID;非必填
  79. inRequest_Body.factoryId = GlobalContext.Factory_Code; // 工厂ID;非必填
  80. string json_Body = JsonConvert.SerializeObject(inRequest_Body);
  81. StationIn stationIn = new StationIn()
  82. {
  83. Workorder_code = workorder_code, // 车间订单号
  84. Mtltmrk = mtltmrk, // 产品型号(物料号)
  85. Sn = sn, // SN
  86. StationIn_body = json_Body, // 进站接口Json数据 - Body
  87. Parameter_values = items, // 进站数据
  88. Write_user = inRequest_Body.userId, // 员工Id
  89. Test_time = inRequest_Body.clientTime // 进站时间
  90. };
  91. // 本地数据
  92. string sql = stationIn.ToStringInsert(0);
  93. string ret = SQLHelper_New.ExecuteNonQuery(sql, null);
  94. result = ret == "成功" ? 1 : 6;
  95. msg = ret;
  96. AddMessage_Station(stationNameStr, LogType.Info, string.Concat(stationNameStr, "_保存本地进站数据---" + ret));
  97. //await Task.Delay(200);
  98. // 上传MES
  99. if (result == 1 && GlobalContext.IsSendStationIn)
  100. {
  101. try
  102. {
  103. XmMES_StationInResponse response = new XmMES_StationInResponse();
  104. string mesRet = string.Empty;
  105. int i = 0;
  106. while (i < 2) // 1009会多次尝试上传
  107. {
  108. response = XiaomiMESHttp_StationInbound.StationIn(inRequest_Body);
  109. if (response != null && response.header.code == "200")
  110. break;
  111. else if (response != null && response.header.code != "503") // 503是服务器报错
  112. i++;
  113. i++;
  114. mesRet = $"[{response?.header?.code}]{response?.header?.desc}";
  115. // 记录失败原因
  116. OnMessage(LogType.Error, "上传出站数据到MES服务器---失败!正在重新上传!接口报错信息:" + mesRet + "参数:" + json_Body);
  117. }
  118. AddMessage_Station(stationNameStr, LogType.Info, stationNameStr + "_上传进站数据到MES服务器---" + mesRet);
  119. if (response?.header?.code == "200")
  120. {
  121. string sql_Upd = stationIn.ToStringUpdateStatusByID(1);
  122. string ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Upd, null);
  123. result = ret_Upd == "成功" ? result : 6;
  124. msg = ret_Upd == "成功" ? msg : "更新【进站数据 id {stationIn.GUID}】上传状态---失败";
  125. AddMessage_Station(stationNameStr, LogType.Info, $"更新【进站数据 id {stationIn.GUID}】上传状态---" + ret_Upd);
  126. }
  127. else
  128. {
  129. result = 5;
  130. msg = "上传进站数据到MES服务器---失败!接口报错信息:" + mesRet + "参数:" + json_Body;
  131. OnMessage(LogType.Error, "上传进站数据到MES服务器---失败!接口报错信息:" + mesRet + "参数:" + json_Body);
  132. }
  133. }
  134. catch (Exception ex)
  135. {
  136. result = 6;
  137. string str = ex.StackTrace;
  138. msg = $"PLC上传进站数据MES报错!错误信息:" + ex.Message.ToString() + ";异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1);
  139. AddMessage_Station(stationNameStr, LogType.Error, $"PLC上传进站数据MES报错!错误信息:" + ex.Message.ToString() + ";异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1));
  140. }
  141. }
  142. return result;
  143. }
  144. #endregion 进站数据
  145. #region 出站数据
  146. /// <summary>
  147. /// 选择如何记录出站数据
  148. /// </summary>
  149. /// <param name="stationNameStr">工站信息</param>
  150. /// <param name="items">出站数据</param>
  151. /// <param name="equipmentCode">设备编号</param>
  152. /// <param name="processItem">测试项目</param>
  153. /// <param name="workorder_code">车间订单号</param>
  154. /// <param name="mtltmrk">型号</param>
  155. /// <param name="sn">产品序列号的</param>
  156. /// <param name="pass">产品结果</param>
  157. /// <param name="vehicleSn">载具SN</param>
  158. /// <param name="vehicleSlot">载具穴号</param>
  159. /// <returns>上位机发送1代表OK;2代表上传客户MES失败;3代表上位机保存数据失败;4代表上位机报警;</returns>
  160. private int SwitctProcessData(string stationNameStr, List<TestItem> items, string equipmentCode, string processItem,
  161. string workorder_code, string mtltmrk, string sn, bool pass, string vehicleSn, string vehicleSlot)
  162. {
  163. //if (DataSwitch == 1)
  164. //{
  165. return SaveProcessDataByDB(stationNameStr, items, equipmentCode, processItem, workorder_code, mtltmrk,
  166. sn, pass, vehicleSn, vehicleSlot);
  167. //}
  168. //else // 旧代码,废弃
  169. //{
  170. // return SaveProcessData(items, equipmentCode, processItem, sn_Number);
  171. //}
  172. }
  173. /// <summary>
  174. /// 添加出站数据(提交到MES+本地保存到数据库)
  175. /// </summary>
  176. /// <param name="stationNameStr">工站信息</param>
  177. /// <param name="items">出站数据</param>
  178. /// <param name="equipmentCode">设备编号</param>
  179. /// <param name="processItem">测试项目</param>
  180. /// <param name="workorder_code">车间订单号</param>
  181. /// <param name="mtltmrk">型号</param>
  182. /// <param name="sn">产品序列号</param>
  183. /// <param name="pass">产品结果</param>
  184. /// <param name="vehicleSn">载具SN</param>
  185. /// <param name="vehicleSlot">载具穴号</param>
  186. /// <returns>上位机发送1代表OK;2代表上传客户MES失败;3代表上位机保存数据失败;4代表上位机报警;</returns>
  187. public int SaveProcessDataByDB(string stationNameStr, List<TestItem> items, string equipmentCode,
  188. string processItem, string workorder_code, string mtltmrk, string sn,
  189. bool pass, string vehicleSn, string vehicleSlot)
  190. {
  191. int mesUpload = 0; // 0未上传或上传失败;1上传成功;2忽略
  192. int iotUpload = 0; // 0未上传或上传失败;1上传成功;2忽略
  193. ProcessData processData = new ProcessData()
  194. {
  195. Equipment_code = equipmentCode,
  196. Testitem = processItem,
  197. Workorder_code = workorder_code,
  198. //Batch_number = batch_num,
  199. Sn = sn, // SN
  200. Parameter_values = items,
  201. Write_user = GlobalContext.CurrentUser,
  202. Test_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
  203. };
  204. // 本地数据
  205. string sql = processData.ToStringInsert(mesUpload, iotUpload);
  206. string ret = SQLHelper_New.ExecuteNonQuery(sql, null);
  207. AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[[", equipmentCode, "]", stationNameStr, "]保存本地出站数据---" + ret));
  208. if (ret != "成功")
  209. return 3; // 3代表上位机保存数据失败
  210. //await Task.Delay(200);
  211. // 上传MES
  212. string mesJson = string.Empty;
  213. if (GlobalContext.IsSendProcessData)
  214. {
  215. try
  216. {
  217. string id = processData.ID;
  218. XmMES_StationOutRequest_Body outRequest_Body = new XmMES_StationOutRequest_Body();
  219. switch (stationNameStr)
  220. {
  221. case "[S1]Tray盘上料装备":
  222. outRequest_Body.machineId = GlobalContext.S1_MachineId; // 装备ID(可配置)
  223. outRequest_Body.stationId = GlobalContext.S1_StationId; // ⼯位ID(可配置)
  224. break;
  225. case "[S2]FCT":
  226. outRequest_Body.machineId = GlobalContext.S2_MachineId; // 装备ID(可配置)
  227. outRequest_Body.stationId = GlobalContext.S2_StationId; // ⼯位ID(可配置)
  228. break;
  229. case "[S3]值板机":
  230. outRequest_Body.machineId = GlobalContext.S3_MachineId; // 装备ID(可配置)
  231. outRequest_Body.stationId = GlobalContext.S3_StationId; // ⼯位ID(可配置)
  232. break;
  233. case "[S4_1]载具下线装备":
  234. outRequest_Body.machineId = GlobalContext.S4_MachineId; // 装备ID(可配置)
  235. outRequest_Body.stationId = GlobalContext.S4_StationId; // ⼯位ID(可配置)
  236. break;
  237. case "[S4_3]提升机1":
  238. //outRequest_Body.machineId = GlobalContext.S5_1_MachineId; // 装备ID(可配置)
  239. //outRequest_Body.stationId = GlobalContext.S5_1_StationId; // ⼯位ID(可配置)
  240. break;
  241. case "[S4_4]提升机2":
  242. //outRequest_Body.machineId = GlobalContext.S5_2_MachineId; // 装备ID(可配置)
  243. //outRequest_Body.stationId = GlobalContext.S5_2_StationId; // ⼯位ID(可配置)
  244. break;
  245. case "[S4_5]载具上线装备":
  246. outRequest_Body.machineId = GlobalContext.S6_MachineId; // 装备ID(可配置)
  247. outRequest_Body.stationId = GlobalContext.S6_StationId; // ⼯位ID(可配置)
  248. break;
  249. case "[S5]Tray盘下料装备":
  250. outRequest_Body.machineId = GlobalContext.S7_MachineId; // 装备ID(可配置)
  251. outRequest_Body.stationId = GlobalContext.S7_StationId; // ⼯位ID(可配置)
  252. break;
  253. default:
  254. break;
  255. }
  256. outRequest_Body.clientMac = GlobalContext.MacStr; // 客⼾端本机MAC地址,格式:XX-XX-XX-XX-XX-XX
  257. outRequest_Body.clientTime = processData.Test_time; // 客⼾端请求时间,格式yyyy-MM-dd HH:mm:ss.fff
  258. outRequest_Body.unitSn = sn; // 产品SN
  259. outRequest_Body.state = pass ? "PASS" : "FAIL"; // 出站条件 PASS或FAIL
  260. outRequest_Body.userId = GlobalContext.MESUserId; // ⽤⼾ID;非必填
  261. outRequest_Body.factoryId = GlobalContext.Factory_Code; // ⼯⼚id;非必填
  262. //outRequest_Body.unitData.vehicleData.Add(
  263. // new XmMES_StationOutRequest_Body.XmStationOut_VehicleData()
  264. // {
  265. // vehicleSn = vehicleSn,
  266. // vehicleType = string.Empty,
  267. // slot = vehicleSlot
  268. // }); // 设备数据 - 载具信息
  269. mesJson = JsonConvert.SerializeObject(outRequest_Body);
  270. XmMES_StationOutResponse response = new XmMES_StationOutResponse();
  271. string mesRet = string.Empty;
  272. int i = 0;
  273. while (i < 2) // 404等会多次尝试上传
  274. {
  275. response = XiaomiMESHttp_StationOutbound.StationOut(outRequest_Body);
  276. if (response != null && response.header.code == "200")
  277. break;
  278. else if (response != null && response.header.code != "503") // 503是服务器报错
  279. i++;
  280. i++;
  281. mesRet = $"[{response?.header?.code}]{response?.header?.desc}";
  282. // 记录失败原因
  283. OnMessage(LogType.Error, "上传出站数据到MES服务器---失败!正在重新上传!接口报错信息:" + mesRet + "参数:" + mesJson);
  284. }
  285. AddMessage_Station(stationNameStr, LogType.Info, "[" + processItem + "]上传出站数据到MES服务器---" + mesRet);
  286. if (response != null && response.header.code == "200")
  287. mesUpload = 1;
  288. else
  289. mesUpload = 0;
  290. }
  291. catch (Exception ex)
  292. {
  293. mesUpload = 0;
  294. string str = ex.StackTrace;
  295. AddMessage_Station(stationNameStr, LogType.Error, $"PLC上传出站数据MES报错!错误信息:" + ex.Message.ToString() + ";异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1));
  296. }
  297. }
  298. else
  299. mesUpload = 2;
  300. // 上传IOT
  301. string iotJson = string.Empty;
  302. if (GlobalContext.IsMqttSendProcessData)
  303. {
  304. try
  305. {
  306. string id = processData.ID;
  307. string guid = Guid.NewGuid().ToString();
  308. // 过站结果 0
  309. PassStationResultRequest passStaResultRequ = new PassStationResultRequest();
  310. passStaResultRequ.pass_station_id = guid; // 过站唯⼀标识(36位)
  311. passStaResultRequ.project_code = GlobalContext.Project_Code; // 项⽬编码
  312. passStaResultRequ.factory_code = GlobalContext.Factory_Code; // ⼯⼚Id
  313. passStaResultRequ.process_section_code = GlobalContext.Process_Section_Code; // ⼯段编码
  314. passStaResultRequ.line_code = GlobalContext.LineCode; // 线体编码
  315. switch (stationNameStr)
  316. {
  317. // [S1] Tray盘上料装备
  318. // [S2] FCT
  319. // [S3] 值板机
  320. // [S4_1] 载具下线装备 [S4_5] 载具上线装备
  321. // [S5] Tray盘下料装备
  322. case "[S1]Tray盘上料装备":
  323. passStaResultRequ.work_station = GlobalContext.S1_work_station; // ⼯站
  324. passStaResultRequ.device_code = GlobalContext.S1_device_code; // 装备编码
  325. passStaResultRequ.station = GlobalContext.S1_station; // ⼯位Id
  326. break;
  327. case "[S2]FCT":
  328. passStaResultRequ.work_station = GlobalContext.S2_work_station; // ⼯站
  329. passStaResultRequ.device_code = GlobalContext.S2_device_code; // 装备编码
  330. passStaResultRequ.station = GlobalContext.S2_station; // ⼯位Id
  331. break;
  332. case "[S3]值板机":
  333. passStaResultRequ.work_station = GlobalContext.S3_work_station; // ⼯站
  334. passStaResultRequ.device_code = GlobalContext.S3_device_code; // 装备编码
  335. passStaResultRequ.station = GlobalContext.S3_station; // ⼯位Id
  336. break;
  337. case "[S4_1]载具下线装备":
  338. passStaResultRequ.work_station = GlobalContext.S4_1_work_station; // ⼯站
  339. passStaResultRequ.device_code = GlobalContext.S4_1_device_code; // 装备编码
  340. passStaResultRequ.station = GlobalContext.S4_1_station; // ⼯位Id
  341. break;
  342. case "[S4_3]提升机1":
  343. passStaResultRequ.work_station = GlobalContext.S4_3_work_station; // ⼯站
  344. passStaResultRequ.device_code = GlobalContext.S4_3_device_code; // 装备编码
  345. passStaResultRequ.station = GlobalContext.S4_3_station; // ⼯位Id
  346. break;
  347. case "[S4_4]提升机2":
  348. passStaResultRequ.work_station = GlobalContext.S4_4_work_station; // ⼯站
  349. passStaResultRequ.device_code = GlobalContext.S4_4_device_code; // 装备编码
  350. passStaResultRequ.station = GlobalContext.S4_4_station; // ⼯位Id
  351. break;
  352. case "[S4_5]载具上线装备":
  353. passStaResultRequ.work_station = GlobalContext.S4_5_work_station; // ⼯站
  354. passStaResultRequ.device_code = GlobalContext.S4_5_device_code; // 装备编码
  355. passStaResultRequ.station = GlobalContext.S4_5_station; // ⼯位Id
  356. break;
  357. case "[S5]Tray盘下料装备":
  358. passStaResultRequ.work_station = GlobalContext.S5_work_station; // ⼯站
  359. passStaResultRequ.device_code = GlobalContext.S5_device_code; // 装备编码
  360. passStaResultRequ.station = GlobalContext.S5_station; // ⼯位Id
  361. break;
  362. default:
  363. break;
  364. }
  365. passStaResultRequ.process_time = processData.Test_time; // 过站时间
  366. passStaResultRequ.slot = "1"; // 槽位编码
  367. passStaResultRequ.sn = processData.Sn; // 产品SN
  368. passStaResultRequ.result = pass ? "PASS" : "FAIL"; // 过站结果
  369. passStaResultRequ.work_type = "OUT_STATION"; // 作业类型
  370. iotJson = JsonConvert.SerializeObject(passStaResultRequ);
  371. int result_Result = XiaomiMqttClient_Extend.Write_PassStationResult(passStaResultRequ);
  372. string result_ResultStr = string.Empty;
  373. var try1 = Enum.TryParse(result_Result.ToString(), out XiaomiMqttResponse_ErrCode errCode);
  374. if (try1)
  375. result_ResultStr = errCode.ToString();
  376. AddMessage_Station(stationNameStr, LogType.Info, "[" + processItem + $"]上传【过站结果 id {id}】到IOT服务器---[" + result_Result + "]" + result_ResultStr);
  377. iotUpload = result_Result == 0 ? 1 : 0;
  378. //// 过站数据 0
  379. int result_Log = 0;
  380. {
  381. //List<PassStationLogRequest> passStaLogRequs = new List<PassStationLogRequest>();
  382. //PassStationLogRequest passStaLogRequ = new PassStationLogRequest();
  383. //passStaLogRequ.pass_station_id = guid;
  384. //passStaLogRequ.sn = processData.Sn; // 产品SN
  385. //passStaLogRequ.slot ="1"; // 槽位
  386. //passStaLogRequ.test_item_num ="1"; // 测试项序号 1,2,递增
  387. //passStaLogRequ.function_name = "Machine_"+stationNameStr; // 功能名称
  388. //passStaLogRequ.test_item =""; // 测试项
  389. //passStaLogRequ.result_val =""; // 测试值/输出值
  390. //passStaLogRequ.hi_limit =""; // 上限值
  391. //passStaLogRequ.low_limit =""; // 下限值
  392. //passStaLogRequ.status =""; // 测试状态
  393. //passStaLogRequ.test_time =""; // 单项测试时间
  394. //passStaLogRequ.error_code =""; // 错误码
  395. //passStaLogRequ.project_code =""; // 描述
  396. //passStaLogRequs.Add(passStaLogRequ);
  397. //int result_Log = XiaomiMqttClient_Extend.Write_PassStationLog(passStaLogRequs);
  398. //if (result_Log == 0)
  399. //{
  400. // string sql_Upd = ProcessData.ToStringUpdateStatusByID(1, processData.ID);
  401. // string ret_Upd = string.Empty;
  402. // //ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Upd, null);
  403. // AddMessage_Station(stationNameStr, LogType.Info, $"更新【过站明细 id {processData.ID}】上传状态---" + ret_Upd);
  404. //}
  405. //else
  406. //{
  407. // OnMessage(LogType.Error, $"上传过站明细到MES服务器---失败!id {processData.ID}");
  408. //}
  409. }
  410. AddMessage_Station(stationNameStr, LogType.Info, "[" + processItem + $"]上传[{processData.Sn}]过站数据到IOT服务器---" + result_Result + "," + result_Log);
  411. }
  412. catch (Exception ex)
  413. {
  414. iotUpload = 0;
  415. string str = ex.StackTrace;
  416. AddMessage_Station(stationNameStr, LogType.Error, $"PLC上传过站数据IOT报错!错误信息:" + ex.Message.ToString() + ";异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1));
  417. }
  418. }
  419. else
  420. iotUpload = 2;
  421. // 更新上传状态
  422. int mesUpload1 = mesUpload;
  423. if (mesUpload1 == 2)
  424. mesUpload1 = 0;
  425. int iotUpload1 = iotUpload;
  426. if (iotUpload1 == 2)
  427. iotUpload1 = 0;
  428. string sql_Upd = ProcessData.ToStringUpdateStatusByID(mesJson, mesUpload1, iotJson, iotUpload1, processData.ID);
  429. string ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Upd, null);
  430. AddMessage_Station(stationNameStr, LogType.Info, $"更新【出站数据 id {processData.ID}】上传状态---" + ret_Upd);
  431. if (mesUpload == 2)
  432. mesUpload = 1;
  433. if (iotUpload == 2)
  434. iotUpload = 1;
  435. int result = (mesUpload == 1 && iotUpload == 1) ? 1 : 2;
  436. return result;
  437. }
  438. #endregion 出站数据
  439. #region 点检数据
  440. /// <summary>
  441. /// 选择如何记录点检数据
  442. /// </summary>
  443. /// <param name="names"></param>
  444. /// <param name="contents"></param>
  445. /// <param name="results"></param>
  446. /// <param name="equipmentCode"></param>
  447. /// <param name="stationNameStr"></param>
  448. private int SwitctOneCheckData(OneCheckData oneCheckData, string equipmentCode, string stationNameStr)
  449. {
  450. //if (DataSwitch == 1)
  451. //{
  452. return SaveOneCheckDataByDB(oneCheckData, equipmentCode, stationNameStr);
  453. //}
  454. //else // 废弃
  455. //{
  456. // SaveOneCheckData(names, contents, results, equipmentCode, stationNameStr);
  457. //}
  458. }
  459. /// <summary>
  460. /// 添加点检数据ByDB(本地保存;不提交到MES)
  461. /// </summary>
  462. /// <param name="oneCheckData">点检数据</param>
  463. /// <param name="equipmentCode">设备编号</param>
  464. /// <param name="stationNameStr">工站名称</param>
  465. public int SaveOneCheckDataByDB(OneCheckData oneCheckData, string equipmentCode, string stationNameStr)
  466. {
  467. int upload = 0;
  468. //本地数据保存
  469. string sql = oneCheckData.ToStringInsert(upload);
  470. string ret = SQLHelper_New.ExecuteNonQuery(sql, null);
  471. AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[[", equipmentCode, "]", stationNameStr, "]保存本地点检数据---", ret));
  472. //Task.Run(() => // 上传mes-异步
  473. //{
  474. // //上传mes
  475. // string jsonstr = JsonConvert.SerializeObject(oneCheckData);
  476. // if (GlobalContext.IsSendCheckOneData)
  477. // {
  478. // string url = @"HTTP://" + GlobalContext.ServerHost + ":" + GlobalContext.ServerPort + @"/api/ProductionLine/OneCheckData";
  479. // string mesRet = HttpUitls.SubmitDataToMES(url, jsonstr);
  480. // AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[[", equipmentCode, "]", stationNameStr, "]上传点检数据到MES---", mesRet));
  481. // if (mesRet == "成功")
  482. // {
  483. // // 更新上传状态
  484. // string sql_Upd = OneCheckData.ToStringUpdateStatusByID(1, oneCheckData.ID);
  485. // string ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Upd, null);
  486. // AddMessage_Station(stationNameStr, LogType.Info, $"更新【点检数据 id {oneCheckData.ID}】上传状态---" + ret_Upd);
  487. // }
  488. // }
  489. //});
  490. return ret == "成功" ? 1 : 0;
  491. }
  492. /// <summary>
  493. /// 提交点检数据到MES
  494. /// </summary>
  495. /// <param name="procedure_code">工序编号 = 设备编号</param>
  496. /// <param name="plcOrder">车间订单号</param>
  497. /// <returns></returns>
  498. public int SubmitToMESByDB(string procedure_code, string stationNameStr, string plcOrder)
  499. {
  500. // 获取今天的点检数据
  501. string querySQL_Today = new OneCheckData().ToQuerySQL_Today(procedure_code, plcOrder);
  502. DataSet ds = SQLHelper_New.Query(querySQL_Today, null);
  503. if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
  504. {
  505. // 拼接所有点检数据
  506. OneCheckData oneCheckDatas_MES = new OneCheckData()
  507. {
  508. ID = ds.Tables[0].Rows[0][0].ToString(),
  509. Line_code = ds.Tables[0].Rows[0][1].ToString(),
  510. Line_name = ds.Tables[0].Rows[0][2].ToString(),
  511. Equipment_code = ds.Tables[0].Rows[0][3].ToString(),
  512. Equipment_name = ds.Tables[0].Rows[0][4].ToString(),
  513. Workorder_code = ds.Tables[0].Rows[0][5].ToString(),
  514. Procedure_code = ds.Tables[0].Rows[0][6].ToString(),
  515. Procedure_name = ds.Tables[0].Rows[0][7].ToString(),
  516. Onecheck_empcode = ds.Tables[0].Rows[0][8].ToString(),
  517. Onecheck_empname = ds.Tables[0].Rows[0][9].ToString(),
  518. Onecheck_time = ds.Tables[0].Rows[0][10].ToString()
  519. };
  520. List<string> upd_Ids = new List<string>();
  521. foreach (DataRow row in ds.Tables[0].Rows)
  522. {
  523. var obj1 = row["Oneckeck_values"];
  524. if (obj1 != null)
  525. {
  526. upd_Ids.Add(row["ID"].ToString());
  527. List<OneCheckItem> item = JsonConvert.DeserializeObject<List<OneCheckItem>>(obj1.ToString());
  528. oneCheckDatas_MES.Oneckeck_values.AddRange(item);
  529. }
  530. }
  531. //上传mes
  532. string jsonstr = JsonConvert.SerializeObject(oneCheckDatas_MES);
  533. if (GlobalContext.IsSendCheckOneData)
  534. {
  535. string url = @"HTTP://" + GlobalContext.ServerHost + ":" + @"/api/ProductionLine/OneCheckData";
  536. string mesRet = HttpUitls.SubmitDataToMES(url, jsonstr);
  537. AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[", stationNameStr, "]PLC通知上传点检数据到MES到---", mesRet));
  538. if (mesRet == "成功")
  539. {
  540. // 更新上传状态
  541. string sql_Upd = OneCheckData.ToStringUpdateStatusByIDs(1, upd_Ids);
  542. string ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Upd, null);
  543. AddMessage_Station(stationNameStr, LogType.Info, $"更新【点检数据 id [{string.Join("','", upd_Ids)}]】上传状态---" + ret_Upd);
  544. // 保存最新一条点检数据 到文件中
  545. StandardLibrary.IniFile.INIWriteValue(GlobalContext.CheckOneDataPath, "S" + procedure_code, "WorkOrderCode", GlobalContext.WorkOrderCode);
  546. StandardLibrary.IniFile.INIWriteValue(GlobalContext.CheckOneDataPath, "S" + procedure_code, "Oneckeck_values", JsonConvert.SerializeObject(oneCheckDatas_MES.Oneckeck_values));
  547. return ret_Upd == "成功" ? 1 : 0;
  548. }
  549. }
  550. }
  551. //else
  552. //{
  553. // AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[", stationNameStr, "]PLC通知上传点检数据到MES---失败!今天还未点检。"));
  554. //}
  555. return 0;
  556. }
  557. /// <summary>
  558. /// 添加点检数据ByDB(本地保存 + 提交到MES)
  559. /// </summary>
  560. /// <param name="oneCheckData">点检数据</param>
  561. /// <param name="equipmentCode">设备编号</param>
  562. /// <param name="stationNameStr">工站名称</param>
  563. /// <returns></returns>
  564. public int SaveOneCheckDataByDBAndSubmit(OneCheckData oneCheckData, string equipmentCode, string stationNameStr)
  565. {
  566. int upload = 0;
  567. //本地数据保存
  568. string sql = oneCheckData.ToStringInsert(upload);
  569. string ret = SQLHelper_New.ExecuteNonQuery(sql, null);
  570. AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[[", equipmentCode, "]", stationNameStr, "]保存本地点检数据---", ret));
  571. Task.Run(() => // 上传mes-异步
  572. {
  573. //上传mes
  574. string jsonstr = JsonConvert.SerializeObject(oneCheckData);
  575. string jsonItems = JsonConvert.SerializeObject(oneCheckData.Oneckeck_values);
  576. if (GlobalContext.IsSendCheckOneData)
  577. {
  578. string url = @"HTTP://" + GlobalContext.ServerHost + ":" + @"/api/ProductionLine/OneCheckData";
  579. string mesRet = HttpUitls.SubmitDataToMES(url, jsonstr);
  580. AddMessage_Station(stationNameStr, LogType.Info, string.Concat("[[", equipmentCode, "]", stationNameStr, "]上传点检数据到MES---", mesRet));
  581. if (mesRet == "成功")
  582. {
  583. // 更新上传状态
  584. string sql_Upd = OneCheckData.ToStringUpdateStatusByID(1, oneCheckData.ID);
  585. string ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Upd, null);
  586. AddMessage_Station(stationNameStr, LogType.Info, $"更新【点检数据 id {oneCheckData.ID}】上传状态---" + ret_Upd);
  587. // 保存最新一条点检数据 到文件中
  588. StandardLibrary.IniFile.INIWriteValue(GlobalContext.CheckOneDataPath, equipmentCode, "WorkOrderCode", GlobalContext.WorkOrderCode);
  589. StandardLibrary.IniFile.INIWriteValue(GlobalContext.CheckOneDataPath, equipmentCode, "Oneckeck_values", jsonItems);
  590. }
  591. }
  592. });
  593. return ret == "成功" ? 1 : 0;
  594. }
  595. /// <summary>
  596. /// 清空 点检数据 By 工序号、订单号
  597. /// </summary>
  598. /// <param name="procedure_code">工序号</param>
  599. /// <param name="stationNameStr">工站号</param>
  600. /// <param name="plcOrder">订单号</param>
  601. /// <returns></returns>
  602. /// <exception cref="NotImplementedException"></exception>
  603. private int ClearOneCheckDataByDB(string procedure_code, string stationNameStr, string plcOrder)
  604. {
  605. // 清空
  606. string sql_Det = OneCheckData.ToDeteleByProcedurecodeAndPlcOrder(procedure_code, plcOrder);
  607. string ret_Upd = SQLHelper_New.ExecuteNonQuery(sql_Det, null);
  608. AddMessage_Station(stationNameStr, LogType.Info, $"清空【工位编号{procedure_code}】【车间订单{plcOrder}】的点检项缓存 ---" + ret_Upd);
  609. return ret_Upd == "成功" ? 1 : 2;
  610. }
  611. /// <summary>
  612. /// 生产过程中,自动判断 是否 使用上次的点检数据
  613. /// 在工单加工第一个产品时触发该方法
  614. /// 如果工单是上次的点检工单则直接返回成功,工单不是上次的点检工单则使用上个工单的点检数据,上传点检信息
  615. /// </summary>
  616. /// <param name="stationNameStr"></param>
  617. /// <param name="equipmentCode">设备编号</param>
  618. /// <param name="accno">工序编号</param>
  619. /// <param name="processItem">点检数据</param>
  620. /// <returns></returns>
  621. private int SwitctOneCheckData_First(string stationNameStr, string equipmentCode, string accno, string processItem)
  622. {
  623. string WorkOrderCode = StandardLibrary.IniFile.INIGetStringValue(GlobalContext.CheckOneDataPath, equipmentCode, "WorkOrderCode", string.Empty);
  624. //如果当前工单和记录中的工单是一致,表示这个工单是需要点检的,跳过
  625. //如果当前工单和记录中的工单是不一致,表示这个工单和上个工单是同型号的,可以使用上个工单的点检数据
  626. if (GlobalContext.WorkOrderCode == WorkOrderCode)
  627. {
  628. return 1;
  629. }
  630. //点检数据
  631. string Oneckeck_values = StandardLibrary.IniFile.INIGetStringValue(GlobalContext.CheckOneDataPath, equipmentCode, "Oneckeck_values", string.Empty);
  632. List<OneCheckItem> items = new List<OneCheckItem>();
  633. try
  634. {
  635. items = JsonConvert.DeserializeObject<List<OneCheckItem>>(Oneckeck_values);
  636. }
  637. catch (Exception ex)
  638. {
  639. return 0;
  640. }
  641. // 拼接所有点检数据
  642. OneCheckData oneCheckDatas_MES = new OneCheckData()
  643. {
  644. ID = Guid.NewGuid().ToString(),
  645. Line_code = GlobalContext.LineCode,
  646. Line_name = GlobalContext.LineName,
  647. Equipment_code = equipmentCode,
  648. Equipment_name = equipmentCode,
  649. Workorder_code = GlobalContext.WorkOrderCode,
  650. Procedure_code = accno,
  651. Procedure_name = processItem,
  652. Onecheck_empcode = "",
  653. Onecheck_empname = "",
  654. Onecheck_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
  655. Oneckeck_values = items
  656. };
  657. // 本地保存 + 提交到MES
  658. return SaveOneCheckDataByDBAndSubmit(oneCheckDatas_MES, equipmentCode, stationNameStr);
  659. }
  660. #endregion 点检数据
  661. #region 报警数据
  662. /// <summary>
  663. /// 添加报警数据ByDB(提交到MES+本地保存)
  664. /// </summary>
  665. /// <param name="alarmData">数据</param>
  666. /// <param name="isUpd">更新而不是新增</param>
  667. public void SaveAlarmDataByDB(string stationNameStr, AlarmData alarmData, bool isUpd)
  668. {
  669. if (isUpd)
  670. {
  671. string sql = alarmData.ToStringUpdate();
  672. SQLHelper_New.ExecuteSQL(sql, null);
  673. AddMessage_Station(stationNameStr, LogType.Info, "消除报警[" + alarmData.LineName + "-" + alarmData.AlarmDesc + "]完毕!");
  674. }
  675. else
  676. {
  677. string sql = alarmData.ToStringInsert();
  678. SQLHelper_New.ExecuteSQL(sql, null);
  679. AddMessage_Station(stationNameStr, LogType.Info, "发生了报警[" + alarmData.LineName + "-" + alarmData.AlarmDesc + "]!");
  680. }
  681. }
  682. #endregion 报警数据
  683. #region 节拍数据
  684. /// <summary>
  685. /// 上传节拍数据
  686. /// </summary>
  687. /// <returns></returns>
  688. public (short, string) SaveOEEData(int plcNo, string stationNameStr, XiaomiDeviceOEE deviceOEE, string oEEPartNo, string oEEProductSN)
  689. {
  690. // 上传OEE
  691. if (GlobalContext.IsMqttStationInputBegin)
  692. {
  693. Task.Run(() =>
  694. {
  695. try
  696. {
  697. StationInputBeginRequest oee = new StationInputBeginRequest();
  698. oee.action = deviceOEE.ToString(); // 节拍动作(XiaomiDeviceOEE)
  699. oee.beat_tm = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); // 节拍发⽣时间
  700. oee.action_subject = oEEPartNo; // 该动作操作的⽬标对象(SN)
  701. oee.action_subject_parent = oEEProductSN; // ⼤板SN/载具SN
  702. oee.action_location = GlobalContext.S1_station; // 该动作的位置信息(⼯位、槽位),如:F06-GSTPLA11_01-SLOT-01
  703. switch (stationNameStr)
  704. {
  705. case "[S1]Tray盘上料装备":
  706. oee.action_location = GlobalContext.S1_station;
  707. break;
  708. case "[S2]FCT":
  709. oee.action_location = GlobalContext.S2_station;
  710. break;
  711. case "[S3]值板机":
  712. oee.action_location = GlobalContext.S3_station;
  713. break;
  714. case "[S4_1]载具下线装备":
  715. oee.action_location = GlobalContext.S4_1_station;
  716. break;
  717. case "[S4_3]提升机1":
  718. oee.action_location = GlobalContext.S4_3_station;
  719. break;
  720. case "[S4_4]提升机2":
  721. oee.action_location = GlobalContext.S4_4_station;
  722. break;
  723. case "[S4_5]载具上线装备":
  724. oee.action_location = GlobalContext.S4_5_station;
  725. break;
  726. case "[S5]Tray盘下料装备":
  727. oee.action_location = GlobalContext.S5_station;
  728. break;
  729. }
  730. oee.action_material = string.Empty; // 该动作的物料信息
  731. oee.extra = string.Empty; // 额外信息
  732. oee.class_level_1 = string.Empty; // 分类层级1
  733. oee.class_level_2 = string.Empty; // 分类层级2
  734. oee.class_level_3 = string.Empty; // 分类层级3
  735. int result = XiaomiMqttClient_Extend.Write_StationInputBegin(oee);
  736. string msg = $"[{result}]";
  737. bool errCodeParse = Enum.TryParse(result.ToString(), out XiaomiMqttResponse_ErrCode errCode);
  738. msg += errCodeParse ? errCode.ToString() : "ERR_UNKOWN";
  739. AddMessage(LogType.Info, stationNameStr + $"_异步上传节拍接口;接口结果:-- {msg}");
  740. }
  741. catch (Exception ex)
  742. {
  743. string str = ex.StackTrace;
  744. AddMessage(LogType.Error, $"PLC{plcNo}_{stationNameStr} 异步上传节拍接口出错!错误信息:" + ex.Message + "异常位置:" + str.Substring(str.LastIndexOf("\\") + 1, str.Length - str.LastIndexOf("\\") - 1));
  745. }
  746. });
  747. return ((short)1, "异步上传中!");
  748. }
  749. else
  750. return ((short)1, "未启用上传!");
  751. }
  752. #endregion 节拍数据
  753. #endregion 保存数据
  754. }
  755. }