The importance of SIP messages is great because often they are used for various purposes. They are for establishing phone calls, making complementary actions etc. Today when we live in a rushing world fast and efficient communication is more important than ever. SMS technology offers one of the quickests ways to send information to each other. This way you can be absolutely sure that your message will be received by the recepient because most of the people keep their mobile phones near themselves.
This sample program was developed to give an effective solution for this kind of matter. During the development I used the SDK offered by Ozeki and the Microsoft Windows Forms presentation technology.
I developed a telephone which can forward and receive phone calls and it also sends and receives DTMF signals to navigate in IVR systems.
Program running
After running the program the telephone automatically registers to the given SIP PBX with the given SIP account. If the registration process is ended successfully on the display Registration succeded can be seen. From now on the softpohne is ready to make, receive calls, during the calls it can send, receive DTMF signals to navigate in IVR systems. (The source code of the sample program contains settings that depend on the environment so after the download do not forget to customize it). When the call is ended a notification is received about the keywords.
Code
The PhoneMain.cs code behind file writes down the actuating events which are related to the interface and connects the logics to the GUI. The sample program lacks design samples and other proprieties and focuses on simplicity because it is only for presentation. This means that the PhoneMain.cs file consists the full logic of the sample program. As you open the file you can see a few lines of declaration which are needed to use Ozeki VoIP SIP SDK.
Expand|Select|Wrap|Line Numbers
- public partial class PhoneMain : Form
- {
- ISoftPhone softPhone;
- IPhoneLine phoneLine;
- PhoneLineInformation phoneLineInformation;
- IPhoneCall call;
- OzPipeStream speakerStream;
- ozWavePlayer wavePlayer;
- ozWaveRecorder waveRecorder;
- bool inComingCall;
- Stream ReceivedStream;
- Stream SentStream;
ISoftphone
It represents a telephone, and its telephone line is represented by the IphoneLine. There can be more telephone lines which means that we can develop a multi line phone.
Iphoneline
It represents a telephone line that can be registered to a SIP PBX for example, Asterisk, 3CX, or maybe to other PBXs that are offered by SIP providers. Registration happens through SIP account.
PhoneLineInformation
It is an enum type that represents the status of the telephone line with the PBX. For example registered, not registered, successful/unsuccessful registration.
IphoneCall
It represents a call: the status of the call, the direction of the call, on which telephone line it was created, the called person, etc.
OzPipeStream
It is an optional device and it helps in the processing of the incoming sound data which comes from the other party.
ozWavePlayer
It plays the received sound data on the speaker.
ozWavRecorder
It processes the sound data which comes from the default input device (microphone) of the operation system.
ReceivedStream
It is the stream that saves the received stream.
SentStream
It is the stream that saves the sent stream.
Thereby assign to the 'Loaded' events of Windows Form window and after the loading of 'PhoneMain' window the initialization and registration of Ozeki SDK softphone can be started.
Expand|Select|Wrap|Line Numbers
- private void InitializeSoftPhone()
- {
- softPhone = SoftPhoneFactory.CreateSoftPhone("192.168.91.42", 5700, 5750, 5780);
- softPhone.IncommingCall += new EventHandler<VoIPEventArgs<IPhoneCall>>(softPhone_IncommingCall);
- phoneLine = softPhone.CreatePhoneLine(new SIPAccount(true, "oz891", "oz891", "oz891", "oz891", "192.168.91.212", 5060));
- phoneLine.PhoneLineInformation += new EventHandler<VoIPEventArgs<PhoneLineInformation>>(phoneLine_PhoneLineInformation);
- softPhone.RegisterPhoneLine(phoneLine);
- }
For an outgoing call we provide the number we want to dial. Then press the Pick Up button and the call starts. The interface buttons are addressed to triggers so let us look it in the case of the ’Pick Up’ button.
Expand|Select|Wrap|Line Numbers
- private void buttonPickUp_Click(object sender, EventArgs e)
- {
- if (inComingCall)
- {
- inComingCall = false;
- call.Accept();
- return;
- }
- if (call != null)
- return;
- if (string.IsNullOrWhiteSpace(labelDialingNumber.Text))
- return;
- if (phoneLineInformation != PhoneLineInformation.RegistrationSucceeded && phoneLineInformation != PhoneLineInformation.NoRegNeeded)
- {
- MessageBox.Show("Phone line state is not valid!");
- return;
- }
- call = softPhone.Call(phoneLine, labelDialingNumber.Text);
- WireUpCallEvents();
- call.Start();
- }
Below you can see how I did the wire up.
Expand|Select|Wrap|Line Numbers
- private void WireUpCallEvents()
- {
- call.CallStateChanged += new EventHandler<VoIPEventArgs<CallState>>(call_CallStateChanged);
- call.MediaDataReceived += new EventHandler<VoIPEventArgs<VoIPMediaData>>(call_MediaDataReceived);
- call.DtmfReceived += new EventHandler<VoIPEventArgs<Tuple<VoIPMediaType, DtmfSignal>>>(call_DtmfReceived);
- call.CallErrorOccured += new EventHandler<VoIPEventArgs<CallError>>(call_CallErrorOccured);
- }
Through the CallErrorOccured event information is received about why the was not created. They can be the following: the call is rejected, the called party is busy, the called number is not available or the number does not exist.
In order to wire up to these essential events start a real call. You can achieve this with the Start function of the call object. It is the ’call.Start()’ line in the example.
The Ozeki VoIP SIP SDK publicates the incoming calls through the ’ISoftphone’ InComingCall event.
Expand|Select|Wrap|Line Numbers
- private void softPhone_IncommingCall(object sender, VoIPEventArgs<IPhoneCall> e)
- {
- InvokeGUIThread(()=>
- {
- labelCallStateInfo.Text = "Incoming call";
- labelDialingNumber.Text = String.Format("from {0}", e.Item.DialInfo);
- call = e.Item;
- WireUpCallEvents();
- inComingCall = true;
- });
- }
The ’Hang Up’ button is also connected to the event handler similarly to the ’Pick Up’ button. The event handler shown below ends the call, you only need to press the ’Hang Up’ button.
Expand|Select|Wrap|Line Numbers
- private void buttonHangUp_Click(object sender, EventArgs e)
- {
- if (call != null)
- {
- inComingCall = false;
- call.HangUp();
- call = null;
- }
- labelDialingNumber.Text = string.Empty;
- }
Ozeki VoIP SIP SDK gives information about the status of the calls. They can be the follows: InCall, Completed, Rejected, ringing etc. Through the CallStateChange event the displaying of these call status happen. The sample program does not handle all possibilities because I only concentrated on the vital ones. According to these significant programs the other programs can be created easily.
Expand|Select|Wrap|Line Numbers
- private void call_CallStateChanged(object sender, VoIPEventArgs<CallState> e)
- {
- InvokeGUIThread(() => { labelCallStateInfo.Text = e.Item.ToString(); });
- switch (e.Item)
- {
- ozWaveFormat waveFormat = new ozWaveFormat(8000, 16, 1);
- ReceivedStream = new ozWaveFileWriter(waveFormat, receivedFilePath);
- SentStream = new ozWaveFileWriter(waveFormat, sentFilePath);
- waveRecorder = new ozWaveRecorder();
- waveRecorder.DataArrived += waveRecorder_DataArrived;
- waveRecorder.StartRecording();
- speakerStream = new OzPipeStream();
- wavePlayer = new ozWavePlayer(speakerStream);
- wavePlayer.Play();
- break;
- case CallState.Completed:
- waveRecorder.Dispose();
- speakerStream.Dispose();
- speakerStream = null;
- wavePlayer.Dispose();
- call = null;
- InvokeGUIThread(() => { labelDialingNumber.Text = string.Empty; });
- break;
- case CallState.Cancelled:
- call = null;
- break;
- } }
Expand|Select|Wrap|Line Numbers
- private void call_MediaDataReceived(object sender, VoIPEventArgs<VoIPMediaData> e)
- {
- if (speakerStream != null)
- speakerStream.Write(e.Item.PCMData, 0, e.Item.PCMData.Length);
- if (ReceivedStream.CanWrite)
- {
- ((ozWaveFileWriter)ReceivedStream).Save(e.Item.PCMData);
- }
- }
Expand|Select|Wrap|Line Numbers
- private void waveRecorder_DataArrived(object sender, ozDataArrivedEventArgs e)
- {
- if (call != null)
- call.SendMediaData(VoIPMediaType.Audio, e.Data);
- if (SentStream.CanWrite)
- {
- ((ozWaveFileWriter)SentStream).Save(e.Data);
- }
- }
After the call has been established there is an opportunity to send DTMF signals. You can navigate in the called customer service’s IVR system. Ozeki VoIP SIP SDK sends DTMF signals in a simple way. Invite the ’StartDTMFSignal’ method on the object that represents the current call as it is shown below.
Expand|Select|Wrap|Line Numbers
- private void buttonKeyPadButton_MouseDown(object sender, MouseEventArgs e)
- {
- if (call != null && call.CallState == CallState.InCall)
- {
- var btn = sender as Button;
- if (btn != null)
- {
- int id;
- if (btn.Tag != null && int.TryParse(btn.Tag.ToString(), out id))
- {
- call.StartDTMFSignal(VoIPMediaType.Audio, id);
- }
- }
- }
- }
Expand|Select|Wrap|Line Numbers
- call.StopDTMFSignal(VoIPMediaType.Audio, id);
Ozeki VoIP SIP SDK informs the content of SIP messages in a simple way. To do so assign to the event that is shown below.
Expand|Select|Wrap|Line Numbers
- OzSIP.Log.SIPMessageLogger.NewSIPMessage += SIPMessageLogger_NewSIPMessage;
Now check the message content
Expand|Select|Wrap|Line Numbers
- void SIPMessageLogger_NewSIPMessage(object sender, VoIPEventArgs<string> e)
- {
- if (e.Item.Contains(txb_SIPText.Text))
- {
- SendSMS();
- }
- }
If there is a match for the searched SIP text snippet you only need to send an SMS. It can be implemented with a request sent to the http API of an SMS server
Expand|Select|Wrap|Line Numbers
- private void SendSMS()
- {
- string url =
- string.Format(@"http://{0}/api?action=sendmessage&username={1}&password={2}&recipient={3}&messagetype=SMS:TEXT&messagedata={4}",Txb_IpAddress.Text, txb_UserName.Text, Txb_Password.Text, Txb_recipient.Text, Txb_SmsText.Text);
- WebRequest request = WebRequest.Create(url);
- request.GetResponse();
- }
Summary
SMS sending became the part of our lives just like mobile phones, TV or the Internet. It is a very efficient and fast way to communicate with each other. The implementation is simple so it is easy to create your own C# SIP SMS example. More specific information can be found on the webpage. I can only recommend this solution to everyone.