USSD-common

USSD-common - это утилита командной строки для отправки USSD запросов с n900. Через нее отправляют запросы ussd-widget и ussd-pad. Вы можете использовать ее непосредственно или в своих скриптах.

Возможности

  • Декодирование всех определенных стандартом кодировок (надеюсь, что всех)
  • Вывод всегда в utf-8
  • Система блокировок, предотвращающая одновременный доступ к модему
  • Поддержка автоматического повторения запросов
  • Поддержка навигации по USSD меню (с блокировками, предотвращающими случайный выбор неправильных пунктов другими приложениями)
  • Интерактивный режим
Блокировки работают только внутри ussdquery.py. Если другое приложение начнет обращаться к модему напрямую, ничего хорошего не гарантируется.

Использование

Все взаимодействие производится через утилиту ussdquery.py. Ее можно запускать в двух режимах:
ussdquery.py <ussd номер> [опции]
ussdquery.py interactive [опции]
Допустимые опции:
  • -l язык. Допустимые языки: German, English, Italian, French, Spanish, Dutch, Swedish, Danish, Portuguese, Finnish, Norwegian, Greek, Turkish, Reserved1, Reserved2, Unspecified
  • -r количество повторов. По умолчанию 0. Для бесконечного повторения сипользуйте -1
  • -f Если указан, ошибки, возникшие на последнем запросе будут считаться фатальными
  • -t время ожидания в секундах. По умолчанию 30. Превышение времени ожидания считается критической ошибкой, так как нельзя будет определить, ответ на какой запрос пришел.
  • -d разделитель. По умолчанию '\n> '.
Для тог, чтобы запросить пункт из USSD меню, разделяйте запросы пробелами (отделяйте каждый выбор меню). Например "*100# 1" означает первый пункт из меню *100#. Но номер должен быть одним параметром, так что, если вызываете ussdquery.py из командной строки, заключите такой номер в кавычки. Для выхода из интерактивного режима наберите exit.
В скриптах вы, скорее всего, будете использовать первый способ: вызыва ussdquery.py с номером в качестве аргумента, а ответ считывтаь из стандартного вывода (stdout). В случае ошибки, гарантируется, что в stdout будет пусто, все ошибки печатаются в stderr:
Nokia-N900-42-11:~# ussdquery.py *100#
Баланс:547,11р
А вот чтобы получить пункт USSD меню нужно больше выкрутасов. Для этого необходимо выполнить несколько USSD запросов. Первый запрос с номером, вызывающим меню, при этом оператор запомнит, что вы вошли в меню и будет ожидать в качестве следующего USSD запроса номер пункта меню. Проблема в том, что если несколько программ попытаются выполнять запросы одновременно, их запросы смешаются. Это может привести к чему угодно. Поэтому операция запроса пункта меню должна быть атомарной и ваш скрипт должен обеспечивать выход из меню. Так как USSD меню это просто текст без какой-либо заранее известной семантики, только ваш собственный скрипт может корректно выйти из меню.
Атомарные запросы делать не так сложно благодаря поддержке ussdquery.py.
  • Можно указать несколько запросов, разделяя их пробелами. Они будут выполнены внутри одной блокировки. Так как, если один из запросов не завершится с ошибкой, выхода из меню не произойдет, а значит последующие запросы не будут обрабатываться корректно, предусмотрен механизм повторных запросов. Чтобы активировать его просто укажите допустимое количество ошибок. Дополнительно вы можете контролировать, считать ли ошибку, произошедшую на последнем запросе фатальной. Теоретически, телефон может сообщить об ошибке, даже если оператор запрос получил и обработал. Если активировано повторение, запрос может быть выполнен дважды, что будет неприятно, если он активирует дорогую услугу. В любом случает, этот режим взаимодействия стоит расценивать как нечто, что работает в подавляющем числе случаев, но таки может сбоить. И, в случае сбоя, y вас не будет инструментов, чтобы повлиять на ситуацию. В худшем случае вам придется выйти из USSD меню вручную, если скрипт засбоит где-то в середине.
  • Использовать интерактивный режим. В этом случае у вас будет полный контроль над запросами и вы сможете обрабатывать почти все возмоные ошибки. Отправляйте USSD запросы в stdin (\n означает, что запрос сформирован) и читайте ответы из stdout. Дополнительно вы можете указать разделитель, который будет дописываться к конец каждого ответа, так что вы сможете отследить его. Постарайтесь выбрать такой разделитель, который бы случайно не встретился в ответе, хорошим вариантом может быть использование \r (возврат коретки) так как \r используется как признак конца USSD ответа, так что что-то вроде "\r-------------------\n" должно вполне подойти.
    Гарантируется, что пока вы находитесь в интерактивном режиме, другие экземпляры ussdquery.py будут ждать своей очереди воспользоваться модемом.