|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.ComponentModel;
|
|
|
using System.Drawing;
|
|
|
using System.Data;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.Windows.Forms;
|
|
|
using POSV.Bean;
|
|
|
using POSV.Utils;
|
|
|
using POS.Language.Language;
|
|
|
|
|
|
namespace POSV.Component
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 稳定通知
|
|
|
/// </summary>
|
|
|
public delegate void StabilizationEvent(decimal vl, bool stabilization);
|
|
|
public partial class WeightShowControl : UserControl
|
|
|
{
|
|
|
|
|
|
static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
|
|
private WeightStatusEnum _status = WeightStatusEnum.待称重;
|
|
|
|
|
|
private decimal _weight = 0.000M;
|
|
|
|
|
|
private static bool _isQuerying = false;
|
|
|
|
|
|
private SerialPortExtension serialPort = null;
|
|
|
|
|
|
public StabilizationEvent StabilizationEvent = null;
|
|
|
|
|
|
#region 清零、去皮、开钱箱结果
|
|
|
//清零结果
|
|
|
private bool _clearZeroResult = false;
|
|
|
//去皮结果
|
|
|
private bool _peelSkinResult = false;
|
|
|
//开钱箱结果
|
|
|
private bool _openCashBoxResult = false;
|
|
|
|
|
|
public bool ClearZeroResult
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return this._clearZeroResult;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public bool PeelSkinResult
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return this._peelSkinResult;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public bool OpenCashBoxResult
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return this._openCashBoxResult;
|
|
|
}
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 定时轮询
|
|
|
/// </summary>
|
|
|
private System.Windows.Forms.Timer timer = null;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 电子秤配置
|
|
|
/// </summary>
|
|
|
private SteelyardParam steelyardParam;
|
|
|
|
|
|
public WeightShowControl()
|
|
|
{
|
|
|
InitializeComponent();
|
|
|
|
|
|
}
|
|
|
|
|
|
protected override void OnLoad(EventArgs e)
|
|
|
{
|
|
|
base.OnLoad(e);
|
|
|
if (this.DesignMode) return;
|
|
|
|
|
|
InitUI();
|
|
|
|
|
|
labelX6.Text = LangProxy.ToLang(labelX6.Text);
|
|
|
labelX8.Text = LangProxy.ToLang(labelX8.Text);
|
|
|
labelX10.Text = LangProxy.ToLang(labelX10.Text);
|
|
|
wlblInfo.Text = LangProxy.ToLang(wlblInfo.Text);
|
|
|
}
|
|
|
|
|
|
private SteelyardParam LoadSteelyard()
|
|
|
{
|
|
|
SteelyardParam result = null;
|
|
|
var param = Global.Instance.GlobalConfigStringValue(ConfigConstant.STEELYARD_DEVICE_PARAMETER);
|
|
|
if (string.IsNullOrEmpty(param))
|
|
|
{
|
|
|
result = new SteelyardParam();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result = JsonUtils.Deserialize<SteelyardParam>(param);
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 打开秤端口
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public bool StartEngine()
|
|
|
{
|
|
|
bool result = false;
|
|
|
try
|
|
|
{
|
|
|
if (steelyardParam == null)
|
|
|
{
|
|
|
steelyardParam = LoadSteelyard();
|
|
|
}
|
|
|
switch (this.steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.大华ACS_15AB:
|
|
|
{
|
|
|
serialPort = new SerialPortExtension();
|
|
|
serialPort.ReceiveDataEvent += SerialPort_ReceiveDataEvent;
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
|
|
|
timer = new System.Windows.Forms.Timer();
|
|
|
timer.Interval = 500;
|
|
|
timer.Tick += TimerQueryWeight;
|
|
|
//timer = new System.Timers.Timer(100);
|
|
|
//timer.Elapsed += TimerQueryWeight;
|
|
|
//timer.AutoReset = true;
|
|
|
timer.Start();
|
|
|
|
|
|
result = true;
|
|
|
logger.Info("打开大华ACS_15AB端口");
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case SteelyardBrandEnum.顶尖PS1X:
|
|
|
{
|
|
|
serialPort = new SerialPortExtension();
|
|
|
serialPort.ReceiveDataEvent += PS1XReceiveDataEvent;
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
|
|
|
timer = new System.Windows.Forms.Timer();
|
|
|
timer.Interval = 500;
|
|
|
timer.Tick += TimerQueryWeight;
|
|
|
//timer = new System.Timers.Timer(100);
|
|
|
//timer.Elapsed += TimerQueryWeight;
|
|
|
//timer.AutoReset = true;
|
|
|
timer.Start();
|
|
|
|
|
|
result = true;
|
|
|
logger.Info("打开顶尖PS1X端口");
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.凯士PRPLUS404:
|
|
|
case SteelyardBrandEnum.凯士PRPLUS216:
|
|
|
{
|
|
|
serialPort = new SerialPortExtension();
|
|
|
serialPort.ReceiveDataEvent += CasReceiveDataEvent;
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
result = true;
|
|
|
logger.Info("打开凯士PRPLUS端口");
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.龙飞C2:
|
|
|
case SteelyardBrandEnum.龙飞C3:
|
|
|
{
|
|
|
timer = new System.Windows.Forms.Timer();
|
|
|
timer.Interval = 500;
|
|
|
timer.Tick += TimerQueryWeight;
|
|
|
//timer = new System.Timers.Timer(800);
|
|
|
//timer.Elapsed += TimerQueryWeight;
|
|
|
//timer.AutoReset = true;
|
|
|
timer.Start();
|
|
|
result = true;
|
|
|
logger.Info("打开龙飞C2,龙飞C3端口");
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.顶尖PBX:
|
|
|
{
|
|
|
serialPort = new SerialPortExtension();
|
|
|
serialPort.ReceiveDataEvent -= PBXReceiveDataEvent;
|
|
|
serialPort.ReceiveDataEvent += PBXReceiveDataEvent;
|
|
|
result = serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
if (result)
|
|
|
{
|
|
|
serialPort.Send(new byte[5] { 0x3C, 0x41, 0x4C, 0x3E, 0x09 });
|
|
|
|
|
|
timer = new System.Windows.Forms.Timer();
|
|
|
timer.Interval = 200;
|
|
|
timer.Tick += TimerQueryWeight;
|
|
|
//timer.Elapsed += TimerQueryWeight;
|
|
|
timer.Start();
|
|
|
|
|
|
logger.Info("打开顶尖PBX端口");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
logger.Info("打开顶尖PBX端口失败");
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "打开电子秤端口失败");
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
private void SerialPort_ReceiveDataEvent(object sender, SerialPortEventArgs e)
|
|
|
{
|
|
|
var bytes = e.ReceivedBytes;
|
|
|
try
|
|
|
{
|
|
|
var _str = System.Text.Encoding.ASCII.GetString(bytes);
|
|
|
string[] _val = _str.Split(' ', 'K', 'G');
|
|
|
|
|
|
this.Invoke((EventHandler)delegate
|
|
|
{
|
|
|
this.Weight = decimal.Parse(_val[1]);
|
|
|
if (this.Weight > 0)
|
|
|
{
|
|
|
Weight = Weight / 1000;
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.称重中;
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
this.Invoke((EventHandler)delegate
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
this.Weight = 0.00M;
|
|
|
});
|
|
|
|
|
|
logger.Info(ex.Message);
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 关闭秤
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public void CloseEngine()
|
|
|
{
|
|
|
switch (this.steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.大华ACS_15AB:
|
|
|
case SteelyardBrandEnum.顶尖PS1X:
|
|
|
{
|
|
|
if (this.timer != null)
|
|
|
{
|
|
|
this.timer.Stop();
|
|
|
//this.timer.Close();
|
|
|
this.timer = null;
|
|
|
}
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
serialPort.Close();
|
|
|
serialPort = null;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.顶尖PBX:
|
|
|
{
|
|
|
if (timer != null)
|
|
|
{
|
|
|
timer.Stop();
|
|
|
//this.timer.Close();
|
|
|
timer = null;
|
|
|
}
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
serialPort.ReceiveDataEvent -= PBXReceiveDataEvent;
|
|
|
serialPort.Close();
|
|
|
serialPort = null;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.凯士PRPLUS404:
|
|
|
case SteelyardBrandEnum.凯士PRPLUS216:
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
serialPort.Close();
|
|
|
serialPort = null;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.龙飞C2:
|
|
|
case SteelyardBrandEnum.龙飞C3:
|
|
|
{
|
|
|
if (this.timer != null)
|
|
|
{
|
|
|
this.timer.Stop();
|
|
|
//this.timer.Close();
|
|
|
this.timer = null;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 顶尖ps1x 健康监控,多次未收到数据提示异常,因为串口发送数据,但是一直未收到秤的数据,表示异常
|
|
|
/// </summary>
|
|
|
readonly int ps1xMaxErrorTimes = 5;
|
|
|
readonly int lfMaxErrorTimes = 3;//龙飞异常次数极限
|
|
|
int ps1xQueryTimes = 0;
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 轮询查询
|
|
|
/// </summary>
|
|
|
/// <param name="sender"></param>
|
|
|
/// <param name="e"></param>
|
|
|
private void TimerQueryWeight(object sender, EventArgs e)
|
|
|
{
|
|
|
if (_isQuerying)
|
|
|
{
|
|
|
logger.Info("称重正在查询中,忽略本次查询");
|
|
|
return;
|
|
|
}
|
|
|
_isQuerying = true;
|
|
|
try
|
|
|
{
|
|
|
switch (this.steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.大华ACS_15AB:
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
//顶尖请求数据
|
|
|
serialPort.Send(new byte[1] { 0x50 });
|
|
|
//logger.Info("发送顶尖数据请求05");
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.顶尖PS1X:
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
//顶尖请求数据
|
|
|
serialPort.Send(new byte[1] { 0x05 });
|
|
|
//logger.Info("发送顶尖数据请求05");
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.顶尖PBX:
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
//顶尖请求数据
|
|
|
serialPort.Send(new byte[1] { 0x11 });
|
|
|
//logger.Info("发送顶尖数据请求05");
|
|
|
if (ps1xQueryTimes >= ps1xMaxErrorTimes)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
this.Weight = 0.000M;
|
|
|
logger.Error("顶尖PBX超过5次未获取到重量,上报异常");
|
|
|
ps1xQueryTimes = 0;
|
|
|
}
|
|
|
ps1xQueryTimes++;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.龙飞C2:
|
|
|
case SteelyardBrandEnum.龙飞C3:
|
|
|
{
|
|
|
var value = GetAllValue();
|
|
|
if (string.IsNullOrEmpty(value))
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
this.Weight = 0.000M;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (value.Contains("┗━┛"))
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.负载;
|
|
|
this.Weight = 0.000M;
|
|
|
}
|
|
|
else if (value.Contains("┏━┓"))
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.超载;
|
|
|
this.Weight = 0.000M;
|
|
|
}
|
|
|
else if (value.Length >= 16)
|
|
|
{
|
|
|
var stu = Convert.ToInt16(value.Substring(0, 1));
|
|
|
var weightStr = value.Substring(1, value.IndexOf('P') - 1);
|
|
|
//var weight = StringUtils.GetDecimal(weightStr);
|
|
|
var weight = DecimalUtils.ToRound(StringUtils.GetDecimal(weightStr), 3);
|
|
|
this.Weight = weight;
|
|
|
switch (stu)
|
|
|
{
|
|
|
case 0://无皮重 非零位 非稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.称重中;
|
|
|
}
|
|
|
break;
|
|
|
case 1://无皮重 非零位 稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
}
|
|
|
break;
|
|
|
case 2://无皮重 零位 非稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
break;
|
|
|
case 3://无皮重 零位 稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
break;
|
|
|
case 4://有皮重 非零位 非稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.称重中;
|
|
|
}
|
|
|
break;
|
|
|
case 5://有皮重 非零位 稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
}
|
|
|
break;
|
|
|
case 6://有皮重 零位 非稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
break;
|
|
|
case 7://有皮重 零位 稳定
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
if (weight < 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.负载;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
this.Weight = 0.000M;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "轮询获取allvalue异常");
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
_isQuerying = false;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#region 顶尖PS1X
|
|
|
|
|
|
private StringBuilder ps1xDataStr = new StringBuilder();
|
|
|
|
|
|
private void PS1XReceiveDataEvent(object sender, SerialPortEventArgs e)
|
|
|
{
|
|
|
var bytes = e.ReceivedBytes;
|
|
|
var hex = BitConverter.ToString(bytes, 0);
|
|
|
//var recv = BitConverter.ToString(bytes).Replace("-", string.Empty);
|
|
|
//logger.Info("收到顶尖数据<{0}>", hex);
|
|
|
//Console.WriteLine("Received Data<{0}>:{1} ", e.ReceivedBytes.Length, recv);
|
|
|
|
|
|
if (bytes.Length > 0)
|
|
|
{
|
|
|
if (bytes.Length == 1)
|
|
|
{
|
|
|
if (bytes[0] == 0x06 || bytes[0] == 0x15)
|
|
|
{
|
|
|
serialBytes = null;
|
|
|
serialBytes = new byte[0];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
serialBytes = serialBytes.Concat(bytes).ToArray();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
serialBytes = serialBytes.Concat(bytes).ToArray();
|
|
|
}
|
|
|
if (serialBytes.Length == 15 && serialBytes[0] == 0x01 && serialBytes[1] == 0x02 && serialBytes[13] == 0x03 && serialBytes[14] == 0x04)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
ParsePs1xData(serialBytes);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "顶尖PS1X称重异常");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void ParsePs1xData(byte[] data)
|
|
|
{
|
|
|
if (data.Length == 15 && data[0] == 0x01 && data[1] == 0x02 && data[13] == 0x03 && data[14] == 0x04)
|
|
|
{
|
|
|
//状态// 53稳定,55不稳定,46异常
|
|
|
var status = System.Text.Encoding.Default.GetString(data.Skip(2).Take(1).ToArray());
|
|
|
var unit = System.Text.Encoding.Default.GetString(data.Skip(10).Take(2).ToArray());
|
|
|
var weightStr = System.Text.Encoding.Default.GetString(data.Skip(3).Take(7).ToArray());
|
|
|
var weight = StringUtils.GetDecimal(weightStr.Replace(" ", string.Empty).Replace(",", "."));
|
|
|
//Console.WriteLine(string.Format("ps1x状态{0},单位{1},重量{2}", status, unit, weightStr));
|
|
|
logger.Info(string.Format("ps1x状态{0},单位{1},zhong:{2},重量{3}", status, unit, weightStr, weight));
|
|
|
decimal kgWeight = 0.000M;
|
|
|
switch (unit)
|
|
|
{
|
|
|
case "KG":
|
|
|
{
|
|
|
kgWeight = weight;
|
|
|
}
|
|
|
break;
|
|
|
case "TJ"://台斤
|
|
|
{
|
|
|
kgWeight = weight * 0.6M; // 1 台斤 = 0.6 公斤
|
|
|
}
|
|
|
break;
|
|
|
case "TL":
|
|
|
{
|
|
|
kgWeight = weight * 37.5M / 500M; // 台两 = 37.5 公克
|
|
|
}
|
|
|
break;
|
|
|
case "SJ":// 市斤
|
|
|
{
|
|
|
kgWeight = weight / 2M;
|
|
|
}
|
|
|
break;
|
|
|
case "LB":
|
|
|
{
|
|
|
kgWeight = weight * 0.454M; // 1磅(lb)=0.454千克(kg)
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
if (this.IsDisposed || !this.IsHandleCreated) return;
|
|
|
this.Invoke(new Action(() =>
|
|
|
{
|
|
|
if (kgWeight == 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
else if (kgWeight < 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.负载;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
switch (status)
|
|
|
{
|
|
|
case "S"://稳定
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
break;
|
|
|
case "U"://不稳定
|
|
|
this.Status = WeightStatusEnum.称重中;
|
|
|
break;
|
|
|
default://异常
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
this.Weight = decimal.Round(kgWeight, 3);
|
|
|
}));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
#region 凯士PRPLUS
|
|
|
|
|
|
private byte[] serialBytes = new byte[0];
|
|
|
|
|
|
/// <summary>
|
|
|
/// 凯士数据接收
|
|
|
/// </summary>
|
|
|
/// <param name="sender"></param>
|
|
|
/// <param name="e"></param>
|
|
|
private void CasReceiveDataEvent(object sender, SerialPortEventArgs e)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
var bytes = e.ReceivedBytes;
|
|
|
var recv = BitConverter.ToString(bytes);
|
|
|
//logger.Info("凯士数据:{0}", recv);
|
|
|
//Console.WriteLine("Received Data<{0}>:{1} ", e.ReceivedBytes.Length, recv);
|
|
|
if (bytes.Length > 0)
|
|
|
{
|
|
|
if (bytes.Length > 1 && bytes[0] == 0x0A && bytes[1] == 0x0D)
|
|
|
{
|
|
|
serialBytes = new byte[0];
|
|
|
serialBytes = serialBytes.Concat(bytes).ToArray();
|
|
|
ParseCas404Data(serialBytes);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
serialBytes = serialBytes.Concat(bytes).ToArray();
|
|
|
//Console.WriteLine("temp:" + serialBytes.Length + ">>>>" + BitConverter.ToString(serialBytes));
|
|
|
}
|
|
|
switch (this.steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.凯士PRPLUS404:
|
|
|
{
|
|
|
if (serialBytes.Length == 25)
|
|
|
{
|
|
|
ParseCas404Data(serialBytes);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.凯士PRPLUS216:
|
|
|
{
|
|
|
if (serialBytes.Length == 7)
|
|
|
{
|
|
|
ParseCas216Data(serialBytes);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception)
|
|
|
{
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void ParseCas216Data(byte[] data)
|
|
|
{
|
|
|
if (data.Length == 7 && data[0] == 0x0A && data[1] == 0x0D)
|
|
|
{
|
|
|
//重量
|
|
|
var weights = System.Text.Encoding.Default.GetString(data.Skip(2).Take(6).ToArray());
|
|
|
|
|
|
//logger.Info(string.Format("凯士216秤:重量:{0};", weights));
|
|
|
|
|
|
decimal weight = StringUtils.GetDecimal(weights);
|
|
|
|
|
|
//g转kg
|
|
|
weight = decimal.Round(weight / 1000M, 3);
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
{
|
|
|
|
|
|
|
|
|
if (weight == 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
else if (weight < 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.负载;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
}
|
|
|
this.Weight = Convert.ToDecimal(weight);
|
|
|
}));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int _weightnumber = 5;
|
|
|
decimal _Lasttime = 0;
|
|
|
|
|
|
private void ParseCas404Data(byte[] data)
|
|
|
{
|
|
|
if (data.Length == 25 && data[0] == 0x0A && data[1] == 0x0D)
|
|
|
{
|
|
|
//重量
|
|
|
var weights = System.Text.Encoding.Default.GetString(data.Skip(2).Take(6).ToArray());
|
|
|
|
|
|
//单价
|
|
|
var prices = System.Text.Encoding.Default.GetString(data.Skip(10).Take(6).ToArray());
|
|
|
|
|
|
//总价
|
|
|
var amounts = System.Text.Encoding.Default.GetString(data.Skip(18).ToArray());
|
|
|
|
|
|
decimal weight = StringUtils.GetDecimal(weights);
|
|
|
|
|
|
this.Invoke(new Action(() =>
|
|
|
{
|
|
|
if (weight == 0)
|
|
|
{
|
|
|
_weightnumber = 5;
|
|
|
_Lasttime = 0;
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
|
|
|
if (weight == _Lasttime)
|
|
|
{
|
|
|
if (_weightnumber > 0)
|
|
|
{
|
|
|
_weightnumber--;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
_weightnumber = 5;
|
|
|
_Lasttime = weight;
|
|
|
this.Status = WeightStatusEnum.称重中;
|
|
|
}
|
|
|
this.Weight = Convert.ToDecimal(weight);
|
|
|
}));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 顶尖PBX
|
|
|
|
|
|
private void PBXReceiveDataEvent(object sender, SerialPortEventArgs e)
|
|
|
{
|
|
|
//健康位归零
|
|
|
ps1xQueryTimes = 0;
|
|
|
|
|
|
var bytes = e.ReceivedBytes;
|
|
|
var hex = BitConverter.ToString(bytes, 0);
|
|
|
//var recv = BitConverter.ToString(bytes).Replace("-", string.Empty);
|
|
|
//logger.Info("收到顶尖数据<{0}>", hex);
|
|
|
//Console.WriteLine("Received Data<{0}>:{1} ", e.ReceivedBytes.Length, recv);
|
|
|
|
|
|
if (bytes.Length > 0)
|
|
|
{
|
|
|
if (bytes.Contains<byte>(0x3C))
|
|
|
{
|
|
|
//logger.Info("跳了跳前前接收到的操作指令返回数据:" + BitConverter.ToString(bytes));
|
|
|
var data = bytes.Skip(Array.FindIndex(bytes, x => x == 0x3C)).ToArray();
|
|
|
//logger.Info("跳了跳以后接收到的操作指令返回数据:" + BitConverter.ToString(data));
|
|
|
|
|
|
if (data.Length >= 8)
|
|
|
{
|
|
|
//清零、去皮、开钱箱
|
|
|
switch (data[1])
|
|
|
{
|
|
|
case 0x5A://置零
|
|
|
{
|
|
|
ParsePBXReceiveClearZeroData(data);
|
|
|
}
|
|
|
break;
|
|
|
case 0x54://去皮
|
|
|
{
|
|
|
ParsePBXReceivePeelSkinData(data);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
serialBytes = null;
|
|
|
serialBytes = new byte[0];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
serialBytes = serialBytes.Concat(bytes).ToArray();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (bytes[0] == 0x01 && serialBytes != null && serialBytes.Length > 0)
|
|
|
{
|
|
|
//发送过来的是初始数据,则清空之前记录的内容,重置。发现有时候这里会保留之前的一半数据,也就是串口两次发送,
|
|
|
//结果始终拿着上一次的第二行数据,拼接上了新来的第一行,一直都是这样 。就会导致秤半天都不会变动重量,收银员会称重错误
|
|
|
serialBytes = new byte[0];
|
|
|
}
|
|
|
serialBytes = serialBytes.Concat(bytes).ToArray();
|
|
|
|
|
|
if (serialBytes.Length == 15 && serialBytes[0] == 0x01 && serialBytes[1] == 0x02 && serialBytes[13] == 0x03 && serialBytes[14] == 0x04)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
ParsePbxData(serialBytes);
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "顶尖PBX称重异常");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (serialBytes.Length >= 15)
|
|
|
{
|
|
|
serialBytes = null;
|
|
|
serialBytes = new byte[0];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void ParsePbxData(byte[] data)
|
|
|
{
|
|
|
if (data.Length == 15 && data[0] == 0x01 && data[1] == 0x02 && data[13] == 0x03 && data[14] == 0x04)
|
|
|
{
|
|
|
var status = System.Text.Encoding.Default.GetString(data.Skip(2).Take(1).ToArray());
|
|
|
var unit = System.Text.Encoding.Default.GetString(data.Skip(10).Take(2).ToArray());
|
|
|
var weightStr = System.Text.Encoding.Default.GetString(data.Skip(3).Take(7).ToArray());
|
|
|
var weight = StringUtils.GetDecimal(weightStr.Replace(" ", string.Empty).Replace(",", "."));
|
|
|
//Console.WriteLine(string.Format("ps1x状态{0},单位{1},重量{2}", status, unit, weightStr));
|
|
|
//logger.Info(string.Format("ps1x状态{0},单位{1},zhong:{2},重量{3}", status, unit, weightStr, weight));
|
|
|
decimal kgWeight = 0.000M;
|
|
|
switch (unit.Trim().ToUpper())
|
|
|
{
|
|
|
case "KG":
|
|
|
{
|
|
|
kgWeight = weight;
|
|
|
}
|
|
|
break;
|
|
|
case "TJ"://台斤
|
|
|
{
|
|
|
kgWeight = weight * 0.6M; // 1 台斤 = 0.6 公斤
|
|
|
}
|
|
|
break;
|
|
|
case "TL":
|
|
|
{
|
|
|
kgWeight = weight * 37.5M / 500M; // 台两 = 37.5 公克
|
|
|
}
|
|
|
break;
|
|
|
case "SJ":// 市斤
|
|
|
{
|
|
|
kgWeight = weight / 2M;
|
|
|
}
|
|
|
break;
|
|
|
case "LB":
|
|
|
{
|
|
|
kgWeight = weight * 0.454M; // 1磅(lb)=0.454千克(kg)
|
|
|
}
|
|
|
break;
|
|
|
case "G":
|
|
|
{
|
|
|
//克 g
|
|
|
kgWeight = weight / 1000M; // 1g = 0.001kg
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
if (kgWeight == 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
}
|
|
|
else if (kgWeight < 0)
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.负载;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
switch (status)
|
|
|
{
|
|
|
case "S"://稳定
|
|
|
this.Status = WeightStatusEnum.稳定;
|
|
|
break;
|
|
|
case "U"://不稳定
|
|
|
this.Status = WeightStatusEnum.称重中;
|
|
|
break;
|
|
|
case "F":
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.超载;
|
|
|
}
|
|
|
break;
|
|
|
default://异常
|
|
|
this.Status = WeightStatusEnum.异常;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
this.Weight = decimal.Round(kgWeight, 3);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 清零 PBX
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private bool ClearZeroPBX()
|
|
|
{
|
|
|
_clearZeroResult = false;
|
|
|
try
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
if (!serialPort.IsOpen)
|
|
|
{
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
}
|
|
|
if (serialPort.IsOpen)
|
|
|
{
|
|
|
serialPort.DiscardOutBuffer();
|
|
|
var sendResult = serialPort.Send(new byte[] { 0x3C, 0x5A, 0x4B, 0x3E, 0x09 });
|
|
|
if (sendResult)
|
|
|
{
|
|
|
System.Threading.Thread.Sleep(100);
|
|
|
sendResult = serialPort.Send(new byte[] { 0x3C, 0x5A, 0x4B, 0x3E, 0x09 });
|
|
|
if (sendResult)
|
|
|
{
|
|
|
System.Threading.Thread.Sleep(100);
|
|
|
sendResult = serialPort.Send(new byte[] { 0x3C, 0x5A, 0x4B, 0x3E, 0x09 });
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
logger.Error("清零失败:未打开端口");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "清零异常");
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
if (!serialPort.IsOpen)
|
|
|
{
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return _clearZeroResult;
|
|
|
}
|
|
|
|
|
|
private void ParsePBXReceiveClearZeroData(byte[] data)
|
|
|
{
|
|
|
if (data.Length >= 8 && data[0] == 0x3C && data[1] == 0x5A)
|
|
|
{
|
|
|
if (data[6] == 0x0E || data[6] == 0x0D)
|
|
|
{
|
|
|
//成功
|
|
|
_clearZeroResult = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//失败
|
|
|
_clearZeroResult = false;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//失败
|
|
|
_clearZeroResult = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 去皮 PBX
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
private bool PeelSkinPBX()
|
|
|
{
|
|
|
_peelSkinResult = false;
|
|
|
try
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
if (!serialPort.IsOpen)
|
|
|
{
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
}
|
|
|
if (serialPort.IsOpen)
|
|
|
{
|
|
|
var sendResult = serialPort.Send(new byte[] { 0x3C, 0x54, 0x4B, 0x3E, 0x09 });
|
|
|
if (sendResult)
|
|
|
{
|
|
|
System.Threading.Thread.Sleep(100);
|
|
|
sendResult = serialPort.Send(new byte[] { 0x3C, 0x54, 0x4B, 0x3E, 0x09 });
|
|
|
if (sendResult)
|
|
|
{
|
|
|
System.Threading.Thread.Sleep(100);
|
|
|
sendResult = serialPort.Send(new byte[] { 0x3C, 0x54, 0x4B, 0x3E, 0x09 });
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
logger.Error("去皮失败:未打开端口");
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "去皮异常");
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
if (serialPort != null)
|
|
|
{
|
|
|
if (!serialPort.IsOpen)
|
|
|
{
|
|
|
serialPort.Open(this.steelyardParam.Port, this.steelyardParam.Baud.ToString(), "8", "1", "0", "None");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return _peelSkinResult;
|
|
|
}
|
|
|
|
|
|
private void ParsePBXReceivePeelSkinData(byte[] data)
|
|
|
{
|
|
|
if (data.Length >= 8 && data[0] == 0x3C && data[1] == 0x54)
|
|
|
{
|
|
|
if (data[6] == 0x0E || data[6] == 0x0D)
|
|
|
{
|
|
|
//成功
|
|
|
_peelSkinResult = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//失败
|
|
|
_peelSkinResult = false;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//失败
|
|
|
_peelSkinResult = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 清零
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public bool ClearZero()
|
|
|
{
|
|
|
bool result = false;
|
|
|
try
|
|
|
{
|
|
|
if (steelyardParam != null)
|
|
|
{
|
|
|
switch (steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.顶尖PS1X:
|
|
|
{
|
|
|
CloseEngine();
|
|
|
System.Threading.Thread.Sleep(500);
|
|
|
result = WeightApi.ClearZero(steelyardParam);
|
|
|
StartEngine();
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.顶尖PBX:
|
|
|
{
|
|
|
result = ClearZeroPBX();
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
{
|
|
|
CloseEngine();
|
|
|
System.Threading.Thread.Sleep(500);
|
|
|
result = WeightApi.ClearZero(steelyardParam);
|
|
|
StartEngine();
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result = false;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "清零异常");
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 去皮
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public bool PeelSkin()
|
|
|
{
|
|
|
bool result = false;
|
|
|
try
|
|
|
{
|
|
|
if (steelyardParam != null)
|
|
|
{
|
|
|
switch (steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.顶尖PS1X:
|
|
|
{
|
|
|
CloseEngine();
|
|
|
result = WeightApi.PeelSkin(steelyardParam);
|
|
|
StartEngine();
|
|
|
}
|
|
|
break;
|
|
|
case SteelyardBrandEnum.顶尖PBX:
|
|
|
{
|
|
|
result = PeelSkinPBX();
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
{
|
|
|
CloseEngine();
|
|
|
System.Threading.Thread.Sleep(500);
|
|
|
result = WeightApi.PeelSkin(steelyardParam);
|
|
|
StartEngine();
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
result = false;
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "去皮异常");
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 初始化显示
|
|
|
/// </summary>
|
|
|
private void InitUI()
|
|
|
{
|
|
|
this.Status = WeightStatusEnum.待称重;
|
|
|
this.Weight = 0.000M;
|
|
|
this.wlblPrice.Text = "0";
|
|
|
this.wlblAmount.Text = "0";
|
|
|
this.wlblInfo.Text = "前台操作时,请注意提示信息";
|
|
|
RefreshStatus(this._status);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取数据
|
|
|
/// </summary>
|
|
|
public string GetAllValue()
|
|
|
{
|
|
|
string result = string.Empty;
|
|
|
try
|
|
|
{
|
|
|
if (steelyardParam != null)
|
|
|
{
|
|
|
switch (steelyardParam.Name)
|
|
|
{
|
|
|
case SteelyardBrandEnum.顶尖PS1X:
|
|
|
{
|
|
|
CloseEngine();
|
|
|
result = WeightApi.GetAllValue(steelyardParam);
|
|
|
StartEngine();
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
{
|
|
|
result = WeightApi.GetAllValue(steelyardParam);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
logger.Error(ex, "获取秤数据异常");
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 秤状态
|
|
|
/// </summary>
|
|
|
public WeightStatusEnum Status
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return _status;
|
|
|
}
|
|
|
set
|
|
|
{
|
|
|
this._status = value;
|
|
|
this.wlblStatus.Text = LangProxy.ToLang(this._status.ToString());
|
|
|
RefreshStatus(this._status);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 重量
|
|
|
/// </summary>
|
|
|
public decimal Weight
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return _weight;
|
|
|
}
|
|
|
set
|
|
|
{
|
|
|
this._weight = value;
|
|
|
this.wlblWeight.Text = this._weight.ToString();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void RefreshStatus(WeightStatusEnum status)
|
|
|
{
|
|
|
this.wlblStatus.Text = LangProxy.ToLang( status.ToString());
|
|
|
switch (status)
|
|
|
{
|
|
|
case WeightStatusEnum.稳定:
|
|
|
{
|
|
|
this.wlblStatus.ForeColor = ColorTranslator.FromHtml("0,192,0");
|
|
|
this.wlblStatus.SymbolColor = ColorTranslator.FromHtml("0,192,0");
|
|
|
|
|
|
if (StabilizationEvent != null)
|
|
|
{
|
|
|
StabilizationEvent(_weight, true);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case WeightStatusEnum.待称重:
|
|
|
case WeightStatusEnum.称重中:
|
|
|
{
|
|
|
this.wlblStatus.ForeColor = Color.Yellow;
|
|
|
this.wlblStatus.SymbolColor = Color.Yellow;
|
|
|
if (StabilizationEvent != null)
|
|
|
{
|
|
|
StabilizationEvent(_weight, false);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case WeightStatusEnum.负载:
|
|
|
case WeightStatusEnum.异常:
|
|
|
{
|
|
|
this.wlblStatus.ForeColor = Color.Red;
|
|
|
this.wlblStatus.SymbolColor = Color.Red;
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public void SetGoodsInfo(string name, decimal price, decimal amount)
|
|
|
{
|
|
|
this.wlblInfo.Text = name.ToString();
|
|
|
this.wlblPrice.Text = price.ToString();
|
|
|
this.wlblAmount.Text = amount.ToString();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public enum WeightStatusEnum
|
|
|
{
|
|
|
稳定 = 0,
|
|
|
待称重 = 1,
|
|
|
称重中 = 2,
|
|
|
异常 = 3,
|
|
|
负载 = 4,
|
|
|
超载 = 5,
|
|
|
}
|
|
|
}
|