private void OnTelephoneReadReady(ReadPortEvent e)
        {
            EventHandler <ReadPortEvent> handler = TelephoneReadReady;

            if (handler != null)
            {
                TelephoneReadReady(this, e);
            }
        }
        private void OnNotificationReadReady(ReadPortEvent e)
        {
            EventHandler <ReadPortEvent> handler = NotificationReadReady;

            if (handler != null)
            {
                NotificationReadReady(this, e);
            }
        }
        /// <summary>
        /// Provides call on the phone and return the status of call
        /// </summary>
        /// <param name="phoneItem">Mobile phone item</param>
        /// <param name="guiEvent">Event which will be passed to GUI</param>
        /// <returns>True if number is activated and notification is sent if it is enabled</returns>
        private bool ProcessCall(XmlTelephoneItem phoneItem, ReadPortEvent guiEvent)
        {
            bool retVal = false;

            guiEvent.Code = _dialUp(phoneItem.Telephone, guiEvent);

            if (DoubleCheckOnTimeout && guiEvent.Code == ResponseCode.TIMEOUT)
            {
                guiEvent.Code = _hangUp();
                if (guiEvent.Code == ResponseCode.OK)
                {
                    Thread.Sleep(WaitCall * 1000);

                    // The second attempt to find out the activation in case line of operator is not stable
                    guiEvent.Code = _dialUp(phoneItem.Telephone, guiEvent);
                }
                else if (guiEvent.Code == ResponseCode.TIMEOUT)
                {
                    // in case modem is not responding on hang up
                    return(true);
                }
            }

            if (guiEvent.Code == ResponseCode.CONNECT || guiEvent.Code == ResponseCode.RING ||
                guiEvent.Code == ResponseCode.BUSY || guiEvent.Code == ResponseCode.NO_ANSWER ||
                guiEvent.Code == ResponseCode.TIMEOUT)
            {
                if (_hangUp() == ResponseCode.OK)
                {
                    retVal = true;
                    if (SendNotification)
                    {
                        Thread.Sleep(WaitCall * 1000);

                        retVal = ProcessNotification(phoneItem.Telephone, guiEvent);
                    }
                }
                else if (guiEvent.Code == ResponseCode.TIMEOUT)
                {
                    // in case modem is not responding on hang up
                    return(false);
                }
            }
            else
            {
                // don't hang up phone on ERROR, BLACKLISTED, NO_ANSWER_MODEM, NO_ANSWER, NO_CARRIER, etc.
                return(false);
            }
            return(retVal);
        }
        private ResponseCode DialUpHibryd(string telephone, ReadPortEvent guiEvent)
        {
            var res = DialUpHandler(telephone, guiEvent, "AT+CPAS", "AT+CLCC",
                                    new[] { ResponseCode.CONNECT, ResponseCode.RING, ResponseCode.NO_CARRIER, ResponseCode.NO_ANSWER_MODEM },
                                    new[] { ResponseCode.CONNECT, ResponseCode.BUSY, ResponseCode.OK, ResponseCode.NO_ANSWER, ResponseCode.NO_CARRIER });

            // In case command returns OК that means the connection line is interrupted
            // Если команда CLCC была выполнена, но соединений нет, то ответ не передается(мы получаем от телефона ответ ОК)
            if (res == ResponseCode.OK)
            {
                res = ResponseCode.NO_CARRIER;
                Logger.Write(String.Format(ResourceManagerProvider.GetLocalizedString("MSG_COMMAND_RESPONSE_CODE_CHANGED", Application.CurrentCulture), res));
            }
            return(res);
        }
        private ResponseCode DialUp(string telephone, ReadPortEvent guiEvent)
        {
            var watch = new Stopwatch();

            watch.Start();

            var res = ExecCommand("ATD" + telephone + ";", WaitAnswer * 1000, new[] { ResponseCode.CONNECT,
                                                                                      ResponseCode.BUSY,
                                                                                      ResponseCode.RING,
                                                                                      ResponseCode.ERROR,
                                                                                      ResponseCode.BLACKLISTED,
                                                                                      ResponseCode.NO_CARRIER,
                                                                                      ResponseCode.NO_ANSWER }).Code;

            watch.Stop();
            guiEvent.RingingSeconds = watch.Elapsed.Seconds;

            return(res);
        }
        /// <summary>
        /// Provides notification of activated number
        /// </summary>
        /// <param name="phone">Activated mobile phone number</param>
        /// <param name="guiEvent">Event which will be passed to GUI</param>
        /// <returns>Result if notification was sent</returns>
        private bool ProcessNotification(string phone, ReadPortEvent guiEvent)
        {
            var retVal = false;

            if (NotificationType == NotificationType.SMS)
            {
                guiEvent.Code = SendSms(phone);
                if (guiEvent.Code == ResponseCode.OK || guiEvent.Code == ResponseCode.SMS)
                {
                    retVal = true;
                }
            }
            else
            {
                guiEvent.Code = SendUSSD(phone);
                if (guiEvent.Code == ResponseCode.OK)
                {
                    retVal = true;
                }
            }

            return(retVal);
        }
        private ResponseCode DialUpHandler(string telephone, ReadPortEvent guiEvent, string ringCommand, string command,
                                           IEnumerable <ResponseCode> commandDialingResponses, IEnumerable <ResponseCode> commandRingingResponses)
        {
            var res = ExecCommand("ATD" + telephone + ";", TimeoutCommand, new[] { ResponseCode.OK,
                                                                                   ResponseCode.NO_CARRIER,
                                                                                   ResponseCode.BLACKLISTED,
                                                                                   ResponseCode.NO_ANSWER_MODEM,
                                                                                   ResponseCode.ERROR }).Code;

            if (res == ResponseCode.OK)
            {
                var watch = new Stopwatch();
                watch.Start();

                var ticker          = 0;
                var ringWasFound    = false;
                var connectWasFound = false;
                do
                {
                    if (!ringWasFound)
                    {
                        res = ExecCommand(ringCommand, commandDialingResponses).Code;
                        // auto caller doesn't give RING code and answer the phone right away
                        if (res == ResponseCode.RING || res == ResponseCode.CONNECT)
                        {
                            if (!connectWasFound)
                            {
                                watch.Stop();
                                guiEvent.DialingSeconds = watch.Elapsed.Seconds;
                                watch.Reset();
                                watch.Start();
                                ticker = -1;
                            }

                            switch (res)
                            {
                            case ResponseCode.RING:
                                ringWasFound = true;
                                break;

                            case ResponseCode.CONNECT:
                                if (!connectWasFound)
                                {
                                    connectWasFound = true;
                                }
                                break;
                            }

                            res = ResponseCode.TIMEOUT;
                            Logger.Write(String.Format(ResourceManagerProvider.GetLocalizedString("MSG_COMMAND_RESPONSE_CODE_CHANGED", Application.CurrentCulture), res));
                        }
                    }
                    else
                    {
                        res = ExecCommand(command, commandRingingResponses).Code;
                    }
                    ++ticker;
                }while ((res == ResponseCode.TIMEOUT) && (ticker < WaitAnswer));
                watch.Stop();

                if (ringWasFound)
                {
                    guiEvent.RingingSeconds = watch.Elapsed.Seconds;
                }
                else
                {
                    // Operator line is broken so we can't even ring
                    if (connectWasFound && res == ResponseCode.TIMEOUT)
                    {
                        // auto caller was defined
                        res = ResponseCode.CONNECT;
                        Logger.Write(String.Format(ResourceManagerProvider.GetLocalizedString("MSG_COMMAND_RESPONSE_CODE_CHANGED", Application.CurrentCulture), res));

                        guiEvent.RingingSeconds = watch.Elapsed.Seconds;
                    }
                    else
                    {
                        guiEvent.DialingSeconds = watch.Elapsed.Seconds;
                    }
                }
            }
            else if (res == ResponseCode.ERROR)
            {
                res = ResponseCode.NO_ANSWER_MODEM;
                Logger.Write(String.Format(ResourceManagerProvider.GetLocalizedString("MSG_COMMAND_RESPONSE_CODE_CHANGED", Application.CurrentCulture), res));
            }
            return(res);
        }
 // CPAS - Данная команда показывает статус активности мобильного оборудования.
 private ResponseCode DialUpCPAS(string telephone, ReadPortEvent guiEvent)
 {
     return(DialUpHandler(telephone, guiEvent, "AT+CPAS", "AT+CPAS",
                          new[] { ResponseCode.CONNECT, ResponseCode.RING, ResponseCode.NO_CARRIER, ResponseCode.NO_ANSWER_MODEM },
                          new[] { ResponseCode.CONNECT, ResponseCode.NO_CARRIER }));
 }
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var worker = sender as BackgroundWorker;

            Thread.CurrentThread.CurrentCulture   = _culture;
            Thread.CurrentThread.CurrentUICulture = _culture;

            Initialization();

            // Call only those phone items which are in some named group from settings.
            foreach (var phoneItem in _listTelephones.Where(x => _groupSettings.Any(g => g.GroupName == x.GroupName)))
            {
                if (!worker.CancellationPending)
                {
                    ValidateIntroductoryVersion();

                    _currentPhoneItem = phoneItem;

                    var guiEvent = new ReadPortEvent {
                        Telephone = _currentPhoneItem.Telephone
                    };
                    switch (Operation)
                    {
                    case PortReaderOperation.Call:
                        if (!_currentPhoneItem.IsActivated())
                        {
                            if (ProcessCall(_currentPhoneItem, guiEvent))
                            {
                                guiEvent.Activated = true;
                                OnTelephoneReadReady(guiEvent);
                                Thread.Sleep(WaitCall * 1000);
                            }
                            else
                            {
                                OnTelephoneReadReady(guiEvent);

                                if (guiEvent.Code == ResponseCode.NO_ANSWER_MODEM || guiEvent.Code == ResponseCode.BLACKLISTED)
                                {
                                    Logger.Write(ResourceManagerProvider.GetLocalizedString("MSG_MODEM_PORT_RESET", Application.CurrentCulture));
                                    // pause in 1 minute
                                    Thread.Sleep(60000);

                                    ClosePort();
                                    OpenPort();
                                    Initialize3GModem();
                                }
                                else
                                {
                                    Thread.Sleep(WaitCall * 1000);
                                }
                            }
                        }
                        break;

                    case PortReaderOperation.Notification:
                        ProcessNotification(_currentPhoneItem.Telephone, guiEvent);
                        OnNotificationReadReady(guiEvent);
                        Thread.Sleep(WaitCall * 1000);
                        break;
                    }
                }
                else
                {
                    e.Cancel = true;
                    break;
                }
            }
        }