using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; using System.Threading; using System.Collections.Concurrent; using ButcherFactory.Utils; namespace ButcherFactory.Controls { public partial class WeightControl : UserControl { WeightConfig config; SerialPort weightPort; IDataFormat _dataFormat; Thread _inQueryThread; private bool _mainProcessIsRun; readonly StringBuilder _dataStrBuilder = new StringBuilder(); private bool switchOn; [Browsable(true), Description("称设置标识")] public string WeightFalg { get; set; } [Browsable(true), Description("读取到值的事件")] public event Action ReceivedValue; [Browsable(false)] public decimal Weight { get { var v = decimal.Parse(lblChengZhong.Text); if (config != null) v -= (config.Discont ?? 0); return v; } } public WeightControl() { InitializeComponent(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); var parentForm = ControlsUtil.GetParentFormm(this); if (parentForm != null) { parentForm.FormClosing += delegate { if (_inQueryThread != null && _inQueryThread.IsAlive) { DisableWeight(); } }; } } private void settingBtn_Click(object sender, EventArgs e) { if (new WeightSettingFrom(WeightFalg).ShowDialog() == DialogResult.OK) config = WeightConfig.Init(WeightFalg); } private void weightSwitch_Click(object sender, EventArgs e) { try { if (config == null) { config = WeightConfig.Init(WeightFalg); WeighAvgControl.config = config; } settingBtn.Enabled = switchOn; switchOn = !switchOn; ChangeWeightBtnState(); if (switchOn) { OpenSerialPort(); _mainProcessIsRun = true; ReadData(); } else { DisableWeight(); } } catch { switchOn = !switchOn; settingBtn.Enabled = !switchOn; ChangeWeightBtnState(); throw; } finally { this.Focus(); } } void ChangeWeightBtnState() { if (switchOn) weightSwitch.Text = "停止称重"; else weightSwitch.Text = "启用称重"; } void OpenSerialPort() { if (!switchOn) return; if (config.RateSet == null) throw new Exception("请先配置称相关信息"); weightPort = new SerialPort(); weightPort.PortName = config.ComSet; weightPort.BaudRate = config.RateSet.Value; weightPort.DataBits = config.BitSet.Value; weightPort.ReadBufferSize = 4096 * 100; if (!string.IsNullOrEmpty(config.Format)) format = "{0:{format}}".Replace("{format}", config.Format); switch (config.WeightSet) { case "IND560": _dataFormat = new IND560DataFormat(); break; case "AHS3000": _dataFormat = new AoHaoSi3000DataFormat(); break; case "Xk3124": case "IND231": _dataFormat = new Xk3124DataFormat(); break; case "Xk3190A9": _dataFormat = new Xk3190A9DataFormat(); break; case "JST2018S": _dataFormat = new JST2018SDataFormat(); break; case "一体称"://02 10 53 54 2C 47 53 3A 20 30 30 30 31 2E 37 31 6B 67 A8 FE 00 49 01 00 AC 99 A8 FE 00 _dataFormat = new CombineWeightDataFormat(); break; default: _dataFormat = new Xk3190D10DataFormat(); break; } if (!weightPort.IsOpen) { try { weightPort.Open(); } catch (InvalidOperationException) { throw new Exception("指定的端口已打开"); } catch (UnauthorizedAccessException) { throw new Exception("对端口的访问被拒绝"); } } } void ReadData() { _inQueryThread = new Thread(InQuery); _inQueryThread.Start(); } string format = "{0:0.00}"; private void InQuery() { while (_mainProcessIsRun) { int availableCount = weightPort.BytesToRead; if (availableCount == 0) { Thread.Sleep(10); } byte[] buffer = new byte[availableCount]; weightPort.Read(buffer, 0, availableCount); foreach (var b in buffer) { var c = (char)b; if (c == _dataFormat.Beginchar) { _dataStrBuilder.Clear(); _dataStrBuilder.Append(c); } //针对JST2018不合适,需要改成&& else if (c == _dataFormat.Endchar || _dataStrBuilder.Length >= _dataFormat.Bufsize) { _dataStrBuilder.Append(c); bool isStatic; string str; if (_dataFormat.ParseAscii(_dataStrBuilder.ToString(), out str, out isStatic)) { if (config.WeightType == 0) { if (string.IsNullOrEmpty(str)) str = "0"; this.Invoke(new Action(delegate() { decimal v = 0; decimal.TryParse(str, out v); lblChengZhong.Text = string.Format(format, v); if (str != "0") { if (ReceivedValue != null) ReceivedValue(v - (config.Discont ?? 0)); } })); } else { decimal num = 0; if (decimal.TryParse(str, out num)) { this.Invoke(new Action(delegate() { lblChengZhong.Text = string.Format(format, num); })); WeighAvgControl.Add(num, isStatic); } if (WeighAvgControl.TryGetValue(out num)) { this.Invoke(new Action(delegate() { if (str != "0") { if (ReceivedValue != null) ReceivedValue(num - (config.Discont ?? 0)); } })); } } } _dataStrBuilder.Clear(); } else { _dataStrBuilder.Append(c); } } } } private class WeighAvgControl { public static WeightConfig config; public static bool TryGetValue(out decimal result) { List> list; if (mWeighList.TryDequeue(out list)) { var r = list.Where(x => x.Item2).Select(x => x.Item1).GroupBy(x => x); var firstOrDefault = r.OrderByDescending(x => x.Count()).FirstOrDefault(); if (firstOrDefault != null) { result = firstOrDefault.Key; return true; } result = 0; return false; } result = 0; return false; } static ConcurrentQueue>> mWeighList = new ConcurrentQueue>>(); static List> _list = new List>(); public static void Add(decimal value, bool isStatic) { if (value >= config.MinWeight && value <= config.MaxWeight) { _list.Add(new Tuple(value, isStatic)); } else { if (_list.Count > 0) { mWeighList.Enqueue(_list); _list = new List>(); } } } } void DisableWeight() { _mainProcessIsRun = false; lblChengZhong.Text = string.Format(format, 0); format = "{0:0.00}"; Thread.Sleep(10); if (_inQueryThread.IsAlive) { _inQueryThread.Abort(); } if (weightPort.IsOpen) weightPort.Close(); } private void roundPanel2_Paint(object sender, PaintEventArgs e) { } } }