for DaHongMen
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

323 lines
8.3 KiB

using FourComponentWeightClient.DataFormat;
using FourComponentWeightClient.Utils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FourComponentWeightClient
{
/// <summary>
/// WeightControl.xaml 的交互逻辑
/// </summary>
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<decimal> ReceivedValue;
[Browsable(false)]
public decimal Weight
{
get
{
var v = Convert.ToDecimal(lblChengZhong.Content);
if (config != null)
v -= (config.Discont ?? 0);
return v;
}
}
[Browsable(false)]
public bool SwitchOn
{
get
{
return switchOn;
}
}
[Browsable(false)]
public decimal? Discont { get { return config.Discont; } }
public WeightControl()
{
InitializeComponent();
this.Loaded += WeightControl_Loaded;
}
void WeightControl_Loaded(object sender, RoutedEventArgs e)
{
var parentWindow = Window.GetWindow(this);
if (parentWindow != null)
{
parentWindow.Closing += delegate
{
if (_inQueryThread != null && _inQueryThread.IsAlive)
{
DisableWeight();
}
};
}
}
private void weightSetBtn_Click(object sender, RoutedEventArgs e)
{
if (new WeightSetForm(WeightFalg).ShowDialog() == true)
config = WeightConfig.Init(WeightFalg);
}
private void weightSwitch_Click(object sender, RoutedEventArgs e)
{
try
{
if (config == null)
{
config = WeightConfig.Init(WeightFalg);
WeighAvgControl.config = config;
}
weightSetBtn.IsEnabled = switchOn;
switchOn = !switchOn;
ChangeWeightBtnState();
if (switchOn)
{
OpenSerialPort();
_mainProcessIsRun = true;
ReadData();
}
else
{
DisableWeight();
}
}
catch
{
switchOn = !switchOn;
weightSetBtn.IsEnabled = !switchOn;
ChangeWeightBtnState();
throw;
}
finally
{
this.Focus();
}
}
void ChangeWeightBtnState()
{
if (switchOn)
weightSwitch.Content = "停止称重";
else
weightSwitch.Content = "启用称重";
}
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 "Xk3124":
case "IND231":
_dataFormat = new Xk3124DataFormat();
break;
case "Xk3190A9":
_dataFormat = new Xk3190A9DataFormat();
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);
}
char[] buffer = new char[availableCount];
weightPort.Read(buffer, 0, availableCount);
foreach (var c in buffer)
{
if (c == _dataFormat.Beginchar)
{
_dataStrBuilder.Clear();
_dataStrBuilder.Append(c);
}
else if (c == _dataFormat.Endchar || _dataStrBuilder.Length > _dataFormat.Bufsize)
{
_dataStrBuilder.Append(c);
bool isStatic;
string str=string.Empty;
if (_dataFormat.ParseAscii(_dataStrBuilder.ToString(), out str, out isStatic))
{
if (config.WeightType == 0)
{
if (string.IsNullOrEmpty(str))
str = "0";
this.Dispatcher.Invoke(new Action(delegate()
{
decimal v = 0;
decimal.TryParse(str, out v);
lblChengZhong.Content = 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.Dispatcher.Invoke(new Action(delegate()
{
lblChengZhong.Content = string.Format(format, num);
}));
WeighAvgControl.Add(num, isStatic);
}
if (WeighAvgControl.TryGetValue(out num))
{
this.Dispatcher.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<Tuple<decimal, bool>> list = null;
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<List<Tuple<decimal, bool>>> mWeighList = new ConcurrentQueue<List<Tuple<decimal, bool>>>();
static List<Tuple<decimal, bool>> _list = new List<Tuple<decimal, bool>>();
public static void Add(decimal value, bool isStatic)
{
if (value >= config.MinWeight && value <= config.MaxWeight)
{
_list.Add(new Tuple<decimal, bool>(value, isStatic));
}
else
{
if (_list.Count > 0)
{
mWeighList.Enqueue(_list);
_list = new List<Tuple<decimal, bool>>();
}
}
}
}
void DisableWeight()
{
_mainProcessIsRun = false;
lblChengZhong.Content = string.Format(format, 0);
format = "{0:0.00}";
Thread.Sleep(10);
if (_inQueryThread.IsAlive)
{
_inQueryThread.Abort();
}
if (weightPort.IsOpen)
weightPort.Close();
}
}
}