Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Неструктурированные дополнительные данные службы (USSD) — это протокол связи, используемый устройствами Global System for Mobile Communications (GSM) для связи с операторами мобильной сети (обычно называется просто "MO").
Чтобы понять USSD, полезно сравнить его с наиболее тесно связанным с ним братом: службой коротких сообщений (SMS). USSD и SMS являются стандартами GSM, то есть они были представлены в качестве функций во втором поколении мобильных устройств. В отличие от SMS, USSD — это подключение на основе сеанса. Хотя SMS используется для короткого обмена сообщениями без сеансов, USSD обычно используется для команд и управления мобильным устройством. Так как это необходимо для поддержания сеанса, USSD не поддерживает возможность хранения и пересылки, как это делает SMS. Сообщения USSD и SMS отправляются с 7-разрядными символами, совместимыми с GSM, но USSD максимум составляет 184 символов в отличие от 160 для SMS.
Сообщения USSD можно отправлять с мобильного телефона, открыв телефон и введя код. Не все коды поддерживаются каждым телефоном или MO. В некоторых случаях программное обеспечение телефона или операционная система могут предотвратить отправку кодов вручную. Один обязательный код, который необходимо реализовать, — *#06#. Этот код возвращает международный идентификатор мобильного оборудования (IMEI) модема, но некоторые телефоны не смогут напрямую набирать этот код. Если следовать обычным средствам поиска IMEI модема с помощью параметров телефона, то это число было получено с помощью этого кода.
Если телефонное оборудование может напрямую обрабатывать команду кода, как в примере IMEI, сетевой сеанс не будет инициирован. Другие коды, требующие сетевого взаимодействия, будут открывать сеанс, а затем отправлять сообщение, состоящее из команды и любых необходимых параметров, если это применимо. Одним из примеров этого является код, который проверяет текущий баланс и состояние тарифного плана у оператора мобильной связи.
USSD в Windows реализуется как область API WinRT. Классы реализации этого интерфейса служат конечным автоматом для сеансов USSD, но в конечном итоге полагаются на службу WWAN для выполнения основной работы. Этот API реализован с помощью паттерна фабрики.
Реализация USSD
Ключевое, что следует помнить, это то, что публичный API определяется IDL. Реализация может быть запутана из-за этого, особенно если вы не знакомы с WinRT. Часть путаницы происходит от, казалось бы, неоднозначного использования слова "фабрика". Фабрика может ссылаться на реализацию класса статического интерфейса или настоящую фабрику, которая предоставляет интерфейс, дающий возможность активизации, для класса среды выполнения.
В этом разделе рассматриваются понятия WinRT, а затем описывается реализация на основе этих понятий. Вы всегда можете обратиться к IDL для дальнейшего уточнения.
Интерфейсы
Интерфейсы определяют двоичный интерфейс приложения (ABI). Они описывают функции, которые можно вызывать для любого класса, реализующего интерфейс.
Классы среды выполнения
Это настоящие классы. Они представляют собой, по имени, то, что в конечном счете предоставляется в качестве имен классов для ABI. Каждый класс среды выполнения может иметь ноль или несколько интерфейсов (но при необходимости должен объявлять хотя бы один интерфейс по умолчанию, если он имеет один или несколько интерфейсов), ноль или несколько статических интерфейсов и активируемый тег. Каждый из этих интерфейсов реализуется в разных файлах, такими как различные классы "Impl", но в ABI они будут выглядеть как единый унифицированный класс.
Типичный интерфейс отображается как методы экземпляра в существующем объекте.
Статический интерфейс представляется клиенту как статические методы в самом классе среды выполнения.
Активируемый тег определяет интерфейс фабрики, который создаст экземпляр исполняемого класса. Это полностью скрыто для клиента, как будто это конструктор для этого класса в среде выполнения.
Реализация USSD
схема
Поток: открытие, отправка, получение, закрытие.
Открытие, отправка
Клиент использует одну из статических функций UssdSession.CreateFromNetworkAccountId или UssdSession.CreateFromNetworkInterfaceId для создания объекта UssdSession.
Независимо от вызываемого API идентификатор сетевого интерфейса требуется для инициализации ussdSession. В случае *NetworkAccountID необходимо выполнить действия по получению идентификатора сетевого интерфейса из идентификатора учетной записи. CreateInternal() вызывается для создания экземпляра UssdSession и вызова Initialize() в созданном экземпляре. Во время этапов инициализации рабочий поток запускается, и создается дескриптор событий для запуска событий потока. Шаги 3 и 4 также выполняются во время вызова экземпляра Initialize().
Initialize() вызывается на объекте-члене WwanWrapper. Эта функция принимает статическую функцию обратного вызова, а также контекст, чтобы разрешить статическую функцию сопоставить обратный вызов с контекстом объекта.
WwanWrapper открывает дескриптор WwanService, перечисляет интерфейсы и подписывается на уведомления USSD, предоставляя указатель функции статической обратной связи и "this" в качестве контекста.
Объект UssdSession возвращается клиенту.
Клиент создает новый ussdMessage путем вызова конструктора со строкой сообщения. WinRT запутывает UssdMessageFactory в этом процессе.
Клиент вызывает SendMessageAndGetReplyAsync в объекте сеанса, передав экземпляр UssdMessage.
В настоящее время SendMessageAndGetReplyAsync создает объект специальной операции UssdSendMessageAndGetReplyOperation. Судя по названию, предполагалось, что объект инкапсулирует логику одного сообщения, отправляемого по стеку (и ожидает ответа), но это не соответствует действительности. WinRT требует специального параметра out для асинхронных операций, который можно увидеть как 2-й параметр определения для этой функции.
HRESULT SendMessageAndGetReplyAsync( [in] UssdMessage* message, [out, retval] Windows.Foundation.IAsyncOperation<UssdReply>** asyncInfo);
Это IUssdSendMessageAndGetReplyOperation, именованный интерфейс, определенный с помощью typedef, который удовлетворяет этому параметру, обещая, что эта операция неизбежно вернет UssdReply. Этот интерфейс не определен в IDL, но реализуется классом UssdSendMessageAndGetReplyOperationImpl. Обратите внимание, что заголовок для этого класса имеет специальное расширение:
class UssdSendMessageAndGetReplyOperationImpl : public Microsoft::WRL::RuntimeClass< Windows::Networking::NetworkOperators::IUssdSendMessageAndGetReplyOperation, Windows::Internal::AsyncBaseFTM<IUssdSendMessageAndGetReplyCompletedHandler, Microsoft::WRL::SingleResult>>
Объект UssdSendMessageAndGetReplyOperation позволяет WinRT скрыть сложности этой асинхронной операции и все разделение и проксирование памяти, которые связаны с ней. Дополнительные сведения см. в разделе SendMessageAndGetReplyAsync.
На данный момент важно понять, что асинхронная операция, описанная выше, просто вызывает обратный вызов в объект UssdSession, где фактически содержится логика для этой операции. Мы можем для простоты представить, что сама UssdSession инкапсулирует всю работу здесь. Теперь мы можем утверждать, что, несмотря на асинхронную природу, в одно время может отправляться только один ussdMessage.
Что фактически делает функция SendMessageAndGetReplyAsync:
- Объект UssdSession переходит в состояние занятости, сохраняет содержимое UssdMessage и инициирует асинхронное действие.
- OnOperationStart() — это точка входа для асинхронной логики. Предположим, что для этого сценария нет активного сеанса. Эта функция создает объект WWAN_USSD_REQUEST с помощью RequestType=WwanUssdRequestInitiate.
- Шаги 9 и 10 выполняются в качестве действий, выполняемых этой функцией.
m_wwanWrapper.SendRequest вызывается для обработки работы передачи сообщения в WwanService.
WwanWrapper использует дескриптор WwanService для вызова API WwanService для выполнения действия.
Получать
После шага 10 мы остаемся в состоянии, когда запрос был отправлен в WwanService для инициализации нового сеанса USSD и отправки сообщения USSD в рамках этого сеанса. Через некоторое время ответ будет доступен.
- WwanService вызовет статическую функцию обратного вызова, предоставленную на шаге 4, с контекстом, который также был прикреплён.
- Контекст будет использоваться для извлечения экземпляра WwanWrapper и вызова функции NotificationCallback().
- WwanWrapper будет соответствовать тому же шаблону, что и шаг 11, вызывая статический обратный вызов в UssdSession, предоставляя контекст, хранящийся на шаге 3.
- Аналогично шагу 12, контекст используется для вызова функции обратного вызова в экземпляре UssdSession.
- UssdSession сохраняет WWAN_USSD_EVENT (под блокировкой на доступ) и уведомляет рабочий поток об обработке события.
- HandleOperationReply() принимает существующий объект UssdSendMessageAndGetReplyOperationImpl и передает данные события во внутренний обработчик.
- Операция будет создавать UssdReply и вызывать FireCompletion(), чтобы пометить асинхронное действие завершенным.
- WinRT скрывает завершение асинхронного действия клиенту. (Либо они ждали выполнения действия, либо используют логику обратного вызова.)
Дополнительные сообщения можно отправлять в одном сеансе. В случае если сеанс был сохранён, в будущем тип запроса будет WwanUssdRequestContinue.
Закрывать
схема потока
После шага 18 клиент получил ответ на USSD-сообщение. Они могут или не продолжали использовать активную ussdSession для отправки дополнительных сообщений. Предположим, что в будущем клиент вручную вызовет Close() в ussdSession. Если клиент явно не вызывает Close(), он будет вызван во время выполнения деструктора UssdSession.
- Клиент вызывает метод Close() на экземпляре UssdSession.
- WWAN_USSD_REQUEST создается с использованием параметра RequestType=WwanUssdRequestCancel.
- Запрос отправляется в m_wwanWrapper, как на шаге 9.
- Запрос отправляется в WwanService, как на шаге 10.
Результат этого запроса не имеет значение. Для всех практических целей сеанс закрыт. Даже в крайнем пограничном случае, когда сообщение каким-то образом никогда не доставлено, новый сеанс USSD всегда переопределяет существующий сеанс.
Тесты лабораторного комплекта оборудования (HLK)
Инструкции по установке HLK см. в разделе.
В HLK Studio подключитесь к драйверу сотового модема устройства и запустите тест: Win6_4.MB.GSM.Data.TestUssd.
Руководство по устранению неполадок с MB USSD
Соберите и декодируйте журналы с помощью инструкций в МБ Сбор журналов.
Ключевые слова для фильтрации
- OID_WWAN_USSD
- NDIS_STATUS_WWAN_USSD
- Запрос USSD для WWAN
- WWAN_USSD_EVENT