Здравствуйте, подскажите как в Delphi отправить SMS с компьютера(через компорт) через телефон (Siemens A60) использую PDU режим - телефон пинимает только этот режим.
Использую, например:
'AT+CMGS=18'+#13
'07918350000005F111000B810805235717F80000A804F4F29C0E'+^Z
Как мне сформировать строку '07918350000005F111000B810805235717F80000A804F4F29C0E'?
Интересует алгоритм или пошаговое объяснение, желательно практика.
Перечитал кучу мануалов по PDU но так и не смог разобраться с структурой октетов и т.д.
p.s. Научился принимать звонок, отбиваться и перезванивать на принятый номер.
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
Добрый день!
Как я понял, вы разобрались в вопросе отправки смс через аппараты, которые держат только pdu режим.
Если не трудно, возможно ли привести пример рабочего примера?
Понимаю, вопрос был задан очень давно, но всё же, надежда умерает последней :)
PC Maniac, берется область данных штампа времени, например, 99 30 92 51 61 95 80 и полуоктеты меняются местами. Штамп времени после преобразования равен "99 03 29 15 16 59 08", где первые 6 знаков представляют дату, следующие 6 - представляет время, и последние два - часовой пояс.
Ну как-то та-а-ак :-) (с) "Авария"
А не знаете ли Вы, уважаемый Usov, в каком формате хранится TimeStamp во входящем PDU? Остальные части входящего сообщения я читаю нормально, а со временем его пока не разбирался.
А не знаете ли Вы, уважаемый Usov, в каком формате хранится TimeStamp во входящем PDU? Остальные части входящего сообщения я читаю нормально, а со временем его пока не разбирался.
function Encode7bit(Src:String):String;
var Dst:String;
i:Integer;
CurS,NextS:Byte;
TStr:String;
begin
for i:=1 to Length(Src) do begin
if (i mod 8)=0 then Continue;
TStr:=Copy(Src,i,1);
CurS:=Ord(TStr[1]);
if (i mod 8)>1 then
CurS:=(CurS shr ((i mod 8)-1) );
if i<Length(Src) then begin
TStr:=Copy(Src,i+1,1);
NextS:=Ord(TStr[1]);
end else
NextS:=0;
NextS:=(NextS shl (8-(i mod 8)));
Dst:=Dst+IntToHex(CurS+NextS,2);
end;
Result:=Dst;
end;
procedure SendSMS(nTel: String);
var
lngt, i: Integer;
nmes, m, tel, vi: String;
begin
m := teSMSMessage.Text;
// Полуоктеты представляют десятичные цифры, и, например, номер отправителя получается
// при перестановке десятичных цифр в каждом октете: от "72 38 88 09 00 F1" к "27 83 88 90 00 1F".
// Длина телефонного номера нечетна, поэтому в последний октет добавлен F.
if Length(nTel) mod 2 = 1 then
nTel := nTel + 'F';
for i := 1 to Length(nTel) do
if i mod 2 = 0 then
tel := tel + nTel[i] + nTel[i-1];
nmes := '00'; // Длина информации о SMSC. Длина - 0 означает, что для отправки СМС должен использоваться номер SMSC, сохраненный в телефоне. Этот октет является дополнительным. Для некотоорых телефонов этот октет должен быть опущен! (Но все равно будет использоватьтся СМСЦ, сохраненный в телефоне.
nmes := nmes + '11'; // Первый октет SMS-SUBMIT
nmes := nmes + '00'; // TP-Message-Reference. Значение 0х00 указывает на то, что в качестве номера телефона отправителя будет использоваться номер.
nmes := nmes + '0B'; // Длина номера получателя (11)
nmes := nmes + '81'; // Тип-адреса. (91 указывает международный формат телефонного номера, 81 - местный формат).
nmes := nmes + tel; // Телефонный номер получателя в международном формате в полуоктетах (46708251358). Если указать номер телефона в местном формате (Type-of-Address равен 81 вместо 91), то для указания номера телефона можно было бы использовать 10 октетов (0x0A) и октеты были бы представлены как 7080523185 (0708251358).
nmes := nmes + '00'; // TP-PID. Идентификатор протокола
nmes := nmes + '00'; // TP-DCS.
nmes := nmes + 'A8'; // TP-Validity-Period. "AA" означает 4 дня. Этот октет является дополнительным, см. 4 и 3 первого октета
nmes := nmes + IntToHex(Length(m),2); // TP-User-Data-Length. Длина сообщения.
nmes := nmes + Encode7bit(m); // TP-User-Data. Эти октеты представляют сообщение "hellohello", преобразованное в 7 битку.
lngt := Round((length(nmes)-2)/2);
//Memo1.Lines.Add('AT+CMGS='+IntToStr(lngt)+#13);
//Memo1.Lines.Add(mes);
ComPort.Open;
ComPort.WriteString('AT+CMGS='+IntToStr(lngt)+#13);
sleep(1000);
ComPort.WriteString(nmes+^Z);
end;
А если надо отправлять сообщение по русски, то надо использовать кодировку UCS2.
(По крайней мере для GSM-модема Siemens T35 ничего другого не остается.)
Командой at+cscs=? можно узнать список поддерживаемых модемом кодировок.
(У вышеуказанного модема есть только две: GSM - для семибитных текстовых сообщений в английской кодировке и UCS2 - для UCS2-кодировок в PDU формате.)
Далее командой at+cscs=ucs2 можно установить кодировку. (После этого пропадает возможность воспользоваться текстовым вариантом команды AT+CMGS. Всегда возвращает ошибку. Отсылать после этого надо исключительно в PDU формате).
Затем можно приступать к формировнию PDU сообщения. Для этого необходимо преобразовать исходное сообщение в hex-коды UCS2. Чтобы это сделать надо сравнить каждый байт сообщения с $C0 (это ord('А')). Если меньше - английский символ. Добавить к нему спереди 00h и все.
(Result := Result + '00' + format('%1.2x', [ofs]))
Если больше - русский символ. Отнять от него $c0 и добавить $410.
(Result := Result + format('%1.4x', [ofs - $C0 + $410]);)
Получится TP-User-Data из поста Usov-а.
Осталось только установить значение TP-DCS в '08', что будет обозначать русскую кодировку.
2 МухаМор
Программирую модем Siemens TC35. Так у него в документации сказано, что команда
AT+CMGS имеет два вида вызова. Для текстового режима применяется тот вызов, который Вы написали. Но текстовый режим не предполагает использование кириллицы. Так что Ваш пример вызывает ошибку. Сразу после Chr(26).
А вот для PDU режима вызов как раз такой, который описал уважаемый Usov.
Теперь что касается телефонного номера получателя. Он, как правильно сказал Usov, указывается в полуоктетах. Я сначала не понял что же это такое. Несколько неочевидное на первый взгляд преобразование. А технология такая вот:
Возьмем, например, телефон: +46708251358.
Уберем плюс. Получится 46708251358.
Количество символов в номере 46708251358 является нечетным, поэтому добавим F.
Получится: 46708251358F
Теперь попарно "развернем" символы и получим из номера
46 70 82 51 35 8F
такой вот номер:
64 07 28 15 53 F8
Полученный номер и есть номер 6407281553F8, указанный в примере уважаемого Usov-а.
Я подставил таким образом в строку PDU свой номер и сообщение было успешно отправлено GSM модемом. Отдельное спасибо Usov-у за описание алгоритма формирования PDU.
Спасибо за помощь я уже разобраляся. Телефон не поддерживает текстовый режим, поэтому и спрашивал о PDA режиме.
AT+CMGF=0 - установить PDU режим
AT+CSMS=0 - установить, если модем поддерживает СМС команды
AT+CMGS=23 - послать сообщение длиной 23 октета (исключая первый октет 0x00)
0011000B916407281553F80000AA0AE8329BFD4697D9EC37
Сообщение состоит из 23 октетов (46 символов). Первый октет (0х00) не считается, он указывает на длину информации о СМСЦ.
Строка PDU:
Октет(ы) Описание
00 - Длина информации о SMSC. Длина - 0 означает, что для отправки СМС должен использоваться номер SMSC, сохраненный в телефоне. Этот октет является дополнительным. Для некотоорых телефонов этот октет должен быть опущен! (Но все равно будет использоватьтся СМСЦ, сохраненный в телефоне.
11 - Первый октет SMS-SUBMIT
00 - TP-Message-Reference. Значение 0х00 указывает на то, что в качестве номера телефона отправителя будет использоваться номер.
0B - Длина номера получателя (11)
91 - Тип-адреса. (91 указывает международный формат телефонного номера).
6407281553F8 - Телефонный номер получателя в международном формате в полуоктетах (46708251358). Если указать номер телефона в местном формате (Type-of-Address равен 81 вместо 91), то для указания номера телефона можно было бы использовать 10 октетов (0x0A) и октеты были бы представлены как 7080523185 (0708251358).
00 - TP-PID. Идентификатор протокола
00 - TP-DCS.
AA - TP-Validity-Period. "AA" означает 4 дня. Этот октет является дополнительным, см. 4 и 3 первого октета
0A - TP-User-Data-Length. Длина сообщения.
E8329BFD4697D9EC37 - TP-User-Data. Эти октеты представляют сообщение "hellohello", преобразованное в 7 битку.
А это функция перекодирования текста сообщения в 7 битку (английский):
function Encode7bit(Src:String):String;
var Dst:String;
i:Integer;
CurS,NextS:Byte;
TStr:String;
begin
for i:=1 to Length(Src) do begin
if (i mod 8)=0 then Continue;
TStr:=Copy(Src,i,1);
CurS:=Ord(TStr[1]);
if (i mod 8)>1 then
CurS:=(CurS shr ((i mod 8)-1) );
if i<Length(Src) then begin
TStr:=Copy(Src,i+1,1);
NextS:=Ord(TStr[1]);
end else
NextS:=0;
//????? ??
NextS:=(NextS shl (8-(i mod 8)));
Dst:=Dst+IntToHex(CurS+NextS,2);
end;
Result:=Dst;
end;
25-04-2007 10:06 | Вопрос к автору: запрос дополнительной информации
чуть не забыл...
Имейте в виду, что у модема, как и у всех устройствах есть флаги.
Хочу сказать, что флаг, отвечающий за режим SMS (АЕ+CMGF?) подвержен сбрасыванию значения к заводским настройкам (AT&V - так их посмотреть можно). Так что, если хотите записывайте в энергонезависимую память (AT&W). А если по-надежней хотите, то "зеркалируйте" натсройки в резерную энергонезависимую память (AT+WMIR, если не ошибаюсь)
Во-первых, позвольте поинтересоваться происхождением строки
'07918350000005F111000B810805235717F80000A804F4F29C0E'+^Z
это где вы ее вычитали?
все немного не так...
модем (в вашем телефоне) поддерживает 2 режима PDA и ТEXT.
в PDA режиме работаем с хексами...
а ведь можно и в текстовом... )))
Смотрим команду AT+CMGF?
И что же она возвращает?! 2 режима: 0 и 1.
Так вот это и означает, что 0 - PDA, 1 - ТЕКСТ.
след движением пальчиков пишем
AT+CMGF = 1
и "что же творят коннадцы на льду?!"
модем в текстовом режиме.
А теперь гвоздь программы:
команда AT+CMGS имеет след синтаксис
"AT+CMGS=+375291101867" затем 13тый символ
"Привет Королевству!!!" затем есди я не обшибаюсь 26 или 27 символ... (уж не помню Esc-символа корректно, уж много этих GSM телефонов и модемов было).
Пробуйте и читайте доки по рассширенным наборам АТ комманд модема
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.