added multi-entry supportfor bool and uint16; poll once option now works

This commit is contained in:
nikzori
2024-12-23 16:30:35 +03:00
parent 70ade6c266
commit 86412fff02
5 changed files with 185 additions and 37 deletions

View File

@@ -25,6 +25,7 @@ namespace Gidrolock_Modbus_Scanner
Device device = App.device; Device device = App.device;
List<Entry> entries; List<Entry> entries;
int activeEntryIndex; // entry index for modbus responses int activeEntryIndex; // entry index for modbus responses
int activeDGVIndex; // index for DGV rows
SerialPort port = Modbus.port; SerialPort port = Modbus.port;
bool closed = false; bool closed = false;
@@ -57,12 +58,47 @@ namespace Gidrolock_Modbus_Scanner
DGV_Device.Columns[4].FillWeight = 20; DGV_Device.Columns[4].FillWeight = 20;
DGV_Device.Columns[4].ValueType = typeof(bool); DGV_Device.Columns[4].ValueType = typeof(bool);
int rowCount = 0;
foreach (Entry e in entries)
{
if (e.length > 1)
{
// multi-register entry check
if ((e.length == 2 && e.dataType == "uint32") || e.dataType == "string")
{
DGV_Device.Rows.Add(rowCount, e.name, "", e.address);
rowCount++;
}
else
{
for (int i = 0; i < e.length; i++)
{
if (i < e.labels.Count)
DGV_Device.Rows.Add(rowCount, e.name + ": " + e.labels[i], "", e.address + i);
else DGV_Device.Rows.Add(rowCount, e.address + i, "", e.address + i);
rowCount++;
}
}
}
else
{
DGV_Device.Rows.Add(rowCount, e.name, "", e.address);
rowCount++;
}
}
foreach (DataGridViewRow row in DGV_Device.Rows)
{
row.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
/*
for (int i = 0; i < entries.Count; i++) for (int i = 0; i < entries.Count; i++)
{ {
DGV_Device.Rows.Add(i.ToString(), entries[i].name, "", entries[i].address); DGV_Device.Rows.Add(i.ToString(), entries[i].name, "", entries[i].address);
DGV_Device.Rows[i].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; DGV_Device.Rows[i].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
} }
*/
foreach (DataGridViewColumn column in DGV_Device.Columns) foreach (DataGridViewColumn column in DGV_Device.Columns)
column.SortMode = DataGridViewColumnSortMode.NotSortable; // disabling sorting for now column.SortMode = DataGridViewColumnSortMode.NotSortable; // disabling sorting for now
@@ -80,34 +116,52 @@ namespace Gidrolock_Modbus_Scanner
while (!closed) while (!closed)
{ {
if (isPolling) if (isPolling)
{
for (int i = 0; i < entries.Count; i++)
{ {
// holy fuck DGV is awful // holy fuck DGV is awful
DataGridViewCheckBoxCell chbox = DGV_Device.Rows[i].Cells[4] as DataGridViewCheckBoxCell; DataGridViewCheckBoxCell chbox = DGV_Device.Rows[activeDGVIndex].Cells[4] as DataGridViewCheckBoxCell;
if (Convert.ToBoolean(chbox.Value)) if (Convert.ToBoolean(chbox.Value))
{ {
Console.WriteLine("Polling for " + device.entries[i].name); Console.WriteLine("Polling for " + device.entries[activeEntryIndex].name);
activeEntryIndex = i; await PollForEntry(entries[activeEntryIndex]);
await PollForEntry(entries[i]); await Task.Delay(150);
}
else //need to skip multiple dgv entries without accidentaly skipping entries
{
if (device.entries[activeEntryIndex].labels is null || device.entries[activeEntryIndex].labels.Count == 0)
activeDGVIndex++;
else
{
for (int i = 0; i < device.entries[activeEntryIndex].labels.Count; i++)
{
activeDGVIndex++;
} }
} }
} }
activeEntryIndex++;
if (activeEntryIndex >= device.entries.Count)
activeEntryIndex = 0;
if (activeDGVIndex >= DGV_Device.RowCount)
activeDGVIndex = 0;
Console.WriteLine("entry index: " + activeEntryIndex + "; dgv index: " + activeDGVIndex);
}
} }
} }
catch (Exception err) catch (Exception err)
{ {
MessageBox.Show(err.Message); MessageBox.Show(err.Message, "AutoPollAsync");
} }
} }
public async Task PollForEntry(Entry entry) public async Task PollForEntry(Entry entry)
{ {
byte[] message = new byte[9]; byte[] message = new byte[8];
var send = await Modbus.ReadRegAsync(port, slaveID, (FunctionCode)entry.registerType, entry.address, entry.length); var send = await Modbus.ReadRegAsync(port, slaveID, (FunctionCode)entry.registerType, entry.address, entry.length);
isAwaitingResponse = true; isAwaitingResponse = true;
Task delay = Task.Delay(timeout).ContinueWith((t) => Task delay = Task.WhenAny(Task.Delay(timeout), Task.Run( () => { while (isAwaitingResponse) { } return; })).ContinueWith((t) =>
{ {
if (isAwaitingResponse) if (isAwaitingResponse)
{ {
@@ -124,23 +178,94 @@ namespace Gidrolock_Modbus_Scanner
{ {
if (isAwaitingResponse) if (isAwaitingResponse)
{ {
isAwaitingResponse = false;
try try
{ {
if (entries[activeEntryIndex].readOnce)
{
DataGridViewCheckBoxCell chbox = DGV_Device.Rows[activeDGVIndex].Cells[4] as DataGridViewCheckBoxCell;
chbox.Value = false;
}
int dbc = e.Message[2]; // data byte count
switch (entries[activeEntryIndex].dataType) switch (entries[activeEntryIndex].dataType)
{ {
case ("bool"): case ("bool"):
if (entries[activeEntryIndex].labels is null || entries[activeEntryIndex].labels.Count == 0) // assume that no labels = 1 entry
{
if (entries[activeEntryIndex].valueParse is null || entries[activeEntryIndex].valueParse.Keys.Count == 0)
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = e.Data[0] > 0x00 ? "true" : "false"; DGV_Device.Rows[activeEntryIndex].Cells[2].Value = e.Data[0] > 0x00 ? "true" : "false";
else
{
try { DGV_Device.Rows[activeEntryIndex].Cells[2].Value = e.Data[0] > 0x00 ? entries[activeEntryIndex].valueParse["true"] : entries[activeEntryIndex].valueParse["false"]; }
catch
{
Console.WriteLine("Value parsing error for bool entry: " + entries[activeEntryIndex].name);
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = e.Data[0] > 0x00 ? "true" : "false";
}
}
activeDGVIndex++;
}
else
{
List<bool> values = new List<bool>();
for (int i = 0; i < dbc; i++)
{
for (int j = 0; j < 8; j++)
{
bool res = (((e.Data[i] >> j) & 0x01) >= 1) ? true : false;
values.Add(res);
}
}
for (int i = 0; i < entries[activeEntryIndex].labels.Count; i++)
{
DGV_Device.Rows[activeDGVIndex].Cells[2].Value = values[i];
activeDGVIndex++;
}
}
break; break;
case ("uint16"): case ("uint16"):
//Array.Reverse(e.Data); // BitConverter.ToUInt is is little endian, so we need to flip the array ushort value = BitConverter.ToUInt16(e.Data, 0);
ushort test = BitConverter.ToUInt16(e.Data, 0); if (entries[activeEntryIndex].labels is null || entries[activeEntryIndex].labels.Count == 0) // single value
Console.WriteLine("ushort parsed value: " + test); {
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = test; if (entries[activeEntryIndex].valueParse is null || entries[activeEntryIndex].valueParse.Keys.Count == 0)
{
//Array.Reverse(e.Data); // this was necessary, but something changed, idk
Console.WriteLine("ushort parsed value: " + value);
DGV_Device.Rows[activeDGVIndex].Cells[2].Value = value;
}
else
{
try
{
DGV_Device.Rows[activeDGVIndex].Cells[2].Value = entries[activeEntryIndex].valueParse[value.ToString()];
}
catch { DGV_Device.Rows[activeDGVIndex].Cells[2].Value = value; Console.WriteLine("Error parsing uint value at address: " + entries[activeEntryIndex].address); }
}
activeDGVIndex++;
}
else // value group
{
List<ushort> values = new List<ushort>();
for (int i = 0; i < dbc; i += 2)
{
ushort s = BitConverter.ToUInt16(e.Data, i);
values.Add(s);
}
for (int i = 0; i < entries[activeEntryIndex].labels.Count; i++)
{
DGV_Device.Rows[activeDGVIndex].Cells[2].Value = values[i];
activeDGVIndex++;
}
}
break; break;
case ("uint32"): case ("uint32"):
Array.Reverse(e.Data); Array.Reverse(e.Data);
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = BitConverter.ToUInt32(e.Data, 0); DGV_Device.Rows[activeDGVIndex].Cells[2].Value = BitConverter.ToUInt32(e.Data, 0);
activeDGVIndex++;
break; break;
case ("string"): case ("string"):
List<byte> bytes = new List<byte>(); List<byte> bytes = new List<byte>();
@@ -150,13 +275,18 @@ namespace Gidrolock_Modbus_Scanner
bytes.Add(e.Data[i]); bytes.Add(e.Data[i]);
} }
bytes.Reverse(); bytes.Reverse();
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = System.Text.Encoding.UTF8.GetString(bytes.ToArray()); DGV_Device.Rows[activeDGVIndex].Cells[2].Value = System.Text.Encoding.UTF8.GetString(bytes.ToArray());
activeDGVIndex++;
break; break;
default: default:
MessageBox.Show("Wrong data type set for entry " + entries[activeEntryIndex].name); MessageBox.Show("Wrong data type set for entry " + entries[activeEntryIndex].name);
activeDGVIndex++;
break; break;
} }
if (activeDGVIndex >= DGV_Device.RowCount)
activeDGVIndex = 0;
//MessageBox.Show("Получен ответ от устройства: " + dataCleaned, "Успех", MessageBoxButtons.OK); //MessageBox.Show("Получен ответ от устройства: " + dataCleaned, "Успех", MessageBoxButtons.OK);
port.DiscardInBuffer(); port.DiscardInBuffer();
@@ -164,6 +294,9 @@ namespace Gidrolock_Modbus_Scanner
catch { return; } catch { return; }
} }
if (activeDGVIndex >= DGV_Device.Rows.Count)
activeDGVIndex = 0;
isAwaitingResponse = false;
} }
private void Button_StartStop_Click(object sender, EventArgs e) private void Button_StartStop_Click(object sender, EventArgs e)

10
Json.cs
View File

@@ -14,6 +14,7 @@ namespace Gidrolock_Modbus_Scanner
public string description; public string description;
public List<Entry> entries; public List<Entry> entries;
public CheckEntry checkEntry; public CheckEntry checkEntry;
public Device(string name, string description, CheckEntry checkEntry, List<Entry> entries) public Device(string name, string description, CheckEntry checkEntry, List<Entry> entries)
{ {
this.name = name; this.name = name;
@@ -29,16 +30,23 @@ namespace Gidrolock_Modbus_Scanner
public ushort address; public ushort address;
public ushort length; public ushort length;
public string dataType; public string dataType;
public List<string> labels;
public Dictionary<string, string> valueParse;
public bool readOnce; public bool readOnce;
public bool isModbusID;
public Entry(string name, RegisterType registerType, ushort address, ushort length = 1, string dataType = "uint16", bool readOnce = false) public Entry(string name, RegisterType registerType, ushort address, ushort length = 1, string dataType = "uint16", List<string> labels = null, Dictionary<string, string> valueParse = null, bool readOnce = false, bool isModbusID = false)
{ {
this.name = name; this.name = name;
this.registerType = registerType; this.registerType = registerType;
this.address = address; this.address = address;
this.length = length; this.length = length;
this.dataType = dataType; this.dataType = dataType;
this.labels = labels;
this.valueParse = valueParse;
this.readOnce = readOnce; this.readOnce = readOnce;
this.isModbusID = isModbusID;
} }
} }
public struct CheckEntry public struct CheckEntry

20
Main.Designer.cs generated
View File

@@ -49,8 +49,8 @@
this.Button_LoadConfig = new System.Windows.Forms.Button(); this.Button_LoadConfig = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox();
this.Label_ConfPath = new System.Windows.Forms.Label(); this.Label_ConfPath = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.button1 = new System.Windows.Forms.Button();
this.GBox_Serial = new System.Windows.Forms.GroupBox(); this.GBox_Serial = new System.Windows.Forms.GroupBox();
this.panel11 = new System.Windows.Forms.Panel(); this.panel11 = new System.Windows.Forms.Panel();
this.CBox_Parity = new System.Windows.Forms.ComboBox(); this.CBox_Parity = new System.Windows.Forms.ComboBox();
@@ -105,12 +105,12 @@
// //
// TextBox_Log // TextBox_Log
// //
this.TextBox_Log.Location = new System.Drawing.Point(12, 192); this.TextBox_Log.Location = new System.Drawing.Point(12, 177);
this.TextBox_Log.Multiline = true; this.TextBox_Log.Multiline = true;
this.TextBox_Log.Name = "TextBox_Log"; this.TextBox_Log.Name = "TextBox_Log";
this.TextBox_Log.ReadOnly = true; this.TextBox_Log.ReadOnly = true;
this.TextBox_Log.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; this.TextBox_Log.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.TextBox_Log.Size = new System.Drawing.Size(498, 118); this.TextBox_Log.Size = new System.Drawing.Size(498, 133);
this.TextBox_Log.TabIndex = 1; this.TextBox_Log.TabIndex = 1;
// //
// groupBox2 // groupBox2
@@ -285,6 +285,13 @@
this.Label_ConfPath.Text = "Файл не выбран."; this.Label_ConfPath.Text = "Файл не выбран.";
this.Label_ConfPath.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; this.Label_ConfPath.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
// //
// progressBar1
//
this.progressBar1.Location = new System.Drawing.Point(172, 54);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(210, 25);
this.progressBar1.TabIndex = 14;
//
// button1 // button1
// //
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
@@ -297,13 +304,6 @@
this.button1.UseVisualStyleBackColor = true; this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.LoadFolder); this.button1.Click += new System.EventHandler(this.LoadFolder);
// //
// progressBar1
//
this.progressBar1.Location = new System.Drawing.Point(172, 54);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(210, 25);
this.progressBar1.TabIndex = 14;
//
// GBox_Serial // GBox_Serial
// //
this.GBox_Serial.Controls.Add(this.panel11); this.GBox_Serial.Controls.Add(this.panel11);

View File

@@ -124,7 +124,14 @@ namespace Gidrolock_Modbus_Scanner
ofd.InitialDirectory = Application.StartupPath + "\\Configs"; ofd.InitialDirectory = Application.StartupPath + "\\Configs";
path = defaultPath; path = defaultPath;
UpdatePathLabel(); UpdatePathLabel();
/* - Version Check - */
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fvi.FileVersion;
Console.WriteLine("Version: " + version);
} }
void UpdatePathLabel() void UpdatePathLabel()
{ {
Label_ConfPath.Text = path; Label_ConfPath.Text = path;
@@ -531,7 +538,7 @@ namespace Gidrolock_Modbus_Scanner
void AddLog(string message) void AddLog(string message)
{ {
dateTime = DateTime.Now; dateTime = DateTime.Now;
TextBox_Log.Invoke((MethodInvoker)delegate { TextBox_Log.AppendText(Environment.NewLine + "[" + dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second + "] " + message); }); TextBox_Log.Invoke((MethodInvoker)delegate { TextBox_Log.AppendText(Environment.NewLine + "[" + dateTime.Hour.ToString().PadLeft(2, '0') + ":" + dateTime.Minute.ToString().PadLeft(2, '0') + ":" + dateTime.Second.ToString().PadLeft(2, '0') + "] " + message); });
} }
private async void Button_SendCommand_Click(object sender, EventArgs e) private async void Button_SendCommand_Click(object sender, EventArgs e)

View File

@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Gidrolock Modbus Scanner")] [assembly: AssemblyTitle("Gidrolock Modbus Scanner")]
[assembly: AssemblyDescription("A collection of Modbus tools.")] [assembly: AssemblyDescription("A collection of Modbus tools.")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Gidroresurs LLC")] [assembly: AssemblyCompany("nikzori")]
[assembly: AssemblyProduct("Gidrolock Modbus Scanner")] [assembly: AssemblyProduct("Gidrolock Modbus Scanner")]
[assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
@@ -30,6 +30,6 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("0.0.0.8")] [assembly: AssemblyVersion("0.9.0.0")]
[assembly: AssemblyFileVersion("0.0.0.8")] [assembly: AssemblyFileVersion("0.9.0.0")]
[assembly: NeutralResourcesLanguage("en")] [assembly: NeutralResourcesLanguage("en")]