autopolling works now
This commit is contained in:
139
Datasheet.cs
139
Datasheet.cs
@@ -5,6 +5,7 @@ using System.Data;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO.Ports;
|
using System.IO.Ports;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Runtime.Remoting.Messaging;
|
using System.Runtime.Remoting.Messaging;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -14,14 +15,22 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
{
|
{
|
||||||
public partial class Datasheet : Form
|
public partial class Datasheet : Form
|
||||||
{
|
{
|
||||||
|
bool isAwaitingResponse = false;
|
||||||
|
bool isProcessingResponse = false;
|
||||||
|
byte[] message = new byte[255];
|
||||||
|
|
||||||
int timeout = 3000;
|
int timeout = 3000;
|
||||||
int pollDelay = 250; // delay between each entry poll, ms
|
int pollDelay = 250; // delay between each entry poll, ms
|
||||||
byte slaveID;
|
byte slaveID;
|
||||||
Device device = App.device;
|
Device device = App.device;
|
||||||
List<Entry> entries;
|
List<Entry> entries;
|
||||||
|
int activeEntryIndex; // entry index for modbus responses
|
||||||
SerialPort port = App.port;
|
SerialPort port = App.port;
|
||||||
|
|
||||||
|
bool closed = false;
|
||||||
public Datasheet(byte slaveID)
|
public Datasheet(byte slaveID)
|
||||||
{
|
{
|
||||||
|
App.port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(PublishResponse);
|
||||||
this.slaveID = slaveID;
|
this.slaveID = slaveID;
|
||||||
entries = device.entries;
|
entries = device.entries;
|
||||||
|
|
||||||
@@ -44,56 +53,122 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
DGV_Device.Columns[4].Name = "Опрос";
|
DGV_Device.Columns[4].Name = "Опрос";
|
||||||
DGV_Device.Columns[4].FillWeight = 20;
|
DGV_Device.Columns[4].FillWeight = 20;
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
Task.Delay(1000).ContinueWith(_ => AutoPollAsync());
|
FormClosing += (s, e) => { closed = true; };
|
||||||
|
Task.Run(() => AutoPollAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> AutoPollAsync()
|
public async void AutoPollAsync()
|
||||||
{
|
{
|
||||||
port.Open();
|
if (!port.IsOpen)
|
||||||
while (true)
|
port.Open();
|
||||||
{
|
port.ReadTimeout = timeout;
|
||||||
for (int i = 0; i < entries.Count; i++)
|
|
||||||
{
|
|
||||||
if ((bool)DGV_Device.Rows[i].Cells[4].Value)
|
|
||||||
{
|
|
||||||
DGV_Device.Rows[i].Cells[2].Value = await PollForEntry(entries[i]);
|
|
||||||
await Task.Delay(pollDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> PollForEntry(Entry entry)
|
|
||||||
{
|
|
||||||
byte[] result = new byte[] { 0xFF };
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Modbus.ReadRegAsync(port, slaveID, (FunctionCode)entry.registerType, entry.address, entry.length);
|
while (!closed)
|
||||||
var task = Task.Delay(10).ContinueWith(_ =>
|
|
||||||
{
|
{
|
||||||
result = new byte[port.BytesToRead];
|
for (int i = 0; i < entries.Count; i++)
|
||||||
port.Read(result, 0, port.BytesToRead);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (await Task.WhenAny(Task.Delay(timeout + 10), task) == task)
|
|
||||||
{
|
|
||||||
if (result.Length > 5)
|
|
||||||
{
|
{
|
||||||
return Modbus.ByteArrayToString(result);
|
activeEntryIndex = i;
|
||||||
|
await PollForEntry(entries[i]);
|
||||||
}
|
}
|
||||||
else return "N/A";
|
|
||||||
}
|
}
|
||||||
else return "N/A";
|
|
||||||
}
|
}
|
||||||
catch (Exception err)
|
catch (Exception err)
|
||||||
{
|
{
|
||||||
MessageBox.Show(err.Message);
|
MessageBox.Show(err.Message);
|
||||||
return "N/A";
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PollForEntry(Entry entry)
|
||||||
|
{
|
||||||
|
byte[] message = new byte[7];
|
||||||
|
Console.WriteLine("Sending message: " + Modbus.ByteArrayToString(Modbus.BuildMessage(slaveID, (byte)entry.registerType, entry.address, entry.length, ref message)));
|
||||||
|
var send = await Modbus.ReadRegAsync(port, slaveID, (FunctionCode)entry.registerType, entry.address, entry.length);
|
||||||
|
isAwaitingResponse = true;
|
||||||
|
|
||||||
|
Task delay = Task.Delay(timeout).ContinueWith((t) =>
|
||||||
|
{
|
||||||
|
if (isAwaitingResponse)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Response timed out.");
|
||||||
|
isAwaitingResponse = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
await delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PublishResponse(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Received data on port.");
|
||||||
|
if (isAwaitingResponse)
|
||||||
|
{
|
||||||
|
isAwaitingResponse = false;
|
||||||
|
|
||||||
|
if (!isProcessingResponse)
|
||||||
|
{
|
||||||
|
isProcessingResponse = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
message = new byte[255];
|
||||||
|
port.Read(message, 0, 3);
|
||||||
|
int length = (int)message[2];
|
||||||
|
for (int i = 0; i < length + 2; i++)
|
||||||
|
{
|
||||||
|
port.Read(message, i + 3, 1);
|
||||||
|
}
|
||||||
|
byte[] data = new byte[length];
|
||||||
|
for (int i = 0; i < length - 2; i++)
|
||||||
|
{
|
||||||
|
data[i] = message[i+3];
|
||||||
|
}
|
||||||
|
Console.WriteLine("Received message: " + Modbus.ByteArrayToString(message));
|
||||||
|
Console.WriteLine("Data trimmed: " + Modbus.ByteArrayToString(data));
|
||||||
|
string dataCleaned = Modbus.ByteArrayToString(message);
|
||||||
|
|
||||||
|
switch (entries[activeEntryIndex].dataType)
|
||||||
|
{
|
||||||
|
case ("bool"):
|
||||||
|
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = data[0] > 0x00 ? "true" : "false";
|
||||||
|
break;
|
||||||
|
case ("uint16"):
|
||||||
|
Array.Reverse(data); // BitConverter.ToUInt is is little endian, I guess, so we need to flip the array
|
||||||
|
ushort test = BitConverter.ToUInt16(data, 0);
|
||||||
|
Console.WriteLine("ushort parsed value: " + test);
|
||||||
|
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = test;
|
||||||
|
break;
|
||||||
|
case ("uint32"):
|
||||||
|
Array.Reverse(data);
|
||||||
|
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = BitConverter.ToUInt32(data, 0);
|
||||||
|
break;
|
||||||
|
case ("utf8"):
|
||||||
|
DGV_Device.Rows[activeEntryIndex].Cells[2].Value = System.Text.Encoding.UTF8.GetString(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MessageBox.Show("Wrong data type set for entry " + entries[activeEntryIndex].name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//MessageBox.Show("Получен ответ от устройства: " + dataCleaned, "Успех", MessageBoxButtons.OK);
|
||||||
|
port.DiscardInBuffer();
|
||||||
|
isProcessingResponse = false;
|
||||||
|
}
|
||||||
|
catch (Exception err)
|
||||||
|
{
|
||||||
|
MessageBox.Show(err.Message, "Event Error");
|
||||||
|
isProcessingResponse = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
2
Json.cs
2
Json.cs
@@ -30,7 +30,7 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
public string dataType;
|
public string dataType;
|
||||||
public bool readOnce;
|
public bool readOnce;
|
||||||
|
|
||||||
public Entry(string name, RegisterType registerType, ushort address, ushort length, string dataType, bool readOnce)
|
public Entry(string name, RegisterType registerType, ushort address, ushort length = 1, string dataType = "uint16", bool readOnce = false)
|
||||||
{
|
{
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.registerType = registerType;
|
this.registerType = registerType;
|
||||||
|
|||||||
17
Main.cs
17
Main.cs
@@ -36,6 +36,7 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
public short[] res = new short[12];
|
public short[] res = new short[12];
|
||||||
public static SerialPort port = new SerialPort();
|
public static SerialPort port = new SerialPort();
|
||||||
public int expectedLength = 0;
|
public int expectedLength = 0;
|
||||||
|
Datasheet datasheet;
|
||||||
|
|
||||||
public static Device device;
|
public static Device device;
|
||||||
#region Initialization
|
#region Initialization
|
||||||
@@ -157,13 +158,9 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
AddLog("Message goes here;");
|
|
||||||
|
|
||||||
var send = await Modbus.ReadRegAsync(port, (byte)UpDown_ModbusID.Value, functionCode, address, length);
|
var send = await Modbus.ReadRegAsync(port, (byte)UpDown_ModbusID.Value, functionCode, address, length);
|
||||||
isAwaitingResponse = true;
|
isAwaitingResponse = true;
|
||||||
Task timer = Task.Delay(port.ReadTimeout);
|
await Task.Delay(port.ReadTimeout).ContinueWith(_ =>
|
||||||
await timer.ContinueWith(_ =>
|
|
||||||
{
|
{
|
||||||
if (isAwaitingResponse)
|
if (isAwaitingResponse)
|
||||||
{
|
{
|
||||||
@@ -233,7 +230,7 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
AddLog("Попытка подключиться к устройству " + device.name);
|
AddLog("Попытка подключиться к устройству " + device.name);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Datasheet datasheet = new Datasheet((byte)UpDown_ModbusID.Value);
|
datasheet = new Datasheet((byte)UpDown_ModbusID.Value);
|
||||||
datasheet.Show();
|
datasheet.Show();
|
||||||
}
|
}
|
||||||
catch (Exception err)
|
catch (Exception err)
|
||||||
@@ -283,6 +280,9 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
|
|
||||||
void PortDataReceived(object sender, EventArgs e)
|
void PortDataReceived(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
if (datasheet.Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
Console.WriteLine("Data receieved on Serial Port");
|
Console.WriteLine("Data receieved on Serial Port");
|
||||||
isAwaitingResponse = false;
|
isAwaitingResponse = false;
|
||||||
|
|
||||||
@@ -302,12 +302,11 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
{
|
{
|
||||||
data[i] = message[i + 3];
|
data[i] = message[i + 3];
|
||||||
}
|
}
|
||||||
Console.WriteLine("Data: " + Modbus.ByteArrayToString(data));
|
|
||||||
string dataCleaned = Modbus.ByteArrayToString(message);
|
|
||||||
|
|
||||||
|
string dataCleaned = Modbus.ByteArrayToString(message);
|
||||||
TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("Получен ответ: " + dataCleaned); });
|
TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("Получен ответ: " + dataCleaned); });
|
||||||
TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("ASCII: " + "wip"); });
|
TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("ASCII: " + "wip"); });
|
||||||
//MessageBox.Show("Получен ответ от устройства: " + dataCleaned, "Успех", MessageBoxButtons.OK);
|
|
||||||
port.DiscardInBuffer();
|
port.DiscardInBuffer();
|
||||||
isProcessingResponse = false;
|
isProcessingResponse = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Gidrolock_Modbus_Scanner
|
|||||||
message[message.Length - 2] = CRC[0];
|
message[message.Length - 2] = CRC[0];
|
||||||
message[message.Length - 1] = CRC[1];
|
message[message.Length - 1] = CRC[1];
|
||||||
string msg = ByteArrayToString(message);
|
string msg = ByteArrayToString(message);
|
||||||
Console.WriteLine("Message: " + msg);
|
//Console.WriteLine("Message: " + msg);
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: bool, uint16, uint32, utf8
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>: bool, uint16, uint32, utf8
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: uint16
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: uint16
|
||||||
"dataType": "utf8",
|
"dataType": "uint16",
|
||||||
|
|
||||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
// <20><><EFBFBD> `false` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>
|
// <20><><EFBFBD> `false` <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>
|
||||||
|
|||||||
Reference in New Issue
Block a user