using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
using B3ButcherWeightClient.Data;
|
|
using BO;
|
|
using Forks.EnterpriseServices.BusinessInterfaces;
|
|
using Forks.EnterpriseServices.DomainObjects2;
|
|
using Forks.Utils.Data;
|
|
using Timer = System.Threading.Timer;
|
|
|
|
namespace B3ButcherWeightClient
|
|
{
|
|
public partial class Main : Form
|
|
{
|
|
|
|
#region 变量实例
|
|
|
|
private string _msg = string.Empty;
|
|
private readonly IDataFormat _dataFormat;
|
|
private Thread _insertThread;
|
|
private Thread _inQueryThread, _outQueryThread;
|
|
private bool _mainProcessIsRun;
|
|
|
|
private static DateTime NewToday
|
|
{
|
|
get
|
|
{
|
|
return new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, ConfigUtil.PerDayStartHour, 0, 0);
|
|
|
|
}
|
|
}
|
|
|
|
private static DateTime NextNewToday
|
|
{
|
|
get { return NewToday.AddHours(24); }
|
|
}
|
|
|
|
private readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
|
|
|
|
private readonly object _queLocker = new object();
|
|
|
|
private readonly Queue<WeightTable> _weightQueue = new Queue<WeightTable>();
|
|
readonly ConcurrentQueue<string> _dataQueue = new ConcurrentQueue<string>();
|
|
readonly StringBuilder _dataStrBuilder = new StringBuilder();
|
|
|
|
readonly Form _parentForm;
|
|
|
|
readonly IList<Livestock.Info> _dTable = new List<Livestock.Info>();
|
|
|
|
readonly IList<Button> _btList = new List<Button>();
|
|
|
|
private Livestock.Info _currentInfo = new Livestock.Info();
|
|
|
|
|
|
static string startDate = NewToday.ToString("yyyy-MM-dd HH:mm:ss");//24小时
|
|
|
|
private readonly string _querySql = string.Format("select [ID],[Sequence],[PhaseCode],[DateTime],[Livestock_Name],[Weight],[SubWeight],[GoodsBatchName] from [WeightTable] where [DateTime] >='{0}' order by [ID] desc", startDate);
|
|
|
|
private string _querySeqSql = string.Format("select top 1 Sequence from [WeightTable] where [DateTime] > '{0}' and [DateTime] <'{1}' order by Sequence desc", NewToday.ToString("yyyy-MM-dd HH:mm"), NextNewToday.ToString("yyyy-MM-dd HH:mm"));
|
|
private DataSet _resultDataSet = new DataSet();
|
|
private readonly Timer _timer;
|
|
|
|
private const int WmProcessMessage = 0x0500 + 1;
|
|
private const int WmUpdDisplayMessage = 0x0500 + 2;
|
|
private const int WmUpdLanStateMessage = 0x0500 + 3;
|
|
private string _displayValue;
|
|
private int _mainHandle;
|
|
|
|
int MainHandle
|
|
{
|
|
get
|
|
{
|
|
if (_mainHandle == 0)
|
|
{
|
|
_mainHandle = WinApiSendMessage.FindWindow(null, @"青花瓷称重客户端");
|
|
}
|
|
return _mainHandle;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
readonly AutoSizeFormClass _asc = new AutoSizeFormClass();
|
|
|
|
public Main(Form form)
|
|
{
|
|
InitializeComponent();
|
|
dataGridView.AutoGenerateColumns = false;
|
|
OpenSerialPort();
|
|
_parentForm = form;
|
|
AddLivestockControl();
|
|
_displayValue = "display";
|
|
_mainProcessIsRun = true;
|
|
pictureBox2.Visible = false;
|
|
switch (ConfigUtil.CType)
|
|
{
|
|
case "XK3130":
|
|
case "XK3124":
|
|
_dataFormat = new Xk3124DataFormat();
|
|
break;
|
|
case "IND560":
|
|
_dataFormat = new IND560DataFormat();
|
|
break;
|
|
case "Xk3190A9":
|
|
_dataFormat = new Xk3190A9DataFormat();
|
|
break;
|
|
default:
|
|
_dataFormat = new Xk3124DataFormat();
|
|
break;
|
|
}
|
|
BeginInsertThread();
|
|
ReadData();
|
|
_timer = new Timer(TimerClick, null, 0, 1000);
|
|
var syncThread = new Thread(SyncTask) { IsBackground = true };
|
|
syncThread.Start();
|
|
CheckForIllegalCrossThreadCalls = false;//线程间操作
|
|
tbxSequence.Text = "1";
|
|
}
|
|
|
|
protected override void DefWndProc(ref Message m)
|
|
{
|
|
switch (m.Msg)
|
|
{
|
|
case WmProcessMessage:
|
|
QueryResult();
|
|
break;
|
|
case WmUpdDisplayMessage:
|
|
lblDisplay.Text = _displayValue;
|
|
break;
|
|
case WmUpdLanStateMessage:
|
|
break;
|
|
default:
|
|
base.DefWndProc(ref m);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#region 控件事件
|
|
|
|
private void Main_Resize(object sender, EventArgs e)
|
|
{
|
|
_asc.controlAutoSize(this);
|
|
}
|
|
|
|
void bt_Click(object sender, EventArgs e)
|
|
{
|
|
var bt = sender as Button;
|
|
foreach (var button in _btList)
|
|
{
|
|
button.BackColor = Color.White;
|
|
}
|
|
if (bt != null)
|
|
{
|
|
bt.BackColor = Color.OrangeRed;
|
|
_currentInfo = bt.Tag as Livestock.Info;
|
|
}
|
|
}
|
|
|
|
private void Main_Load(object sender, EventArgs e)
|
|
{
|
|
InitSequence();
|
|
//_asc.ControllInitializeSize(this);
|
|
//WindowState = FormWindowState.Maximized;
|
|
FormLoadQueryResult();
|
|
}
|
|
|
|
private void saveButton_Click(object sender, EventArgs e)
|
|
{
|
|
decimal w;
|
|
if (decimal.TryParse(_displayValue, out w))
|
|
AddWeightInfo(w);
|
|
}
|
|
|
|
private void DataGridViewCellContentClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (DeleteDetail.Index == e.ColumnIndex)
|
|
{
|
|
if (MessageBox.Show("确定要删除吗?", "删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
|
|
return;
|
|
|
|
var sql = string.Format("delete [WeightTable] where id = {0}", dataGridView.Rows[e.RowIndex].Cells["ID"].Value);
|
|
//var sequence = dataGridView.Rows[e.RowIndex].Cells["Sequence"].Value;
|
|
using (var sqlUtil = new SqlUtil(ConfigUtil.ConnectionStr))
|
|
{
|
|
sqlUtil.ExecuteNonQuery(sql);
|
|
|
|
}
|
|
//同步删除远程数据库的数据
|
|
pictureBox2.Visible = !SyncUtil.TryDeleteServerData(dataGridView.Rows[e.RowIndex].Cells["ID"].Value.ToString(), out _msg);
|
|
|
|
dataGridView.Rows.RemoveAt(e.RowIndex);
|
|
InitSequence();
|
|
|
|
//
|
|
}
|
|
}
|
|
|
|
|
|
private void pictureBox2_Click(object sender, EventArgs e)
|
|
{
|
|
MessageBox.Show(_msg);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 方法
|
|
|
|
private void InitSequence()
|
|
{
|
|
using (var sqlUtil = new SqlUtil(ConfigUtil.ConnectionStr))
|
|
{
|
|
var obj = sqlUtil.ExecuteScalar(_querySeqSql);
|
|
tbxSequence.Text = obj != null ? (long.Parse(obj.ToString()) + 1).ToString() : @"1";
|
|
}
|
|
}
|
|
|
|
private void AddLivestockControl()
|
|
{
|
|
ConfigUtil.SetLivestock(_dTable);
|
|
var i = 0;
|
|
var j = 0;
|
|
foreach (var info in _dTable)
|
|
{
|
|
var bt = new Button();
|
|
bt.Text = info.名称;
|
|
bt.Size = new Size(200, 100);
|
|
bt.Left = i * 203;
|
|
bt.Top = j * 102;
|
|
bt.Tag = info;
|
|
bt.Click += bt_Click;
|
|
panel1.Controls.Add(bt);
|
|
_btList.Add(bt);
|
|
i++;
|
|
if (i == 3)
|
|
{
|
|
i = 0;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OpenSerialPort()
|
|
{
|
|
_serialPort.PortName = ConfigUtil.ComName;
|
|
_serialPort.BaudRate = int.Parse(ConfigUtil.BaundRate);
|
|
_serialPort.DataBits = int.Parse(ConfigUtil.DataBits);
|
|
_serialPort.ReadBufferSize = 4096 * 100;
|
|
|
|
// 打开串口
|
|
if (!_serialPort.IsOpen)
|
|
{
|
|
try
|
|
{
|
|
_serialPort.Open();
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
MessageBox.Show(@"指定的端口已打开");
|
|
}
|
|
catch (UnauthorizedAccessException)
|
|
{
|
|
MessageBox.Show(@"对端口的访问被拒绝");
|
|
}
|
|
}
|
|
}
|
|
|
|
// 接受数据: 称仪表连续输出
|
|
void ReadData()
|
|
{
|
|
|
|
_inQueryThread = new Thread(InQuery);
|
|
_inQueryThread.Start();
|
|
|
|
_outQueryThread = new Thread(OutQuery);
|
|
_outQueryThread.Start();
|
|
|
|
}
|
|
|
|
private void InQuery()
|
|
{
|
|
while (_mainProcessIsRun)
|
|
{
|
|
int availableCount = _serialPort.BytesToRead;
|
|
if (availableCount == 0)
|
|
{
|
|
Thread.Sleep(1);
|
|
}
|
|
char[] buffer = new char[availableCount];
|
|
_serialPort.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);
|
|
_dataQueue.Enqueue(_dataStrBuilder.ToString());
|
|
_dataStrBuilder.Clear();
|
|
}
|
|
else
|
|
{
|
|
_dataStrBuilder.Append(c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OutQuery()
|
|
{
|
|
while (_mainProcessIsRun)
|
|
{
|
|
try
|
|
{
|
|
bool isStatic;
|
|
string str;
|
|
|
|
string subStr;
|
|
|
|
if (!_dataQueue.TryDequeue(out subStr))
|
|
{
|
|
Thread.Sleep(1);
|
|
continue;
|
|
}
|
|
// 解析接受的端口数据
|
|
if (_dataFormat.ParseAscii(subStr, out str, out isStatic))
|
|
{
|
|
_displayValue = str;
|
|
WinApiSendMessage.SendMessage(_mainHandle, WmUpdDisplayMessage, 0, 0);
|
|
}
|
|
decimal num;
|
|
if (ConfigUtil.ReadType == "0")
|
|
{
|
|
if (decimal.TryParse(str, out num))
|
|
{
|
|
WeighAvgControl.Add(num, isStatic);
|
|
}
|
|
if (WeighAvgControl.TryGetValue(out num))
|
|
{
|
|
AddWeightInfo(num);
|
|
}
|
|
}
|
|
else if (ConfigUtil.ReadType == "1")
|
|
{
|
|
if (decimal.TryParse(str, out num))
|
|
{
|
|
if (num >= ConfigUtil.MinWeight && num <= ConfigUtil.MaxWeight)
|
|
AddWeightInfo(num);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Thread.Sleep(1000);
|
|
continue;
|
|
}
|
|
Thread.Sleep(1);
|
|
}
|
|
}
|
|
|
|
private void TimerClick(object o)
|
|
{
|
|
WinApiSendMessage.SendMessage(MainHandle, WmUpdLanStateMessage, 0, 0);
|
|
}
|
|
|
|
private void AddWeightInfo(decimal curValue)
|
|
{
|
|
var info = new WeightTable();
|
|
info.DateTime = DateTime.Now;
|
|
info.SubWeight = ConfigUtil.SubWeight;//默认取设置的扣重
|
|
decimal subWeight = 0;
|
|
if (!string.IsNullOrEmpty(subWeightTextBox.Text))
|
|
{
|
|
if (decimal.TryParse(subWeightTextBox.Text, out subWeight))
|
|
info.SubWeight = subWeight;
|
|
}
|
|
info.Weight = curValue - subWeight;
|
|
info.Livestock_ID = _currentInfo.ID;
|
|
info.Livestock_Name = _currentInfo.名称;
|
|
info.Sequence = long.Parse(tbxSequence.Text);
|
|
info.PhaseCode = jdTextBox.Text;
|
|
info.GoodsBatchName = txtBatch.Text;
|
|
WeightEnQueue(info);
|
|
}
|
|
|
|
private void WeightEnQueue(WeightTable inforStruct)
|
|
{
|
|
Monitor.Enter(_queLocker);
|
|
_weightQueue.Enqueue(inforStruct);
|
|
_manualResetEvent.Set();
|
|
Monitor.Exit(_queLocker);
|
|
}
|
|
|
|
private WeightTable WeightDeQueue()
|
|
{
|
|
Monitor.Enter(_queLocker);
|
|
|
|
WeightTable weightInfo = null;
|
|
if (_weightQueue.Count > 0)
|
|
{
|
|
weightInfo = _weightQueue.Dequeue();
|
|
}
|
|
|
|
Monitor.Exit(_queLocker);
|
|
|
|
return weightInfo;
|
|
}
|
|
|
|
private void BeginInsertThread()
|
|
{
|
|
_insertThread = new Thread(DoInser) { IsBackground = true };
|
|
_insertThread.Start(new object());
|
|
}
|
|
|
|
private void DoInser(object o)
|
|
{
|
|
_manualResetEvent.WaitOne();
|
|
|
|
while (_mainProcessIsRun)
|
|
{
|
|
var weightInfo = WeightDeQueue();//获取队列对象
|
|
|
|
if (weightInfo != null)
|
|
{
|
|
|
|
string err = string.Empty;
|
|
try
|
|
{
|
|
using (var context = new TransactionContext(Dmo.NewSession(ConfigUtil.ConnectionStr)))
|
|
{
|
|
context.Session.Insert(weightInfo);
|
|
//_displayValue = weightInfo.Weight.ToString();
|
|
context.Commit();
|
|
}
|
|
tbxSequence.Text = (weightInfo.Sequence + 1).ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
err = ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
lock (EncodeString.RwLocker)
|
|
{
|
|
using (ISqlUtil sqlUtil = new SqlUtil(ConfigUtil.ConnectionStr))
|
|
{
|
|
try
|
|
{
|
|
lock (EncodeString.RwLocker)
|
|
{
|
|
_resultDataSet = sqlUtil.ExecuteSql(_querySql);
|
|
}
|
|
sqlUtil.Close();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(err))
|
|
MessageBox.Show(err);
|
|
WinApiSendMessage.SendMessage(_mainHandle, WmProcessMessage, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void QueryResult()
|
|
{
|
|
lock (EncodeString.RwLocker)
|
|
{
|
|
dataGridView.DataSource = _resultDataSet.Tables[0];
|
|
}
|
|
}
|
|
|
|
private void FormLoadQueryResult()
|
|
{
|
|
using (ISqlUtil sqlUtil = new SqlUtil(ConfigUtil.ConnectionStr))
|
|
{
|
|
try
|
|
{
|
|
lock (EncodeString.RwLocker)
|
|
{
|
|
_resultDataSet = sqlUtil.ExecuteSql(_querySql);
|
|
}
|
|
sqlUtil.Close();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
}
|
|
|
|
dataGridView.DataSource = _resultDataSet.Tables[0];
|
|
|
|
}
|
|
|
|
void SyncTask()
|
|
{
|
|
var sleeptime = 500;
|
|
pictureBox2.Visible = true;
|
|
while (_mainProcessIsRun)
|
|
{
|
|
Thread.Sleep(sleeptime);
|
|
sleeptime = 20000;
|
|
if (string.IsNullOrEmpty(ConfigUtil.RemoteConStr))
|
|
{
|
|
_msg = "没有设置服务器数据库,无法同步!";
|
|
LogUtil.WriteLog(DateTime.Now + ":" + _msg);
|
|
continue;
|
|
}
|
|
pictureBox2.Visible = !SyncUtil.TryUpdateServerData(out _msg);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
private class WeighAvgControl
|
|
{
|
|
public static bool TryGetValue(out decimal result)
|
|
{
|
|
List<Tuple<decimal, bool>> 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<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 >= ConfigUtil.MinWeight && value <= ConfigUtil.MaxWeight)
|
|
{
|
|
_list.Add(new Tuple<decimal, bool>(value, isStatic));
|
|
}
|
|
else
|
|
{
|
|
if (_list.Count > 0)
|
|
{
|
|
mWeighList.Enqueue(_list);
|
|
_list = new List<Tuple<decimal, bool>>();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dataGridView_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
if (!ConfigUtil.AllowChangeLevel)
|
|
{
|
|
return;
|
|
}
|
|
// e.RowIndex
|
|
long id;
|
|
if (long.TryParse(dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString(), out id))
|
|
{
|
|
var levelName = dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString();
|
|
var f = new ChangeLevelForm();
|
|
f.Init(levelName);
|
|
if (f.ShowDialog() == DialogResult.OK)
|
|
{
|
|
var newLevelId = f.mID;
|
|
var newLevelName = f.mName;
|
|
var updateSql = "update [WeightTable] set [Livestock_ID]=" + newLevelId + ",[Livestock_Name]='" + newLevelName + "' where ID=" + id + " ";
|
|
bool needUpdate = false;
|
|
lock (EncodeString.RwLocker)
|
|
{
|
|
using (ISqlUtil sqlUtil = new SqlUtil(ConfigUtil.ConnectionStr))
|
|
{
|
|
try
|
|
{
|
|
lock (EncodeString.RwLocker)
|
|
{
|
|
sqlUtil.ExecuteNonQuery(updateSql);
|
|
_resultDataSet = sqlUtil.ExecuteSql(_querySql);
|
|
|
|
dataGridView.DataSource = _resultDataSet.Tables[0];
|
|
needUpdate = true;
|
|
}
|
|
sqlUtil.Close();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show(ex.Message);
|
|
}
|
|
}
|
|
}
|
|
if (needUpdate)
|
|
{
|
|
//同步修改远程数据库的数据
|
|
pictureBox2.Visible = !SyncUtil.TryUpdateLevel(id.ToString(), newLevelId, newLevelName, out _msg);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void button1_Click(object sender, EventArgs e)
|
|
{
|
|
var form = new QueryForm();
|
|
form.StartPosition = FormStartPosition.CenterParent;
|
|
form.ShowDialog();
|
|
}
|
|
|
|
}
|
|
}
|