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.

799 lines
22 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Utils;
using System.IO.Ports;
using System.Configuration;
using BWP.WebSocket;
using System.Diagnostics;
using System.IO;
using CutupClient.Utils;
namespace SerialPortWebSocketAdapter
{
public delegate void ReadParamEventHandler(string sParam);
public class MyThread
{
public enum ElectronicScale
{
1,
2,
}
private long received_count = 0;//接收计数
private long send_count = 0;//发送计数
private bool Listening = false;//是否没有执行完发送数据
private bool Closing = false;//是否正在关闭串口
public Thread thread2;
ReadParamEventHandler OnReadParamEvent;
public MyThread(ElectronicScale es = ElectronicScale.1)
{
MyRead(es);
}
public void CloseThread()
{
try
{
if (thread1 != null && thread1.IsAlive)
{
thread1.Abort();
}
if (thread2 != null && thread2.IsAlive)
{
thread2.Abort();
}
CloseSerialPort();
}
catch (ThreadAbortException e)
{
LogUtil.LogError("Abort:" + e.ToString());
}
}
public void Wait()
{
Closing = true;
if (port.IsOpen)
{
while (Listening)
DispatcherHelper.DoEvents();
port.Close();
}
Closing = false;
}
public void Start()
{
try
{
if (!port.IsOpen)
{
port.Open();
}
Closing = false;
}
catch (Exception ex)
{
ReadSerialPort();
}
}
public event ReadParamEventHandler ReadParam
{
add { OnReadParamEvent += new ReadParamEventHandler(value); }
remove { OnReadParamEvent -= new ReadParamEventHandler(value); }
}
public void MyRead(ElectronicScale es = ElectronicScale.1)
{
try
{
_Main(es);
}
catch (Exception ex)
{
LogUtil.LogError(ex);
}
}
const string Version = "20160408";
public class _Config
{
public static _Config Instance = new _Config();
public string PortName { get; set; }
public int BaudRate { get; set; }
public int? DataBits { get; set; }
public int DataLength { get; set; }
public byte BeginByte { get; set; }
public int ServicePort { get; set; }
public string Format { get; set; }
public string DataSource { get; set; }
public string DataType { get; set; }
public string ServiceType { get; set; }
public string Parity { get; set; }
public int? Delay { get; set; }
public int? OnlySteady { get; set; }
public bool NoBeginChar { get; set; }
}
_Config _config;
_Config Config
{
get
{
if (_config == null)
_config = new _Config();
return _config;
}
}
private static readonly string[] Source = { "XK3190-D2+", "DDI200", "XK3124", "XK3190A9", "XK3139", "XK3190-A1+", "ACS-30B", "XK3190-A12+E","AWH-SA"};
public void _Main(ElectronicScale es = ElectronicScale.1)
{
if (es == ElectronicScale.1)
{
LogUtil.LogLine(string.Format("欢迎使用串口通信服务{0}", Version));
var settting = System.Configuration.ConfigurationManager.AppSettings;
Config.PortName = settting["PortName"];
Config.BaudRate = int.Parse(settting["BaudRate"]);
Config.DataLength = int.Parse(settting["DataLength"]);
Config.DataType = settting["DataType"];
int dataBits;
if (int.TryParse(settting["DataBits"], out dataBits))
Config.DataBits = dataBits;
int delay;
if (int.TryParse(settting["Delay"], out delay))
Config.Delay = delay;
int onlySteady;
if (int.TryParse(settting["OnlySteady"], out onlySteady))
Config.OnlySteady = onlySteady;
Config.Parity = settting["Parity"];
Config.Format = settting["Format"];
Config.BeginByte = byte.Parse(settting["BeginHexNumber"], System.Globalization.NumberStyles.HexNumber);
Config.DataSource = settting["DataSource"];
Config.NoBeginChar = bool.Parse(settting["NoBeginChar"]);
if (!Source.Contains(Config.DataSource))
{
LogUtil.LogError(string.Format("DataSource配置错误,必须是这些可选项之一:{0}", string.Join(" ", Source)));
return;
}
}
else if (es == ElectronicScale.2)
{
LogUtil.LogLine(string.Format("欢迎使用串口通信服务{0}", Version));
var settting = System.Configuration.ConfigurationManager.AppSettings;
Config.PortName = settting["PortName2"];
Config.BaudRate = int.Parse(settting["BaudRate2"]);
Config.DataLength = int.Parse(settting["DataLength2"]);
Config.DataType = settting["DataType2"];
int dataBits;
if (int.TryParse(settting["DataBits2"], out dataBits))
Config.DataBits = dataBits;
int delay;
if (int.TryParse(settting["Delay2"], out delay))
Config.Delay = delay;
int onlySteady;
if (int.TryParse(settting["OnlySteady2"], out onlySteady))
Config.OnlySteady = onlySteady;
Config.Parity = settting["Parity2"];
Config.Format = settting["Format2"];
Config.BeginByte = byte.Parse(settting["BeginHexNumber2"], System.Globalization.NumberStyles.HexNumber);
Config.DataSource = settting["DataSource2"];
Config.NoBeginChar = bool.Parse(settting["NoBeginChar2"]);
if (!Source.Contains(Config.DataSource))
{
LogUtil.LogError(string.Format("DataSource配置错误,必须是这些可选项之一:{0}", string.Join(" ", Source)));
return;
}
}
ReadSerialPort();
thread2 = new Thread(new ThreadStart(ClearMsgTask));
thread2.Start();
}
void ClearMsgTask()
{
var milisec = 500;
var milliseconds = ConfigurationManager.AppSettings["TotalMilliseconds"];
if (!string.IsNullOrEmpty(milliseconds))
{
milisec = int.Parse(milliseconds);
}
while (true)
{
Thread.Sleep(milisec);
if (!port.IsOpen)
continue;
if (lastSendTime.HasValue && (DateTime.Now - lastSendTime).Value.TotalMilliseconds >= milisec && lastMsg != "")
OnReadParamEvent("0");
}
}
class ReceiverManager
{
readonly List<byte> readBuffer = new List<byte>();
bool _enableReceiveData;
void RestartReceive(bool enableReceiveData)
{
readBuffer.Clear();
_enableReceiveData = enableReceiveData;
}
public void Append(byte data, _Config config, ReadParamEventHandler even)
{
lock (readBuffer)
{
if (config.NoBeginChar)
{
_NoBeginCharAppendData(data, config, even);
}
else
{
_AppendData(data, config, even);
}
}
}
private void _NoBeginCharAppendData(byte data, _Config config, ReadParamEventHandler even)
{
readBuffer.Add(data);
if (readBuffer.Count < config.DataLength)
return;
var buffer = readBuffer.ToArray();
readBuffer.Clear();
string message;
if (TryParseMessage(buffer, config, out message) && !string.IsNullOrEmpty(message))
{
even(message);
}
}
private void _AppendData(byte data, _Config config, ReadParamEventHandler even)
{
if (data == config.BeginByte)
{
RestartReceive(true);
return;
}
if (!_enableReceiveData)
{
return;
}
readBuffer.Add(data);
if (readBuffer.Count < config.DataLength)
return;
var buffer = readBuffer.ToArray();
_enableReceiveData = false;
readBuffer.Clear();
string message;
if (TryParseMessage(buffer, config, out message) && !string.IsNullOrEmpty(message))
{
even(message);
lastSendTime = DateTime.Now;
lastMsg = message;
}
}
private static bool TryParseMessage(byte[] buffer, _Config config, out string message)
{
try
{
switch (config.DataSource)
{
case "XK3139":
case "XK3124":
message = FormatBaseXk3124(buffer, config);
break;
case "DDI200":
case "XK3190A9":
case "XK3190-A1+":
message = FormatBaseXk3190A9(buffer, config);
break;
case "XK3190-D2+":
message = FormatBaseXk3190D2(buffer, config);
break;
case "ACS-30B":
message = FormatBaseACS30B(buffer, config);
break;
case "XK3190-A12+E":
message = FormatBase3190A12(buffer, config);
break;
case "AWH-SA":
case "ACS-W(SA)":
message = FormatBaseAWH_SA(buffer, config);
break;
default:
{
message = "";
LogUtil.LogError(string.Format("未知的数据来源:{0}", config.DataSource));
return false;
}
}
return true;
}
catch (Exception ex)
{
message = string.Empty;
LogUtil.LogError(string.Format("使用数据来源{0}解析数据{1}时出现错误:{2}",
config.DataSource, Convert.ToBase64String(buffer), ex.ToString()));
return false;
}
}
private static string FormatBaseACS30B(byte[] buffer, _Config config)
{
var output = Encoding.ASCII.GetString(buffer);
if (output.Length > 0)
{
output = Reverse(output);
output = output.TrimStart('0');
output = (decimal.Parse(output) / 1000).ToString();
}
return output;
}
private static string FormatBaseACS_W_SA(byte[] buffer, _Config config)
{
var output = Encoding.ASCII.GetString(buffer);
if (output.Length > 0) {
//output = Reverse(output);
output = output.TrimStart('0');
output = (decimal.Parse(output) / 1000).ToString();
}
return output;
}
private static string FormatBaseAWH_SA(byte[] buffer, _Config config)
{
var output = Encoding.ASCII.GetString(buffer);
output = output.Substring(6, 8).Replace(" ",string.Empty);
decimal? result = null;
if (config.DataType == "Decimal")
{
decimal decimalValue;
if (decimal.TryParse(output, out decimalValue))
{
result = decimalValue;
}
}
if (result == null)
{
return string.Empty;
}
if (!string.IsNullOrEmpty(config.Format))
{
output = string.Format(config.Format, result);
}
return output;
}
private static string FormatBaseXk3190D2(byte[] buffer, _Config config)
{
var strs = new byte[buffer.Length];
for (int index = 0; index < buffer.Length; index++)
{
strs[index] = buffer[buffer.Length - index - 1];
}
var output = Encoding.ASCII.GetString(strs);
// LogLine(string.Format("接收到串口数据:{0}", output));
object result = null;
if (config.DataType == "Decimal")
{
decimal decimalValue;
if (decimal.TryParse(output, out decimalValue))
{
result = decimalValue;
}
}
if (result == null)
{
LogUtil.LogError(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", output, config.DataType));
return string.Empty;
// throw new Exception(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", output, Config.DataType));
}
if (!string.IsNullOrEmpty(config.Format))
{
output = string.Format(config.Format, result);
}
return output;
}
private static string FormatBaseXk3124(byte[] buffer, _Config config)
{
var output = Encoding.ASCII.GetString(buffer);
//LogLine(string.Format("接收到串口数据:{0}", output));
var str = new StringBuilder();
char swa = output[0]; // 状态字A
char swb = output[1]; // 状态字B
int dotIndex = (swa & 0x07) - 2; // 小数点位置
bool isPositive = (((swb >> 1) & 0x01) == 0); // 符号:是否为正数
var isStatic = (((swb >> 3) & 0x01) == 0); //是否稳定值 暂时无用
char[] num = new char[6];
for (int i = 0; i < 6; i++)
{
num[i] = output[i + 3];
}
// 不考虑精确到十,百位
if (dotIndex > 0)
{
for (int i = 0; i < 6 - dotIndex; i++)
{
str.Append(num[i]);
}
str.Append('.');
for (int i = 0; i < dotIndex; i++)
{
str.Append(num[6 - dotIndex + i]);
}
}
else
{
foreach (var n in num)
{
str.Append(n);
}
}
var strValue = str.ToString().Trim();
if (strValue.IndexOf('.') == 0)
{
strValue = strValue.Insert(0, "0");
}
if (strValue.IndexOf('.') == strValue.Length - 1)
{
strValue = strValue.Replace(".", "");
}
// 负数
if (!isPositive)
{
strValue = strValue.Insert(0, "-");
}
decimal? result = null;
if (config.DataType == "Decimal")
{
decimal decimalValue;
if (decimal.TryParse(strValue, out decimalValue))
{
result = decimalValue;
}
}
if (result == null)
{
LogUtil.LogError(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", strValue, config.DataType));
return string.Empty;
// throw new Exception(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", strValue, Config.DataType));
}
DelySomeTime(result, config);
if (!string.IsNullOrEmpty(config.Format))
{
output = string.Format(config.Format, result);
LogUtil.LogLine(string.Format("数据:{0} 稳定:{1} 延迟:{2}", output, isStatic, _isDelying));
}
if (config.OnlySteady.HasValue && config.OnlySteady == 1 && !isStatic)
{
output = string.Empty;
}
return _isDelying ? string.Empty : output;
}
static bool _isDelying;
static bool _waitingZero;//等待归0
private static DateTime? _startDelyTime;
private static void DelySomeTime(decimal? result, _Config config)
{
if (!config.Delay.HasValue)
return;
if (_waitingZero && result <= 0)
{
_waitingZero = false;
}
if (_waitingZero || result <= 0)
return;
if (!_isDelying)
{
_isDelying = true;
_startDelyTime = DateTime.Now;
}
else
{
var diffm = (DateTime.Now - _startDelyTime);
if (diffm.HasValue)
{
if (diffm.Value.Seconds >= config.Delay.Value)
{
_isDelying = false;
_startDelyTime = null;
_waitingZero = true;
}
}
else
{
_isDelying = false;
}
}
}
private static string FormatBase3190A12(byte[] buffer, _Config config)
{
var weight = Encoding.ASCII.GetString(buffer);
decimal? result = null;
if (config.DataType == "Decimal")
{
decimal decimalValue;
if (decimal.TryParse(weight, out decimalValue))
{
result = decimalValue;
}
}
if (result == null)
{
LogUtil.LogError(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", weight, config.DataType));
return string.Empty;
}
if (!string.IsNullOrEmpty(config.Format))
{
return string.Format(config.Format, result);
}
return string.Empty;
}
private static string FormatBaseXk3190A9(byte[] buffer, _Config config)
{
var output = Encoding.ASCII.GetString(buffer);
//LogLine(string.Format("接收到串口数据:{0}", output));
string weight;
// 小数位数0-4
int dot = (short)(0x0F & output[7]);
weight = output.Substring(1, 6).Trim();
// insert dot
weight = InsertDot(weight, dot);
// buffer[1] 符号位
if (output[0] == '-')
{
weight = weight.Insert(0, "-");
}
decimal? result = null;
if (config.DataType == "Decimal")
{
decimal decimalValue;
if (decimal.TryParse(weight, out decimalValue))
{
result = decimalValue;
}
}
if (result == null)
{
LogUtil.LogError(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", weight, config.DataType));
return string.Empty;
//throw new Exception(string.Format("串口接收到的数据{0}不能转换为所期望的类型{1}", weight, Config.DataType));
}
if (!string.IsNullOrEmpty(config.Format))
{
output = string.Format(config.Format, result);
// LogLine(string.Format("串口数据格式化为:{0}", output));
}
return output;
}
private static string InsertDot(string weight, int dotBits)
{
var str = weight.TrimStart(new[] { '0' });
str = str.Trim();
if (dotBits > 0)
{
if (string.IsNullOrEmpty(str))
{
return "0";
}
str = str.Insert(str.Length - dotBits, ".");
}
if (str.IndexOf(".", StringComparison.Ordinal) == 0)
{
str = str.Insert(0, "0");
}
return str;
}
}
SerialPort port = null;
private static DateTime? lastSendTime = null;
private static string lastMsg = null;
public static Thread thread1;
void ReadSerialPort()
{
if (!string.IsNullOrEmpty(Config.DataSource) && !Source.Contains(Config.DataSource))
{
LogUtil.LogError(string.Format("数据来源{0}无效,无法处理数据", Config.DataSource));
return;
}
port = new SerialPort(Config.PortName, Config.BaudRate);
port.ReceivedBytesThreshold = Config.DataLength + 1;
if (Config.DataBits.HasValue)
port.DataBits = Config.DataBits.Value; //数据位
if (Config.Parity == "Even")
port.Parity = Parity.Even;
if (Config.Parity == "Odd")
port.Parity = Parity.Odd;
port.ErrorReceived += (sender, e) => {
LogUtil.LogError(new Exception(string.Format("串口接收到一个错误,类型为{0}", e.ToString())));
};
var receiver = new ReceiverManager();
port.DataReceived += delegate {
if (Closing)
return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环
Listening = true;//设置标记,说明已经开始处理数据,
while (port.IsOpen && port.BytesToRead > 0)
{
try
{
var data = Convert.ToByte(port.ReadByte());
receiver.Append(data, Config, OnReadParamEvent);
}
catch (ThreadAbortException e)
{
LogUtil.LogError("Abort:" + e.ToString());
break;
}
}
Listening = false;
};
// OpenSerialPort();
if (Config.DataSource == "ACS-30B")
{
try
{
thread1 = new Thread(new ThreadStart(PortWriteA));
//thread1.IsBackground = true;
thread1.Start();
//PortWriteA();
}
catch (ThreadAbortException e)
{
LogUtil.LogError("Abort:" + e.ToString());
}
}
}
void PortWriteA()
{
try
{
while (true)
{
if (port.IsOpen)
port.Write("a");
Thread.Sleep(500);
}
}
catch (ThreadAbortException e)
{
LogUtil.LogError(e.ToString());
}
}
void CloseSerialPort()
{
try
{
Closing = true;
if (port.IsOpen)
{
while (Listening)
DispatcherHelper.DoEvents();
port.Close();
}
port.Dispose();
Closing = false;
LogUtil.LogLine(string.Format("关闭串口{0}成功", Config.PortName));
}
catch (Exception ex)
{
LogUtil.LogError(string.Format("关闭串口{0}失败:{1}", Config.PortName, ex.Message));
}
}
void OpenSerialPort()
{
try
{
if (!port.IsOpen)
port.Open();
LogUtil.LogLine(string.Format("连接串口{0}成功", Config.PortName));
}
catch (Exception ex)
{
LogUtil.LogError(string.Format("连接串口{0}失败:{1}", Config.PortName, ex.Message));
}
}
/// <summary>
/// 反转字符串
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
static string Reverse(string value)
{
char[] rs = value.ToCharArray();
Array.Reverse(rs);
var ret = new string(rs);
return ret;
}
}
}