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.
169 lines
6.5 KiB
169 lines
6.5 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using GodSharp.SerialPort.Extensions;
|
|
using GodSharp.SerialPort;
|
|
using System.IO.Ports;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Soul2.SerialPort.utils {
|
|
/// <summary>
|
|
/// 串口通信工具类
|
|
/// </summary>
|
|
public static class GodSerialPortUtils {
|
|
|
|
private static GodSerialPort? gsp = null;
|
|
public static bool debug = false;
|
|
public static bool be_sending = false;
|
|
private static byte[]? back_data;
|
|
|
|
public class Messages {
|
|
/// <summary>
|
|
/// 645协议读取通信地址报文
|
|
/// </summary>
|
|
public const string _645CommunicationAddress = "FE FE FE FE 68 AA AA AA AA AA AA 68 13 00 DF 16";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 打印log
|
|
/// </summary>
|
|
/// <param name="log"></param>
|
|
private static void log(string log) {
|
|
if (debug) {
|
|
Debug.WriteLine("[GodSerialPortUtils] " + log);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 查询所有可用串口
|
|
/// </summary>
|
|
/// <returns>串口名称数组</returns>
|
|
public static string[] find() => System.IO.Ports.SerialPort.GetPortNames();
|
|
|
|
/// <summary>
|
|
/// 当前连接状态
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public static bool status() => (gsp != null && gsp.IsOpen != false);
|
|
|
|
/// <summary>
|
|
/// 发送报文信息
|
|
/// </summary>
|
|
/// <param name="data">发送的内容</param>
|
|
/// <param name="callback">回调函数,参数为byte[]类型的回信</param>
|
|
/// <param name="wait_complete">是否等待回信完成再执行回调函数,默认为否</param>
|
|
/// <exception cref="Exception"></exception>
|
|
public static void send(string data, Action<byte[]> callback = null, bool wait_complete = false) => send(data.HexToByte(), callback, wait_complete);
|
|
|
|
/// <summary>
|
|
/// 发送报文信息
|
|
/// </summary>
|
|
/// <param name="data">发送的内容</param>
|
|
/// <param name="callback">回调函数,参数为byte[]类型的回信</param>
|
|
/// <param name="wait_complete">是否等待回信完成再执行回调函数,默认为否</param>
|
|
/// <exception cref="Exception"></exception>
|
|
public static void send(byte[] data, Action<byte[]> callback = null, bool wait_complete = false) {
|
|
if (status() && !be_sending && gsp != null) {
|
|
// 发送报文并启用 DataReceived 事件
|
|
void onBack(GodSerialPort _gsp, byte[] bytes) {
|
|
string buffer = string.Join("", bytes.Select(b => b.ToString("X2")));
|
|
log("收到数据:" + buffer);
|
|
be_sending = false;
|
|
if (back_data != null) {
|
|
back_data = back_data.Concat(bytes).ToArray();
|
|
} else {
|
|
back_data = bytes;
|
|
}
|
|
if (!wait_complete || (back_data != null && back_data.Length > 0 && back_data[^1] == 0x16)) {
|
|
callback?.Invoke(back_data);
|
|
}
|
|
}
|
|
be_sending = true;
|
|
gsp.Write(data);
|
|
log($"发送数据:{data.ToHexString()}");
|
|
gsp.UseDataReceived(true, onBack);
|
|
} else if (!status() || gsp == null) {
|
|
// 连接未建立或者串口对象不存在,则抛出异常
|
|
throw new Exception("先连接再发送报文");
|
|
} else if (be_sending) {
|
|
// 上一个报文还未收到回信,则抛出异常
|
|
throw new Exception("上一个报文还未收到回信!");
|
|
}
|
|
// 清空 back_data 数组,避免数据混乱
|
|
back_data = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 打开串口通信
|
|
/// </summary>
|
|
/// <param name="name">串口名称</param>
|
|
/// <param name="baudRate">波特率</param>
|
|
/// <param name="parity">校验码</param>
|
|
/// <param name="dataBits">数据位</param>
|
|
/// <param name="stopBits">停止位</param>
|
|
/// <param name="handshake">握手协议</param>
|
|
/// <returns></returns>
|
|
public static bool open(string name, int baudRate = 9600, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.None, Handshake handshake = Handshake.None) {
|
|
if (gsp == null) {
|
|
gsp = new GodSerialPort(name, baudRate, parity, dataBits, stopBits, handshake);
|
|
}
|
|
return gsp.Open() & status();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 关闭连接
|
|
/// </summary>
|
|
/// <returns>是否已关闭</returns>
|
|
public static bool close() {
|
|
if (gsp == null) {
|
|
return true;
|
|
}
|
|
var r = gsp.Close();
|
|
gsp = null;
|
|
return r;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 16进制加法计算
|
|
/// 2位,按空格分割,加负数来算减法
|
|
/// </summary>
|
|
/// <param name="hexStr">16进制文本</param>
|
|
/// <param name="m">增加的值</param>
|
|
/// <returns>计算后的文本</returns>
|
|
public static string AddValueToHexString(string hexStr, int m) {
|
|
// 检查输入字符串是否符合要求
|
|
if (!Regex.IsMatch(hexStr, @"^[\da-fA-F]{2}( [\da-fA-F]{2})*$")) {
|
|
return "==";
|
|
}
|
|
var hexBytes = hexStr.HexToByte();
|
|
for (int i = 0; i < hexBytes.Length; i++) {
|
|
hexBytes[i] = (byte)((int)hexBytes[i] + m);
|
|
}
|
|
|
|
return hexBytes.ToHexString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算校验码
|
|
/// </summary>
|
|
/// <param name="msg">当前报文,不应包含校验码的部分</param>
|
|
/// <returns></returns>
|
|
public static string CalcChecksum(string msg) {
|
|
if (msg.StartsWith("FE FE FE FE ")) {
|
|
msg = msg.Replace("FE FE FE FE ", "");
|
|
}
|
|
|
|
// 检查输入字符串是否符合要求
|
|
if (!Regex.IsMatch(msg, @"^[\da-fA-F]{2}( [\da-fA-F]{2})*$")) {
|
|
return "==";
|
|
}
|
|
|
|
var bts = msg.Split(' ').Select(b => Convert.ToInt32(b, 16)).ToArray();
|
|
var r = (bts.Sum() % 256).ToString("X2");
|
|
return r;
|
|
}
|
|
}
|
|
}
|
|
|