How to make caller id in c#.net - c#

I know this is answered question however I want to know hardware required and how to setup.
I am trying to build a take-out's delivery system wherein users call and their phone number gets captured on a WINFORM.
I googled and it says I need to use TAPI API. That's fine but do I need to connect anything to the PC or will just using TAPI work?
This Link explains it in VB.net. I am looking for it in c#.net.
I have also gone through the links provided here.
But nowhere does it explain the setup. So please help.

First thing
See if your hardware supports caller ID
Add the serial port control, set it to whatever comm port your modem is on and watch for the CALLER ID number, then react
To see if your modem supports Caller ID open a serial port terminal (I like putty) and set it to the com port of your modem then call the phone number attached to that that modem, you should see something like RING 5555555555 (where 5555555555 is the phone number of the person calling you)
You may have to turn caller id on for that modem (if so)
1) Open the "Phone And Modem Options" control panel
2) Click the "Modems" tab
3) Select your modem in the list (if it is not already selected)
4) Click the "Properties" button
5) Click the "Advanced" tab
6) Type "#CID=1" into the "Extra initialization commands" edit box
Note: replace "#CID=1" with the command to enable caller id on your modem
Do not include the "AT" part of the command
Do not include the quotes
7) Click OK
8) Click OK
9) restart the computer
Here is some code for interacting with a serial port in c# (incase you need that)
public SerialPort sp;
string dataReceived = string.Empty;
private delegate void SetTextDeleg(string text);
private void FormLoad()
{
sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
this.sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.Open();
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
Thread.Sleep(500);
string x = sp.ReadLine(); // will read to the first carriage return
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { x });
}
catch
{ }
}
private void si_DataReceived(string data)
{
dataReceived = data.Trim();
// Do whatever with the data that is coming in.
}
Also I just searched amazon for "Caller ID Modem" and there seem to be alot for between 10 and 20 dollars (US) that support this exact use. I would recommend the Trendnet TFM-561U

If you are using a phone and fax modem, just plug-in your telephone line into the modem.
Next on your windows form drag-n-drop a SerialPort control and initialize it.
this.serialPort1.PortName = "COM3";
this.serialPort1.BaudRate = 9600;
this.serialPort1.DataBits = 8;
this.serialPort1.RtsEnable = true;
this.serialPort1.DataReceived += serialPort1_DataReceived;
this.serialPort1.Open();
Pass the following command to modem in order to activate Caller-ID
this.serialPort1.WriteLine("AT#cid=1" + System.Environment.NewLine);
Handle its DataReceived event and display the received data
void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
richTextBox1.Text += this.serialPort1.ReadLine();
}
Output:
RING //On 1st Ring
DATE = xxxxx //On 2nd Ring
TIME = xxxx
NMBR = xxxxxxxxx
RING //On 3rd Ring
RING //On 4th Ring
P.S. If the telephone line sends DTMF tones as Caller-ID then you need DTMF to FSK converter to detect the number, or else you will receive the rings but not the number.

Related

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

I use at-command for get Caller ID but just write ok ring

I am using the following method to detect the CallerID when someone calls.
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.PortName = "COM3";
serialPort1.RtsEnable = true;
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.RtsEnable = true;
serialPort1.Open();
serialPort1.WriteLine("AT+VCID=1" + System.Environment.NewLine);
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
textBox1.Text += serialPort1.ReadLine();
}
I excepted something like this :
RING //On 1st Ring
DATE = xxxxx //On 2nd Ring
TIME = xxxx
NMBR = xxxxxxxxx
RING //On 3rd Ring
RING //On 4th Ring
But I have just :
OK
RING
RING
RING
NOTE:
line support CallerID
I guess modem support CallerID too because I see the word RING for each incoming ring
Confirmed: I have caller id device and I checked it; I'm sure that I have caller id service.
You need to setup calling line presentation on your device I believe. Just send the command:
AT+CLIP=1
You should then see that when the number is called the following will be displayed:
+CLIP 1234567890
most common CALLER ID command is "AT#CID=1"
Found that commands
AT#CID=1
AT#CC1
AT+VCID=1
AT%CCID=1
AT*ID1
No one worked because of... linefeed (facepalm). So try them with \r\n or \n
i had a similar issue . i changed to different usb modem. it worked fine.

Checking device status, while receiving data from serial port c#

Life status of device connected via serial port.
Hello everyone.
How can I check if the device responds to the request? I'm googling this for couple days and tried lot of solutions also from SO, but nothing gave me results that I've expected. After lot of tries I'm in point described below. I think I'm very close but now I need little help, so thanks for every answer in advance.
The current situation
What am I doing right now is very simple. First of all I'm opening serial port serialPort.Open() at very beggining of app (data is receiving almost all the application running time).
As this is just an example in my form is only one label called labelStatus and labelStatus.Text = "Not connected"
Next I'm adding a timer and it's tick method, that contains execute of serialPort.Write(). Timer Interval is set to 100 if that matters.
private void timer_Tick(object sender, EventArgs e)
{
if (serialPort.IsOpen)
{
serialPort.WriteLine("r"); //I'm sending "r" message and device send data back
}
}
Next step is create DataReceived event like below (very simplified version, in my app received data is parsing to floats and storing in array, but it's just to show the problem)
private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string someVariable = serialPort.ReadLine();
labelStatus.Invoke((MethodInvoker)(() => labelStatus.Text = "Connected"));
//If i received something that means the device is plugged in and connection is correct (still very simplified)
}
One last thing is create ErrorReceived method.
private void serialPort_ErrorReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
labelStatus.Invoke((MethodInvoker)(() => labelStatus.Text = "Not connected"));
}
Untill now everything works brilliant. Sending data works. DataReceived event is executig each 100 miliseconds when data is send. My data is received properly with no problems. When I start application labelStatus text is "Not connected" (device cable is not plugged in). When I plugged in device labelStatus text changing to "Connected". But now when I plugged of cable ErrorReceived event is not executing and labelStatus text is still "Connected". So as I've asked before: How can I check is device still connected to computer? (Or maybe: how to execute ErrorReceived event, when data is not receiving?).
Note: Serial port ReadTimeout is set to 300 miliseconds.
What have I tried
I've tried lot of things but this one in my head seems to should work but doesn't.
I've modified DataReceived event and I've put serialPort.ReadLine() into try/catch block with TimeoutException where I've tried to manually execute ErrorReceived method like below
private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
string someVariable = serialPort.ReadLine();
labelStatus.Invoke((MethodInvoker)(() => labelStatus.Text = "Connected"));
//If i received something that means the device is plugged in and connection is correct (still very simplified)
}
catch (TimeoutException)
{
serialPort_ErrorReceived(null, null);
}
}
I was hoping that will work like I want.
BTW. Sorry for my English. It's not perfect, but I do my best. Cheers!
Listen to the WM_DEVICECHANGE event that will be fired when a device is removed or inserted.
Here is an example of a implementation and some more information:
Detect serial port insertion/removal
http://www.codemiles.com/download/file.php?id=719 (USB Sample)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363480(v=vs.85).aspx
This is solution in my case
Regarding to Martjin's answer i need to further explain my situation. First of all I want to say that I'm not installing any hardware into my computer, so in my opinion WM_DEVICECHANGE event was not what i need (but of course thanks for information, I've learned something new). Application is reading data from scale. Scale after plug into com port is not sending any data and actually there's no communication between it and computer at all. The only way to read data is to send request to scale, so I have to rely on that.
First try
The plan:
Add two static int fields (flags) checkOld and checkNew,
increment checkNew in DataReceived, check in timer Tick method
is checkOld is equal to checkNew. If true that means checkNew
was not increment, and that means DataReceived was not executed.
`
private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
checkNew++;
string someVariable = serialPort.ReadLine();
labelStatus.Invoke((MethodInvoker)(() => labelStatus.Text = "Connected"));
//If i received something that means the device is plugged in and connection is correct (still very simplified)
}
private void timer_Tick(object sender, EventArgs e)
{
if (serialPort.IsOpen)
{
serialPort.WriteLine("r"); //I'm sending "r" message and device send data back
}
if (checkOld == checkNew)
{
labelStatus.Invoke((MethodInvoker)(() => labelStatus.Text = "Not connected"));
}
}
`
The plan was good but when I've tested it result was not even good. What happened? Actually device status was blinking connected-not connected-connected-not connected etc. I've wrote some data to output and get answer. The timer was looping so fast that DataReceived event could not always increment checkNew value.
Final solution
Based on what I had at the moment I've decided to add some little changes. Instead of comparing two integers values try to collect couple last values ad check if all were the sem or not.
The plan:
Add three static fields: first six elements array of integers
statusArray, second integer index with value equals to 6 (last
element of array + 1), third integer checkNew,
increment checkNew in
DataReceived event,
in timer Tick event fill array to index,
decrement index value untill whole array is filled, and if index == 0 reset index value to
6,
and last check if last six values of checkNew, stored in
statusArray are the same. If true that means DataReceived did not
executed six times in a row, and now I can be sure that connection is
lost.
`
static int index = 6;
static int checkNew = 0;
static int[] statusArray = {0,0,0,0,0,0};
private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
checkNew++;
string someVariable = serialPort.ReadLine();
labelStatus.Invoke((MethodInvoker)(() => labelStatus.Text = "Connected"));
//If i received something that means the device is plugged in and connection is correct (still very simplified)
}
private void timer_Tick(object sender, EventArgs e)
{
if (serialPort.IsOpen)
{
serialPort.WriteLine("r"); //I'm sending "r" message and device send data back
}
if (index == 0)
index = 6;
index--;
int value = statusArray[index] = checkNew;
}
`

C# + USB Barcode Reader

How can i read barcode text in background in my C# app? I googled but its of no use. And other resources on stackoverflow are not close to what i need. I want to read barcode in background. And i want to know if the data is coming from barcode or key board. If the data comes from the barcode then it mustnot be displayed on textbox even though the textbox is highlighted. I got similar code for stackoverflow but if there is presence of textbox in the window then the textbox will contain barcode data; which i dont want.
Link : get barcode reader value form background monitoring
DateTime _lastKeystroke = new DateTime(0);
List<char> _barcode = new List<char>(10);
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
// check timing (keystrokes within 100 ms)
TimeSpan elapsed = (DateTime.Now - _lastKeystroke);
if (elapsed.TotalMilliseconds > 100)
_barcode.Clear();
// record keystroke & timestamp
_barcode.Add(e.KeyChar);
_lastKeystroke = DateTime.Now;
// process barcode
if (e.KeyChar == 13 && _barcode.Count > 0) {
string msg = new String(_barcode.ToArray());
MessageBox.Show(msg);
_barcode.Clear();
}
}
Most barcode scanners simply act as keyboard inputs and a quick / easy work around is to place a textbox "Out of sight". An example would be something like this:
// Pseudo code (could be Web, Windows etc)
public void Form1_Load()
{
txtBarcodeScanner.Top = -10000;
txtBarcodeScanner.Left = -10000;
txtBarcodeScanner.Width = 10;
txtBarcodeScanner.Height = 10;
txtBarcodeScanner.Focus();
}
That way the input can be captured by txtBarcodeScanner but will not be visible and the barcode will not seen being captured but will fire KeyDown etc.
Barcode device like keyboard.
1 When entering the barcode, press f12
2 The enter was pressed after inserting the barcode
private void textbox_Keydown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.F12){
Textbox.Focus();
}
if(e.KeyCode == Keys.Enter){
/// after enter barcode
/// save
}
}
check user manual that came with the scanner box.!!
does your barcode scanner supports interfaceType: "usb virtual com port" ?
if yes:
you can do it using serialport() class
1) put your scanner into "usb virtual com port" by scanning that barcode.
it will popup in the device manager.
2) get your baudrate info from device manager
device manager ->
com lpt ports ->
usb serial ch341a (com6)
-> (dobule click) -> "goto tab connection point settings"
there is your baudrate parity etc. info ( write that info to connect port)
3) use this example to do the c# coding. serialport to read data
done!.

Categories

Resources