SMS (Short Message Service) возможно отправить в двух форматах. Один из форматов это текстовый, и другой PDU (Protocol Description Unit). Текстовый формат достаточно прост и из-за простоты у него есть достаточно много ограничении. Например, в текстовом режиме нет доступа к настройкам параметров сообщения, а также нет возможности отправлять сообщение русскими буквами. Самый большой минус текстового формата то, что не все оборудование поддерживают его. Учитывая все вышесказанные причины обратим наш взор на формат PDU.
Обратите внимание, что бит № 7 должны всегда быть установлен в 1
бит 6, 5 и 4 обозначает Тип номера
бит 3, 2, 1, 0 обозначает Идентификация плана нумерации
Наиболее распространенные значения этого октета составляет 91h = (10010001) двоичный, что указывает на международный формат. Номер телефона в международном формате выглядит 37494221122 (где код страны 374). В национальном формате тот же телефонный номер будет выглядеть 094221122. Международный формат является наиболее распространенным.
В национальном формате номера телефона, выглядит следующим образом:
81h=(10000001) двоичный формат.
И так для отправки сообщения "Тип номера SMS-центра" выбираем или 91 или 81.
Номер получателя +37494123456.
00: кодировка 7-бит (160 знаков, только латинские символы)
TP-UDL — TP-User-Data-Length – длина сообщения.
Если сообщение закодирована UCS2, то каждый символ кодируется двумя байтами. Сообщение из 10 букв будет иметь длину 20 байт, шестнадцатеричной системе счисления 14.
Если сообщение закодирована в 7-битной кодировке, то указывается количество символов. Сообщение из 10 букв будет иметь длину 10 байт, шестнадцатеричной системе счисления 0A.
TP-User-Data – текст SMS-сообщения, закодированный согласно полю TP-DCS
Для кодирования символа ASCII используется 7 бит , а поскольку 1 байт равен целых 8 бит, по этому 7-й бит всегда равен 0. Этот свободный бит будет использован для упаковки.
Ниже приведена пошаговая инструкция:
1. Берем первый байт, берется семь бит первого данного байта, потом из семи битов второго символа самый младший 0-й бит переносится в старший разряд первого байта.
2. Берем второй байт, от второго байта осталось 6 бит, это означает что есть еще место для двух битов, берем из третьего байта два младших бита 1-й и 0-й и переносим их в старшие разряды второго байта. Получаем 1-й и 0-й бит третьего байта и 6 бит второго байта.
3. Берем третий байт, от второго байта осталось 5 бит, место найдется для трех битов, берем из четвертого байта три младших бита 2-й, 1-й и 0-й и переносим их в старшие разряды третьего байта. Получаем 2-й ,1-й и 0-й бит четвертого байта и 5 бит третьего.
4. Продолжаем до конца тем же образом.
Написание сообщений в кодировке UCS2 необходимо брать символ, перекодировать ее в двухбайтовое представление и отправлять.
Для преобразования телефонного номера получателя и SMS-центра можно воспользоваться вот такой функцией
private string EncodeNumber(string Number)
{
string result = "";
Number = Number.Replace("+", "");
if ((Number.Length % 2) > 0)
Number += "F";
int i = 0;
while (i < Number.Length)
{
result += Number[i + 1].ToString() + Number[i].ToString();
i += 2;
}
return result;
}
Нам остается преобразовать текст, и вот как это делается в C#.
String7To8 функция перекодирует ASCII символы.
public string String7To8(string str)
{
string result = "";
ASCIIEncoding enc = new ASCIIEncoding();
byte[] arr = enc.GetBytes(str);
int i = 1;
while (i < arr.Length)
{
int j = arr.Length - 1;
while (j >= i)
{
byte firstBit = (arr[j] % 2 > 0) ? (byte)0x80 : (byte)0x00;
arr[j - 1] = (byte)((arr[j - 1] & 0x7f) | firstBit);
arr[j] = (byte)(arr[j] >> 1);
j--;
}
i++;
}
i = 0;
while ((i < arr.Length) && (arr[i] != 0))
{
result += arr[i].ToString("X2");
i++;
}
return result;
}
Для кодировки UCS2 можно воспользоваться функцией StringToUCS2.
public string StringToUCS2(string str)
{
UnicodeEncoding ue = new UnicodeEncoding();
byte[] ucs = ue.GetBytes(str);
int i = 0;
while (i < ucs.Length)
{
byte b = ucs[i + 1];
ucs[i + 1] = ucs[i];
ucs[i] = b;
i += 2;
}
return BitConverter.ToString(ucs2).Replace("-", "");
}
Для перекодировки из PDU в нормальный вид номер абонента и SMS-центра надо воспользоваться функцией DecodeNumber.
private string DecodeNumber(string Number)
{
string result = "";
int i = 0;
while (i < Number.Length)
{
result += Number[i + 1].ToString() + Number[i].ToString();
i += 2;
}
result = result.Replace("F", "");
return result;
}
Тема не столько трудная, на сколько запутанная благодаря формату PDU. Для этого представляю Демо версию программы для отправки SMS и его исходники.
В исходниках есть еще класс для преобразования PDU в текст, так что экспериментируйте и делитесь!!!!
Несколько сайтов для рассылки смс
Программы и плагины для смс рассылок
SMS рассылка
Отправка SMS-сообщений в сети мобильных операторов по всему миру
Самые выгодные тарифы для рассылки смс по всему миру
PDU формат достаточно запутан, но при этом он дает возможность употребить все потенциалы SMS. PDU содержит не только сообщения, но также много мета-информации об отправителе, его SMS-сервис центре, штампе времени и т.д.
Для отправки sms используют две основные кодировки: 7-битная и UCS2. Первая из кодировок используется для отправки ASCII символов. Данная кодировка дает возможность отправить 140 байт информации, но если ее преобразовать в 8-битный вид мы сможем отправить целых 160 ASCII символов. В кодировке UCS2 есть возможность отправить сообщение русскими буквами, каждый символ кодируется двумя байтами и поэтому можно отправить всего 70 символов.
Подробно о PDU
PDU это строка из шестнадцатеричных байтов, из которой можно получить все параметры sms.
PDU строку, содержащую sms, можно изначально разделить на две части. Первая часть содержит информацию о СМС-центре, и вторая часть, которая содержит информацию о номере получателя/отправителя, текст сообщения, тип сообщения и т.д.
SMS в PDU режиме можно представить в виде формулы следующим образом
SMS=SCA+TPDU
SCA- содержит информацию о смс-центре.
TPDU (Transport Protocol Data Unit) - основная информация.
Для отправки сообщения необходимо получить PDU.
Первым шагом составим SCA.
Первым шагом составим SCA.
SCA состоит из трех блоков
1 байт | 1 байт | От 0 до 6 байт |
Длина всего блока SCA | Тип номера SMS-центра | Номер SMS-центра |
Длина всего блока SCA, это длина типа номера СМС центра + длина номера СМС центра.
Тип номера, это формат номера телефона SMS-центра. В большинстве международный формат, например +37494221122. Международному формату соответствует шестнадцатеричный байт 91h. Ниже посмотрим как получаем 91. Так как, тип номера SMS-центра 1 байт и 1 байт равен 8 битам, то
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Всегда установлен в 1 | Тип номера | Идентификация плана нумерации |
Обратите внимание, что бит № 7 должны всегда быть установлен в 1
бит 6, 5 и 4 обозначает Тип номера
бит 3, 2, 1, 0 обозначает Идентификация плана нумерации
Тип номера
Биты 6 5 4 | Значение типа из битов (6, 5 и 4) |
---|---|
0 0 0 | Неизвестно. Эта функция используется, когда пользователь или сеть не имеет априорной информации о плане нумерации. |
0 0 1 | Международный номер. |
0 1 0 | Национальный номер. Префикс или номер выхода не включаются. |
1 0 1 | Буквенное-цифровое, (код в соответствии с GSM TS 03,38 7-битный алфавит по умолчанию) |
1 1 0 | Сокращенный номер |
1 1 1 | Зарезервировано для расширений |
Наиболее распространенные значения этого октета составляет 91h = (10010001) двоичный, что указывает на международный формат. Номер телефона в международном формате выглядит 37494221122 (где код страны 374). В национальном формате тот же телефонный номер будет выглядеть 094221122. Международный формат является наиболее распространенным.
В национальном формате номера телефона, выглядит следующим образом:
Бит № | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Имя | Всегда установлен в 1 | Тип номера | Идентификация плана нумерации | |||||
Значение | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
81h=(10000001) двоичный формат.
И так для отправки сообщения "Тип номера SMS-центра" выбираем или 91 или 81.
Номер SMS-центра
Для того, чтобы получить номер SMS-центра в нужном виде надо сделать несколько шагов.- Из номера надо убрать все, кроме цифр.
- Если количество цифр нечетное, добавить в конце цифр букву "F".
- В каждой паре цифр переставить местами символы (цифры).
Вот это как будет выглядеть на примере.
Номер SMS-центра +37493297111
Уберем "+" символ, поскольку надо оставить только цифры. Останется у нас номер 37493297111, количество цифр 11 значит надо добавить "F". Получится 37493297111F.
И в конце переместим местами символы в номере - 7394237911F1.
В итоге у нас есть тип номера (91), и есть сам номер (7394237911F1) соответственно можно получить длину всего блока (91 73 94 23 79 11 F1)=7 получившихся байт в шестнадцатеричном виде.
И так, как мы помним SCA=Длина всего блока SCA (07) + Тип номера SMS-центра (91) + Номер SMS-центра (37493297111F) получим 079137493297111F, это наш SCA.
Разбираем TPDU
Вот что из себя представляет TPDU.
TPDU = "PDU-Type" + "TP-MR" + "TP-DA" + "TP-PID" + "TP-DCS" + "TP-VP" + "TP-UDL" + "TP-UD"
- PDU-Type – Тип сообщения. Если поставлено "01" значит это исходящее сообщение.
- TP- MR – (TP-Message-Reference) – ставим TP-MR = "00"
- TP- DA – (TP-Destination-Address) – Номер телефона получателя сообщения
- TP- PID – (TP-Protocol ID) – всегда равен "00"
- TP- DCS – (TP-Data-Coding-Scheme) – указывает схему кодирования данных для поля TP-UD поле
- TP- VP — TP-Validity-Period — Срок действия сообщения
- TP-UDL — TP-User-Data-Length – длина сообщения.
- TP- UD — TP-User-Data – текст SMS-сообщения, закодированный согласно полю TP-DCS
Как получить TP- DA Номер телефона получателя сообщения.
1 байт | 1 байт | От 0 до 6 байт |
Длина номера получателя | Тип номера получателя | Номер получателя |
Тип номера получателя или международный формат (91) или национальный (81).
Номер получателя составляется также, как и выше составили номер SMS центра.
Поле "Длина номера получателя" считается не как количество байт, а как количество цифр в номере без учета символа "F", и указываем шестнадцатеричном виде.
Вот как поле TP-DA будет выглядеть на примере.
Номер получателя +37494123456.
Убираем все кроме цифр, необходимо добавить "F" если количество цифр нечетное, у нас получится 37494123456F. После переставим символы в каждой паре 7394143254F6.
И так длина будет равна 0B поскольку количество цифр 11 (7394143254F6).
TP-DA=0B917394143254F6.
TP-DCS -схема кодирования.
00: кодировка 7-бит (160 знаков, только латинские символы)
08: кодировка UCS2 -70 знаков.
Если первый полубайт поставить 1, то сообщение будет FLASH типа, со соответствующей схемой кодировки.
TP-VP - Срок действия сообщения.
Срок действия сообщения надо вычислять как указано в таблице
TP-VP | Значение срока действия |
0 to 143 | (TP-VP + 1) * 5 минут (то есть 5 минут интервалом до 12 часов) |
144 to 167 | 12 часов + ((TP-VP - 143) * 30 минут) |
168 to 196 | (TP-VP - 166) * 1 день |
197 to 255 | (TP-VP - 192) * 1 неделя |
Например если значение данного поля равно AA а это равно 170, значит срок равен (170-166)*1 день= 4 дня.
TP-UDL — TP-User-Data-Length – длина сообщения.
Если сообщение закодирована UCS2, то каждый символ кодируется двумя байтами. Сообщение из 10 букв будет иметь длину 20 байт, шестнадцатеричной системе счисления 14.
Если сообщение закодирована в 7-битной кодировке, то указывается количество символов. Сообщение из 10 букв будет иметь длину 10 байт, шестнадцатеричной системе счисления 0A.
TP-User-Data – текст SMS-сообщения, закодированный согласно полю TP-DCS
Для кодирования символа ASCII используется 7 бит , а поскольку 1 байт равен целых 8 бит, по этому 7-й бит всегда равен 0. Этот свободный бит будет использован для упаковки.
Ниже приведена пошаговая инструкция:
1. Берем первый байт, берется семь бит первого данного байта, потом из семи битов второго символа самый младший 0-й бит переносится в старший разряд первого байта.
2. Берем второй байт, от второго байта осталось 6 бит, это означает что есть еще место для двух битов, берем из третьего байта два младших бита 1-й и 0-й и переносим их в старшие разряды второго байта. Получаем 1-й и 0-й бит третьего байта и 6 бит второго байта.
3. Берем третий байт, от второго байта осталось 5 бит, место найдется для трех битов, берем из четвертого байта три младших бита 2-й, 1-й и 0-й и переносим их в старшие разряды третьего байта. Получаем 2-й ,1-й и 0-й бит четвертого байта и 5 бит третьего.
4. Продолжаем до конца тем же образом.
Написание сообщений в кодировке UCS2 необходимо брать символ, перекодировать ее в двухбайтовое представление и отправлять.
Как отправить SMS
Для отправки SMS можно воспользоваться программой Hyper Terminal, которая поставляется с Windows. Управление модемов осуществляется AT командами. Данные команды должны передаваться модему. Сначала настроить COM port,
Bits per second - 9600
Data bits - 8
Parity - None
Stop bits - 1
Flow control - Hardware
Я использую Siemens A60 и вышеуказанные настройки могут отличатся.
Перевод модема на PDU режим осуществляются командой AT+CMGF=0 модем даст ответ ОК если режим поддерживается и переключен на PDU режим, состояния режима можно проверить командой AT+CMGF=? .
И, так для отправки даем команду AT+CMGS="длина TPDU в байтах" , если все в порядке модем ответит приглашающей кавычкой ">". После передаем остальную часть - весь PDU. Для подтверждения надо нажать ALT+Z, код данной комбинации в ASCII равняется 26, этот код мы потом употребим в программе для отправки sms. Если все сделано правильно, то модем ответит +CMGS: "номер" .
Bits per second - 9600
Data bits - 8
Parity - None
Stop bits - 1
Flow control - Hardware
Я использую Siemens A60 и вышеуказанные настройки могут отличатся.
Перевод модема на PDU режим осуществляются командой AT+CMGF=0 модем даст ответ ОК если режим поддерживается и переключен на PDU режим, состояния режима можно проверить командой AT+CMGF=? .
И, так для отправки даем команду AT+CMGS="длина TPDU в байтах" , если все в порядке модем ответит приглашающей кавычкой ">". После передаем остальную часть - весь PDU. Для подтверждения надо нажать ALT+Z, код данной комбинации в ASCII равняется 26, этот код мы потом употребим в программе для отправки sms. Если все сделано правильно, то модем ответит +CMGS: "номер" .
Отправка SMS средствами C#
Ниже приведены методы преобразования телефонного номера и сообщения в PDU формат и обратное действие.
Для преобразования телефонного номера получателя и SMS-центра можно воспользоваться вот такой функцией
private string EncodeNumber(string Number)
{
string result = "";
Number = Number.Replace("+", "");
if ((Number.Length % 2) > 0)
Number += "F";
int i = 0;
while (i < Number.Length)
{
result += Number[i + 1].ToString() + Number[i].ToString();
i += 2;
}
return result;
}
Нам остается преобразовать текст, и вот как это делается в C#.
String7To8 функция перекодирует ASCII символы.
public string String7To8(string str)
{
string result = "";
ASCIIEncoding enc = new ASCIIEncoding();
byte[] arr = enc.GetBytes(str);
int i = 1;
while (i < arr.Length)
{
int j = arr.Length - 1;
while (j >= i)
{
byte firstBit = (arr[j] % 2 > 0) ? (byte)0x80 : (byte)0x00;
arr[j - 1] = (byte)((arr[j - 1] & 0x7f) | firstBit);
arr[j] = (byte)(arr[j] >> 1);
j--;
}
i++;
}
i = 0;
while ((i < arr.Length) && (arr[i] != 0))
{
result += arr[i].ToString("X2");
i++;
}
return result;
}
Для кодировки UCS2 можно воспользоваться функцией StringToUCS2.
public string StringToUCS2(string str)
{
UnicodeEncoding ue = new UnicodeEncoding();
byte[] ucs = ue.GetBytes(str);
int i = 0;
while (i < ucs.Length)
{
byte b = ucs[i + 1];
ucs[i + 1] = ucs[i];
ucs[i] = b;
i += 2;
}
return BitConverter.ToString(ucs2).Replace("-", "");
}
Для перекодировки из PDU в нормальный вид номер абонента и SMS-центра надо воспользоваться функцией DecodeNumber.
private string DecodeNumber(string Number)
{
string result = "";
int i = 0;
while (i < Number.Length)
{
result += Number[i + 1].ToString() + Number[i].ToString();
i += 2;
}
result = result.Replace("F", "");
return result;
}
Тема не столько трудная, на сколько запутанная благодаря формату PDU. Для этого представляю Демо версию программы для отправки SMS и его исходники.
В исходниках есть еще класс для преобразования PDU в текст, так что экспериментируйте и делитесь!!!!
Несколько сайтов для рассылки смс
Программы и плагины для смс рассылок
SMS рассылка
Отправка SMS-сообщений в сети мобильных операторов по всему миру
Самые выгодные тарифы для рассылки смс по всему миру
боже, какой изврат.
ОтветитьУдалитьТакое впечатление, что создатели этого формата долго курили чего не надо.
И что самое поганое с этими СМС - необходимость работать с платным посредником.
Изврат еще какой...............
УдалитьПри разработке данного стандарта упор шел на уменьшение размера пакета. То есть приходилось выбирать - либо красиво, просто, но пакеты значительно увеличиваются в размерах и усложняется разработка оборудования, либо немного выносим мозг программерам, но пакет короткий, сложность разработки оборудования снижается. Как бы Вы поступили?
УдалитьА как можно задать вместо номера отправителя его "имя", ну что-то вроде "SMS SUBS" ?
ОтветитьУдалитьЕсли я правильно понял ты хочешь отправить смс номеру который записан в телефоне? Если так, то надо AT командами сперва получить номер из памяти сим или телефона.
УдалитьОтлично работает. Огромное спасибо за статью
ОтветитьУдалитьДык я не понял отправка идет бесплатно от сервиса или нужно башлять?
ОтветитьУдалитьНет не бесплатно, по тарифному плану!
Удалить