c# with dotras - Status Box not updating automatically after dial connect/disconnect - c#

Greeting,
OS: Windows 7 /64bit
Application: Visual Studio 2012 / C# and DotRas 1.3 Library
I am very new to c# or VS thing so please bear with me. After doing many hours R&D, I have finaly made a pppoe dialer program in C# / Dotras. This program have 3 main buttons
Create /Add PPPoE Internet Dialer Connection in network connections , working fine
Dial button, which connects the newly created dialer , working Fine
Disconnect working fine
I have added StatuBox where dialup events should appear as showed on dotras youtube video tutorial (which was for vpn, but my project is for pppoe dialer)
StatusBox Not updating the dialup events like connecting/password error/connected etc. This is the part where I am finally confused.
Following is my Code.
// Dial Button Action
private void button2_Click_1(object sender, EventArgs e)
{
using (RasDialer dialer = new RasDialer())
{
// I had to add below line to update statusTextBox Manualy , want to get rid of it by adding auto status update
this.StatusTextBox.AppendText(string.Format("{0}\r\n\r\n", "Connection in progress ...", "{0}\r\n\r\n"));
dialer.EntryName = ("pppoe2");
string username = textBox1.Text;
string passwd = textBox2.Text;
// If username is empty dont connect
if (string.IsNullOrWhiteSpace(textBox1.Text))
{
this.StatusTextBox.AppendText(string.Format("{0}\r\n", "Cancelled. Cannot continue with username/password.", "{0}\r\n"));
MessageBox.Show("Enter username.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
dialer.Credentials = new System.Net.NetworkCredential(textBox1.Text, textBox2.Text);
dialer.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.User);
dialer.Timeout = 1000;
dialer.AllowUseStoredCredentials = true;
// start dialing,
dialer.Dial();
// If dialer connects successfully update StatuTextbox
this.StatusTextBox.AppendText(string.Format("{0}\r\n\r\n", "Connected."));
}
}
private void rasDialer1_StateChanged(object sender, StateChangedEventArgs e)
{
this.StatusTextBox.AppendText(string.Format("{0}\r\n", "Status Changed"));
}
private void rasDialer1_Error(object sender, System.IO.ErrorEventArgs e)
{
this.StatusTextBox.AppendText(string.Format("{0}\r\n", "STATUS UPDATE TEXT XYZ"));
}
private void rasDialer1_DialCompleted(object sender, DialCompletedEventArgs e)
{
this.StatusTextBox.AppendText(string.Format("{0}\r\n", "STATUS UPDATE TEXT XYZ"));
}
Any help would be highly appreciable.

Ok I have managed to enable status box text append work fine.
this.Invoke((MethodInvoker)delegate
{
this.StatusTextBox.AppendText(string.Format(e.State.ToString() + "\r\n"));
});
}

Depending on how you were using it, if the background thread from the OS isn’t marshaled back to the UI thread it won’t update. Similarly to what you had done, the SynchronizingObject property on the RasDialer can be set to your form and the thread synchronization will occur automatically.

Related

C# - Force windows around 20s delay to realize bluetooth not connected

I'm currently using the 32feet library for bluetooth in my application. I'm trying to check whether the device is still alive before it takes windows the 20s to change the status from "Connected" --> "Paired".
"True" --> "False"
I'm forcing a device refresh with:
holders.storedDevice.Refresh();
but it seems that the refresh isn't actually forcing windows to do anything. For reference storedDevice is of type
BluetoothDeviceInfo name {get; set;}
Timer code:
private void refreshDevice(object Sender, EventArgs e)
{
holders.StoredDevice.Refresh();
if(!holders.StoredDevice.Connected)
{
deviceRefreshTimer.Enabled = false;
updateTextBox( connectButton ,"Disconnecting...");
ExecuteSecure(() => connectButton.Enabled = false);
updateTextBox(statusTextBox, "Lost connection");
readBackgroundWorker.CancelAsync();
holders.localClient.Close();
storedStream = null;
}
}

COM port communication problems, Text To ASCII

I'm making a simple program, to send information from PC to COM port. So far I have established a connection between the PC and the COM port and I can send information and see what the port received, but I have two problems, the first one is that when I send the info to an actual com port (COM port to USB cable made to echo the signal) the first time I all of the information is received. Then it becomes random, sometimes again, all of what I have written, sometimes only the first character. And sometimes nothing. My assumption is this happens because I haven't put any time-outs or anything at all. Help with this would be nice.
But the real problem that I have is that I want all of the information sent from the textbox to be sent in ASCII code since I'm making the program for communication with PLC.
Here is the code:
public Form1()
{
InitializeComponent();
}
//BTN new serial port creation - port taken from comport text box
private void button1_Click(object sender, EventArgs e)
{
System.IO.Ports.SerialPort sport = new System.IO.Ports.SerialPort(comport.Text, 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);
//opening the com port and sending the information from textbox1
try
{
sport.Open();
sport.Write(textBox1.Text);
}
//if there is an error - show error message
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
//Adding timestamp to received info
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
//reading the information form the com port
textBox2.AppendText("[" + dtn + "] " + "Recieved: " + sport.ReadExisting() + "\n");
//closing the port
sport.Close();
}
The problem is, you are reading every time you click the button and may not have recieved everything. You should use the SerialPort class' DataReceived event to receive your data. The event fires every time data is received through your COM port, so you can press your button to write to the port then as the data comes in you should see the event fire with your data.
Microsoft has a good definition and example here.
The event is on a separate thread, so to write it to a textbox you may have to invoke it to display it on your gui. See the example code below:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string Data = serialPort1.ReadExisting();
this.Invoke((MethodInvoker)delegate
{
textBox2.AppendText(Data);
});
}

How to store data through web service when data coming to my serial port will be asynchronous?

I have one device "installed" on a users desk (a desk is nothing but a chair or table on which user will sit), and I will be supporting thousands of desks.
A user will have one "chip" and the user will scan this chip on the device which is installed on their desk.
The device will read the data off the chip and will send it to my laptop which will also have one of the devices installed, except this device is the main device responsible for collecting all user scan chip data.
All the data will be routed to my device via a wifi router and I will listen to this from my Main device and read data from this device from my laptop via serial port connection.
This data sending will happen as each user number scans his/her chip.
I have created a windows form application which will continuously run in the background on my laptop, and will be listening to my serial port on which main device is connected.
This is my code taken from here: Source Code Reference:
public partial class MainUI : Form
{
SerialPortManager _spManager;
public MainUI()
{
InitializeComponent();
UserInitialization();
}
}
private void UserInitialization()
{
_spManager = new SerialPortManager();
_spManager.NewSerialDataRecieved += new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataRecieved);
this.FormClosing += new FormClosingEventHandler(MainUI_FormClosing);
}
private void MainUI_Load(object sender, EventArgs e)
{
_spManager.StartListening()
}
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
// Send data to whom ever interested
if (NewSerialDataRecieved != null)
{
NewSerialDataRecieved(this, new SerialDataEventArgs(data));
}
}
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)
{
if (this.InvokeRequired)
{
// Using this.Invoke causes deadlock when closing serial port, and BeginInvoke is good practice anyway.
this.BeginInvoke(new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataRecieved), new object[] { sender, e });
return;
}
//data is converted to text
string str = Encoding.ASCII.GetString(e.Data);
if (!string.IsNullOrEmpty(str))
{
//Here i will store that data in to my database through web service.
//What i should use whether WCF service or Web Api because data will be continuos like at a
//time more than 10 or 100 user can scan data at the same time so this event will be fired continuously.
//I am using entity framework to store data in to my database and how to ansynchornously call web service to store my data
//so that my call doesnt block incoming data to serial port
}
}
My main concern is I will have numerous users who will scan data at the same time and how I will handle when more than 10 or 100 user scan the data at the same time.
How can I mitigate this potential issue?
Ok, if i got the question right you need to do something like this ...
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
// Send data to api
string str = Encoding.ASCII.GetString(e.Data);
if (!string.IsNullOrEmpty(str))
{
var api = new HttpClient();
api.BaseUrl("http://somewhere.com");
api.PostAsJsonAsync("api/Something", str)
}
if (this.InvokeRequired)
{
// Using this.Invoke causes deadlock when closing serial port,
// and BeginInvoke is good practice anyway.
this.BeginInvoke(new EventHandler<SerialDataEventArgs>(
_spManager_NewSerialDataRecieved), new object[] { sender, e
});
return;
}
}
// i think this can go completely ...
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)
That posts the data to webapi but whilst that post is taking place on another thread the serial port can carry on receiving data
close your serial port and load every some-amount-of-time. After that some-amount-of-time open the port and scan all devices, then close it again.
public void MainUI.Load(Object sender, Eventargs e)
{
if (_spmanager != null && !_spManager.IsOpen)
//*write the code here where it opens and starts listening
_spmanager.StartListening();
//*write the code here where it waits a little bit then
_spmanager.Close();
}
Therefore everytime it loads it starts when the port is closed, it opens for a little bit, scans whatever values are true and then closes again.
I am not very sure about this but it is just an idea of how to handle it. The code might not be accurate or currect I just wrote it quickly. Take the idea from this

can not hit the SerialDataReceivedEvent?

All these comes from the idea that i want to use the SerialPort class in .Net , but the only way is by calling dll . Because i can only get interfaces from the program calling this dll. mycode is below.
i wrote a class about serialport,
public class CommClass
{
public SerialPort _port;
private string _receivedText;
public string receivedText
{
get { return _receivedText; }
set
{
_receivedText = value;
}
}
public CommClass(string _pname)
{
portList = SerialPort.GetPortNames();
_port = new SerialPort(portList[0]);
if (portList.Length < 1)
_port= null;
else
{
if(portList.Contains(_pname.ToUpper()))
{
_port = new SerialPort(_pname);
_port.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
}
}
}
private void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string indata = _port.ReadExisting();
receivedText = indata;
}
}
from Bytestoread i can see there r data coming in and i can get data from port.ReadExisting(), but receivedText did not change ,it did not hit the SerialDataReceived event . Is my way wrong?any suggestion?thanks
i created a dll from CommClass ,then i call it in my winform program which has a button and a textbox . Clicking the button , then i initialize the port
public Form1()
{
InitializeComponent();
}
public CommClass mycom;
private void button1_Click(object sender, EventArgs e)
{
mycom = new CommClass("com3");
mycom._port.Open();
textbox.Text=mycom.receivedText;//i add a breakpoint at this line ,
}
when hitting it , i check mycom._port.PortName is "com3", its IsOpen() is "Open" , i use virtual port to send data . i send "1111",then check the mycom._port.BytestoRead is 4, and mycom._port.ReadExisting() is "1111", but mycom.receivedText is null. My puzzle is that i have no idea when the data is coming . How to use the DataReceived event in my winform without code "using System.Io.Ports",just with reference CommClass.dll. Did i make it clear? Thanks for help.
mycom._port.Open();
textbox.Text=mycom.receivedText;//i add a breakpoint at this line ,
That code cannot work, it is a threading race bug. The DataReceived event does not fire instantly after you open the port. It will take a microsecond or so, give or take. A threadpool thread has to get started to fire the event. And of course the device actually has to send something, they usually only do so when you transmit something first.
Which clearly did not happen, your DataReceived event handler has a bug as well. It is not allowed to update the Text property of a control in that event since it runs on a worker thread. Your program will bomb with an InvalidOperationException.
You'll have to write something like this instead:
private void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string indata = _port.ReadExisting();
this.BeginInvoke(new Action(() => {
textbox.AppendText(indata);
}));
}
With the additional stipulation that you must not leave it this way, updating the Text property of a TextBox and making it visible on the screen is an expensive operation that's going to turn your user interface catatonic when the device starts transmitting data at a high rate.

Detect incoming call from a GSM modem in c#

I am developing a C# application to make and receive calls from a GSM modem. I am using a timer_tick event to regularly read the port using port.ReadExisting() and comparing it with RING. If there is a match, display in a label that there is an incoming call. However I couldn't get it to work. Looking for suggestions.
I solved the problem. Cheers. This is the code that i wrote.. Might help some one
private void timer1_Tick(object sender, EventArgs e)
{
if (port.IsOpen)
{
string s = port.ReadExisting();
if (s.Contains("\r\nRING\r\n"))
{
incall_status.Text = "Incoming Call....";
incall_status.Visible = true;
}
else if (s.Contains("\r\nNO CARRIER\r\n"))
{
incall_status.Text = "Call Disconnected";
bgwrkr_calldisconect.RunWorkerAsync();
}
}
}

Categories

Resources