О размере, кодировках и "склевивании" SMS и как это отрабатывает Kannel

Все началось с того, что один мой друг озадачил вопросом, почему сообщение из 160 символов было разбито в Kannel на 3 SMS. Немного разобравшись в сути проблемы, вопрос был закрыт, а у меня появился повод написать эту заметку. Если почитать спецификации на реализацию SMS в сетях GSM (ETSI GSM 03.40), то можно выяснить следующие моменты:

  • Текстовые сообщения могут быть в кодировках GSM 03.38 (7 бит на символ) или UCS2 (16 бит на символ). Соответственно, при передаче кириллицы, что у нас бывает нередко, приходится использовать кодировку UCS2 (она же UTF16-BE), где каждый символ будет занимать 2 байта.
  • Максимальный размер данных SMS составляет 140 байт. Именно байт, а не символов. Таким образом, в одной SMS может поместиться до 160 символов в GSM-алфавите либо до 70 символов в UCS2. Так что, отправляя сообщения в кириллице, можно немного улучшить финансовые показатели любимого оператора ;-)
  • Если сообщение не получается уместить в одну SMS-ку, то их можно склеивать. При этом, кроме данных (user_data), в SMS добавляются UDH (User Data Headers), содержащие информацию о номере цепочки, количестве SMS в ней и номере сообщения в цепочке. А телефон, получая эту информацию, может восстановить в результате всю цепочку.

Чтобы Kannel автоматически производил разбиение SMS на части, необходимо в настройках сервиса (секция sms-service) и пользователя (секция sendsms-user) указать следующее: concatenation = true max-messages = 3 Так мы укажем, что можно отправлять длинные сообщения, которые разбиваются не более, чем на 3 SMS. При этом, нам нужно явно указать Kannel, какая кодировка будет у сообщения при доставке на терминал абонента. Это делается указанием параметра coding при отправке сообщения через HTTP-интерфейс. Допустимые значения: 0 - 7 бит, 1 - 8 бит (бинарник), 2 - UCS2. Также бывает полезно указать кодировку данных, передаваемых по HTTP, чтобы Kannel самостоятельно перекодировал их в правильный вид. Для этого нужно правильно указать параметр charset Таким образом, параметры HTTP запроса charset=UTF-8&coding=2 объяснят Kannel-у, что ему переданы данные в кодировке UTF-8 и их нужно доставить на телефон в кодировке UCS-2.