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.

297 lines
6.4 KiB

3 years ago
using EasyModbus;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
3 years ago
using System.Timers;
using ModbusSlave.Dialog;
3 years ago
namespace ModbusSlave
{
public partial class MainForm : Form
{
3 years ago
private readonly int DATA_COUNT = 20;
private ModbusServer server;
private System.Timers.Timer updateTimer;
private bool isFirstLog = true;
3 years ago
public MainForm()
{
InitializeComponent();
InitInstance();
}
private void btnRun_Click(object sender, EventArgs e)
{
try
{
server.Port = (int)nudPort.Value;
server.UnitIdentifier = Convert.ToByte(nudAddress.Value);
if (!CheckPortInUse(server.Port))
{
Log("[WARNING] unavailable port");
return;
}
server.Listen();
Log("--- Server start ---");
btnRun.Enabled = false;
nudAddress.Enabled = false;
nudPort.Enabled = false;
tbStatus.Text = "Run";
tbStatus.BackColor = Color.Lime;
3 years ago
updateTimer.Start();
3 years ago
}
catch (Exception ex)
{
Log("[ERROR] " + ex.Message);
}
}
private void btnStop_Click(object sender, EventArgs e)
{
try
{
server.StopListening();
Log("--- Server stop ---");
btnRun.Enabled = true;
nudAddress.Enabled = true;
nudPort.Enabled = true;
tbStatus.Text = "Stop";
tbStatus.BackColor = Color.Silver;
3 years ago
updateTimer.Stop();
3 years ago
}
catch (Exception ex)
{
Log("[ERROR] " + ex.Message);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
ClearLog();
}
3 years ago
private void Lv_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (btnRun.Enabled)
return;
3 years ago
3 years ago
ListView lv = sender as ListView;
if (lv.SelectedItems.Count < 1)
return;
3 years ago
3 years ago
int idx = lv.SelectedItems[0].Index;
short tmp = 0;
InputValueDialog dlg = new InputValueDialog();
dlg.Value = lv.SelectedItems[0].SubItems[1].Text;
dlg.StartPosition = FormStartPosition.CenterParent;
switch (lv.Name)
{
case "lv0x":
server.coils[idx + 1] = !server.coils[idx + 1];
break;
case "lv1x":
server.discreteInputs[idx + 1] = !server.discreteInputs[idx + 1];
break;
case "lv3x":
if (dlg.ShowDialog() != DialogResult.OK)
return;
if (!short.TryParse(dlg.Value, out tmp))
{
Log($"[ERROR] Value should be a number and in range of {short.MinValue} to {short.MaxValue}");
return;
}
server.inputRegisters[idx + 1] = tmp;
break;
case "lv4x":
if (dlg.ShowDialog() != DialogResult.OK)
return;
if (!short.TryParse(dlg.Value, out tmp))
{
Log($"[ERROR] Value should be a number and in range of {short.MinValue} to {short.MaxValue}");
return;
}
server.holdingRegisters[idx + 1] = tmp;
break;
}
}
3 years ago
3 years ago
private void InitInstance()
{
server = new ModbusServer();
updateTimer = new System.Timers.Timer();
updateTimer.Interval = 1000;
updateTimer.Elapsed += UpdateTimer_Elapsed;
3 years ago
3 years ago
lv0x.MouseDoubleClick += Lv_MouseDoubleClick;
lv1x.MouseDoubleClick += Lv_MouseDoubleClick;
lv3x.MouseDoubleClick += Lv_MouseDoubleClick;
lv4x.MouseDoubleClick += Lv_MouseDoubleClick;
3 years ago
3 years ago
InitListView();
}
3 years ago
3 years ago
private void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
3 years ago
{
3 years ago
UpdateListView(0);
UpdateListView(1);
UpdateListView(3);
UpdateListView(4);
3 years ago
}
private void Log(string text)
{
rtbLog.AppendText((isFirstLog ? "" : Environment.NewLine) + text);
isFirstLog = false;
ScrollToEnd();
}
private void ScrollToEnd()
{
if (!chkAutoScroll.Checked)
return;
rtbLog.SelectionStart = rtbLog.Text.Length;
rtbLog.ScrollToCaret();
}
private void ClearLog()
{
rtbLog.Clear();
isFirstLog = true;
ScrollToEnd();
}
private bool CheckPortInUse(int port)
{
bool isAvailable = true;
var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
var tcpListenerArray = ipGlobalProperties.GetActiveTcpListeners();
foreach (var ip in tcpListenerArray)
{
if (ip.Port == port)
{
isAvailable = false;
break;
}
}
return isAvailable;
}
3 years ago
private void InitListView()
{
for (int i = 0; i < 5; i++)
{
if (i == 2)
continue;
string controlName = $"lv{i}x";
Control[] foundControls = this.Controls.Find(controlName, true);
if (foundControls.Length < 1 || !(foundControls[0] is ListView))
continue;
ListView listView = foundControls[0] as ListView;
listView.GetType()
.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
.SetValue(listView, true, null);
listView.BeginUpdate();
listView.Items.Clear();
for (int j = 0; j < DATA_COUNT; j++)
{
ListViewItem item = new ListViewItem();
switch(i)
{
case 0: // 0x: 00001 ~ 00010
item.Text = string.Format("{0:D5}", j + 1);
break;
case 1: // 1x: 10001 ~ 10010
item.Text = (10000 + j + 1).ToString();
break;
case 3: // 3x: 30001 ~ 30010
item.Text = (30000 + j + 1).ToString();
break;
case 4: // 4x: 40001 ~ 40010
item.Text = (40000 + j + 1).ToString();
break;
}
item.SubItems.Add("0");
listView.Items.Add(item);
}
listView.Columns[0].Width = -2;
listView.Columns[1].Width = -2;
listView.EndUpdate();
}
}
private void UpdateListView(int regNum)
{
string controlName = $"lv{regNum}x";
Control[] foundControls = this.Controls.Find(controlName, true);
if (foundControls.Length < 1 || !(foundControls[0] is ListView))
return;
ListView listView = foundControls[0] as ListView;
if (listView.InvokeRequired)
{
listView.BeginInvoke(new MethodInvoker(delegate
{
UpdateListView(regNum);
}));
return;
}
listView.BeginUpdate();
for (int i = 0; i < DATA_COUNT; i++)
{
string value = "";
switch (regNum)
{
case 0:
value = server.coils[i + 1] ? "1" : "0";
break;
case 1:
value = server.discreteInputs[i + 1] ? "1" : "0";
break;
case 3:
value = server.inputRegisters[i + 1].ToString();
break;
case 4:
value = server.holdingRegisters[i + 1].ToString();
break;
}
listView.Items[i].SubItems[1].Text = value;
}
listView.EndUpdate();
}
3 years ago
}
}