develop
soul liu 2 years ago
parent d5c8af08ed
commit a6d321546e
  1. 4
      SerialPort/SerialPort.csproj
  2. 16
      Soul2-Library.sln
  3. 15
      Tools/Tools.csproj
  4. 48
      Tools/general/CollectionsUtils.cs
  5. 129
      Tools/general/StringUtils.cs
  6. 152
      Tools/general/TimerUtils.cs
  7. 168
      Tools/serialport/GodSerialPortUtils.cs
  8. 87
      Tools/sql/SqlBuilder.cs
  9. 20
      Tools/sql/SqlUtils.cs

@ -13,8 +13,4 @@
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\General\General.csproj" />
</ItemGroup>
</Project>

@ -3,9 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33530.505
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "General", "General\General.csproj", "{8B24AB73-0D6F-426D-92D3-25CBE6ED718E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerialPort", "SerialPort\SerialPort.csproj", "{B2EFA26A-A2CF-4090-85FD-31085D7A1A65}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tools", "Tools\Tools.csproj", "{093CFFEE-8B28-40B0-9752-6614616383C4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -13,14 +11,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8B24AB73-0D6F-426D-92D3-25CBE6ED718E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B24AB73-0D6F-426D-92D3-25CBE6ED718E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B24AB73-0D6F-426D-92D3-25CBE6ED718E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B24AB73-0D6F-426D-92D3-25CBE6ED718E}.Release|Any CPU.Build.0 = Release|Any CPU
{B2EFA26A-A2CF-4090-85FD-31085D7A1A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2EFA26A-A2CF-4090-85FD-31085D7A1A65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2EFA26A-A2CF-4090-85FD-31085D7A1A65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2EFA26A-A2CF-4090-85FD-31085D7A1A65}.Release|Any CPU.Build.0 = Release|Any CPU
{093CFFEE-8B28-40B0-9752-6614616383C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{093CFFEE-8B28-40B0-9752-6614616383C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{093CFFEE-8B28-40B0-9752-6614616383C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{093CFFEE-8B28-40B0-9752-6614616383C4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Soul2.$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
<AssemblyName>Soul2.$(MSBuildProjectName)</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GodSharp.SerialPort" Version="1.2.0.6" />
</ItemGroup>
</Project>

@ -0,0 +1,48 @@
using System.Collections;
namespace Soul2.Tools.General {
public static class CollectionsUtils {
/// <summary>
/// 判断非空
/// </summary>
/// <param name="collection">集合对象</param>
/// <returns>是否非空</returns>
public static bool isNotEmpty(this IEnumerable collection) {
return !isEmpty(collection);
}
/// <summary>
/// 判断为空
/// </summary>
/// <param name="collection">集合对象</param>
/// <returns>是否为空</returns>
public static bool isEmpty(this IEnumerable collection) {
if (collection == null) {
return true;
}
foreach (var item in collection) {
return false;
}
return true;
}
/// <summary>
/// 去重
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <returns></returns>
public static List<T> duplicateRemoval<T>(this List<T> list) {
if (list.isNotEmpty()) {
var set = new HashSet<T>(list);
return new List<T>(set);
} else {
return list;
}
}
public static HashSet<T> toSet<T>(this IEnumerable<T> collection) {
return new HashSet<T>(collection);
}
}
}

@ -0,0 +1,129 @@
namespace Soul2.Tools.General {
/// <summary>
/// 字符串工具类
/// By Soul2
/// </summary>
public static class StringUtils {
/// <summary>
/// 判断空值(null或"")
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static bool isEmpty(this string str) {
return string.IsNullOrEmpty(str);
}
public static bool isNotEmpty(this string str) {
return !string.IsNullOrEmpty(str);
}
/// <summary>
/// 判断空值(null、""或只有空格)
/// </summary>
/// <param name="str">被判断的字符串</param>
/// <returns></returns>
public static bool isNotBlank(this string str) { return !string.IsNullOrWhiteSpace(str); }
public static bool IsBlank(this string str) { return string.IsNullOrWhiteSpace(str); }
/// <summary>
/// 任何一个为空
/// </summary>
/// <param name="strs"></param>
/// <returns></returns>
public static bool isAnyBlank(params string[] strs) {
foreach (var str in strs) {
if (string.IsNullOrWhiteSpace(str)) {
return true;
}
}
return false;
}
/// <summary>
/// 任何一个为空
/// 空格属于非空
/// </summary>
/// <param name="strs"></param>
/// <returns></returns>
public static bool isAnyEmpty(params string[] strs) {
foreach (var str in strs) {
if (string.IsNullOrEmpty(str)) {
return true;
}
}
return false;
}
/// <summary>
/// 任何一个不为空
/// </summary>
/// <param name="strs"></param>
/// <returns></returns>
public static bool isNoneBlank(params string[] strs) {
foreach (var str in strs) {
if (string.IsNullOrWhiteSpace(str)) {
return false;
}
}
return true;
}
/// <summary>
/// 任何一个不为空
/// 空格属于非空
/// </summary>
/// <param name="strs"></param>
/// <returns></returns>
public static bool isNoneEmpty(params string[] strs) {
foreach (var str in strs) {
if (string.IsNullOrEmpty(str)) {
return false;
}
}
return true;
}
/// <summary>
/// 如果不以val结尾,则添加到结尾
/// </summary>
/// <param name="original"></param>
/// <param name="str"></param>
public static void appendIfMissing(this string original, string str) {
if (!original.EndsWith(str)) {
original += str;
}
}
/// <summary>
/// 如果不以val开头,则添加到开头
/// </summary>
/// <param name="original"></param>
/// <param name="str"></param>
public static void prependIfMissing(this string original, string str) {
if (!original.StartsWith(str)) {
original = str + original;
}
}
/// <summary>
/// 翻转
/// 例:"123"->"321"
/// </summary>
/// <param name="original"></param>
/// <returns></returns>
public static string flip(this string original) {
char[] chars = original.ToCharArray();
Array.Reverse(chars);
return new string(chars);
}
public static string subStrWith(this string original, int begin, int end) {
if (begin < 0 || end > original.Length || begin > end) {
throw new ArgumentException("Invalid input parameters");
}
return original.Substring(begin, end - begin);
}
}
}

@ -0,0 +1,152 @@
using System.Timers;
using Timer = System.Timers.Timer;
namespace Soul2.Tools.General {
/// <summary>
/// 扩展System.Timers.Timer
/// By Soul2
/// </summary>
public static class TimerUtils {
private const int default_loop_times = 512;
/// <summary>
/// 一次性计时器
/// 运行结束后自动销毁
/// </summary>
/// <param name="timer"></param>
/// <param name="time"></param>
/// <param name="callback"></param>
/// <returns></returns>
public static Timer startOnce(this Timer timer, double time, Action<Timer> callback) {
void onElapsed(object source, ElapsedEventArgs e) {
callback(timer);
timer.destroy();
}
return run(timer, (int)(time * 1000), false, onElapsed);
}
public static Timer startOnce(this Timer timer, double time, Action callback) {
return timer.startOnce(time, (t) => callback?.Invoke());
}
/// <summary>
/// 循环计时器
/// 可以指定运行次数
/// 运行结束后自动销毁
/// </summary>
/// <param name="timer">计时器</param>
/// <param name="time">时长</param>
/// <param name="times">次数</param>
/// <param name="callback"></param>
/// <returns></returns>
public static Timer startLoop(this Timer timer, double time, int times, Action<Timer, int> callback) {
int run_times = 0;
void onElapsed(object source, ElapsedEventArgs e) {
run_times += 1;
if (run_times <= times) {
callback(timer, run_times);
} else {
timer.destroy();
}
}
return run(timer, (int)(time * 1000), true, onElapsed);
}
public static Timer startLoop(this Timer timer, double time, int times, Action<Timer> callback) {
return timer.startLoop(time, times, (t, i) => callback?.Invoke(t));
}
public static Timer startLoop(this Timer timer, double time, int times, Action<int> callback) {
return timer.startLoop(time, times, (t, i) => callback?.Invoke(i));
}
public static Timer startLoop(this Timer timer, double time, int times, Action callback) {
return timer.startLoop(time, times, (t, i) => callback?.Invoke());
}
/// <summary>
/// 循环计时器
/// 默认运行次数512
/// </summary>
/// <param name="timer">计时器</param>
/// <param name="time">时长</param>
/// <param name="times">次数</param>
/// <param name="callback"></param>
/// <returns></returns>
public static Timer startKeep(this Timer timer, double time, Action<Timer, int> callback, int times = default_loop_times) {
int run_times = 0;
void onElapsed(object source, ElapsedEventArgs e) {
run_times += 1;
if (run_times <= times) {
callback(timer, run_times);
} else {
timer.destroy();
}
}
return run(timer, (int)(time * 1000), true, onElapsed);
}
public static Timer startKeep(this Timer timer, double time, Action<int> callback, int times = default_loop_times) {
return timer.startKeep(time, (t, i) => callback?.Invoke(i));
}
public static Timer startKeep(this Timer timer, double time, Action<Timer> callback, int times = default_loop_times) {
return timer.startKeep(time, (t, i) => callback?.Invoke(t));
}
public static Timer startKeep(this Timer timer, double time, Action callback, int times = default_loop_times) {
return timer.startKeep(time, (t, i) => callback?.Invoke());
}
public static void destroy(this Timer timer) {
if (timer.Enabled) {
timer.Stop();
}
timer.Dispose();
}
// -----------------------------------------
private static Timer run(Timer timer, int interval, bool loop, ElapsedEventHandler elapsed) {
timer.Elapsed += elapsed;
timer.Interval = interval;
timer.AutoReset = loop;
timer.Start();
return timer;
}
public static Timer startOnce(double time, Action<Timer> callback) {
return new Timer().startOnce(time, callback);
}
public static Timer startOnce(double time, Action callback) {
return new Timer().startOnce(time, callback);
}
// -----------------------------------------
public static Timer startLoop(double time, int times, Action<Timer, int> callback) {
return new Timer().startLoop(time, times, callback);
}
public static Timer startLoop(double time, int times, Action<Timer> callback) {
return new Timer().startLoop(time, times, callback);
}
public static Timer startLoop(double time, int times, Action<int> callback) {
return new Timer().startLoop(time, times, callback);
}
public static Timer startLoop(double time, int times, Action callback) {
return new Timer().startLoop(time, times, callback);
}
// -----------------------------------------
public static Timer startKeep(double time, Action<Timer, int> callback, int times = default_loop_times) {
return new Timer().startKeep(time, callback, times);
}
public static Timer startKeep(double time, Action<int> callback, int times = default_loop_times) {
return new Timer().startKeep(time, callback, times);
}
public static Timer startKeep(double time, Action<Timer> callback, int times = default_loop_times) {
return new Timer().startKeep(time, callback, times);
}
public static Timer startKeep(double time, Action callback, int times = default_loop_times) {
return new Timer().startKeep(time, callback, times);
}
}
}

@ -0,0 +1,168 @@
using System.Diagnostics;
using GodSharp.SerialPort.Extensions;
using GodSharp.SerialPort;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Soul2.Tools.SerialPort {
/// <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() {
be_sending = false;
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;
}
}
}

@ -0,0 +1,87 @@
using Soul2.Tools.General;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Soul2.Tools.sql {
/// <summary>
/// SQL语句简单生成器
/// </summary>
public class SqlBuilder {
private class WhereItem {
public string Key { get; set; }
public string Value { get; set; }
public WhereItem(string key, string value) {
Key = key;
Value = value;
}
}
private List<WhereItem> _where;
private List<string> _select;
private string _tbName;
private List<string> _isNullList;
private string _lastJoin;
public SqlBuilder(string tbName) {
_tbName = tbName;
_where = new List<WhereItem>();
_select = new List<string>();
_isNullList = new List<string>();
}
public SqlBuilder Where(string whichCol, string whatValue) {
_where.Add(new WhereItem(whichCol, whatValue));
return this;
}
public SqlBuilder Select(string select) {
_select.Add(select);
return this;
}
public SqlBuilder IsNull(string col) {
_isNullList.Add($"{col} is null");
return this;
}
public SqlBuilder IsNotNull(string col) {
_isNullList.Add($"{col} is not null");
return this;
}
public SqlBuilder Last(string lastSql) {
_lastJoin = lastSql;
return this;
}
public string Build() {
var select = "*";
if (_select.Count > 0) {
select = string.Join(", ", _select);
}
var sql = $"select {select} from {_tbName}";
if (_where.Count > 0) {
var whereBuilder = new StringBuilder();
foreach (var item in _where) {
if (_where.IndexOf(item) != 0) {
whereBuilder.Append(" and ");
}
whereBuilder.Append($"{item.Key} = @{item.Key}");
}
sql += $" where {whereBuilder}";
}
if (_isNullList.Count > 0) {
foreach (var item in _isNullList) {
sql += $" {item}";
}
}
sql += _lastJoin;
return sql;
}
}
}

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Xml;
using System.Data.SqlClient;
using System.Collections;
namespace Soul2.Tools.sql {
/// <summary>
/// SQL常用操作 工具类
/// </summary>
public class SqlUtils {
}
}
Loading…
Cancel
Save