I'm trying to show Myo datas on a chart using c#. I receive the data from Myo and sends it to chart but it won't show anything. Examples on the net hasn't helped me! this is the code (I think i have thread but don't know much, producer class receives the raw emg data from myo and Form1 is supposed to show it):
using MyoSharp.Communication;
using MyoSharp.Device;
using MyoSharp.Exceptions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
namespace MyoThings
{
public partial class Form1 : Form
{
int i = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Producer producer = new Producer();
producer.StartConnection();
}
public void receiveData(int data)
{
Console.WriteLine(data);
chart1.Series[0].Points.Add(i++, data); // won't add anything -
chart1.Invalidate();
}
}
class Producer
{
Chart chart = new Chart();
public void StartConnection()
{
using (var channel = Channel.Create(ChannelDriver.Create(ChannelBridge.Create(),
MyoErrorHandlerDriver.Create(MyoErrorHandlerBridge.Create()))))
{
using (var hub = Hub.Create(channel))
{
hub.MyoConnected += (sender, e) =>
{
Console.WriteLine($"Myo Connected, handle: {e.Myo.Handle}");
e.Myo.Vibrate(VibrationType.Short);
e.Myo.EmgDataAcquired += Myo_EmgDataAcquired;
e.Myo.SetEmgStreaming(true);
};
channel.StartListening();
//int i = 0;
while (true)
{
}
}
}
}
private static void Myo_EmgDataAcquired(object sender, EmgDataEventArgs e)
{
//Console.WriteLine(e.EmgData.GetDataForSensor(1));
Producer producer = new Producer();
Form1 form = new Form1();
//sends data of myo to chart
form.receiveData(e.EmgData.GetDataForSensor(1));
}
}
}
I could answer it myself. I sent the chart to producer class and add points
using MyoSharp.Communication;
using MyoSharp.Device;
using MyoSharp.Exceptions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Windows.Forms.DataVisualization.Charting;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private Producer producer;
private bool sitSensorOne = true;
private bool sitSensorTwo = true;
private bool sitSensorThree = true;
private bool sitSensorFour = true;
private bool sitSensorFive = true;
private bool sitSensorSix = true;
private bool sitSensorSeven = true;
private bool sitSensorEighth = true;
public Form1()
{
InitializeComponent();
producer = new Producer(chart1);
producer.YSeriesEvent += MyHandler;
chart1.Series[0].Enabled = true;
Load += (sender, e) => producer.Start();
}
private void MyHandler(object sender, int data)
{
Invoke(new Action(() =>
{
}));
}
}
}
class Producer
{
public event EventHandler<int> YSeriesEvent;
private Thread thread;
public int Data;
private Chart chart;
public Producer(Chart chart)
{
this.chart = chart;
thread = new Thread(new ThreadStart(this.Work));
thread.IsBackground = true;
thread.Name = "My Worker";
}
public void Start()
{
thread.Start();
}
private void Work()
{
using (var channel = Channel.Create(ChannelDriver.Create(ChannelBridge.Create(),
MyoErrorHandlerDriver.Create(MyoErrorHandlerBridge.Create()))))
{
using (var hub = Hub.Create(channel))
{
hub.MyoConnected += (sender, e) =>
{
Console.WriteLine($"Myo connected, handle: {e.Myo.Handle}");
e.Myo.Vibrate(VibrationType.Short);
e.Myo.EmgDataAcquired += Myo_EmgDataAcquired;
e.Myo.SetEmgStreaming(true);
YSeriesEvent?.Invoke(this, Data);
};
channel.StartListening();
while (true) { }
}
}
}
private void Myo_EmgDataAcquired(object sender, EmgDataEventArgs e)
{
Data = e.EmgData.GetDataForSensor(3);
Console.WriteLine(Data);
chart.Invoke(new Action(() =>
{
for (int i = 0; i < 8; i++)
chart.Series[i].Points.AddY(e.EmgData.GetDataForSensor(i));
}
));
}
private void returnData()
{
chart.Series[0].Points.AddY(Data);
Console.WriteLine(Data);
}
}
}
Related
I want to download the specific file (the first item of the page) from a website, below is my code
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializeAsyc();
}
async void InitializeAsyc()
{
await webView21.EnsureCoreWebView2Async(null);
webView21.CoreWebView2.Navigate("https://www.moodys.com");
}
private async void button1_Click(object sender, EventArgs e)
{
var checkJs = "document.documentElement.innerText.indexOf('Sign In or Register')>-1";
string res = await webView21.CoreWebView2.ExecuteScriptAsync(checkJs);
//MessageBox.Show(res);
if (res == "true")
{
MessageBox.Show("Please login Moody's");
}
else
{
MessageBox.Show("Successful");
webView21.CoreWebView2.Navigate("https://www.moodys.com/search?keyword=Annual%20default%20study%20excel&searchfrom=GS");
webView21.NavigationCompleted += webView21_NavigationCompleted;
}
}
private void webView21_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
var checkfirst = "document.querySelector('.result-details > .result-detail:nth-child(1) a').getAttribute('href')";
var result = webView21.CoreWebView2.ExecuteScriptAsync(checkfirst);
webView21.CoreWebView2.Navigate("http://www.moodys.com/" + result);
}
}
}
But I found that webView21_NavigationCompleted part always run before complete loading the page, and always returns null then I fail to download.
Are there a method to load the js after the page complete loaded?
Thanks to all who try to help me in this problem.
Although the solution is not perfect enough, it can help me to deal with the problem. I use wait time for 10 seconds and start doing the next steps afterwards. And I also use the TAB key to download the necessary documents.
If there are any good solutions you find please tell me, thank you.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
namespace WinFormsApp2
{
public partial class Form1 : Form
{
private static readonly string indexUrl = "http://www.moodys.com";
public Form1()
{
InitializeComponent();
}
private async void Form1_Load(object sender, EventArgs e)
{
await InitializeAsync(webView21);
}
public async Task InitializeAsync(WebView2 webView21)
{
CoreWebView2Environment webView2Environment = null;
await webView21.EnsureCoreWebView2Async(webView2Environment);
}
private void webView21_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
webView21.CoreWebView2.Navigate(indexUrl);
}
private void webView21_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
string url = webView21.CoreWebView2.Source.ToString();
Console.WriteLine(url);
}
private void button1_Click(object sender, EventArgs e)
{
bool res = IsLogin();
if (res == true)
{
MessageBox.Show("Please login Moody's");
}
else
{
MessageBox.Show("Successful");
webView21.CoreWebView2.Navigate("https://www.moodys.com/search?keyword=Annual%20default%20study%20excel&searchfrom=GS");
int waittime = 10; //wait 10 seconds
int actualwaittime = waittime * 1000;
wait(actualwaittime);
SendKeys.SendWait("{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}");
SendKeys.SendWait("{ENTER}");
}
}
public void wait(int milliseconds)
{
var timer1 = new System.Windows.Forms.Timer();
if (milliseconds == 0 || milliseconds < 0) return;
// Console.WriteLine("start wait timer");
timer1.Interval = milliseconds;
timer1.Enabled = true;
timer1.Start();
timer1.Tick += (s, e) =>
{
timer1.Enabled = false;
timer1.Stop();
// Console.WriteLine("stop wait timer");
};
while (timer1.Enabled)
{
Application.DoEvents();
}
}
private bool IsLogin()
{
var js = #"document.documentElement.innerText.indexOf('Sign In or Register');";
int res = Convert.ToInt32(ExecuteScript(js));
return res >= 1;
}
private string ExecuteScript(string javaScript)
{
var taskAwaiter = webView21.CoreWebView2.ExecuteScriptAsync(javaScript).GetAwaiter();
WaitAsyncTask(5, taskAwaiter);
return taskAwaiter.GetResult();
}
public void WaitAsyncTask(int waitSecond, System.Runtime.CompilerServices.TaskAwaiter<string> activeTask)
{
DateTime WaitStartTime = DateTime.Now;
double secondDiffer = (DateTime.Now - WaitStartTime).TotalSeconds;
while (secondDiffer < waitSecond)
{
secondDiffer = (DateTime.Now - WaitStartTime).TotalSeconds;
Application.DoEvents();
if (activeTask.IsCompleted)
{
break;
}
}
}
}
}
I'm trying to make a windows form application in Visual Studio in C# and the purpose is to be able to communicate with an Arduino microcontroller. Right now I have 2 forms (Form1 and Form2) and I need to send and receive data from both windows to the microcontroller. I have defined a class SerialComms.cs in which there I start my serialPort and I have been able to send messages from both forms to the Arduino.
The problem is I don't know how to go about to receiving data from the Arduino as soon as the data is received. If I were to create the serialPort from one of the forms i would be able to create a function for DataReceived that will run anytime data is received but I don't know how to do that when I start my serialPort from a class. Any help?
Here is my code for both forms and my serialComms class:
Form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
namespace Test_Comms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
connectToArduino();
}
void connectToArduino()
{
try { SerialComms.SerialPort.Close(); }
catch { }
getAvailablePorts();
for (int i = 0; i < COMcomboBox.Items.Count; i++)
{
string inputMsg = "None";
string commport = COMcomboBox.GetItemText(COMcomboBox.Items[i]);
//Wait for Arduino message sent
//If not receieved go to next port
SerialComms.SerialPort.PortName = commport;
SerialComms.SerialPort.BaudRate = 9600;
SerialComms.SerialPort.Open();
try { SerialComms.SerialPort.Open(); }
catch { }
int counter1 = 0;
while (counter1 < 100)
{
inputMsg = SerialComms.SerialPort.ReadLine();
try { inputMsg = SerialComms.SerialPort.ReadLine(); }
catch { }
counter1++;
if (inputMsg == "Arduino")
{
counter1 = 1000;
}
}
if (inputMsg != "Arduino")
{
try { SerialComms.SerialPort.Close(); }
catch { }
}
else
{
i = COMcomboBox.Items.Count;
SerialComms.SerialPort.WriteLine("Connection Established");
toolStripStatusLabel1.Text = "Connected";
break;
}
}
}
void getAvailablePorts()
{
COMcomboBox.Items.Clear();
String[] ports = SerialPort.GetPortNames();
COMcomboBox.Items.AddRange(ports);
}
private void button1_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED ON");
}
private void button2_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED OFF");
}
private void button3_Click(object sender, EventArgs e) //Opens second form
{
Form2 settingsForm = new Form2();
settingsForm.ShowDialog();
}
}
}
Form2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
namespace Test_Comms
{
public partial class Form2 : Form
{
public static string text = "Test text";
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED ON");
}
private void button2_Click(object sender, EventArgs e)
{
SerialComms.SerialPort.WriteLine("LED OFF");
button2.Text = text;
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
}
SerialComms.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.IO;
namespace Test_Comms
{
public static class SerialComms
{
//public static delegate void DataReceivedEventHandler(object sender, ReceivedEventArgs e);
//public static event DataReceivedEventHandler DataReceived;
private static SerialPort _serialPort = new SerialPort();
public static SerialPort SerialPort
{
get { return _serialPort; }
set { _serialPort = value; }
}
}
}
I cannot get the ui thread to update the ui while the file copy thread is running. My end goal is to have the animation continue to rotate until the large file copy finally completes to let the user know that the program is not frozen. It's a very simple server to server file copy program.
Can someone tell me what I'm doing wrong?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void fileCopy()
{
File.Copy("large file source", "large file destination", true);
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private async void button1_Click(object sender, EventArgs e)
{
SetupProgress();
await Task.Run(() => fileCopy());
ResetProgress();
}
private void btnStop_Click(object sender, EventArgs e)
{
// unhandled currently
}
}
}
* Original version *
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Thread workItemsProducerThread;
private Thread workItemsCopyThread;
public Form1()
{
InitializeComponent();
}
private void ResetProgress()
{
lblStep1.Image = null;
}
private void SetupProgress()
{
this.BeginInvoke((MethodInvoker)delegate ()
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private void fileCopy()
{
File.Copy("Large file source", "Large file destination", true);
this.BeginInvoke((MethodInvoker)delegate ()
{
MessageBox.Show("Done");
});
}
private void Form1_Load(object sender, EventArgs e)
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
private void btnStart_Click(object sender, EventArgs e)
{
this.workItemsProducerThread = new Thread(new ThreadStart(this.SetupProgress));
this.workItemsProducerThread.IsBackground = true;
this.workItemsProducerThread.Start();
this.SetupProgress();
this.workItemsCopyThread = new Thread(new ThreadStart(this.fileCopy));
this.workItemsCopyThread.IsBackground = true;
this.workItemsCopyThread.Start();
while (workItemsCopyThread.IsAlive)
{
Thread.Sleep(1000); // wait
}
MessageBox.Show("Done");
}
private void btnStop_Click(object sender, EventArgs e)
{
if (this.workItemsProducerThread != null)
{
this.workItemsProducerThread.Abort();
lblStep1.Image = global::animation1.Properties.Resources.animation;
}
}
private void btnTest_Click(object sender, EventArgs e)
{
fileCopy();
}
}
}
Don’t sleep in your click handler. That freezes the UI thread. Just let the clock handler exit. In your file copy thread, when the copy is don’t. Use Invoke(or BeginInvoke) to cause the done messagebox to pop up on the UI thread.
Try this oldy style
private void SetupProgress()
{
Invoke((MethodInvoker) delegate
{
lblStep1.Image = global::animation1.Properties.Resources.animation;
});
}
private Thread TDoSomeWork()
{
var t = new Thread(() => DoSomeWork());
t.Start();
return t;
}
TDoSomeWork();
I would like to ask why is my communicator receiving sent frames. I'm trying to fix this problem using flag PacketDeviceOpenAttributes.NoCaptureLocal for receiving communicator but I'm still receiving sent frames. Could anyone know how to fix this problem? Thank you. Here is my code:
using PcapDotNet.Core;
using PcapDotNet.Packets;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PSIP
{
public partial class Form2 : Form
{
private Packet packet;
private List<Packet> buffer;
private IList<LivePacketDevice> allDevices;
private LivePacketDevice selectedDevice, sendDevice;
private int pkt_cnt;
private Thread thrReceive,thrSend;
public Form2(LivePacketDevice device)
{
InitializeComponent();
Show();
selectedDevice = device;
pkt_cnt = 0;
buffer = new List<Packet>();
allDevices = LivePacketDevice.AllLocalMachine;
for (int i = 0; i != allDevices.Count; ++i)
{
LivePacketDevice tempDevice = allDevices[i];
if (device.Description != null)
{
ListViewItem row = new ListViewItem(tempDevice.Name);
listDevices.Items.Add(row);
}
}
}
private void PacketHandler(object obj)
{
throw new NotImplementedException();
}
private void PacketHandler(Packet packet)
{
ListViewItem itemPacket = new ListViewItem(pkt_cnt.ToString());
itemPacket.SubItems.Add(packet.Ethernet.Destination.ToString());
itemPacket.SubItems.Add(packet.Ethernet.Source.ToString());
pktView.Items.Add(itemPacket);
buffer.Add(packet);
pkt_cnt++;
}
private void Sending()
{
for (int i = 0; i <= allDevices.Count; ++i)
{
sendDevice = allDevices[i];
if (sendDevice.Name.Equals(listDevices.SelectedItems[0].Text))
{
i = allDevices.Count;
}
}
using (PacketCommunicator communicator = sendDevice
.Open(100, PacketDeviceOpenAttributes.Promiscuous | PacketDeviceOpenAttributes.NoCaptureLocal, 1000))
{
int index = Int32.Parse(pktView.SelectedItems[0].Text);
Packet tmpPacket = buffer.ElementAt(index);
communicator.SendPacket(tmpPacket);
}
}
private void Receiving()
{
int c = int.Parse(packetcount.Text);
using (PacketCommunicator communicator = selectedDevice.Open(65536,
PacketDeviceOpenAttributes.NoCaptureRemote | PacketDeviceOpenAttributes.Promiscuous, 1000))
{
communicator.ReceivePackets(c, PacketHandler);
}
}
private void button1_Click(object sender, EventArgs e)
{
thrReceive = new Thread(Receiving);
thrReceive.Start();
}
private void buttonSend_Click(object sender, EventArgs e)
{
thrSend = new Thread(Sending);
thrSend.Start();
}
private void pktView_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
int index = Int32.Parse(pktView.SelectedItems[0].Text);
Packet tmpPacket = buffer.ElementAt(index);
textPacket.ResetText();
textPacket.AppendText(tmpPacket.Ethernet.ToHexadecimalString());
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
}
private void buttonClear_Click(object sender, EventArgs e)
{
pktView.Items.Clear();
buffer.Clear();
pkt_cnt = 0;
}
} }
You seem to be using different PacketCommunicators, one for sending and one for receiving.
The documentation for NoCaptureRemote states "Defines if the local adapter will capture its own generated traffic.".
Since you're using two different communicators, the receiving communicator captures the sending communicator.
I'm tying stop thread by nothing works.
I was trying on 100 ways.
What is wrong ?
It is irritating
(I have to write some text here because stackoverflow.com don't allow me to send this post)(I have to write some text here because stackoverflow.com don't allow me to send this post)(I have to write some text here because stackoverflow.com don't allow me to send this post)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
private static CancellationTokenSource cts = new CancellationTokenSource();
private CancellationToken ct = cts.Token;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
work_for_task(ct);
}, this.ct);
}
private void work_for_task(CancellationToken ct)
{
if (ct.IsCancellationRequested)
{
ct.ThrowIfCancellationRequested();
}
for (int i = 0; i < 5; i++)
{
if (richTextBox2.InvokeRequired)
{
richTextBox2.Invoke((MethodInvoker)delegate
{
richTextBox2.AppendText("I AM IN: " + Thread.CurrentThread.Name + "\n");
});
Thread.Sleep(1400);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("CANCELED");
cts.Cancel();
}
}
}
Just this instead of your work_for_task method:
private void work_for_task(CancellationToken ct)
{
for (int i = 0; i < 5; i++)
{
if (ct.IsCancellationRequested)
{
return;
}
if (richTextBox2.InvokeRequired)
{
richTextBox2.Invoke((MethodInvoker)delegate
{
richTextBox2.AppendText("I AM IN: " + Thread.CurrentThread.Name + "\n");
});
Thread.Sleep(1400);
}
}
}