Files
ModbusTool/CommonControls/BaseForm.cs
T
2020-07-27 09:20:24 -04:00

754 lines
24 KiB
C#

using System;
using System.Configuration;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
namespace Modbus.Common
{
public partial class BaseForm : Form
{
private DisplayFormat _displayFormat = DisplayFormat.Integer;
private CommunicationMode _communicationMode = CommunicationMode.TCP;
protected Socket _socket;
protected readonly ushort[] _registerData;
private bool _logPaused = false;
#region Form
public BaseForm()
{
InitializeComponent();
_registerData = new ushort[65600];
}
private void BaseFormLoading(object sender, EventArgs e)
{
comboBoxBaudRate.SelectedIndex = 4;
FillRTUDropDownLists();
CurrentTab.RegisterData = _registerData;
if (_registerData == null)
{
throw new ApplicationException("Failed to allocate 128k block");
}
LoadUserData();
CurrentTab.DisplayFormat = DisplayFormat;
RefreshData();
}
private void BaseFormClosing(object sender, FormClosingEventArgs e)
{
SaveUserData();
}
private void FillRTUDropDownLists()
{
comboBoxSerialPorts.Items.Clear();
foreach (var port in SerialPort.GetPortNames())
{
comboBoxSerialPorts.Items.Add(port);
}
if (comboBoxSerialPorts.Items.Count > 0)
comboBoxSerialPorts.SelectedIndex = 0;
comboBoxParity.Items.Clear();
comboBoxParity.Items.Add(Parity.None.ToString());
comboBoxParity.Items.Add(Parity.Odd.ToString());
comboBoxParity.Items.Add(Parity.Even.ToString());
comboBoxParity.Items.Add(Parity.Mark.ToString());
comboBoxParity.Items.Add(Parity.Space.ToString());
}
private void LoadUserData()
{
CommunicationMode mode;
if (Enum.TryParse(Properties.Settings.Default.CommunicationMode, out mode))
CommunicationMode = mode;
DisplayFormat format;
if (Enum.TryParse(Properties.Settings.Default.DisplayFormat, out format))
DisplayFormat = format;
IPAddress ipAddress;
if (IPAddress.TryParse(Properties.Settings.Default.IPAddress, out ipAddress))
IPAddress = ipAddress;
TCPPort = Properties.Settings.Default.TCPPort;
PortName = Properties.Settings.Default.PortName;
Baud = Properties.Settings.Default.Baud;
Parity = Properties.Settings.Default.Parity;
StartAddress = Properties.Settings.Default.StartAddress;
DataLength = Properties.Settings.Default.DataLength;
SlaveId = Properties.Settings.Default.SlaveId;
SlaveDelay = Properties.Settings.Default.SlaveDelay;
DataBits = Properties.Settings.Default.DataBits;
StopBits = Properties.Settings.Default.StopBits;
}
private void SaveUserData()
{
Properties.Settings.Default.CommunicationMode = CommunicationMode.ToString();
Properties.Settings.Default.IPAddress = IPAddress.ToString();
Properties.Settings.Default.DisplayFormat = DisplayFormat.ToString();
Properties.Settings.Default.TCPPort = TCPPort;
Properties.Settings.Default.PortName = PortName;
Properties.Settings.Default.Baud = Baud;
Properties.Settings.Default.Parity = Parity;
Properties.Settings.Default.StartAddress = StartAddress;
Properties.Settings.Default.DataLength = DataLength;
Properties.Settings.Default.SlaveId = SlaveId;
Properties.Settings.Default.SlaveDelay = SlaveDelay;
Properties.Settings.Default.DataBits = DataBits;
Properties.Settings.Default.StopBits = StopBits;
Properties.Settings.Default.Save();
}
#endregion
#region Import - Export
private void ButtonImportClick(object sender, EventArgs e)
{
openFileDialog.AddExtension = true;
openFileDialog.DefaultExt = ".csv";
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
using (var s = new FileStream(openFileDialog.FileName, FileMode.Open, FileAccess.Read))
{
using (var r = new StreamReader(s))
{
var rec = r.ReadToEnd();
var sets = rec.Split(',');
var first = true;
foreach (var s1 in sets)
{
DisplayFormat fmt;
var v = s1.Split(':');
var address = int.Parse(v[0]);
ushort data;
if (v[1].StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
{
fmt = DisplayFormat.Hex;
var sub = v[1].Substring(2);
ushort.TryParse(sub, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out data);
}
else if (v[1].Length > 6) //must be binary
{
fmt = DisplayFormat.Binary;
data = Convert.ToUInt16(v[1], 2);
}
else
{
fmt = DisplayFormat.Integer;
data = Convert.ToUInt16(v[1], 10);
}
if (address < _registerData.Length)
{
_registerData[address] = data;
}
if (first)
{
SetFunction(fmt);
first = false;
StartAddress = UInt16.Parse(v[0]);
}
}
r.Close();
DataLength = Convert.ToUInt16(sets.Length);
// display data
}
s.Close();
}
RefreshData();
}
}
public delegate void SetFunctionDelegate(DisplayFormat log);
protected void SetFunction(DisplayFormat fmt)
{
if (InvokeRequired)
{
BeginInvoke(new SetFunctionDelegate(SetFunction), new object[] { fmt });
return;
}
DisplayFormat = fmt;
switch (fmt)
{
case DisplayFormat.Integer:
radioButtonInteger.Checked = true;
break;
case DisplayFormat.Binary:
radioButtonBinary.Checked = true;
break;
case DisplayFormat.Hex:
radioButtonHex.Checked = true;
break;
case DisplayFormat.LED:
radioButtonLED.Checked = true;
break;
case DisplayFormat.FloatReverse:
radioButtonReverseFloat.Checked = true;
break;
}
}
private void ButtonExportClick(object sender, EventArgs e)
{
var startAddress = StartAddress;
var length = DataLength;
string suffix = "-";
switch (DisplayFormat)
{
case DisplayFormat.Integer:
suffix = "_Decimal_";
break;
case DisplayFormat.Hex:
suffix = "_HEX_";
break;
case DisplayFormat.Binary:
suffix = "_Binary_";
break;
case DisplayFormat.LED:
suffix = "_LED_";
break;
}
var filename = "ModbusExport_" + startAddress + suffix + DateTime.Now.ToString("yyyyMMddHHmm") + ".csv";
saveFileDialog.AddExtension = true;
saveFileDialog.DefaultExt = ".csv";
saveFileDialog.FileName = filename;
saveFileDialog.OverwritePrompt = true;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
using (var s = saveFileDialog.OpenFile())
{
using (var w = new StreamWriter(s))
{
for (var x = 0; x < length; x++)
{
w.Write(startAddress++);
w.Write(':');
var data = _registerData[StartAddress + x];
switch (DisplayFormat)
{
case DisplayFormat.Integer:
w.Write(string.Format("{0}", data));
break;
case DisplayFormat.Hex:
w.Write(string.Format("0x{0:x4}", data));
break;
case DisplayFormat.Binary:
case DisplayFormat.LED:
w.Write(Convert.ToString(data, 2).PadLeft(16, '0'));
break;
}
if (x < length - 1)
w.Write(',');
}
w.Flush();
w.Close();
}
s.Close();
}
}
}
#endregion
#region Radion button check handlers
private void RadioButtonModeChanged(object sender, EventArgs e)
{
SetMode();
}
protected void SetMode()
{
if (radioButtonTCP.Checked)
{
_communicationMode = CommunicationMode.TCP;
groupBoxTCP.Enabled = true;
groupBoxRTU.Enabled = false;
}
if (radioButtonRTU.Checked)
{
_communicationMode = CommunicationMode.RTU;
groupBoxTCP.Enabled = false;
groupBoxRTU.Enabled = true;
}
if (radioButtonUDP.Checked)
{
_communicationMode = CommunicationMode.UDP;
groupBoxTCP.Enabled = true;
groupBoxRTU.Enabled = false;
}
}
private void RadioButtonDisplayFormatCheckedChanged(object sender, EventArgs e)
{
if (sender is RadioButton)
{
var rb = (RadioButton)sender;
if (rb.Checked)
{
DisplayFormat.TryParse(rb.Tag.ToString(), true, out _displayFormat);
CurrentTab.DisplayFormat = DisplayFormat;
RefreshData();
}
}
}
#endregion
#region properties
private ushort _startAddress;
protected ushort StartAddress
{
get
{
return _startAddress;
}
set
{
CurrentTab.StartAddress = value;
var tab = tabControl1.SelectedTab;
tab.Text = value.ToString();
_startAddress = value;
}
}
private ushort _dataLength;
private bool showDataLength;
protected ushort DataLength
{
get
{
return _dataLength;
}
set
{
_dataLength = value;
CurrentTab.DataLength = value;
}
}
public bool ShowDataLength
{
get => showDataLength;
set
{
showDataLength = value;
foreach (DataTab tab in tabPage1.Controls)
{
tab.ShowDataLength = value;
}
foreach (DataTab tab in tabPage2.Controls)
{
tab.ShowDataLength = value;
}
}
}
protected IPAddress IPAddress
{
get
{
return IPAddress.Parse(txtIP.Text);
}
set
{
txtIP.Text = value.ToString();
}
}
protected int TCPPort
{
get
{
return Int32.Parse(textBoxPort.Text);
}
set
{
textBoxPort.Text = Convert.ToString(value);
}
}
protected byte SlaveId
{
get
{
return Byte.Parse(textBoxSlaveID.Text);
}
set
{
textBoxSlaveID.Text = Convert.ToString(value);
}
}
protected int SlaveDelay
{
get
{
return int.Parse(textBoxSlaveDelay.Text);
}
set
{
textBoxSlaveDelay.Text = Convert.ToString(value);
}
}
protected string PortName
{
get
{
return comboBoxSerialPorts.Text;
}
set
{
comboBoxSerialPorts.Text = value;
}
}
protected int Baud
{
get
{
return Int32.Parse(comboBoxBaudRate.Text);
}
set
{
comboBoxBaudRate.SelectedItem = Convert.ToString(value);
}
}
protected Parity Parity
{
get
{
var parity = Parity.None;
if (comboBoxParity.SelectedItem.Equals(Parity.None.ToString()))
{
parity = Parity.None;
}
else if (comboBoxParity.SelectedItem.Equals(Parity.Odd.ToString()))
{
parity = Parity.Odd;
}
else if (comboBoxParity.SelectedItem.Equals(Parity.Even.ToString()))
{
parity = Parity.Even;
}
else if (comboBoxParity.SelectedItem.Equals(Parity.Mark.ToString()))
{
parity = Parity.Mark;
}
else if (comboBoxParity.SelectedItem.Equals(Parity.Space.ToString()))
{
parity = Parity.Space;
}
return parity;
}
set
{
comboBoxParity.SelectedItem = Convert.ToString(value);
}
}
protected int DataBits
{
get
{
int bits = 0;
switch (comboBoxDataBits.SelectedIndex)
{
case 0:
bits = 7;
break;
case 1:
bits = 8;
break;
}
return bits;
}
set
{
switch (value)
{
case 7:
comboBoxDataBits.SelectedIndex = 0;
break;
case 8:
comboBoxDataBits.SelectedIndex = 1;
break;
}
}
}
protected StopBits StopBits
{
get
{
StopBits bits = StopBits.None;
switch (comboBoxStopBits.SelectedIndex)
{
case 0:
bits = StopBits.None;
break;
case 1:
bits = StopBits.One;
break;
case 2:
bits = StopBits.OnePointFive;
break;
case 3:
bits = StopBits.Two;
break;
}
return bits;
}
set
{
switch (value)
{
case StopBits.None:
comboBoxStopBits.SelectedIndex = 0;
break;
case StopBits.One:
comboBoxStopBits.SelectedIndex = 1;
break;
case StopBits.OnePointFive:
comboBoxStopBits.SelectedIndex = 2;
break;
case StopBits.Two:
comboBoxStopBits.SelectedIndex = 3;
break;
}
}
}
protected DisplayFormat DisplayFormat
{
get { return _displayFormat; }
set
{
switch (value)
{
case DisplayFormat.LED:
radioButtonLED.Checked = true;
break;
case DisplayFormat.Binary:
radioButtonBinary.Checked = true;
break;
case DisplayFormat.Hex:
radioButtonHex.Checked = true;
break;
case DisplayFormat.Integer:
radioButtonInteger.Checked = true;
break;
case DisplayFormat.FloatReverse:
radioButtonReverseFloat.Checked = true;
break;
}
_displayFormat = value;
CurrentTab.DisplayFormat = DisplayFormat;
RefreshData();
}
}
protected CommunicationMode CommunicationMode
{
get { return _communicationMode; }
set
{
switch (value)
{
case CommunicationMode.TCP:
radioButtonTCP.Checked = true;
break;
case CommunicationMode.UDP:
radioButtonUDP.Checked = true;
break;
case CommunicationMode.RTU:
radioButtonRTU.Checked = true;
break;
}
_communicationMode = value;
}
}
#endregion
#region Logging
public delegate void AppendLogDelegate(String log);
protected void ButtonClearLogClick(object sender, EventArgs e)
{
listBoxCommLog.Items.Clear();
}
private void buttonPauseLog_Click(object sender, EventArgs e)
{
_logPaused = !_logPaused;
buttonPauseLog.Text = _logPaused ? "Resume" : "Pause";
}
protected void DriverIncommingData(byte[] data, int len)
{
if (_logPaused)
return;
var hex = new StringBuilder(len);
for(int i = 0; i < len; i++)
{
hex.AppendFormat("{0:x2} ", data[i]);
}
AppendLog(String.Format("RX: {0}", hex));
}
protected void DriverOutgoingData(byte[] data)
{
if (_logPaused)
return;
var hex = new StringBuilder(data.Length * 2);
foreach (byte b in data)
hex.AppendFormat("{0:x2} ", b);
AppendLog(String.Format("TX: {0}", hex));
}
protected void AppendLog(String log)
{
if (_logPaused)
return;
if (InvokeRequired)
{
BeginInvoke(new AppendLogDelegate(AppendLog), new object[] { log });
return;
}
var now = DateTime.Now;
var tmpStr = ">" + now.ToLongTimeString() + ": " + log;
listBoxCommLog.Items.Add(tmpStr);
listBoxCommLog.SelectedIndex = listBoxCommLog.Items.Count - 1;
listBoxCommLog.SelectedIndex = -1;
}
#endregion
#region Data Table
protected void ButtonDataClearClick(object sender, EventArgs e)
{
ClearRegisterData();
}
protected void ClearRegisterData()
{
for (int i = 0; i < _registerData.Length; i++)
{
_registerData[i] = 0;
}
RefreshData();
}
protected DataTab CurrentTab
{
get
{
var tab = tabControl1.SelectedTab;
return (DataTab)tab.Controls[0];
}
}
public void RefreshData()
{
if (InvokeRequired)
{
BeginInvoke(new Action(RefreshData));
return;
}
CurrentTab.RefreshData();
// Reset event handler
CurrentTab.OnApply -= dataTab_OnApply;
CurrentTab.OnApply += dataTab_OnApply;
}
public void UpdateDataTable()
{
if (InvokeRequired)
{
BeginInvoke(new Action(UpdateDataTable));
return;
}
CurrentTab.UpdateDataTable();
}
#endregion
private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
CurrentTab.RegisterData = _registerData;
CurrentTab.DisplayFormat = DisplayFormat;
var tab = tabControl1.SelectedTab;
if (tab.Text.Equals("...") && tabControl1.TabPages.Count < 20)
{
DataTab dataTab = new DataTab();
dataTab.DataLength = 256;
dataTab.DisplayFormat = DisplayFormat.Integer;
dataTab.Location = new Point(3, 3);
dataTab.Name = "dataTab" + (tabControl1.TabPages.Count + 1);
dataTab.RegisterData = _registerData;
dataTab.ShowDataLength = ShowDataLength;
dataTab.Size = new Size(839, 406);
dataTab.StartAddress = 0;
dataTab.TabIndex = 0;
dataTab.OnApply += dataTab_OnApply;
TabPage tabPage = new TabPage();
tabPage.Controls.Add(dataTab);
tabPage.Location = new Point(4, 22);
tabPage.Name = "tabPage" + (tabControl1.TabPages.Count + 1);
tabPage.Padding = new Padding(3);
tabPage.Size = new Size(851, 411);
tabPage.TabIndex = tabControl1.TabPages.Count;
tabPage.Text = "...";
tabPage.UseVisualStyleBackColor = true;
tabControl1.Controls.Add(tabPage);
}
var address = CurrentTab.StartAddress;
tab.Text = address.ToString();
_startAddress = address;
_dataLength = CurrentTab.DataLength;
}
void dataTab_OnApply(object sender, EventArgs e)
{
var tab = tabControl1.SelectedTab;
var address = CurrentTab.StartAddress;
tab.Text = address.ToString();
_startAddress = address;
_dataLength = CurrentTab.DataLength;
}
private void donate_Click(object sender, EventArgs e)
{
string url = "";
string business = "graham.a.ross@gmail.com";
string description = "Support%20ModbusTool%20development";
string currency = "USD";
url += "https://www.paypal.com/cgi-bin/webscr" +
"?cmd=" + "_donations" +
"&business=" + business +
"&item_name=" + description +
"&currency_code=" + currency +
"&source=url";
System.Diagnostics.Process.Start(url);
}
}
}