/
AwsomeMeNGL
/
SerialMonitor_582-1_Practicing
Обзор
Документация
Войти
/
AwsomeMeNGL
/
SerialMonitor_582-1_Practicing
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
SerialMonitor2/SerialPort.cs
1 045 строк
40 KB
ShadowRec
RichTextBoxFormat
03 мар 2025, 10:26
03 мар 2025, 10:26
caab7e5
Код
Авторство
О чём код?
using System; using System.Linq; using System.IO; using System.IO.Ports; using System.Windows.Forms; using System.Drawing; using System.Xml; // My namespaces using Utilities; using SerialMonitor2.Properties; using SettingsManagement; using static SerialPortNamespace.CSerialPort; using System.Timers; using static System.Net.Mime.MediaTypeNames; using SerialMonitor2; using System.Security.Permissions; //using WakeUpProtocol; namespace SerialPortNamespace { public class CSerialPortGUI { // Constants #region private string[] strLABEL_NAMES = { "Порт", "Скорость", "Бит данных", "Четность", "Стоп бит" }; private string[] strCOMBOBOX_ITEMS_BAUD = { "110", "300", "600", "1200", "2400", "4800", "9600", "14400", "19200", "38400", "56000", "57600", "115200", "128000" }; private string[] strCOMBOBOX_ITEMS_DATABITS = { "5", "6", "7", "8" }; private string[] strCOMBOBOX_ITEMS_PARITY = { "None", "Odd", "Even", "Mark", "Space" }; private string[] strCOMBOBOX_ITEMS_STOPBITS = { "None", "One", "Two", "OnePointFive" }; const string SETTING_NO_PORT = "Не найден"; const string strGROUPBOX_TEXT = "Настройки порта"; const string strBUTTON_TEXT_OPEN = "Открыть порт"; const string strBUTTON_TEXT_CLOSE = "Закрыть порт"; const string strCHECKBOX_TEXT_DTR_0 = "DTR = 0"; const string strCHECKBOX_TEXT_DTR_1 = "DTR = 1"; const string strCHECKBOX_TEXT_RTS_0 = "RTS = 0"; const string strCHECKBOX_TEXT_RTS_1 = "RTS = 1"; const string strMESSAGE_PORT = "Порт"; const string strMESSAGE_OPEN = "успешно открыт"; const string strMESSAGE_CLOSE = "успешно закрыт"; private const int DR_POS_Y_CONTROLS_INC = 27; private const int DR_GROUPBOX_MAIN_WIDTH = 300; private const int DR_GROUPBOX_MAIN_HIGHT_MIN = 100; private const int DR_GROUPBOX_MAIN_HIGHT_FULL = 170; private const int DR_POS_GROUPBOX_MAIN_X = 12; private const int DR_POS_GROUPBOX_MAIN_Y = 12; private const int PORT_SETTINGS_NUM_FULL = 5; private const int PORT_SETTINGS_NUM_MIN = 2; private const int LIMIT_TEXTBOX_TEXTLENGTH = 100000; #endregion public GroupBox groupBox_SerialPort_Main; private Panel panel_Settings; private ComboBox comboBox_SerialPort_Name; private ComboBox comboBox_SerialPort_Baud; private ComboBox comboBox_SerialPort_DataBits; private ComboBox comboBox_SerialPort_Parity; private ComboBox comboBox_SerialPort_StopBit; private Button button_SerialPort_OpenClose; private CheckBox checkBox_RTS; private CheckBox checkBox_DTR; private Label label_AllSettings; public RichTextBox richTextBox_Log; private string Status; public delegate void Data_Recieved(); public event Data_Recieved RXD_Count_up; byte[] TxData, RxData = { }; CSerialPort[] serialPort = { }; int currentPort = 0; CSerialPort.SSettings settingsDefault = new CSerialPort.SSettings() { name = "", // Doesn't metter baudRate = 115200, dataBits = 8, parity = Parity.None, stopBits = StopBits.One }; CSerialPort.SSettings[] settingsPortAll = { }; string[] serialPortNames = { }; public enum eMainBoxSize { MINIMAL = 0, FULL }; // Constructor public CSerialPortGUI(eMainBoxSize size) { Label l; int tabIndex = 0; int x = 6, y = 30; int gbHight, gbWidth; int settingCount; gbWidth = DR_GROUPBOX_MAIN_WIDTH; switch (size) { case eMainBoxSize.MINIMAL: gbHight = DR_GROUPBOX_MAIN_HIGHT_MIN; settingCount = PORT_SETTINGS_NUM_MIN; break; case eMainBoxSize.FULL: gbHight = DR_GROUPBOX_MAIN_HIGHT_FULL; settingCount = PORT_SETTINGS_NUM_FULL; break; default: gbHight = DR_GROUPBOX_MAIN_HIGHT_FULL; settingCount = PORT_SETTINGS_NUM_FULL; break; } this.groupBox_SerialPort_Main = new GroupBox() { Name = "groupBox_SerialPort_Main", Location = new Point(DR_POS_GROUPBOX_MAIN_X, DR_POS_GROUPBOX_MAIN_Y), Size = new Size(gbWidth, gbHight), Text = strGROUPBOX_TEXT }; this.panel_Settings = new Panel() { Name = "panel_SerialPort_Settings", Location = new Point(80, 52), Size = new Size(96, gbHight - 57), TabIndex = 1 }; this.groupBox_SerialPort_Main.Controls.Add(this.panel_Settings); for (int i = 0; i < settingCount; i++) { l = new Label() { AutoSize = true, Location = new Point(x, y), Text = strLABEL_NAMES[i] }; this.groupBox_SerialPort_Main.Controls.Add(l); y += DR_POS_Y_CONTROLS_INC; } x = 83; y = 27; this.comboBox_SerialPort_Name = new ComboBox() { Name = "comboBox_SerialPort_Name", DropDownStyle = ComboBoxStyle.DropDownList, Location = new Point(x, y), Size = new Size(90, 21), TabIndex = tabIndex++ }; this.comboBox_SerialPort_Name.DropDown += ComboBox_SerialPort_Name_DropDown; this.comboBox_SerialPort_Name.SelectedIndexChanged += ComboBox_SerialPort_Name_SelectedIndexChanged; this.groupBox_SerialPort_Main.Controls.Add(this.comboBox_SerialPort_Name); x = 3; y = 2; this.comboBox_SerialPort_Baud = new ComboBox() { Name = "comboBox_SerialPort_BaudRate", DropDownStyle = ComboBoxStyle.DropDownList, Location = new Point(x, y), Size = new Size(90, 21), TabIndex = tabIndex++ }; this.comboBox_SerialPort_Baud.Items.AddRange(strCOMBOBOX_ITEMS_BAUD); this.comboBox_SerialPort_Baud.SelectedItem = this.settingsDefault.baudRate.ToString(); this.panel_Settings.Controls.Add(this.comboBox_SerialPort_Baud); if (eMainBoxSize.MINIMAL < size) { y += DR_POS_Y_CONTROLS_INC; this.comboBox_SerialPort_DataBits = new ComboBox() { Name = "comboBox_SerialPort_DataBits", DropDownStyle = ComboBoxStyle.DropDownList, Location = new Point(x, y), Size = new Size(90, 21), TabIndex = tabIndex++ }; this.comboBox_SerialPort_DataBits.Items.AddRange(strCOMBOBOX_ITEMS_DATABITS); this.comboBox_SerialPort_DataBits.SelectedItem = this.settingsDefault.dataBits.ToString(); this.panel_Settings.Controls.Add(this.comboBox_SerialPort_DataBits); y += DR_POS_Y_CONTROLS_INC; this.comboBox_SerialPort_Parity = new ComboBox() { Name = "comboBox_SerialPort_Parity", DropDownStyle = ComboBoxStyle.DropDownList, Location = new Point(x, y), Size = new Size(90, 21), TabIndex = tabIndex++ }; this.comboBox_SerialPort_Parity.Items.AddRange(strCOMBOBOX_ITEMS_PARITY); this.comboBox_SerialPort_Parity.SelectedItem = this.settingsDefault.parity.ToString(); this.panel_Settings.Controls.Add(this.comboBox_SerialPort_Parity); y += DR_POS_Y_CONTROLS_INC; this.comboBox_SerialPort_StopBit = new ComboBox() { Name = "comboBox_SerialPort_StopBits", DropDownStyle = ComboBoxStyle.DropDownList, Location = new Point(x, y), Size = new Size(90, 21), TabIndex = tabIndex++ }; this.comboBox_SerialPort_StopBit.Items.AddRange(strCOMBOBOX_ITEMS_STOPBITS); this.comboBox_SerialPort_StopBit.SelectedItem = this.settingsDefault.stopBits.ToString(); this.panel_Settings.Controls.Add(this.comboBox_SerialPort_StopBit); x = 180; y += 21; // y -= 60; this.checkBox_DTR = new CheckBox() { Name = "checkBox_SerialPort_DTR", Appearance = Appearance.Button, Location = new Point(x, y), Size = new Size(110, 24), TextAlign = ContentAlignment.MiddleCenter, Text = strCHECKBOX_TEXT_DTR_0, TabIndex = tabIndex++ }; this.groupBox_SerialPort_Main.Controls.Add(this.checkBox_DTR); y += 30; this.checkBox_RTS = new CheckBox() { Name = "checkBox_SerialPort_RTS", Appearance = Appearance.Button, Location = new Point(x, y), Size = new Size(110, 24), TextAlign = ContentAlignment.MiddleCenter, Text = strCHECKBOX_TEXT_RTS_0, TabIndex = tabIndex++ }; this.groupBox_SerialPort_Main.Controls.Add(this.checkBox_RTS); } this.button_SerialPort_OpenClose = new Button() { Name = "button_SerialPort_OpenClose", Location = new Point(180, 27), Size = new Size(110, 48), Text = strBUTTON_TEXT_OPEN, TabIndex = tabIndex++ }; this.button_SerialPort_OpenClose.Click += Button_SerialPort_OpenClose_Click; this.groupBox_SerialPort_Main.Controls.Add(this.button_SerialPort_OpenClose); this.richTextBox_Log = new RichTextBox() { Name = "richTextBox_SerialPort_Log", Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top, Font = new Font("Courier New", 8.25f), Location = new Point(12 + gbWidth, 16), Size = new Size(gbWidth, gbHight) }; this.richTextBox_Log.TextChanged += RichTextBox_Log_TextChanged; SerialPortScan(); } // EventHandlers #region private void ComboBox_SerialPort_Name_DropDown(object sender, EventArgs e) { SettingsApplyFromControls(); SerialPortScan(); } private void ComboBox_SerialPort_Name_SelectedIndexChanged(object sender, EventArgs e) { if (this.serialPortNames.Length > 0) { if (String.Equals(serialPort[currentPort].GetName(), this.comboBox_SerialPort_Name.SelectedItem.ToString())) SettingsApplyFromControls(); this.currentPort = this.comboBox_SerialPort_Name.SelectedIndex; this.SettingsShowOnControls(); } } private void Button_SerialPort_OpenClose_Click(object sender, EventArgs e) { OpenPort(); } private void RichTextBox_Log_TextChanged(object sender, EventArgs e) { if (this.richTextBox_Log.TextLength > LIMIT_TEXTBOX_TEXTLENGTH) this.richTextBox_Log.Clear(); } #endregion public void OpenPort() { string str, message; if (!this.serialPort[this.currentPort].IsOpened) { SettingsApplyFromControls(); str = this.serialPort[this.currentPort].Open(eMode.Normal, DataParsNormal); // str = this.serialPort[this.currentPort].Open(eMode.Modbus, DataParsModbus); // str = this.serialPort[this.currentPort].Open(eMode.Normal, DataParsWakeup); message = strMESSAGE_PORT + " " + this.serialPort[this.currentPort].GetName() + " " + strMESSAGE_OPEN+" / "; SerialPortControlsEnable(false, false); this.button_SerialPort_OpenClose.Text = strBUTTON_TEXT_CLOSE; this.Status = strMESSAGE_OPEN; } else { str = this.serialPort[this.currentPort].Close(); message = strMESSAGE_PORT + " " + this.serialPort[this.currentPort].GetName() + " " + strMESSAGE_CLOSE + " / "; SerialPortControlsEnable(true, true); this.button_SerialPort_OpenClose.Text = strBUTTON_TEXT_OPEN; this.Status = strMESSAGE_CLOSE; } if (String.IsNullOrEmpty(str)) this.richTextBox_Log.AppendText(message + "\n"); else { this.richTextBox_Log.AppendText(str + "\n"); this.Status = str; } } public string GetPotrProperties() { return serialPort[currentPort].SettingsToString(); } public string GetPortStatus() { return this.Status; } private void SerialPortControlsEnable(bool stateComboName, bool stateControls) { this.comboBox_SerialPort_Name.Enabled = stateComboName; this.panel_Settings.Enabled = stateControls; } private void PortNameSort(ref string[] portName) { for (byte i = 0; i < portName.Length; i++) { for (byte j = 0; j < portName.Length - 1; j++) { if (Functions.StringCompare(portName[j], portName[j + 1]) > 0) { string tmp = portName[j]; portName[j] = portName[j + 1]; portName[j + 1] = tmp; } } } } public void SerialPortScan() { string lastPortName = ""; if (this.serialPort.Length > 0) lastPortName = this.serialPort[currentPort].GetName(); try { Array.Resize(ref serialPort, 0); Array.Resize(ref serialPortNames, 0); serialPortNames = SerialPort.GetPortNames(); } catch (Exception ex) { this.richTextBox_Log.AppendText(ex.Message + "\n"); } this.comboBox_SerialPort_Name.Items.Clear(); if (serialPortNames.Length > 0) {// There are some ports PortNameSort(ref serialPortNames); this.comboBox_SerialPort_Name.Items.AddRange(serialPortNames); // Enable port controls SerialPortControlsEnable(true, true); this.button_SerialPort_OpenClose.Enabled = true; // Init all ports with its settings Array.Resize(ref this.serialPort, serialPortNames.Length); InitPortApplySettingsAll(); // Select last port if it is exist if (!String.IsNullOrEmpty(lastPortName)) { if (serialPortNames.Contains(lastPortName)) { this.comboBox_SerialPort_Name.SelectedItem = lastPortName; currentPort = this.comboBox_SerialPort_Name.SelectedIndex; } else this.comboBox_SerialPort_Name.SelectedIndex = 0; } else { this.comboBox_SerialPort_Name.SelectedIndex = 0; currentPort = 0; } } else {// No ports exist this.comboBox_SerialPort_Name.Items.Add(SETTING_NO_PORT); this.comboBox_SerialPort_Name.SelectedItem = SETTING_NO_PORT; // Disable port controls SerialPortControlsEnable(true, false); this.button_SerialPort_OpenClose.Enabled = false; } } private const int PORT_SETTINGS_NUM = 5; /* Meaning number of settings for one port */ private string[] DefaultSettings = { "COM1", // Current port "1", // Number of ports "COM1", // Port name "38400", // Baudrate "8", // Databits "None", // Parity "One" // Stopbits }; public void SettingsLoad(XmlNode node) { XmlDocument xmlDoc = new XmlDocument(); XmlNode settingRoot = xmlDoc.ImportNode(node, true); XmlNode attr; // Validate Settings attr = settingRoot.Attributes.GetNamedItem(XML_TAG.NAME); if (attr == null) return; if (!String.Equals(attr.Value, XML_TAG.STRUCT_PORT_SETTINGS_NAME)) return; string[] strSettings = DefaultSettings; int portIdx = 0; int portNum = 0; // Extract settings from XML foreach (XmlNode childNode in settingRoot.ChildNodes) { if (String.Equals(childNode.Name, XML_TAG.PARAM_PORT_CURRENT_PORT)) strSettings[0] = childNode.InnerText; if (String.Equals(childNode.Name, XML_TAG.PARAM_PORT_NUM)) { strSettings[1] = childNode.InnerText; portNum = Convert.ToInt32(strSettings[1]); Array.Resize(ref strSettings, strSettings.Length + PORT_SETTINGS_NUM * portNum); for (int i = 2; i < strSettings.Length; i++) strSettings[i] = DefaultSettings[(i - 2) % PORT_SETTINGS_NUM + 2]; } if (String.Equals(childNode.Name, XML_TAG.PARAM_PORT_CONFIG)) { int idx = portIdx * PORT_SETTINGS_NUM + 2; if (idx >= strSettings.Length) throw new Exception("Port number parameter is too less"); strSettings[idx + 0] = childNode.InnerText; // Port name if (childNode.Attributes.Count > 0) { attr = childNode.Attributes.GetNamedItem(XML_TAG.ATTR_PORT_BAUD); if (attr != null) strSettings[idx + 1] = attr.Value; // Baud attr = childNode.Attributes.GetNamedItem(XML_TAG.ATTR_PORT_DATABITS); if (attr != null) strSettings[idx + 2] = attr.Value; // Databits attr = childNode.Attributes.GetNamedItem(XML_TAG.ATTR_PORT_PARITY); if (attr != null) strSettings[idx + 3] = attr.Value; // Parity attr = childNode.Attributes.GetNamedItem(XML_TAG.ATTR_PORT_STOPBITS); if (attr != null) strSettings[idx + 4] = attr.Value; // Stopbits } portIdx++; } } // Apply configs int strIdx = 0; string currentPortName = strSettings[strIdx++]; Array.Resize(ref this.settingsPortAll, portNum); strIdx++; for (int i = 0; i < portNum; i++) { this.settingsPortAll[i] = new CSerialPort.SSettings(); this.settingsPortAll[i].name = strSettings[strIdx++]; this.settingsPortAll[i].baudRate = Convert.ToInt32(strSettings[strIdx++]); this.settingsPortAll[i].dataBits = Convert.ToInt32(strSettings[strIdx++]); string word = strSettings[strIdx++]; Parity parity = Parity.None; ; if (String.Compare(word, "None") == 0) parity = Parity.None; else if (String.Compare(word, "Even") == 0) parity = Parity.Even; else if (String.Compare(word, "Odd") == 0) parity = Parity.Odd; else if (String.Compare(word, "Mark") == 0) parity = Parity.Mark; else if (String.Compare(word, "Space") == 0) parity = Parity.Space; this.settingsPortAll[i].parity = parity; word = strSettings[strIdx++]; StopBits stopBits = StopBits.One; if (String.Compare(word, "None") == 0) stopBits = StopBits.None; else if (String.Compare(word, "One") == 0) stopBits = StopBits.One; else if (String.Compare(word, "Two") == 0) stopBits = StopBits.Two; else if (String.Compare(word, "OnePointFive") == 0) stopBits = StopBits.OnePointFive; this.settingsPortAll[i].stopBits = stopBits; } InitPortApplySettingsAll(); SettingsShowOnControls(); if (this.comboBox_SerialPort_Name.Items.Contains(currentPortName)) this.comboBox_SerialPort_Name.SelectedItem = currentPortName; else this.comboBox_SerialPort_Name.SelectedIndex = 0; } public XmlNode SettingsToXML() { XmlDocument xmlDoc = new XmlDocument(); XmlNode setting; XmlElement param; XmlAttribute attr; XmlText text; // Setting structure name setting = xmlDoc.CreateElement(XML_TAG.SETTING); attr = xmlDoc.CreateAttribute(XML_TAG.NAME); text = xmlDoc.CreateTextNode(XML_TAG.STRUCT_PORT_SETTINGS_NAME); attr.AppendChild(text); setting.Attributes.Append(attr); // Param Current port param = xmlDoc.CreateElement(XML_TAG.PARAM_PORT_CURRENT_PORT); text = xmlDoc.CreateTextNode(this.comboBox_SerialPort_Name.SelectedItem.ToString()); param.AppendChild(text); setting.AppendChild(param); // Param number of ports int portNum = this.settingsPortAll.Length; param = xmlDoc.CreateElement(XML_TAG.PARAM_PORT_NUM); text = xmlDoc.CreateTextNode(portNum.ToString()); param.AppendChild(text); setting.AppendChild(param); for (int i = 0; i < portNum; i++) { CSerialPort.SSettings portSet = this.settingsPortAll[i]; // Create param portConfig param = xmlDoc.CreateElement(XML_TAG.PARAM_PORT_CONFIG); text = xmlDoc.CreateTextNode(portSet.name); param.AppendChild(text); // Add attribute Baudrate attr = xmlDoc.CreateAttribute(XML_TAG.ATTR_PORT_BAUD); text = xmlDoc.CreateTextNode(portSet.baudRate.ToString()); attr.AppendChild(text); param.Attributes.Append(attr); // Add attribute DataBits attr = xmlDoc.CreateAttribute(XML_TAG.ATTR_PORT_DATABITS); text = xmlDoc.CreateTextNode(portSet.dataBits.ToString()); attr.AppendChild(text); param.Attributes.Append(attr); // Add attribute Parity attr = xmlDoc.CreateAttribute(XML_TAG.ATTR_PORT_PARITY); text = xmlDoc.CreateTextNode(portSet.parity.ToString()); attr.AppendChild(text); param.Attributes.Append(attr); // Add attribute StopBits attr = xmlDoc.CreateAttribute(XML_TAG.ATTR_PORT_STOPBITS); text = xmlDoc.CreateTextNode(portSet.stopBits.ToString()); attr.AppendChild(text); param.Attributes.Append(attr); setting.AppendChild(param); } return setting; } private void InitPortApplySettingsAll() { bool portFound; if (this.settingsPortAll.Length == 0 && this.serialPort.Length > 0) { // Init settingsPortAll array with default values Array.Resize(ref this.settingsPortAll, this.serialPort.Length); for (int i = 0; i < this.serialPort.Length; i++) this.settingsPortAll[i] = settingsDefault; } for (int i = 0; i < this.serialPort.Length; i++) { if (this.serialPort[i] == null) { // Port is not init portFound = false; foreach (CSerialPort.SSettings portSetting in this.settingsPortAll) { if (string.Equals(portSetting.name, this.serialPortNames[i])) { portFound = true; this.serialPort[i] = new CSerialPort(portSetting); break; } } if (!portFound) { // Set default settings this.settingsDefault.name = serialPortNames[i]; this.serialPort[i] = new CSerialPort(settingsDefault); // Add new setting to settingsPortAll array int idx = this.settingsPortAll.Length; Array.Resize(ref this.settingsPortAll, idx + 1); this.settingsPortAll[idx] = settingsDefault; } } else { portFound = false; foreach (CSerialPort.SSettings portSetting in this.settingsPortAll) { if (string.Equals(portSetting.name, this.serialPort[i].GetName())) { portFound = true; this.serialPort[i].Set(portSetting); break; } } if (!portFound) { // Set default settings this.settingsDefault.name = serialPortNames[i]; this.serialPort[i].Set(this.settingsDefault); // Add new setting to settingsPortAll array int idx = this.settingsPortAll.Length; Array.Resize(ref this.settingsPortAll, idx + 1); this.settingsPortAll[idx] = settingsDefault; } } } } private void SettingsShowOnControls() { int portIdx = this.currentPort; if (serialPort.Length <= portIdx) return; if (serialPort[portIdx] == null) return; CSerialPort.SSettings setting = serialPort[portIdx].GetSettings(); try { this.comboBox_SerialPort_Baud.SelectedItem = setting.baudRate.ToString(); this.comboBox_SerialPort_DataBits.SelectedItem = setting.dataBits.ToString(); this.comboBox_SerialPort_Parity.SelectedItem = setting.parity.ToString(); this.comboBox_SerialPort_StopBit.SelectedItem = setting.stopBits.ToString(); } catch (Exception e) { this.richTextBox_Log.AppendText("Settings error! " + e.Message); } } private void SettingsApplyFromControls() { int portIdx = this.currentPort; if (serialPort.Length <= portIdx) return; if (serialPort[portIdx] == null) return; CSerialPort.SSettings setting = new CSerialPort.SSettings(); setting.name = this.serialPort[portIdx].GetName(); setting.baudRate = Convert.ToInt32(this.comboBox_SerialPort_Baud.SelectedItem); setting.dataBits = Convert.ToInt32(this.comboBox_SerialPort_DataBits.SelectedItem); string word = this.comboBox_SerialPort_Parity.SelectedItem.ToString(); if (String.Compare(word, "None") == 0) setting.parity = Parity.None; else if (String.Compare(word, "Even") == 0) setting.parity = Parity.Even; else if (String.Compare(word, "Odd") == 0) setting.parity = Parity.Odd; else if (String.Compare(word, "Mark") == 0) setting.parity = Parity.Mark; else if (String.Compare(word, "Space") == 0) setting.parity = Parity.Space; word = this.comboBox_SerialPort_StopBit.SelectedItem.ToString(); if (String.Compare(word, "None") == 0) setting.stopBits = StopBits.None; else if (String.Compare(word, "One") == 0) setting.stopBits = StopBits.One; else if (String.Compare(word, "Two") == 0) setting.stopBits = StopBits.Two; else if (String.Compare(word, "OnePointFive") == 0) setting.stopBits = StopBits.OnePointFive; // Apply settings for port and for settings array this.serialPort[portIdx].Set(setting); for (int i = 0; i < settingsPortAll.Length; i++) if (string.Equals(settingsPortAll[i].name, setting.name)) settingsPortAll[i] = setting; } // Communication #region private void ThreadSafe_RichTextBox_AppendText(string text) { this.richTextBox_Log.BeginInvoke((MethodInvoker)(() => this.richTextBox_Log.AppendText(text))); this.richTextBox_Log.BeginInvoke((MethodInvoker)(() => this.richTextBox_Log.ScrollToCaret())); } public delegate void DSendResponse(byte[] buf); public event DSendResponse PacketReceivedModbus; public event DSendResponse PacketReceivedWakeup; public void SendNormal(byte[] buf) { this.serialPort[currentPort].Send(buf); } public void SendModbus(byte[] buf) { string str = "Modbus TxD: "; for (byte i = 0; i < buf.Length; i++) str += buf[i].ToString("X2") + " "; str += "\n"; ThreadSafe_RichTextBox_AppendText(str); this.serialPort[currentPort].Send(buf); } /* The methods could be accessed by other threads! Need thread-safety code */ private void DataParsNormal(byte[] buf) { /* Old method foreach (char ch in buf) { ThreadSafe_RichTextBox_AppendText(ch.ToString()); } */ string formatType = Form_Main.Instance.RXD_PacketType; string formattedMessage = Functions.FormatPacket(buf, formatType); ThreadSafe_RichTextBox_AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " Получено / " + formattedMessage + Environment.NewLine); RXD_Count_up?.Invoke(); } private void DataParsModbus(byte[] buf) { string str = "Modbus RxD: "; for (byte i = 0; i < buf.Length; i++) str += buf[i].ToString("X2") + " "; str += "\n"; ThreadSafe_RichTextBox_AppendText(str); if (this.PacketReceivedModbus != null) this.PacketReceivedModbus(buf); } private void DataParsWakeup(byte[] buf) { } #endregion } public class CSerialPort { private const int TIMER_CHECK_PORT_INTERVAL = 10; /* mS */ public const string strPORT_OPEN = ""; public class CStatistics { public struct SCounters { public int bytesTotalRXD; public int bytesTotalTXD; public int packetsModbusDamaged; public int packetsModbusNoResponse; public int packetsModbusRXD; public int packetsModbusTXD; public int packetsWakeUpDamaged; public int packetsWakeUpNoResponse; public int packetsWakeUpRXD; public int packetsWakeUpTXD; } private SCounters counters; public CStatistics() { this.Clear(); } public void Clear() { counters.bytesTotalRXD = 0; counters.bytesTotalTXD = 0; counters.packetsModbusDamaged = 0; counters.packetsModbusNoResponse = 0; counters.packetsModbusRXD = 0; counters.packetsModbusTXD = 0; counters.packetsWakeUpDamaged = 0; counters.packetsWakeUpNoResponse = 0; counters.packetsWakeUpRXD = 0; counters.packetsWakeUpTXD = 0; } public void BytesReceived(int byteCounter) { this.counters.bytesTotalRXD += byteCounter; } public void BytesTransmitted(int byteCounter) { this.counters.bytesTotalTXD += byteCounter; } public void PacketModbusReceived(int packCounter) { this.counters.packetsModbusRXD += packCounter; } public void PacketModbusTransmitted(int packCounter) { this.counters.packetsModbusTXD += packCounter; } public void PacketModbusDamaged(int packCounter) { this.counters.packetsModbusDamaged += packCounter; } public void PacketModbusNoResponse(int packCounter) { this.counters.packetsModbusNoResponse += packCounter; } public void PacketWakeupReceived(int packCounter) { this.counters.packetsWakeUpRXD += packCounter; } public void PacketWakeupTransmitted(int packCounter) { this.counters.packetsWakeUpTXD += packCounter; } public void PacketWakeupDamaged(int packCounter) { this.counters.packetsWakeUpDamaged += packCounter; } public void PacketWakeupNoResponse(int packCounter) { this.counters.packetsWakeUpNoResponse += packCounter; } public SCounters GetInfo() { return counters; } } public struct SSettings { public string name; public int baudRate; public int dataBits; public Parity parity; public StopBits stopBits; }; public enum eMode { Normal = 0, Modbus, Wakeup } private SerialPort port; private bool isOpened; private eMode currentMode; public bool IsOpened { get { return isOpened; } } private System.Timers.Timer timerReadPort; public delegate void DDataPars(byte[] data); private DDataPars dataPars; // Constructor public CSerialPort(SSettings settings) { port = new SerialPort() { PortName = settings.name, BaudRate = settings.baudRate, DataBits = settings.dataBits, Parity = settings.parity, StopBits = settings.stopBits, }; this.timerReadPort = new System.Timers.Timer() { AutoReset = true, Enabled = false, Interval = TIMER_CHECK_PORT_INTERVAL }; this.timerReadPort.Elapsed += TimerReadPort_Elapsed; } private const byte MODBUS_ENDPACK_TIME = 2; /* Number of timer ticks that indicates "end packet" marker */ private byte[] modbusReceiveBuf = { }; private byte modBusEndPackCounter = 0; private void TimerReadPort_Elapsed(object sender, ElapsedEventArgs e) { byte[] buf = { }; int byteCount = Receive(ref buf); if (eMode.Modbus == this.currentMode) { if (byteCount != 0) { int idx = this.modbusReceiveBuf.Length; this.modBusEndPackCounter = 0; Array.Resize(ref modbusReceiveBuf, modbusReceiveBuf.Length + byteCount); Array.ConstrainedCopy(buf, 0, modbusReceiveBuf, idx, byteCount); } else this.modBusEndPackCounter++; if ((this.modBusEndPackCounter > MODBUS_ENDPACK_TIME) && (modbusReceiveBuf.Length > 0)) { this.dataPars(modbusReceiveBuf); Array.Resize(ref modbusReceiveBuf, 0); this.modBusEndPackCounter = 0; } } else if (byteCount > 0) this.dataPars(buf); } public string Open(eMode mode, DDataPars dataParsDeligate) { this.dataPars = dataParsDeligate; this.currentMode = mode; try { port.Open(); } catch (Exception e) { return e.Message; } this.isOpened = true; this.timerReadPort.Start(); return ""; } public string Close() { try { port.Close(); } catch (Exception e) { return e.Message; } this.isOpened = false; this.timerReadPort.Stop(); return ""; } public void Send(byte[] buf) { string toggle; Send(buf, out toggle); } public void Send(byte[] buf, out string errorMessage) { errorMessage = ""; try { this.port.Write(buf, 0, buf.Length); } catch (Exception e) { errorMessage = e.Message; } } private int Receive(ref byte[] buf) { string toggle; return Receive(ref buf, out toggle); } private int Receive(ref byte[] buf, out string errorMeassage) { errorMeassage = ""; int count = 0; if (!this.port.IsOpen) { this.timerReadPort.Stop(); return count; } count = this.port.BytesToRead; Array.Resize(ref buf, count); try { if (this.port.BytesToRead > 0) this.port.Read(buf, 0, this.port.BytesToRead); } catch (Exception e) { errorMeassage = e.Message; } return count; } public void Set(SSettings settings) { port.PortName = settings.name; port.BaudRate = settings.baudRate; port.DataBits = settings.dataBits; port.Parity = settings.parity; port.StopBits = settings.stopBits; } public SSettings GetSettings() { SSettings setting = new SSettings(); setting.name = this.port.PortName; setting.baudRate = this.port.BaudRate; setting.dataBits = this.port.DataBits; setting.parity = this.port.Parity; setting.stopBits = this.port.StopBits; return setting; } public string SettingsToString() { string str = ""; str += port.PortName; str += " | " + port.BaudRate.ToString(); str += " | " + port.Parity.ToString(); str += " | " + port.DataBits.ToString(); str += " | " + port.StopBits.ToString(); return str; } public string GetName() { return port.PortName; } } }