frmMain.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. using com.hnshituo.core.webapp.vo;
  2. using Newtonsoft.Json;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel;
  6. using System.Data;
  7. using System.Diagnostics;
  8. using System.Drawing;
  9. using System.Drawing.Drawing2D;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Net.NetworkInformation;
  13. using System.Runtime.InteropServices;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using System.Windows.Forms;
  18. namespace CarLocalMeter
  19. {
  20. public partial class frmMain : Form
  21. {
  22. public frmMain()
  23. {
  24. InitializeComponent();
  25. }
  26. Log lg = Log.GetInstance();
  27. private LED_Control led_controler;
  28. //List<CamerEs> lc = new List<CamerEs>();
  29. /// <summary>
  30. /// 硬盘录像机图片抓拍通道
  31. /// </summary>
  32. List<int> lc = new List<int>();
  33. /// <summary>
  34. /// 服务端委托获取
  35. /// </summary>
  36. private PreTrackScaleService PreTrackScaleService = new PreTrackScaleService();
  37. RESTfulResult<List<PreTrackScale>> rmScaleListCarTimer = new RESTfulResult<List<PreTrackScale>>();
  38. private MeterWorkCarActualFirstService workCarActualFirstService = new MeterWorkCarActualFirstService(); //一次计量数据
  39. RESTfulResult<List<MeterWorkCarActualFirst>> RESTfulResultOutTimer = new RESTfulResult<List<MeterWorkCarActualFirst>>();
  40. PlcCls plc = new PlcCls();
  41. /// <summary>
  42. /// redis操作类
  43. /// </summary>
  44. RedisOption redis = new RedisOption();
  45. /// <summary>
  46. /// 图片操作类
  47. /// </summary>
  48. ImageOption imgControl = new ImageOption();
  49. /// <summary>
  50. /// 语音播放
  51. /// </summary>
  52. VoicePlay vicPlayClass = new VoicePlay();
  53. /// <summary>
  54. /// 摄像头车号识别枪机
  55. /// </summary>
  56. CarNoCls carCls = new CarNoCls();
  57. /// <summary>
  58. /// 摄像头识别球机
  59. /// </summary>
  60. CarNoCls carCls2 = new CarNoCls();
  61. /// <summary>
  62. /// rfid车号识别
  63. /// </summary>
  64. RfIdCarNo rfid = new RfIdCarNo();
  65. /// <summary>
  66. /// 以下是硬盘录像机的控制
  67. /// </summary>
  68. bool bVoice = false;
  69. CamerEs ce = new CamerEs(AppConfigCache.voicePlayIp, $"{AppConfigCache.voicePlayPort}", AppConfigCache.voicePlayUid, AppConfigCache.voicePlayPwd);
  70. List<int> voPlay = new List<int>();
  71. int iPic = 0;
  72. private void frmMain_Load(object sender, EventArgs e)
  73. {
  74. btnSave.Enabled = false;
  75. if (!string.IsNullOrEmpty(AppConfigCache.ledIp))
  76. {
  77. led_controler = new LED_Control(AppConfigCache.ledIp);
  78. }
  79. #region 读取音频文件名称
  80. List<string> ls = new List<string>();
  81. DirectoryInfo folder = new DirectoryInfo(AppConfigCache.path + "\\Sound");
  82. foreach (FileInfo file in folder.GetFiles("*.wav"))
  83. {
  84. ls.Add(file.Name.Replace(".wav", ""));
  85. }
  86. CacleCls.voiceInfo = ls;
  87. #endregion
  88. string[] strTd1 = AppConfigCache.channelOther.Split(',');
  89. string[] strTd2 = AppConfigCache.channelVis.Split(',');
  90. string[] strAll = new string[strTd1.Length + strTd2.Length];
  91. strTd1.CopyTo(strAll, 0);
  92. strTd2.CopyTo(strAll, strTd1.Length);
  93. List<string> lcs = strAll.Distinct().OrderBy(s => s).ToList(); //
  94. lc.Add(AppConfigCache.channelCarNo);
  95. foreach (string str in lcs)
  96. {
  97. if ($"{AppConfigCache.channel}" != str && $"{AppConfigCache.channelCarNo}" != str)
  98. {
  99. lc.Add(Convert.ToInt32(str)); //抓拍通道与数组中不相同的时候写入,因为我们仪表抓拍的通道需单独进行处理
  100. }
  101. }
  102. plImgShow.Visible = false;
  103. lbPointName.Text = AppConfigCache.pointName;
  104. foreach (string str in AppConfigCache.channelVis.Split(','))
  105. {
  106. voPlay.Add(Convert.ToInt32(str));
  107. }
  108. ce.Connection();
  109. foreach(int i in voPlay)
  110. {
  111. PictureBox pb = new PictureBox();
  112. pb.Dock = DockStyle.Top;
  113. pb.DoubleClick += new EventHandler(PictureBoxDoubleClick);
  114. pb.Height = AppConfigCache.channelVisHeight;
  115. pb.Name = $"pb{i}";
  116. panel1.Controls.Add(pb);
  117. ce.RealPlay(pb, i);
  118. }
  119. rfid.Start();
  120. /*
  121. TaskMain();
  122. TaskPing();
  123. TaskDbUpload();
  124. imgControl.Start();
  125. plc.Start();
  126. //*/
  127. carCls.Login(AppConfigCache.voiceCarNoIp, AppConfigCache.voiceCarNoPort, AppConfigCache.voiceCarNoUid, AppConfigCache.voiceCarNoPwd);
  128. //carCls2.Login(AppConfigCache.voiceCarNoIp2, AppConfigCache.voiceCarNoPort2, AppConfigCache.voiceCarNoUid2, AppConfigCache.voiceCarNoPwd2, false);
  129. }
  130. CancellationTokenSource _cts,_cts2,_dbCts;
  131. bool getPreInfo = false, getFirst = false, flagCaption = false, isVoiceDownCar = false;
  132. string strOldCarNo = "";
  133. bool isMeasureSuccess = false;
  134. int voiceNum = 0;
  135. int iImgCnt = 0;
  136. /// <summary>
  137. /// 主定时任务
  138. /// </summary>
  139. private void TaskMain()
  140. {
  141. _cts = new CancellationTokenSource();
  142. Task.Run(() => {
  143. while (!_cts.IsCancellationRequested)
  144. {
  145. this.panel3.Invoke(new Action(() => {
  146. if (!CacleCls.isLock)
  147. {
  148. ucWeightT1.setWgt(Math.Round((double)CacleCls.weight / 1000, 2)); //2021年5月10日界面显示单位,调整为T
  149. ucWeightT1.setStable(CacleCls.isWd != 1 ? true : false);
  150. ucWeightT1.setExceed(CacleCls.weight > AppConfigCache.maxRange * 1000 ? false : true);
  151. if (cbCarNo.Text.Trim() != "" && txtCarNo.Text.Trim() != "")
  152. {
  153. CacleCls.lockCarNo = cbCarNo.Text.Trim() + txtCarNo.Text.Trim();
  154. }
  155. else if (CacleCls.rfidCarNo != "")
  156. {
  157. CacleCls.lockCarNo = CacleCls.rfidCarNo;
  158. }
  159. else if (CacleCls.voicCarNo != "")
  160. {
  161. CacleCls.lockCarNo = CacleCls.voicCarNo;
  162. }
  163. else if (!string.IsNullOrEmpty(CacleCls.voicCarNo2))
  164. {
  165. CacleCls.lockCarNo = CacleCls.voicCarNo2;
  166. }
  167. if (CacleCls.lockCarNo != "" && cbCarNo.Text.Trim() == "" && txtCarNo.Text.Trim() == "")
  168. {
  169. cbCarNo.Text = CacleCls.lockCarNo.Substring(0, 1);
  170. if (CacleCls.lockCarNo.Length > 1)
  171. {
  172. txtCarNo.Text = CacleCls.lockCarNo.Substring(1);
  173. }
  174. }
  175. if (strOldCarNo != CacleCls.lockCarNo)
  176. {
  177. strOldCarNo = CacleCls.lockCarNo;
  178. getPreInfo = false;
  179. getFirst = false;
  180. }
  181. }
  182. if (CacleCls.weight > 500)
  183. {
  184. iImgCnt = 0;
  185. CacleCls.isClear = false;
  186. //是否能连上远程服务器,这里只是服务器,不是服务器上的服务端
  187. pbLineOn.Load(CacleCls.serverFlag ? (AppConfigCache.path + "\\image\\icon\\green.gif") : (AppConfigCache.path + "\\image\\icon\\red.gif"));
  188. #region 一些必要验证及提醒
  189. if (!CacleCls.isLock)
  190. {
  191. //重量最后一位不为0也是超量程
  192. if ((AppConfigCache.maxRange * 1000 < CacleCls.weight) || CacleCls.weight.ToString().Substring(CacleCls.weight.ToString().Length - 1, 1) != "0")
  193. {
  194. //超量程
  195. vicPlayClass.GetVoicePlay("已超量程", CacleCls.lockCarNo);
  196. txtMsgInfo.Text = "当前重量已超量程,秤体量程为【" + AppConfigCache.maxRange + "】T,不允许进行自助计量操作!";
  197. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "当前重量已超量程,秤体量程为【" + AppConfigCache.maxRange + "】T,不允许进行自助计量操作!");
  198. CacleCls.isLock = false;
  199. return;
  200. }
  201. if (CacleCls.isWd == 0 && !string.IsNullOrEmpty(CacleCls.lockCarNo))
  202. {
  203. if ((CacleCls.topJg == "1" || CacleCls.bottomJg == "1"))
  204. {
  205. //重量稳定,且对射验证不合格
  206. vicPlayClass.GetVoicePlay("车辆超出秤台,请调整车位2", CacleCls.lockCarNo);
  207. txtMsgInfo.Text = "车辆超出秤台,请调整车位2";
  208. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "车辆超出秤台,请调整车位2");
  209. CacleCls.isLock = false;
  210. return;
  211. }
  212. else if (CacleCls.rightGs == "1")
  213. {
  214. //重量稳定,且右光栅不合格
  215. vicPlayClass.GetVoicePlay("车辆超出秤台,请调整车位3", CacleCls.lockCarNo);
  216. txtMsgInfo.Text = "车辆超出秤台,请调整车位3";
  217. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "车辆超出秤台,请调整车位3");
  218. CacleCls.isLock = false;
  219. return;
  220. }
  221. else if (CacleCls.leftGs == "1")
  222. {
  223. //重量稳定,且左光栅不合格
  224. vicPlayClass.GetVoicePlay("车辆超出秤台,请调整车位4", CacleCls.lockCarNo);
  225. txtMsgInfo.Text = "车辆超出秤台,请调整车位4";
  226. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "车辆超出秤台,请调整车位4");
  227. CacleCls.isLock = false;
  228. return;
  229. }
  230. }
  231. /*
  232. if (PbCache.isOvertimeAlarm)
  233. {
  234. //停留超时提醒,不作为计量卡控的条件
  235. if (!isPlayOvertimeVoice && !PbCache.isLockFrm)
  236. {
  237. vicPlayClass.GetVoicePlay("停留超时", PbCache.collect.carno);
  238. led_controler.setStaticLineMsg(PbCache.sportInfo.ledIp, "停留超时");
  239. txtMsgInfo.Text = "停留超时";
  240. PbCache.ResultMessage = "停留超时";
  241. isPlayOvertimeVoice = true;
  242. return;
  243. }
  244. }
  245. //*/
  246. #region 一次计量数据跟预报获取一次
  247. if (!string.IsNullOrEmpty(CacleCls.lockCarNo))
  248. {
  249. //查询一次计量数据
  250. if (!getFirst)
  251. {
  252. RESTfulResultOutTimer = workCarActualFirstService.doQueryWf(new MeterWorkCarActualFirst { valueFlag = "1", carNo = CacleCls.lockCarNo });
  253. if (RESTfulResultOutTimer.Succeed)
  254. {
  255. if (RESTfulResultOutTimer.Data != null && RESTfulResultOutTimer.Data.Count > 0)
  256. {
  257. CacleCls.firstDb = RESTfulResultOutTimer.Data[0];
  258. if (CacleCls.firstDb.predictionNo != null && !CacleCls.firstDb.predictionNo.Contains("_"))
  259. {
  260. txtMATTER_NAME.Text = CacleCls.firstDb.matterName;
  261. txtFORWARDING_UNIT_NAME.Text = CacleCls.firstDb.forwardingUnitName;
  262. txtRECEIVING_UINT_NAME.Text = CacleCls.firstDb.receivingUintName;
  263. txtMETER_TYPE.Text = CacleCls.firstDb.meterTypeName;
  264. }
  265. }
  266. }
  267. getFirst = true;
  268. }
  269. //根据网络状态及车号以及是否存在一次计量数据,查询一次预报信息,然后将getPreInfo改为true
  270. if (!getPreInfo && CacleCls.serverFlag)
  271. {
  272. if (CacleCls.firstDb == null || string.IsNullOrEmpty(CacleCls.firstDb?.predictionNo))
  273. {
  274. //如果没有一次信息或者一次信息里面没带预报信息,则查询一次预报信息
  275. rmScaleListCarTimer = PreTrackScaleService.doQueryByFlag(new PreTrackScale { lineDesc = "1", carNo = CacleCls.lockCarNo });
  276. if (rmScaleListCarTimer.Succeed)
  277. {
  278. if (rmScaleListCarTimer.Data != null && rmScaleListCarTimer.Data.Count == 1)
  279. {
  280. CacleCls.preTrackScale = rmScaleListCarTimer.Data[0];
  281. txtMATTER_NAME.Text = CacleCls.preTrackScale.matterName;
  282. txtFORWARDING_UNIT_NAME.Text = CacleCls.preTrackScale.forwardingUnitName;
  283. txtRECEIVING_UINT_NAME.Text = CacleCls.preTrackScale.receivingUintName;
  284. txtMETER_TYPE.Text = CacleCls.preTrackScale.meterTypeName;
  285. }
  286. }
  287. }
  288. getPreInfo = true;
  289. }
  290. }
  291. #endregion
  292. //进行计量称重条件的判断 车号不为空、重量稳定、车辆已停到位
  293. if (!string.IsNullOrEmpty(CacleCls.lockCarNo) && CacleCls.isWd == 0 && CacleCls.leftGs != "1" && CacleCls.rightGs != "1" && CacleCls.topJg != "1" && CacleCls.bottomJg != "1")
  294. {
  295. if (!isVoiceDownCar)
  296. {
  297. isVoiceDownCar = true;
  298. vicPlayClass.GetVoicePlay("车上人员请下车", CacleCls.lockCarNo);//只播放一次
  299. }
  300. //if(!btnSave.Enabled) btnSave.Enabled = true;
  301. if (!CacleCls.isJg)
  302. {
  303. lg.WriteLog(LogType.SystemLog, CacleCls.lockCarNo + "开始保存:" + DateTime.Now.ToLongTimeString());
  304. btnSave.PerformClick();
  305. }
  306. }
  307. }
  308. #endregion
  309. //计量完成后进行语音播报,提示离开秤台,播报5次
  310. if (isMeasureSuccess)
  311. {
  312. if (voiceNum < AppConfigCache.voiceNum)
  313. {
  314. if (CacleCls.voiceOver)
  315. {
  316. vicPlayClass.GetVoicePlay("计量完成,请离开秤台", CacleCls.lockCarNo);
  317. voiceNum++;
  318. }
  319. }
  320. return;
  321. }
  322. }
  323. else
  324. {
  325. voiceNum = 0;
  326. isMeasureSuccess = false;
  327. lockWgtImg = CacleCls.weight;
  328. getFirst = false;
  329. getPreInfo = false;
  330. flagCaption = false;
  331. isVoiceDownCar = false;
  332. strGuid = "";
  333. if (!CacleCls.isClear)
  334. {
  335. CacleCls.Clear(); //清理一次数据
  336. btnSave.Enabled = false;
  337. cbCarNo.Text = "";
  338. cbCarNo.SelectedIndex = -1;
  339. txtCarNo.Text = "";
  340. txtMATTER_NAME.Text = "";
  341. txtFORWARDING_UNIT_NAME.Text = "";
  342. txtRECEIVING_UINT_NAME.Text = "";
  343. txtMETER_TYPE.Text = "";
  344. cbCarNo.Enabled = true;
  345. txtCarNo.Enabled = true;
  346. txtGroess.Text = "";
  347. txtTare.Text = "";
  348. txtNet.Text = "";
  349. //释放一次内存
  350. FlushMemory();
  351. }
  352. //避免海康截图完成时间在下磅后,所以压缩图片在下磅后5秒继续执行,超过这个时间则认为没有图片需压缩了
  353. if (iImgCnt < 10)
  354. {
  355. iImgCnt++;//最多在车辆下磅后,5秒内继续压缩下图片,如果都下磅5秒了还没图片说明没有图片需压缩了
  356. imgControl.ZipFiles();
  357. }
  358. }
  359. }));
  360. Thread.Sleep(500);
  361. }
  362. }, _cts.Token);
  363. }
  364. /// <summary>
  365. /// ping服务器
  366. /// </summary>
  367. private void TaskPing()
  368. {
  369. _cts2 = new CancellationTokenSource();
  370. Task.Run(() => {
  371. try
  372. {
  373. Ping pingSend = new Ping();
  374. PingReply reply = pingSend.Send(AppConfigCache.ServiceIp, 1000);
  375. if (reply.Status == IPStatus.Success)
  376. CacleCls.serverFlag = true;
  377. else
  378. CacleCls.serverFlag = false;
  379. }
  380. catch (Exception)
  381. {
  382. CacleCls.serverFlag = false;
  383. }
  384. Thread.Sleep(500);
  385. }, _cts2.Token);
  386. }
  387. /// <summary>
  388. /// 结净数据上传服务
  389. /// 这里需等重量小于500且网络正常时触发
  390. /// 因为假如网络正常且重量大于500的时候,会优先将当前计量的数据存储到服务器上,然后返回结果进行打印操作
  391. /// 所以这里为了避免重复数据插入,所以需重量小于500且网络正常
  392. /// </summary>
  393. private void TaskDbUpload()
  394. {
  395. Dictionary<string, string> dic = new Dictionary<string, string>();
  396. _dbCts = new CancellationTokenSource();
  397. Task.Run(() => {
  398. try
  399. {
  400. if (CacleCls.weight < 500 && CacleCls.serverFlag)
  401. {
  402. dic.Clear();
  403. //检索本地实时库中结净数据。(若本地数据结净后,一次数据得删除,而结净数据中会保留一次数据的编号、重量、计量时间、计量点信息)
  404. //若本地存在结净数据未进行上传的,则进行数据上传并得到返回的结果:老一次计量编号|一次计量编号,老二次计量编号|新二次计量编号
  405. //得到结果后构造成Dictionary然后进行图片操作,修改图片名称及位置
  406. bool bReadFlag = false;
  407. string strRtMsgInfo = "";
  408. List<MeterWorkCarActualFirst> lm = FileOption.ReadDb(ref bReadFlag, ref strRtMsgInfo);
  409. if (bReadFlag)
  410. {
  411. //进行结净
  412. RESTfulResult<List<DjPbModel>> rmRst = workCarActualFirstService.doDbUpload(lm);
  413. if (rmRst.Succeed)
  414. {
  415. if (rmRst.Data.Count == lm.Count)
  416. {
  417. //直接重写文件
  418. FileOption.clearFile();
  419. //然后对图片进行压缩及修改名称处理
  420. foreach (DjPbModel dm in rmRst.Data)
  421. {
  422. dic.Add(dm.key, dm.value);
  423. }
  424. }
  425. else
  426. {
  427. //清理下文件
  428. FileOption.clearFile();
  429. //重写下未成功的数据
  430. foreach (MeterWorkCarActualFirst first in lm)
  431. {
  432. DjPbModel pm = rmRst.Data.Where(s => s.key == first.actualFirstNo).FirstOrDefault();
  433. if (pm == null || string.IsNullOrEmpty(pm.key) || string.IsNullOrEmpty(pm.value))
  434. {
  435. //Thread.Sleep(100);
  436. bool flag = FileOption.WriterDb(new ActualFirstModel { actualFirstNo = first.actualFirstNo, baseSpotNo = first.baseSpotNo, baseSpotName = first.baseSpotName, carNo = first.carNo, createTime = first.createTime, meterWeight = first.meterWeight }, out string msgInfo);
  437. if (!flag)
  438. {
  439. lg.WriteLog(LogType.serverLog, $"重写失败:{msgInfo},数据:actualFirstNo{first.actualFirstNo},baseSpotNo:{first.baseSpotNo},baseSpotName:{first.baseSpotName},carNo:{first.carNo},createTime:{first.createTime},meterWeight:{first.meterWeight}");
  440. }
  441. }
  442. else
  443. {
  444. dic.Add(pm.key, pm.value);
  445. }
  446. }
  447. }
  448. if (dic.Count > 0) imgControl.ZipFiles(dic);
  449. }
  450. else
  451. {
  452. //计量失败,播报失败,然后写led屏幕及日志
  453. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "计量失败,请联系管理员");
  454. txtMsgInfo.Text = "计量失败:" + rmRst.ResultMessage;
  455. lg.WriteLog(LogType.serverLog, rmRst.ResultMessage);
  456. CacleCls.isLock = false;
  457. return;
  458. }
  459. }
  460. }
  461. }
  462. catch (Exception)
  463. {
  464. CacleCls.serverFlag = false;
  465. }
  466. Thread.Sleep(1000);
  467. }, _dbCts.Token);
  468. }
  469. int lockWgtImg = 0;
  470. string strGuid = "";
  471. private void btnSave_Click(object sender, EventArgs e)
  472. {
  473. #region 下面是业务逻辑代码
  474. string msgInfo = "";
  475. if (txtCarNo.Focused) return; //如果正在修改车号,就必须等光标离开后再保存,否则容易导致车号输入了一半保存了
  476. if (CacleCls.isWd != 0) return;
  477. ucWeightT1.setStable(true); // 重量稳定
  478. ucWeightT1.setWgt(Math.Round((double)CacleCls.weight / 1000, 2)); // 最新重量
  479. CacleCls.lockWgt = CacleCls.weight;
  480. if (!CacleCls.lockWgt.ToString().EndsWith("0")) //个位不是0则说明超量程了
  481. {
  482. //txtMsgInfo.Text = "仪表重量[" + CacleCls.lockWgt + "]不是以0结尾,禁止计量操作!";
  483. vicPlayClass.GetVoicePlay("已超量程", CacleCls.lockCarNo);
  484. txtMsgInfo.Text = "当前重量已超量程,秤体量程为【" + AppConfigCache.maxRange + "】T,不允许进行自助计量操作!";
  485. return;
  486. }
  487. //接管状态点的保存
  488. if (CacleCls.isJg)
  489. {
  490. if (string.IsNullOrEmpty(CacleCls.lockCarNo))
  491. {
  492. txtMsgInfo.Text = "没有车号,无法保存";
  493. return;
  494. }
  495. else if (CacleCls.lockWgt < 500)
  496. {
  497. txtMsgInfo.Text = "重量过小,无法保存";
  498. return;
  499. }
  500. else if (CacleCls.isWd != 0)
  501. {
  502. txtMsgInfo.Text = "重量不稳定,无法保存";
  503. return;
  504. }
  505. else if (CacleCls.leftGs == "1" || CacleCls.rightGs == "1" || CacleCls.topJg == "1" || CacleCls.bottomJg == "1")
  506. {
  507. txtMsgInfo.Text = "激光被遮挡,车辆未停到位,无法保存";
  508. return;
  509. }
  510. else
  511. {
  512. lg.WriteLog(LogType.SystemLog, CacleCls.lockCarNo + "接管状态下进行的保存:" + DateTime.Now.ToLongTimeString());
  513. }
  514. }
  515. //存在零点,且不为接管状态则禁止计量
  516. if (CacleCls.isZeroState && !CacleCls.isJg)
  517. {
  518. vicPlayClass.GetVoicePlay("仪表未归零,无法计量,请联系大厅", CacleCls.lockCarNo);
  519. txtMsgInfo.Text = "仪表未归零,无法计量,请联系大厅"; //btnSave_Click
  520. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "仪表未归零,无法计量");
  521. return;
  522. }
  523. if (!CacleCls.isJg && CacleCls.firstDb != null)
  524. {
  525. if (Math.Abs(CacleCls.firstDb.meterWeight.Value - CacleCls.lockWgt) < AppConfigCache.differenceWgt)
  526. {
  527. vicPlayClass.GetVoicePlay("计量失败,洁净重量过小,请联系计量大厅", CacleCls.lockCarNo);
  528. txtMsgInfo.Text = "计量失败,洁净重量过小";
  529. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "计量失败,洁净重量过小");
  530. return;
  531. }
  532. }
  533. txtMsgInfo.Text = "称重保存中......";
  534. CacleCls.isLock = true;
  535. cbCarNo.Enabled = false;
  536. txtCarNo.Enabled = false;
  537. strGuid = strGuid == "" ? Guid.NewGuid().ToString() : strGuid;
  538. #region 截图
  539. if (!flagCaption)
  540. {
  541. for (int i = 0; i < lc.Count(); i++)
  542. {
  543. if (i == 0)
  544. {
  545. carCls.CapturePictrue2($"{AppConfigCache.path}/imgShort/formalImg/{AppConfigCache.pointNo}_C{strGuid}_tempImg_{i + 2}.jpg");
  546. continue;
  547. }
  548. //从_2开始,因为_1是仪表图片 2是车号快照抓拍
  549. ce.CapPic((uint)lc[i], $"{AppConfigCache.path}/imgShort/formalImg/{AppConfigCache.pointNo}_C{strGuid}_tempImg_{i + 2}.jpg");
  550. }
  551. flagCaption = true;
  552. }
  553. if (lockWgtImg != CacleCls.lockWgt)
  554. {
  555. lockWgtImg = CacleCls.lockWgt;
  556. foreach (Control cn in panel1.Controls)
  557. {
  558. if (cn.Name.Substring(cn.Name.Length - 1) == $"{AppConfigCache.channel}")
  559. {
  560. if (cn is PictureBox)
  561. {
  562. Bitmap bit = new Bitmap(cn.Width, cn.Height);//实例化一个和窗体一样大的bitmap
  563. Graphics g = Graphics.FromImage(bit);
  564. g.CompositingQuality = CompositingQuality.HighQuality;//质量设为最高 HighQuality
  565. g.CopyFromScreen(panel1.Left, panel1.Top + 25, 0, 0, new Size(cn.Width, cn.Height));//保存整个窗体为图片
  566. bit.Save($"{AppConfigCache.path}/imgShort/formalImg/{AppConfigCache.pointNo}_C{strGuid}_tempImg_1.jpg");//默认保存格式为PNG,保存成jpg格式质量不是很好
  567. bit.Dispose();
  568. break;
  569. }
  570. }
  571. }
  572. #region
  573. /* //下面的代码可实现抓放大的图,不过我这为了时间更准,抓的左侧显示的图
  574. if (iPic != 0)
  575. {
  576. ce.StopRealPlay(iPic);
  577. }
  578. ce.RealPlay(pictureShow, AppConfigCache.channel);
  579. plImgShow.Visible = true;
  580. Thread.Sleep(200);
  581. Bitmap bit = new Bitmap(plImgShow.Width, plImgShow.Height);//实例化一个和窗体一样大的bitmap
  582. Graphics g = Graphics.FromImage(bit);
  583. g.CompositingQuality = CompositingQuality.HighQuality;//质量设为最高 HighQuality
  584. g.CopyFromScreen(plImgShow.Left, plImgShow.Top + 25, 0, 0, new Size(plImgShow.Width, plImgShow.Height));//保存整个窗体为图片
  585. bit.Save($"{AppConfigCache.path}/imgShort/formalImg/{AppConfigCache.pointNo}_C{strGuid}_tempImg_1.jpg");//默认保存格式为PNG,保存成jpg格式质量不是很好
  586. bit.Dispose();
  587. plImgShow.Visible = false;
  588. ce.StopRealPlay(AppConfigCache.channel);
  589. //*/
  590. #endregion
  591. }
  592. #endregion
  593. if (CacleCls.serverFlag) //网络正常
  594. {
  595. //没有接管的情况下
  596. if (!CacleCls.isJg && CacleCls.firstDb != null && Math.Abs(CacleCls.firstDb.meterWeight.Value - AppConfigCache.differenceWgt) < AppConfigCache.differenceWgt)
  597. {
  598. string str = "第一次计量重量【" + CacleCls.firstDb.meterWeight.Value / 1000 + "T】和第二次计量重量【" + CacleCls.lockWgt / 1000 + "T】接近,小于结净最小值【" + AppConfigCache.differenceWgt / 1000 + " T】";
  599. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "计量失败,请联系管理员");
  600. txtMsgInfo.Text = str;
  601. lg.WriteLog(LogType.serverLog, str);
  602. CacleCls.isLock = false;
  603. return;
  604. }
  605. //一次计量
  606. if (CacleCls.firstDb == null)
  607. {
  608. //进行计量,不管有没有一次计量数据,都调用这个,如果服务端判断有一次计量数据则进行结净,没有则做一次计量操作
  609. RESTfulResult<MeterWorkCarActualFirst> rmRst = workCarActualFirstService.doAddFirstDjDb(CacleCls.preTrackScale, new MeterWorkCarActualFirst
  610. {
  611. baseSpotNo = AppConfigCache.pointNo,
  612. baseSpotName = AppConfigCache.pointName,
  613. carNo = CacleCls.lockCarNo,
  614. createTime = DateTime.Now,
  615. meterWeight = CacleCls.lockWgt,
  616. createManNo = "system",
  617. createManName = "system",
  618. valueFlag = "1",
  619. meterMode = "2",
  620. isPreScale = "0",
  621. dataSource = "1",
  622. checkFlag = "1"
  623. });
  624. }
  625. else //结净操作
  626. {
  627. RESTfulResult<string> rmRst = workCarActualFirstService.doAddNet(CacleCls.preTrackScale, CacleCls.firstDb, new MeterWorkCarActualFirst
  628. {
  629. baseSpotNo = AppConfigCache.pointNo,
  630. baseSpotName = AppConfigCache.pointName,
  631. carNo = CacleCls.lockCarNo,
  632. createTime = DateTime.Now,
  633. meterWeight = CacleCls.lockWgt,
  634. createManNo = "system",
  635. createManName = "system",
  636. valueFlag = "1",
  637. meterMode = "2",
  638. isPreScale = "0",
  639. dataSource = "1",
  640. checkFlag = "1"
  641. });
  642. }
  643. if (rmRst.Succeed)
  644. {
  645. isMeasureSuccess = true;
  646. CacleCls.actualNo = rmRst.Data?.actualFirstNo;
  647. CacleCls.tempNo = strGuid;
  648. }
  649. else
  650. {
  651. //计量失败,播报失败,然后写led屏幕及日志
  652. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "计量失败,请联系管理员");
  653. txtMsgInfo.Text = "计量失败:" + rmRst.ResultMessage;
  654. lg.WriteLog(LogType.serverLog, rmRst.ResultMessage);
  655. CacleCls.isLock = false;
  656. return;
  657. }
  658. }
  659. else
  660. {
  661. //写本地文件
  662. bool flag = FileOption.WriterDb(new ActualFirstModel { actualFirstNo = strGuid, baseSpotNo = AppConfigCache.pointNo, baseSpotName = AppConfigCache.pointName, carNo = CacleCls.lockCarNo, createTime = DateTime.Now, meterWeight = CacleCls.lockWgt },out msgInfo);
  663. if (flag)
  664. {
  665. isMeasureSuccess = true;
  666. }
  667. else
  668. {
  669. led_controler.setStaticLineMsg(AppConfigCache.ledIp, "计量失败,请联系管理员");
  670. txtMsgInfo.Text = "计量失败:" + msgInfo;
  671. lg.WriteLog(LogType.serverLog, msgInfo);
  672. CacleCls.isLock = false;
  673. return;
  674. }
  675. }
  676. //计量成功
  677. if (isMeasureSuccess)
  678. {
  679. #region 毛皮净赋值
  680. if (CacleCls.firstDb != null && CacleCls.firstDb.meterWeight > 0 && CacleCls.lockWgt > 0)
  681. {
  682. if (CacleCls.firstDb.meterWeight > CacleCls.lockWgt)
  683. {
  684. txtGroess.Text = $"{CacleCls.firstDb.meterWeight / 1000}";
  685. txtTare.Text = $"{CacleCls.lockWgt / 1000}";
  686. txtNet.Text = $"{(CacleCls.firstDb.meterWeight - CacleCls.lockWgt) / 1000}";
  687. }
  688. else
  689. {
  690. txtGroess.Text = $"{CacleCls.lockWgt / 1000}";
  691. txtTare.Text = $"{CacleCls.firstDb.meterWeight / 1000}";
  692. txtNet.Text = $"{(CacleCls.lockWgt - CacleCls.firstDb.meterWeight) / 1000}";
  693. }
  694. }
  695. if (!string.IsNullOrEmpty(CacleCls.LEDResultMessage))
  696. {
  697. led_controler.setStaticLineMsg(AppConfigCache.ledIp, CacleCls.LEDResultMessage);
  698. }
  699. #endregion
  700. //屏幕截图操作
  701. _ = BeginInvoke(new Action(() => { shotImageScreen(strGuid); }));
  702. }
  703. #endregion
  704. }
  705. private void btnOpenVoice_Click(object sender, EventArgs e)
  706. {
  707. //*
  708. if (btnOpenVoice.Text == "打开对讲")
  709. {
  710. VoiceOpen();
  711. }
  712. else
  713. {
  714. VoiceClose();
  715. }
  716. //*/
  717. }
  718. private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
  719. {
  720. try { rfid.ClosingCollect(); } catch { }
  721. try { if (bVoice) ce.StopTalk(); } catch { }
  722. foreach (int i in voPlay)
  723. {
  724. try { ce.StopRealPlay(i); } catch { }
  725. }
  726. try { plc.Stop(); } catch { }
  727. try { _cts?.Cancel(); } catch { }
  728. try { _cts2?.Cancel(); } catch { }
  729. try { _dbCts?.Cancel(); } catch { }
  730. try { carCls?.LoginOut(); } catch { }
  731. //try { carCls2?.LoginOut(); } catch { }
  732. try { imgControl.Stop(); } catch { }
  733. }
  734. /// <summary>
  735. /// 必须先打开视频,然后再打开语音
  736. /// </summary>
  737. private void VoiceOpen()
  738. {
  739. try
  740. {
  741. if (ce.StartTalk())
  742. {
  743. btnOpenVoice.Text = "关闭对讲";
  744. bVoice = true;
  745. }
  746. }
  747. catch (Exception ex)
  748. {
  749. txtMsgInfo.Text = "打开对讲失败:" + ex.Message;
  750. }
  751. }
  752. /// <summary>
  753. /// 关闭语音对讲
  754. /// </summary>
  755. private void VoiceClose()
  756. {
  757. try
  758. {
  759. if (ce.StopTalk())
  760. {
  761. btnOpenVoice.Text = "打开对讲";
  762. bVoice = false;
  763. }
  764. }
  765. catch (Exception ex)
  766. {
  767. txtMsgInfo.Text = "关闭对讲失败:" + ex.Message;
  768. }
  769. }
  770. private void btnExport_Click(object sender, EventArgs e)
  771. {
  772. ClsControlPack.ExportDataWithSaveDialog2(ref ultraGridFirst, DateTime.Now.ToString("yyyyMMddHHmmss"));
  773. }
  774. private void cbCarNo_SelectedIndexChanged(object sender, EventArgs e)
  775. {
  776. CacleCls.isLock = false;
  777. }
  778. private void cbJg_CheckedChanged(object sender, EventArgs e)
  779. {
  780. CacleCls.isJg = cbJg.Checked;
  781. btnSave.Enabled = cbJg.Checked;
  782. }
  783. private void txtCarNo_TextChanged(object sender, EventArgs e)
  784. {
  785. CacleCls.isLock = false;
  786. }
  787. private void PictureBoxDoubleClick(object sender, EventArgs e)
  788. {
  789. if (iPic != 0)
  790. {
  791. ce.StopRealPlay(iPic);
  792. }
  793. PictureBox picture = (PictureBox)sender;
  794. iPic = Convert.ToInt32(picture.Name.Substring(picture.Name.Length - 1, 1));
  795. plImgShow.Visible = true;
  796. ce.RealPlay(pictureShow, iPic);
  797. }
  798. private void pictureShow_DoubleClick(object sender, EventArgs e)
  799. {
  800. plImgShow.Visible = false;
  801. ce.StopRealPlay(iPic);
  802. iPic = 0;
  803. }
  804. private void timer1_Tick(object sender, EventArgs e)
  805. {
  806. if (!string.IsNullOrEmpty(CacleCls.voicCarNo))
  807. {
  808. txtMsgInfo.Text += CacleCls.voicCarNo + "\n\r";
  809. }
  810. CacleCls.voicCarNo = "";
  811. if(!string.IsNullOrEmpty(CacleCls.rfidCarNo))
  812. txtMsgInfo.Text += CacleCls.rfidCarNo + "\n\r";
  813. //*/
  814. }
  815. /// <summary>
  816. /// 终端截图(临时截图,使用临时ID存储)
  817. /// </summary>
  818. public void shotImageScreen(string strActualFirstNo)
  819. {
  820. try
  821. {
  822. #region 截取图片信息
  823. //截取屏幕信息
  824. Point screenPoint = plCaptionMain.PointToScreen(new Point());
  825. Rectangle rect = new Rectangle(screenPoint, plCaptionMain.Size);
  826. Image img = new Bitmap(plCaptionMain.Width, plCaptionMain.Height);
  827. Graphics g = Graphics.FromImage(img);
  828. g.CopyFromScreen(rect.X - 1, rect.Y - 1, 0, 0, rect.Size);//"D://file/1.jpg"
  829. img.Save(string.Format("{0}imgShort\\formalImg\\{1}_{2}_{3}.jpg",
  830. AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
  831. AppConfigCache.pointNo, "C" + strActualFirstNo, 7), System.Drawing.Imaging.ImageFormat.Jpeg);
  832. //lg.WriteLog(35, "完成截图 成功标识:" + PbCache.shotSuccess.ToString() + "车号:" + PbCache.lockCarNo + ";重量:" + PbCache.lockWgt + ";时间:" + DateTime.Now.ToLongTimeString());
  833. #endregion 截取图片信息
  834. }
  835. catch (Exception ex)
  836. {
  837. lg.WriteLog(LogType.SystemLog, "计量完成,但图片截取失败,编号:" + strActualFirstNo);
  838. }
  839. }
  840. #region 释放内存
  841. [DllImport("kernel32.dll")]
  842. private static extern bool SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);
  843. //刷新存储器
  844. private static void FlushMemory()
  845. {
  846. GC.Collect();
  847. GC.WaitForPendingFinalizers();
  848. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  849. {
  850. SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
  851. }
  852. }
  853. #endregion
  854. }
  855. }