///********************************************************** ///RJCP.IO.Ports 可以跨平台,同样System.Ports也同样可以使用 ///********************************************************** using System; using RJCP.IO.Ports; using System.Threading; using SHJX.Service.Common.Logging; using Microsoft.Extensions.Logging; namespace SHJX.Service.ServerClient.RS485 { public static class Rs485Client { private static readonly ILogger logger = LogFactory.BuildLogger(typeof(Rs485Client)); /// /// RS485通信对象 /// public static SerialPortStream Sport { get; set; } /// /// 发送命令时锁定 /// private static readonly object SnedLocker = new(); /// /// 延时等待的单位间隔,默认20ms /// private static int DelayUnit { get; set; } /// /// 超时时长,默认1000ms /// private static int Timeout { get; set; } /// /// 端口状态: /// True=打开,False=关闭 /// public static bool IsValid => Sport is not null && Sport.IsOpen; /// /// 初始化 /// public static void InitPort() { // 创建COM通信对象 Sport ??= new SerialPortStream { BaudRate = 9600, DataBits = 8, StopBits = StopBits.One, Parity = Parity.None }; DelayUnit = 10; Timeout = 1000; } /// /// 打开COM通信端口,使用指定参数 /// /// 端口号 /// 是否正常打开 public static bool Open(string portName) { try { lock (SnedLocker) { if (Sport.IsOpen) Sport.Close(); Sport.PortName = portName; try { Sport.Open(); } catch (Exception ex) { logger?.LogError(ex.Message); } } return Sport.IsOpen; } catch (UnauthorizedAccessException exIo) { logger?.LogError(exIo.ToString()); return false; } catch (Exception ex) { logger?.LogError(ex.ToString()); return false; } } /// /// 关闭COM通信端口 /// /// true=已关闭,false=未关闭 public static void Close() { //var open = Sport.IsOpen; if (!Sport.IsOpen) return; Sport.Close(); //Sport.Dispose(); } /// /// 向端口发送指令,并等待回复。 /// 以lastChar字符作为回复的结尾识别字符,收到该字符后返回。 /// 失败时,返回string.Empty /// /// 指令 /// 结尾识别字符 /// 完整的应答数据,含结尾识别字符 public static string SendData(string cmdStr, char lastChar) { if (Sport.IsOpen.Equals(false)) return string.Empty; lock (SnedLocker) { for (; ; ) { try { var strRes = string.Empty; Sport.DiscardInBuffer(); Sport.DiscardOutBuffer(); Sport.Write(cmdStr);// 发送指令 // 等待回复 for (var i = 0; i < Timeout / DelayUnit; i++) { // 判断数据是否接收完整 if (Sport.BytesToRead > 0) strRes += Sport.ReadExisting(); if (strRes.IndexOf(lastChar) != -1) break; Thread.Sleep(DelayUnit); } if (strRes.Length.Equals(0)) { strRes = string.Empty; } return strRes; } catch (UnauthorizedAccessException exIo) { logger?.LogError(exIo.ToString()); } catch (Exception ex) { logger?.LogError(ex.ToString()); } } } } /// /// 向端口发送指令,并等待回复。 /// 以lastStr字符串作为回复的结尾识别字符,收到该字符串后返回。 /// 失败时,返回string.Empty /// /// 指令 /// /// 收到的回复数据,含结尾识别字符串 public static string SendData(string cmdStr, string lastStr) { if (Sport.IsOpen == false) return string.Empty; lock (SnedLocker) { for (; ; ) { try { var strRes = string.Empty; Sport.DiscardInBuffer(); Sport.DiscardOutBuffer(); Sport.Write(cmdStr);// 发送指令 // 等待回复 for (var i = 0; i < Timeout / DelayUnit; i++) { // 判断数据是否接收完整 if (Sport.BytesToRead > 0) { strRes += Sport.ReadExisting(); } if (strRes.IndexOf(lastStr, StringComparison.Ordinal) > 0) { break; } Thread.Sleep(DelayUnit); } if (strRes.Length == 0) { strRes = string.Empty; } return strRes; } catch (UnauthorizedAccessException exIo) { logger?.LogError(exIo.ToString()); } catch (Exception ex) { logger?.LogError(ex.ToString()); } } } } } }